## Google Auth Library for Trusted Platform Module based Service Account Keys
This is an extension of GCP [google-auth-python](https://github.com/googleapis/google-auth-library-python) specifically intended to use service account credentials which are embedded inside a `Trusted Platform Module (TPM)`.
```python
from google.cloud import storage
from google_auth_tpm.credentials import TPMCredentials
### acquire credential source on the TPM
pc = TPMCredentials(tcti="device:/dev/tpmrm0",
path="/HS/SRK/sign1",
email="jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com")
storage_client = storage.Client(project="$PROJECT_ID", credentials=pc)
buckets = storage_client.list_buckets()
for bkt in buckets:
print(bkt.name)
```
on python pypi: [https://pypi.org/project/google-auth-tpm/](https://pypi.org/project/google-auth-tpm/)
> **>>WARNING<<**: This code is not affiliated with or supported by google
---
| Option | Description |
|:------------|-------------|
| **`-tcti`** | Path to TPM: (required; default: `device:/dev/tpmrm0`) |
| **`-path`** | Path to FAPI signing object (required; default: ``) |
| **`-email`** | ServiceAccount email (required; default: ``) |
| **`-scopes`** | Signed Jwt Scopes (optional default: `"https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email"`) |
| **`-keyid`** | ServiceAccount keyid (optional; default: ``) |
| **`-expire_in`** | Token expiration in seconds (optional; default: `3600`) |
| **`-profile`** | FAPI Profile name (optional; default: `P_RSA2048SHA256`) |
| **`-system_dir`** | FAPI system_dir (optional; default: `"~/.local/share/tpm2-tss/system/keystore"`) |
| **`-profile_dir`** | FAPI profile_dir (optional; default: `"/etc/tpm2-tss/fapi-profiles"`) |
| **`-user_dir`** | FAPI user_dirs (optional; default: `"~/.local/share/tpm2-tss/user/keystore/" `) |
---
#### Setup
This library uses the [Feature API](https://tpm2-pytss.readthedocs.io/en/latest/fapi.html) provided through `tpm2_pytss`.
To install that:
```bash
## tpm2-tss > 4.1.0 https://github.com/tpm2-software/tpm2-tss
apt-get install libtss2-dev
python3 -m pip install tpm2-pytss
```
There are several ways you can have a TPM based service account key:
1. create a key on the tpm, use it to create an x509 and upload the certificate
2. import an the raw private key into the TPM
3. securely transfer a key from on machine to the machine with the TPM and then import
This example will just cover (2) for simplicity. For more info, see [oauth2/tpm2tokensource](https://github.com/salrashid123/oauth2?tab=readme-ov-file#usage)
For additional examples on using FAPI with python to perform operations, see [salrashid123/tpm2/pytss](https://github.com/salrashid123/tpm2/tree/master/pytss)
Once you install the FAPI, you will need to embed a service account key into the TPM.
Setup a new key and download the json
```bash
export PROJECT_ID=`gcloud config get-value core/project`
gcloud iam service-accounts create jwt-access-svc-account --display-name "Test Service Account"
export SERVICE_ACCOUNT_EMAIL=jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com
gcloud iam service-accounts keys create jwt-access-svc-account.json --iam-account=$SERVICE_ACCOUNT_EMAIL
gcloud projects add-iam-policy-binding $PROJECT_ID --member=serviceAccount:$SERVICE_ACCOUNT_EMAIL --role=roles/storage.admin
```
Extract the `key_id`, `email` and the raw RSA key
```bash
export KEYID=`cat jwt-access-svc-account.json | jq -r '.private_key_id'`
export EMAIL=`cat jwt-access-svc-account.json | jq -r '.client_email'`
cat jwt-access-svc-account.json | jq -r '.private_key' > /tmp/private.pem
```
Now use the `load.py` FAPI commands to embed the key into the TPM and save it at FAPI path of your choice, eg `/HS/SRK/sign1`:
```bash
cd example/
pip3 install -r requirements.txt
# rm -rf ~/.local/share/tpm2-tss # warning, this'll delete fapi objects you have
python3 load.py --path="/HS/SRK/sign1" --private_key=/tmp/private.pem --tcti=device:/dev/tpmrm0 # --tcti="swtpm:port=2321"
### then run:
python3 main.py --path=/HS/SRK/sign1 --email=$EMAIL --project_id=$PROJECT_ID --tcti=device:/dev/tpmrm0 # --tcti="swtpm:port=2321"
```
### How it works
GCP APIs allows for service account authentication using a [Self-signed JWT with scope](https://google.aip.dev/auth/4111).
What that means is if you take a private key and generate a valid JWT with in the following format, you can just send it to the service as an auth token, that simple.
```json
{
"alg": "RS256",
"typ": "JWT",
"kid": "abcdef1234567890"
}
{
"iss": "jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com",
"sub": "jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"iat": 1511900000,
"exp": 1511903600
}
```
So since we have the RSA key on the TPM, we can use the FAPI to make it "sign" data for the JWT.
#### Local Build
to generate the library from scratch and run local, run
```bash
python3 setup.py sdist bdist_wheel
cd example
virtualenv env
source env/bin/activate
pip3 install ../
pip3 install -r requirements.txt
```
#### Software TPM
If you want to test locally, you can use a software TPM `swtpm`:
```bash
rm -rf /tmp/myvtpm && mkdir /tmp/myvtpm
sudo swtpm_setup --tpmstate /tmp/myvtpm --tpm2 --create-ek-cert
sudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=5
```
Once its setup, you can export the following environment variables and use this with `tpm2_tools`
```bash
export TPM2TOOLS_TCTI="swtpm:port=2321"
export TPM2OPENSSL_TCTI="swtpm:port=2321"
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
```
Raw data
{
"_id": null,
"home_page": "https://github.com/salrashid123/google-auth-library-python-tpm",
"name": "google-auth-tpm",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "Sal Rashid",
"author_email": "salrashid123@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/38/ff/28da38d6018684282c874abed62b1b14199e0dd557649fbb0c513e617830/google_auth_tpm-0.0.35.tar.gz",
"platform": null,
"description": "## Google Auth Library for Trusted Platform Module based Service Account Keys \n\nThis is an extension of GCP [google-auth-python](https://github.com/googleapis/google-auth-library-python) specifically intended to use service account credentials which are embedded inside a `Trusted Platform Module (TPM)`.\n\n\n```python\nfrom google.cloud import storage\nfrom google_auth_tpm.credentials import TPMCredentials\n\n### acquire credential source on the TPM\npc = TPMCredentials(tcti=\"device:/dev/tpmrm0\",\n path=\"/HS/SRK/sign1\",\n email=\"jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com\")\n\nstorage_client = storage.Client(project=\"$PROJECT_ID\", credentials=pc)\n\nbuckets = storage_client.list_buckets()\nfor bkt in buckets:\n print(bkt.name)\n``` \n\non python pypi: [https://pypi.org/project/google-auth-tpm/](https://pypi.org/project/google-auth-tpm/)\n\n> **>>WARNING<<**: This code is not affiliated with or supported by google\n\n---\n\n| Option | Description |\n|:------------|-------------|\n| **`-tcti`** | Path to TPM: (required; default: `device:/dev/tpmrm0`) |\n| **`-path`** | Path to FAPI signing object (required; default: ``) |\n| **`-email`** | ServiceAccount email (required; default: ``) |\n| **`-scopes`** | Signed Jwt Scopes (optional default: `\"https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email\"`) |\n| **`-keyid`** | ServiceAccount keyid (optional; default: ``) |\n| **`-expire_in`** | Token expiration in seconds (optional; default: `3600`) |\n| **`-profile`** | FAPI Profile name (optional; default: `P_RSA2048SHA256`) |\n| **`-system_dir`** | FAPI system_dir (optional; default: `\"~/.local/share/tpm2-tss/system/keystore\"`) |\n| **`-profile_dir`** | FAPI profile_dir (optional; default: `\"/etc/tpm2-tss/fapi-profiles\"`) |\n| **`-user_dir`** | FAPI user_dirs (optional; default: `\"~/.local/share/tpm2-tss/user/keystore/\" `) |\n\n---\n\n#### Setup\n\nThis library uses the [Feature API](https://tpm2-pytss.readthedocs.io/en/latest/fapi.html) provided through `tpm2_pytss`.\n\nTo install that:\n\n```bash\n## tpm2-tss > 4.1.0 https://github.com/tpm2-software/tpm2-tss\napt-get install libtss2-dev\npython3 -m pip install tpm2-pytss\n```\n\nThere are several ways you can have a TPM based service account key:\n\n1. create a key on the tpm, use it to create an x509 and upload the certificate \n2. import an the raw private key into the TPM\n3. securely transfer a key from on machine to the machine with the TPM and then import\n\nThis example will just cover (2) for simplicity. For more info, see [oauth2/tpm2tokensource](https://github.com/salrashid123/oauth2?tab=readme-ov-file#usage)\n\nFor additional examples on using FAPI with python to perform operations, see [salrashid123/tpm2/pytss](https://github.com/salrashid123/tpm2/tree/master/pytss)\n\nOnce you install the FAPI, you will need to embed a service account key into the TPM.\n\nSetup a new key and download the json\n\n```bash\nexport PROJECT_ID=`gcloud config get-value core/project`\n\ngcloud iam service-accounts create jwt-access-svc-account --display-name \"Test Service Account\"\n\nexport SERVICE_ACCOUNT_EMAIL=jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com\n\ngcloud iam service-accounts keys create jwt-access-svc-account.json --iam-account=$SERVICE_ACCOUNT_EMAIL\n\ngcloud projects add-iam-policy-binding $PROJECT_ID --member=serviceAccount:$SERVICE_ACCOUNT_EMAIL --role=roles/storage.admin\n```\n\nExtract the `key_id`, `email` and the raw RSA key\n\n```bash\nexport KEYID=`cat jwt-access-svc-account.json | jq -r '.private_key_id'`\n\nexport EMAIL=`cat jwt-access-svc-account.json | jq -r '.client_email'`\n\ncat jwt-access-svc-account.json | jq -r '.private_key' > /tmp/private.pem\n```\n\nNow use the `load.py` FAPI commands to embed the key into the TPM and save it at FAPI path of your choice, eg `/HS/SRK/sign1`:\n\n```bash\ncd example/\npip3 install -r requirements.txt\n\n# rm -rf ~/.local/share/tpm2-tss # warning, this'll delete fapi objects you have\npython3 load.py --path=\"/HS/SRK/sign1\" --private_key=/tmp/private.pem --tcti=device:/dev/tpmrm0 # --tcti=\"swtpm:port=2321\"\n\n\n### then run:\npython3 main.py --path=/HS/SRK/sign1 --email=$EMAIL --project_id=$PROJECT_ID --tcti=device:/dev/tpmrm0 # --tcti=\"swtpm:port=2321\"\n```\n\n### How it works\n\nGCP APIs allows for service account authentication using a [Self-signed JWT with scope](https://google.aip.dev/auth/4111).\n\nWhat that means is if you take a private key and generate a valid JWT with in the following format, you can just send it to the service as an auth token, that simple.\n\n```json\n{\n \"alg\": \"RS256\",\n \"typ\": \"JWT\",\n \"kid\": \"abcdef1234567890\"\n}\n{\n \"iss\": \"jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com\",\n \"sub\": \"jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com\",\n \"scope\": \"https://www.googleapis.com/auth/cloud-platform\",\n \"iat\": 1511900000,\n \"exp\": 1511903600\n}\n```\n\nSo since we have the RSA key on the TPM, we can use the FAPI to make it \"sign\" data for the JWT.\n\n#### Local Build\n\nto generate the library from scratch and run local, run \n\n```bash\npython3 setup.py sdist bdist_wheel\n\ncd example\nvirtualenv env\nsource env/bin/activate\n\npip3 install ../\npip3 install -r requirements.txt \n```\n\n#### Software TPM\n\nIf you want to test locally, you can use a software TPM `swtpm`:\n\n```bash\nrm -rf /tmp/myvtpm && mkdir /tmp/myvtpm\nsudo swtpm_setup --tpmstate /tmp/myvtpm --tpm2 --create-ek-cert \nsudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=5\n```\n\nOnce its setup, you can export the following environment variables and use this with `tpm2_tools`\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\nexport TPM2OPENSSL_TCTI=\"swtpm:port=2321\"\n\ntpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l\n```\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Python TPM based Credentials for Google Cloud Platform",
"version": "0.0.35",
"project_urls": {
"Homepage": "https://github.com/salrashid123/google-auth-library-python-tpm"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "cd6d088cef37691e46dfd6da6648c72ce84f052c5e0fa7e01274d3cc8351dc88",
"md5": "e70ac4d16972deb16921c8c8414f7826",
"sha256": "96ce17662ce317aa3f12bd31229e1d25ca22222342ddbc8bc7b90bba338b3a1d"
},
"downloads": -1,
"filename": "google_auth_tpm-0.0.35-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e70ac4d16972deb16921c8c8414f7826",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 9643,
"upload_time": "2024-09-06T15:31:56",
"upload_time_iso_8601": "2024-09-06T15:31:56.274465Z",
"url": "https://files.pythonhosted.org/packages/cd/6d/088cef37691e46dfd6da6648c72ce84f052c5e0fa7e01274d3cc8351dc88/google_auth_tpm-0.0.35-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "38ff28da38d6018684282c874abed62b1b14199e0dd557649fbb0c513e617830",
"md5": "c4e83ccf69742303ac530027cc787582",
"sha256": "c3489d2db3b8f2ae107225d34c795dbbb47f653aa87f1945f5b780f6ad44f91a"
},
"downloads": -1,
"filename": "google_auth_tpm-0.0.35.tar.gz",
"has_sig": false,
"md5_digest": "c4e83ccf69742303ac530027cc787582",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 9170,
"upload_time": "2024-09-06T15:31:57",
"upload_time_iso_8601": "2024-09-06T15:31:57.973759Z",
"url": "https://files.pythonhosted.org/packages/38/ff/28da38d6018684282c874abed62b1b14199e0dd557649fbb0c513e617830/google_auth_tpm-0.0.35.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-06 15:31:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "salrashid123",
"github_project": "google-auth-library-python-tpm",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "google-auth-tpm"
}