{"id":15291841,"url":"https://github.com/salrashid123/cloud_auth_tpm","last_synced_at":"2025-11-05T01:01:35.732Z","repository":{"id":255446280,"uuid":"852522799","full_name":"salrashid123/cloud_auth_tpm","owner":"salrashid123","description":"Trusted Platform Module based python auth library for cloud providers","archived":false,"fork":false,"pushed_at":"2025-03-07T18:07:42.000Z","size":98,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T02:07:45.710Z","etag":null,"topics":["aws","azure","gcp","google-auth","google-auth-library","tpm2","trusted-platform-module"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-05T00:32:02.000Z","updated_at":"2025-03-07T18:06:59.000Z","dependencies_parsed_at":"2025-03-07T19:20:13.001Z","dependency_job_id":null,"html_url":"https://github.com/salrashid123/cloud_auth_tpm","commit_stats":null,"previous_names":["salrashid123/google-auth-library-python-tpm","salrashid123/cloud_auth_tpm"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_auth_tpm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_auth_tpm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_auth_tpm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_auth_tpm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/cloud_auth_tpm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248701975,"owners_count":21148111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","azure","gcp","google-auth","google-auth-library","tpm2","trusted-platform-module"],"created_at":"2024-09-30T16:14:45.720Z","updated_at":"2025-11-05T01:01:35.716Z","avatar_url":"https://github.com/salrashid123.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Cloud Auth Library using Trusted Platform Module (TPM)\n\nPython library which supports `TPM` embedded authenticated credentials for various cloud providers.\n\nThe supported set of providers and credential types:\n\n* `Google Cloud`\n  - using [Service Account Credentials](https://cloud.google.com/iam/docs/service-account-creds) where the RSA private key is on the TPM\n\n* `AWS`\n  - using [IAM Roles Anywhere](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/introduction.html) where the RSA private key is on the TPM\n  - using [HMAC Access Keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) where the `AWS_SECRET_ACCESS_KEY` is on the TPM\n\n* `Azure`\n  - using [Certificate Credentials](https://learn.microsoft.com/en-us/entra/identity-platform/certificate-credentials) where the RSA private key is on the TPM\n\non python pypi: [https://pypi.org/project/cloud-auth-tpm/](https://pypi.org/project/cloud-auth-tpm/)\n\nif your'e interested in `PKCS-11`, see\n\n* [Cloud Auth Library using PKCS-11](https://github.com/salrashid123/cloud_auth_pkcs)\n\n\u003e This code is not affiliated with or supported by google\n\n---\n\n### Usage\n\nYou need to first embed an RSA key into a TPM which is then read  using [PEM formatted TPM Keys](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html) and is compatible with [python-tss](https://github.com/tpm2-software/tpm2-pytss) and openssl.\n\nTo do that, see the [Using RSA Keys on TPM](#using-rsa-keys-on-tpm) section for options.\n\nFrom there, depending on the provider, reference the credential in a standard SDK client:\n\n##### **GCPCredentials**\n\n```python\nfrom google.cloud import storage\nfrom cloud_auth_tpm.gcp.gcpcredentials import GCPCredentials\n\n####  pip3 install cloud_auth_tpm[gcp]\npc = GCPCredentials(\n  tcti=\"device:/dev/tpmrm0\",\n  keyfile='/path/to/key.pem',   # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----\n  ownerpassword=None,\n  password=None,\n  policy_impl=None,\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\n##### **AWSCredentials**\n\n```python\nimport boto3\nfrom cloud_auth_tpm.aws.awscredentials import AWSCredentials\n\n####  pip3 install cloud_auth_tpm[aws]\npc = AWSCredentials(\n  tcti=\"device:/dev/tpmrm0\",\n  keyfile='/path/to/key.pem',   # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----\n  ownerpassword=None,\n  password=None,\n  policy_impl=None,\n\n  public_certificate_file=\"certs/alice-cert.crt\",\n  region=\"us-east-2\",\n  duration_seconds=1000,\n  trust_anchor_arn='arn:aws:rolesanywhere:us-east-2:291738886522:trust-anchor/a545a1fc-5d86-4032-8f4c-61cdd6ff92ac',\n  session_name=\"foo\", \n  role_arn=\"arn:aws:iam::291738886522:role/rolesanywhere1\",\n  profile_arn=\"arn:aws:rolesanywhere:us-east-2:291738886522:profile/6f4943fb-13d4-4242-89c4-be367595c560\")\n\nsession = pc.get_session()\n\ns3 = session.resource('s3')\nfor bucket in s3.buckets.all():\n    print(bucket.name)\n```\n\n##### **AWSHMACCredentials**\n\n```python\nimport boto3\nfrom cloud_auth_tpm.aws.awshmaccredentials import AWSHMACCredentials\n\n####  pip3 install cloud_auth_tpm[aws]\npc = AWSHMACCredentials(\n  tcti=\"device:/dev/tpmrm0\",\n  keyfile='/path/to/key.pem',   # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----\n  ownerpassword=None,\n  password=None,\n  policy_impl=None,\n\n  access_key=\"AWS_ACCESS_KEY_ID\",\n  region=\"us-east-2\",\n  duration_seconds=1000,\n  role_session_name=\"foo\",\n  assume_role_arn=\"arn:aws:iam::291738886522:role/gcpsts\")\n\nsession = pc.get_session()\n\ns3 = session.resource('s3')\nfor bucket in s3.buckets.all():\n    print(bucket.name)\n```\n\n##### **AzureCredentials**\n\n```python\nfrom azure.storage.blob import BlobServiceClient\nfrom cloud_auth_tpm.azure.azurecredentials import AzureCredentials\n\n####  pip3 install cloud_auth_tpm[azure]\npc = AzureCredentials(\n  tcti=\"device:/dev/tpmrm0\",\n  keyfile='/path/to/key.pem',   # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----\n  ownerpassword=None,\n  password=None,\n  policy_impl=None,\n\n  tenant_id=\"45243fbe-b73f-4f7d-8213-a104a99e428e\",\n  client_id=\"cffeaee2-5617-4784-8a4b-b647efd676e1\",\n  certificate_path=\"certs/azclient.crt\")\n\nblob_service_client = BlobServiceClient(\n    account_url=\"https://$STORAGE_ACCOUNT.blob.core.windows.net\",\n    credential=pc\n)\ncontainer_client = blob_service_client.get_container_client('container_name')\nblob_list = container_client.list_blobs()\nfor blob in blob_list:\n    print(blob.name)\n```\n\n---\n\n### Configuration\n\n| Option | Description |\n|:------------|-------------|\n| **`tcti`** | Path to TPM:  (required; default: `device:/dev/tpmrm0`) |\n| **`keyfile`** | Path to TPM PEM keyfile:  (required; default: ``) |\n| **`ownerpassword`** | Password for the OWNER hierarchy used by H2 template:  (optional; default: ``) |\n| **`password`** | Password for the Key (userAuth):  (optional; default: ``) |\n| **`policy_impl`** | Concrete implementation class for Policy:  (optional; default: ``) |\n| **`enc_key_name`** | Hex \"name\" for the TPM key to use for session encryption:  (optional; default: ``) |\n| **`use_ek_cert`** | Use the EKRSA parent instead of the H2 template  (optional; default: `False`) |\n\n##### **GCPCredentials**\n\n| Option | Description |\n|:------------|-------------|\n| **`email`** | ServiceAccount email (required; default: ``) |\n| **`scopes`** | Signed Jwt Scopes (optional default: `\"https://www.googleapis.com/auth/cloud-platform\"`) |\n| **`keyid`** | ServiceAccount keyid (optional; default: ``) |\n| **`expire_in`** | Token expiration in seconds (optional; default: `3600`) |\n\n##### **AWSCredentials**\n\n| Option | Description |\n|:------------|-------------|\n| **`public_certificate_file`** | Path to public x509 (required; default: ``) |\n| **`region`** | AWS Region (optional default: ``) |\n| **`duration_seconds`** | Duration in seconds for the token lifetime (optional; default: `3600`) |\n| **`trust_anchor_arn`** | RolesAnywhere Trust anchor ARN (required; default: ``) |\n| **`role_arn`** | RolesAnywhere RoleArn (required; default: ``) |\n| **`profile_arn`** | RolesAnywhere Profile Arn (Required; default: ``) |\n| **`session_name`** | AWS Session Name (optional; default: ``) |\n\n##### **AWSHMACCredentials**\n\n| Option | Description |\n|:------------|-------------|\n| **`region`** | AWS Region (optional default: ``) |\n| **`aws_access_key_id`** | AWS_ACCESS_KEY_ID if using HMAC based credentials (required; default: ``) |\n| **`duration_seconds`** | Duration in seconds for the token lifetime (optional; default: `3600`) |\n| **`get_session_token`** | If using GetSessionToken (optional; default: `False`) |\n| **`assume_role_arn`** | AssumeRole ARN (required if AssumeRole set; default: ``) |\n| **`role_session_name`** | RoleSessionName if AssumeRole set (optional; default: ``) |\n\n##### **AzureCredentials**\n\n| Option | Description |\n|:------------|-------------|\n| **`tenant_id`** | Azure TentantID (required; default: ``) |\n| **`client_id`** | Azure Application (client) ID (required; default: ``) |\n| **`certificate_path`** | x509 certificate to authenticate with (required; default ``) |\n\n---\n\n### Setup\n\nThis library uses the [Enhanced Systems API (ESAPI)](https://tpm2-pytss.readthedocs.io/en/latest/esys.html) provided through `tpm2_pytss`.\n\nYou need to first install [tpm2-tss](https://github.com/tpm2-software/tpm2-tss) `version\u003e=4.1.0` (see [issue#596](https://github.com/tpm2-software/tpm2-pytss/issues/596))\n\n```bash\n## tpm2-tss \u003e 4.1.0 https://github.com/tpm2-software/tpm2-tss\napt-get install libtss2-dev\npython3 -m pip install tpm2-pytss\n```\n\n#### Using RSA Keys on TPM\n\nYou can initialize a TPM based RSA key and optional certificate in several ways:\n\n1. create a key on the TPM and generate an x509  (`tpm2_create`)\n2. import the raw RSA private key into the TPM (`tpm2_import`)\n3. securely transfer a RAW key from one TPM into another (`tpm2_duplicate`)\n\nThis example will just cover (2) using [tpm2_tools](https://github.com/tpm2-software/tpm2-tools) for simplicity.\n\nFor options 1 and 3, see examples [appendix](#set-tpm-based-private-key)\n\nFirst step is to acquire the private RSA keys for whichever provider you're interested in\n\n- `GCP`\n\n  Uses [Service Account Self-signed JWT](https://google.aip.dev/auth/4111 ) with Scopes.\n  \n  Extract the service account json's private key and embed into the TPM.\n\n- `AWS`\n\n  Uses [IAM Roles Anywhere](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/introduction.html) which involves using a local RSA key to authenticate\n\n  This repo also supports `AWS HMAC Credentials` which you can embed into a TPM.\n\n- `Azure`\n\n   Uses [Azure Certificate Credentials](https://learn.microsoft.com/en-us/entra/identity-platform/certificate-credentials)\n\n\nOnce you have the raw RSA private key in in regular PEM format, you can use [tpm2_tools](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_import.1.md#import-an-rsa-key) to load the key into the TPM.  Each provider has its own way to create the raw RSA key and associate it with a cloud credential.  See instructions below for each provider.\n\nNote, you don't have to use `tpm2_tools`: alternatives is to use [ESAPI](https://github.com/salrashid123/tpm2/tree/master/pytss) directly or [go-tpm](https://github.com/salrashid123/tpm2/tree/master/rsa_import)\n\nFor this implementation, each key's parent is defined using the standard [H2 TPM template for ECC](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html).  This allows use of the PEM formatted Keys compatible with `openssl`.\n\n\nFor details on how to import an RSA or HMAC key into the TPM see [KeyImport](#keyimport)\n\n#### Setup Software TPM\n\nThe following demo uses a [swtpm](https://github.com/stefanberger/swtpm). \n\nOfcourse if you would like to use a real TPM, skip initializing the `swtpm` and specify the env variables (`TPM2TOOLS_TCTI=`) variable to an actual TPM one (eg, `device:/dev/tpmrm0`)\n\n```bash\n## initialize swtpm\nrm -rf /tmp/myvtpm \u0026\u0026 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 \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n```\n\n#### Setup - GCP\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\nSetup a new key and download the json\n\n```bash\nexport PROJECT_ID=`gcloud config get-value core/project`\nexport SERVICE_ACCOUNT_EMAIL=jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com\n\ngcloud iam service-accounts create jwt-access-svc-account --display-name \"Test Service Account\"\ngcloud iam service-accounts keys create jwt-access-svc-account.json --iam-account=$SERVICE_ACCOUNT_EMAIL\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'`\nexport SERVICE_ACCOUNT_EMAIL=`cat jwt-access-svc-account.json | jq -r '.client_email'`\n\ncat jwt-access-svc-account.json | jq -r '.private_key' \u003e /tmp/rsakey.pem\n```\n\nImport `/tmp/rsakey.pem` into the TPM following the [KeyImport](#keyimport) section\n\nAt this point, you need to embed the _raw_ RSA key at `/tmp/rsakey.pem` into the TPM. \n\neg, for a software TPM and GCP\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"  # for real tpm use device:/dev/tpmrm0\n\n### create H2 template\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n    -c primary.ctx \\\n    -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\ntpm2_import -C primary.ctx  -G rsa2048:rsassa:null \\\n   -g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv\n\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\ntpm2_load -C primary.ctx -u  rsa.pub -r  rsa.prv -c  rsa.ctx \n\ntpm2_encodeobject -C primary.ctx -u rsa.pub -r rsa.prv -o rsa_auth.pem\n# tpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n```\n\nOnce the key is embedded into the TPM, you can discard the raw key since the TPM based version in PEM format is now at `rsakey.pem` (for example) which you can reference it directly for access:\n\n```bash\ncd example/\npip3 install -r requirements-gcp.txt\n\npython3 main_gcp.py --keyfile=rsa_auth.pem \\\n  --email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \\\n   --tcti=$TPM2TOOLS_TCTI\n```\n\nHow 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 ESAPI to make it \"sign\" data for the JWT.\n\n#### Setup - AWS\n\n[AWS Roles Anywhere](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/introduction.html) allows for client authentication based on digital signature from trusted private keys.\n\nThe trusted client RSA or EC key is embedded within a TPM and that is used to sign the RolesAnywhere header values.\n\nFor a detailed example, see [AWS SDK CredentialProvider for RolesAnywhere](https://github.com/salrashid123/aws_rolesanywhere_signer?tab=readme-ov-file#setup)\n\nIn the example in this repo, we will use a *EXAMPLE* CA and key.  If you follow this setup, you are using the rsa key and CA found in this repo....so  *please* remember to use test resources and promptly delete/disable this.  You can find a sample setup using the link below and in this repo at `example/certs/alice-cert.key`.\n\nCopy `example/certs/alice-cert.key` to `rsakey.pem` and run through the [Using RSA Keys on TPM](#using-rsa-keys-on-tpm) load step\n\nThe specific certificate CA and private key is the same as described in the sample here:\n\n* [AWA RolesAnywhere Signer](https://github.com/salrashid123/aws_rolesanywhere_signer)\n\nWhen you setup RolesAnywhere, note down the ARN for the `TrustAnchorArn`, `ProfileArn` and `RoleArn` as well as the `region`.  Ideally, the role has `AmazonS3ReadOnlyAccess` to list buckets.\n\nThen attempt to use the credentials and specify the specific ARN values\n\n```bash\nexport CERTIFICATE=\"certs/alice-cert.crt\"\nexport REGION=\"us-east-2\"\nexport TRUST_ANCHOR_ARN=\"arn:aws:rolesanywhere:us-east-2:291738886522:trust-anchor/a545a1fc-5d86-4032-8f4c-61cdd6ff92ac\"\nexport ROLE_ARN=\"arn:aws:iam::291738886522:role/rolesanywhere1\"\nexport PROFILE_ARN=\"arn:aws:rolesanywhere:us-east-2:291738886522:profile/6f4943fb-13d4-4242-89c4-be367595c560\"\n\npip3 install -r requirements-aws.txt\n\npython3 main_aws.py --public_certificate_file=$CERTIFICATE \\\n   --region=$REGION  --trust_anchor_arn=$TRUST_ANCHOR_ARN \\\n     --role_arn=$ROLE_ARN \\\n          --profile_arn=$PROFILE_ARN \\\n            --keyfile=rsa_auth.pem \\\n            --tcti=$TPM2TOOLS_TCTI\n```\n\nCurrently ONLY `RSASSA` keys are supported (its easy enough to support others, TODO)\n\nAn alternative to using this library is invoking a process to acquire credentials from any SDK.  See: [AWS Process Credentials for Trusted Platform Module (TPM)](https://github.com/salrashid123/aws-tpm-process-credential).\n\n\n##### AWS HMAC\n\nAWS supports HMAC based authentication as well. see: [AWS Credentials for Hardware Security Modules and TPM based AWS_SECRET_ACCESS_KEY](https://github.com/salrashid123/aws_hmac) and specifically [AWS v4 signed request using Trusted Platform Module](https://gist.github.com/salrashid123/bca7a24e1d59567adb89fef093d8564d)\n\nThis repo includes an example setup and to use this, you need your `AWS_ACCESS_KEY_ID` `AWS_SECRET_ACCESS_KEY` and embed the secret into the TPM and make it perform the HMAC\n\n```bash\n### first embed the hmac key with an optional password\nexport AWS_ACCESS_KEY_ID=recacted\nexport AWS_SECRET_ACCESS_KEY=redacted\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\nexport KEY_PASSWORD=passwd\n\n## add the AWS4 prefix to the key per the signing protocol\nexport secret=\"AWS4$AWS_SECRET_ACCESS_KEY\"\necho -n $secret \u003e hmac.key\n\n## create the h2 template\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n    -c primary.ctx \\\n    -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\n# embed the hmac key\ntpm2_import -C primary.ctx -G hmac -i hmac.key -u hmac.pub -r hmac.prv  -p $KEY_PASSWORD\ntpm2_load -C primary.ctx -u hmac.pub -r hmac.prv -c hmac.ctx \n\ntpm2_encodeobject -C primary.ctx -u hmac.pub -r hmac.prv -o hmac.pem -p $KEY_PASSWORD\n```\n\nTo use this, you need to specify the key file and the `AWS_ACCESS_KEY_ID`\n```bash\nexport REGION=\"us-east-1\"\npip3 install -r requirements-aws.txt\n\n## for getsessiontoken\npython3 main_aws_hmac.py --get_session_token=False \\\n   --region=$REGION  --aws_access_key_id=$AWS_ACCESS_KEY_ID \\\n             --keyfile=hmac.pem \\\n            --password=$KEY_PASSWORD \\\n            --tcti=$TPM2TOOLS_TCTI\n\n## for assumerole\nexport ASSUME_ROLE_ARN=\"arn:aws:iam::291738886548:role/gcpsts\"\npython3 main_aws_hmac.py  --assume_role_arn=$ASSUME_ROLE_ARN --role_session_name=bar \\\n               --region=$REGION  --aws_access_key_id=$AWS_ACCESS_KEY_ID  \\\n                         --keyfile=hmac.pem \\\n                        --password=$KEY_PASSWORD \\\n                        --tcti=$TPM2TOOLS_TCTI\n```\n\n#### Setup - Azure\n\nAzure authentication uses an the basic [Microsoft identity platform application authentication certificate credentials](https://learn.microsoft.com/en-us/entra/identity-platform/certificate-credentials) where the variation here is that the client rsa key is on the TPM\n\nThe following example assumes you have set this up similar to\n\n* [KMS, TPM and HSM based Azure Certificate Credentials](https://github.com/salrashid123/azsigner)\n\nIf you want to follow the instructions above and use the key provided in this repo, copy `example/certs/azclient.key\"` to `rsakey.pem` and run through the [Using RSA Keys on TPM](#using-rsa-keys-on-tpm) load step\n\n\n```bash\n## this is just the public cert and key pem in one file\nexport CERTIFICATE_PATH_COMBINED_DER=\"certs/azclient-cert-key.pem\" \n## this is just the public cert\nexport CERTIFICATE_PATH=\"certs/azclient.crt\" \nexport CLIENT_ID=\"cffeaee2-5617-4784-8a4b-b647efd676e1\"\nexport TENANT_ID=\"45243fbe-b73f-4f7d-8213-a104a99e428e\"\n\n## test that you have the cert based auth working\naz login --service-principal -u $CLIENT_ID -p $CERTIFICATE_PATH_COMBINED_DER --tenant=$TENANT_ID\naz account get-access-token   --scope=\"api://$CLIENT_ID/.default\"\n\n## if the principal has access to a storage container, test that\nexport STORAGE_ACCOUNT=your-storage-account\nexport CONTAINER=your-container\nexport AZURE_TOKEN=$(az account get-access-token --resource https://storage.azure.com/ --query accessToken -o tsv)\n\ncurl -s --oauth2-bearer \"$AZURE_TOKEN\"  -H 'x-ms-version: 2017-11-09'  \\\n     \"https://$STORAGE_ACCOUNT.blob.core.windows.net/$CONTAINER?restype=container\u0026comp=list\" | xmllint -  --format\n\n## now you're ready to test with the client using the embedded TPM key\n\npip3 install -r requirements-azure.txt\n\npython3 main_azure.py --keyfile=rsa_auth.pem \\\n   --certificate_path=$CERTIFICATE_PATH \\\n    --client_id=$CLIENT_ID  --tenant_id=$TENANT_ID \\\n    --tcti=$TPM2TOOLS_TCTI\n```\n\nCurrently ONLY RSASSA  keys are supported (its easy enough to support others, TODO)\n\n\n#### KeyImport\n\nThe following details how you can import an RSA PEM key file into a given TPM.\n\nThe first stage loads the PEM and saves it as `(TPM2B_PUBLIC,TPM2B_PRIVATE)` binary structures\n\nYou would then convert it those to TPM PEM formatted files (`-----BEGIN TSS2 PRIVATE KEY-----`)\n\nFirst step is to create an \"H2 Template\" primary key:\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"  # for real tpm use device:/dev/tpmrm0\n### create H2 template\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n    -c primary.ctx \\\n    -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n```\n\nThen depending on what constraints you want to have on the key:\n\n##### No Auth\n\nFor a plain key\n\n```bash\n# import the key, note we're not setting the password.  \n## Each provider has a different way to get this rsa private key; see examples below\ntpm2_import -C primary.ctx  -G rsa2048:rsassa:null \\\n   -g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv\n\ntpm2_load -C primary.ctx -u  rsa.pub -r  rsa.prv -c  rsa.ctx \ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ntpm2_encodeobject -C primary.ctx -u rsa.pub -r rsa.prv -o rsa_auth.pem\n```\n\n##### Password Auth\n\nIf you want to provide a passphrase to use the TPM based key, you can setup userAuth based access.  To skip password based auth, omit the `-p $KEY_PASSWORD` option during tpm key generation and `--keyPassword=` option while converting to set no auth on the keyfile \n\n```bash\n# import the key, note we're setting the password.  \n## Each provider has a different way to get this rsa private key; see examples below\ntpm2_import -C primary.ctx  -G rsa2048:rsassa:null \\\n   -g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv -p $KEY_PASSWORD\n\ntpm2_load -C primary.ctx -u  rsa.pub -r  rsa.prv -c  rsa.ctx \ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ntpm2_encodeobject -C primary.ctx -u rsa.pub -r rsa.prv -o rsa_auth.pem -p\n```\n\n##### PCR Policy\n\nTo create a key with a PCR policy (i.,e a policy which enforces the key can only be used if certain PCR values exist)\n\n```bash\nexport PCR=23\nexport HASH=sha256\nexport PCRBANK=$HASH:$PCR\n\n## set a pcr policy trial session and import the key\ntpm2_startauthsession -S session.dat\ntpm2_pcrread \"$PCRBANK\" -o pcr23_val.bin\ntpm2_policypcr -S session.dat -l \"$PCRBANK\"  -L policy.dat -f pcr23_val.bin\ntpm2_flushcontext session.dat\n\ntpm2_import -C primary.ctx  -G rsa2048:rsassa:null \\\n   -g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv -L policy.dat\n\ntpm2_load -C primary.ctx -u rsa.pub -r rsa.prv -c .ctx \ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ntpm2_readpublic -c rsa.ctx  -o rsapub.pem -f PEM -Q \ncat rsapub.pem\n\ntpm2_encodeobject -C primary.ctx -u rsa.pub -r rsa.prv -o rsa_pcr.pem\n```\n\n##### PCR and PolicyAuthValue\n\nTo create a key with a PCR policy and a password, use `tpm2_policyauthvalue`\n\n```bash\nexport PCR=23\nexport HASH=sha256\nexport PCRBANK=$HASH:$PCR\nexport KEY_PASSWORD=passwd\n\ntpm2_startauthsession -S session.dat\ntpm2_pcrread sha256:23 -o pcr23_val.bin\ntpm2_policypcr -S session.dat -l sha256:23  -L policy.dat -f pcr23_val.bin\ntpm2_policyauthvalue -S session.dat -L policy.dat\ntpm2_flushcontext session.dat\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ntpm2_import -C primary.ctx  -G rsa2048:rsassa:null \\\n   -g sha256  -i rsakey.pem \\\n   -u rsa.pub -r rsa.prv -L policy.dat  -p $KEY_PASSWORD \n\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l   \n\ntpm2_encodeobject -C primary.ctx -u rsa.pub -r rsa.prv -o rsa_pcr_auth.pem -p\n```\n\n#### PolicyAuthValue and PolicyDuplicateSelect\n\nIf you remotely transferred the key using [tpmcopy](https://github.com/salrashid123/tpmcopy/tree/main?tab=readme-ov-file#rsa), you will need to fulfill `PolicyAuthValue` and `PolicyDuplicateSelect`.\n\nFrom there, you can instantiate `PolicyORAndDuplicateSelectPolicy` as shown in `example/main_gcp_duplicate.py`\n\n#### Custom Policy Implementation\n\nThe built repo contains a helper function which fulfills a `PCR` policy (i.,e certain PCR values must be present to use the key).\n\nYou can define your own class which fulfills any number of supported polcies as described in [TCG TSS 2.0 JSON Data Types and Policy LanguageSpecification](https://trustedcomputinggroup.org/wp-content/uploads/TSS_JSON_Policy_v0.7_r04_pubrev.pdf)\n\n\nThe way to do this is to implement an abstract class:\n\n```python\nfrom cloud_auth_tpm.policy.policy import PolicyEval\n```\n\nwhich requires you to pass in a policy json on init and then impelment whatever you need to do in `policy_callback(ectx: ESAPI, handle: ESYS_TR):`, eg:\n\n\n```python\nclass PolicyEval(object, metaclass=ABCMeta):\n    def __init__(self, policy: dict[str, any] , debug: bool):\n\n    @abstractmethod\n    def policy_callback(self, ectx: ESAPI, handle: ESYS_TR):\n        pass\n```\n\nwhere `ectx` is just the TPM context and `handle` is what key used for session encryption.\n\nFor a built-in policy see [cloud_auth_tpm/policy/pcr.py](cloud_auth_tpm/policy/pcr.py).\n\nTo use a custom policy, fist import a class (in this example, its the default `PCRPolicy`), supply it with the json format of the policy and specify it when invoking credentials.\n\neg, with \n\n```bash\n$ tpm2_pcrread sha256:23\n   sha256:\n    23: 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B\n```\n\nthen define a pcr binding:\n\n```python\nfrom cloud_auth_tpm.policy import PCRPolicy\n\n    pol = {\n        \"description\": \"Policy PCR 23 TPM2_ALG_SHA256\",\n        \"policy\": [\n            {\n                \"type\": \"POLICYPCR\",\n                \"pcrs\": [\n                    {\n                        \"pcr\": 23,\n                        \"hashAlg\": \"TPM2_ALG_SHA256\",\n                        \"digest\": \"F5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B\"\n                    }\n                ]\n            }\n        ]\n    }\n    pc = GCPCredentials(tcti=args.tcti,\n                        keyfile=args.keyfile,\n                        ownerpassword=args.ownerpassword,                        \n                        password=args.password,\n                        policy_impl=PCRPolicy(policy=pol),\n                        email=args.email)\n```\n#### Set TPM Based Private Key \n\nThe following outlines the various options to embed an RSA or HMAC key into a TPM.\n\nthe details of these options, see [here](https://github.com/salrashid123/oauth2?tab=readme-ov-file#usage)\n\n##### 1 Create Key on TPM and use Openssl to generate CSR\n\nThe idea is the the system with the TPM creates an RSA key on its TPM and then issues a CSR against it\n\n```bash\napt install tpm2-openssl tpm2-tools tpm2-abrmd libtss2-tcti-tabrmd0\n\n### verify openssl tpm provider is installed\nopenssl list --providers -provider tpm2\n    Providers:\n      tpm2\n        name: TPM 2.0 Provider\n        version: \n        status: active\n\n## create H2 primary\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256  -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\n## create a key\ntpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx\ntpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n# tpm2_evictcontrol -C o -c key.ctx 0x81010002\ntpm2_readpublic -c key.ctx -f PEM -o svc_account_tpm_pub.pem\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\n## you may need to add a -p if your tpm2 tools is not recent (see https://github.com/tpm2-software/tpm2-tools/issues/3458)\ntpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o svc_account_tpm.pem\n\n### issue the x509 as self-signed or csr\n\n## now use it to generate a csr\n# export SAN=\"DNS:client.domain.com\"\n# openssl req -new  -provider tpm2  -provider default  \\\n#   -out client.csr  \\\n#   -key svc_account_tpm.pem    \\\n#   -subj \"/C=US/O=Google/OU=Enterprise/CN=client.domain.com\" \n\n# or self-signed certificate\nopenssl req  -provider tpm2  -provider default   -new -x509 -key svc_account_tpm.pem -out svc_account_tpm.crt -days 365\n```\n\n##### 2 Import external RSA Key to TPM\n\nThis is the default flow in this repo re an external RSA key is directly imported into the TPM.\n\n```bash\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n   -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\ntpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx\ntpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\ntpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o rsa_tpm.pem\n```\n\n##### 3  Duplicate and Transfer RSA or HMAC key\n\nWith this flow, you can generate an RSA key on one system and security transfer it to another such that only the target TPM can load it.\n\n- `RSA`: [Duplicate and transfer using endorsement key](https://github.com/salrashid123/tpm2/tree/master/tpm2_duplicate#duplicate-and-transfer-using-endorsement-key)\n\n- `HMAC`: [Duplicate an externally loaded HMAC key](https://github.com/salrashid123/tpm2/tree/master/tpm2_duplicate#duplicate-an-externally-loaded-hmac-key)\n\nAlternatively, you can use \n\n- [tpmcopy](https://github.com/salrashid123/tpmcopy)\n\n#### PEM Keyfile format\n\nThe TPM based keys are in PEM format compatible with openssl details of which you can find at [ASN.1 Specification for TPM 2.0 Key Files](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html).\n\nYou can generate or convert TPM based keys on your own using openssl, [tpm2tss-genkey](https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md) or [tpm2genkey](https://github.com/salrashid123/tpm2genkey)\n\ndecoded keys on TPM are readable as:\n\n```bash\nexport OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/\nexport TPM2OPENSSL_TCTI=\"swtpm:port=2321\"\n\n$ openssl rsa -provider tpm2  -provider default -in rsatpm.pem -text\n\nPrivate-Key: (RSA 2048 bit, TPM 2.0)\nModulus:\n    00:ec:26:5b:93:c6:09:b9:11:60:aa:d6:8f:21:6c:\n    b5:6e:8a:52:30:b6:83:a1:0c:58:e7:61:ae:75:22:\n    0d:8a:c9:da:dc:98:d0:32:20:a3:05:17:f4:c1:5d:\n    06:f7:d7:05:09:81:e0:13:26:d7:be:74:53:4f:e0:\n    e1:35:79:6e:bc:72:07:23:61:41:69:63:18:16:f4:\n    27:8d:1c:33:31:59:61:6c:c1:76:f0:2c:e5:7c:e9:\n    d4:d0:93:2b:07:27:77:10:2f:ab:c1:01:78:1c:27:\n    68:e7:28:ba:ef:64:84:fe:62:2f:d4:f1:a8:ca:83:\n    df:27:51:50:a3:b8:51:78:0b:04:be:d5:b5:43:a1:\n    4c:89:fa:78:22:d6:45:50:f2:4a:1a:28:00:a5:6a:\n    15:84:1b:46:51:de:2d:3c:65:c2:8b:9c:93:1d:53:\n    da:4f:34:34:1f:b5:d3:d4:a7:81:aa:2b:44:80:b4:\n    ff:58:51:2c:e7:cb:d4:53:18:ad:a3:49:81:9b:51:\n    c5:4a:5d:f0:a7:7d:f7:eb:cc:00:89:13:9f:36:9e:\n    8f:4d:23:7e:f2:36:dd:cb:cc:e3:b6:7b:b1:b9:4d:\n    87:12:8a:33:2d:96:8c:c1:0a:6e:98:a3:54:29:98:\n    86:79:97:33:42:6d:ca:e1:61:7b:bc:20:0d:30:54:\n    92:3f\nExponent: 65537 (0x10001)\nObject Attributes:\n  userWithAuth\n  sign / encrypt\nSignature Scheme: PKCS1\n  Hash: SHA256\nwriting RSA key\n-----BEGIN TSS2 PRIVATE KEY-----\nMIICNQYGZ4EFCgEDoAMBAQECBEAAAAEEggEaARgAAQALAAQAQAAAABAAFAALCAAA\nAQABAQDsJluTxgm5EWCq1o8hbLVuilIwtoOhDFjnYa51Ig2KydrcmNAyIKMFF/TB\nXQb31wUJgeATJte+dFNP4OE1eW68cgcjYUFpYxgW9CeNHDMxWWFswXbwLOV86dTQ\nkysHJ3cQL6vBAXgcJ2jnKLrvZIT+Yi/U8ajKg98nUVCjuFF4CwS+1bVDoUyJ+ngi\n1kVQ8koaKAClahWEG0ZR3i08ZcKLnJMdU9pPNDQftdPUp4GqK0SAtP9YUSzny9RT\nGK2jSYGbUcVKXfCnfffrzACJE582no9NI37yNt3LzOO2e7G5TYcSijMtlozBCm6Y\no1QpmIZ5lzNCbcrhYXu8IA0wVJI/BIIBAAD+ACDBg/cpGTl++OOHhFwz+nBvPvNm\nqdSNg+gqEzF1Eu2gNgAQ1qv0VDvcnIwo0DlItYWKfL7i1QHVMjp85eVgOGC8Qc65\nVollWVse/DhTZOXz8N6qJhvXbj9HuRK2wdxka4mVjbAbgqNQdJfWbpyJk0d52hJ7\nd71zvOwild71OLe/lvBqQlV3Hrk6Zvaed4C/38K3yPmICFR6YOfsFeDIAirzT+wp\n9WGF9fq9CNzlKZgXAMoYLA6ZthtHKWdUUUYyyK0+yCqeNb32E5jN3Mn3GVxX9tc5\nm5OgWpXX8bLqlRLY38P5J3HZOStjYxNBj5I3PdkvD7DFdlb7ZrJZoUg=\n-----END TSS2 PRIVATE KEY-----\n```\n\nAs a side note, although this is a private key in PEM format, this is NOT usable anywhere outside of that specific TPM and the actual private rsa/hmac key is never exposed outside of the TPM.\n\n#### Session Encryption\n\nTo Enable [TPM Bus encryption](https://trustedcomputinggroup.org/wp-content/uploads/TCG_CPU_TPM_Bus_Protection_Guidance_Passive_Attack_Mitigation_8May23-3.pdf), you need to pass in the hex formatted 'name' of a trusted key you know thats on the TPM  shown [here](https://github.com/salrashid123/tpm2/blob/master/pytss/README.md).\n\nFor example, the following prints the EKRSA Public \"name\" on the tpm.  \n\n```bash\ntpm2_createek -c primary.ctx -G rsa -u ek.pub -Q\ntpm2_readpublic -c primary.ctx -o ek.pem -n name.bin -f pem -Q\nxxd -p -c 100 name.bin \n  000bc947113c66100e860949eaa17bd5aa2a66dac54b55816e459669ef3975bbc91e\n```\n\nso pass that in as\n\n```bash\n--enc_key_name=000bc947113c66100e860949eaa17bd5aa2a66dac54b55816e459669ef3975bbc91e\n```\n\nIf you don't provide the name, the EKPub will get read in live and used as-is\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 ../\n## depending on the variant provider\n# pip3 install -r requirements-gcp.txt \n# pip3 install -r requirements-aws.txt \n# pip3 install -r requirements-azure.txt \n\n\n### to deploy/upload\n# virtualenv env \n# source env/bin/activate\n# python3 -m pip install --upgrade build\n# python3 -m pip install --upgrade twine\n# python3 -m build\n# python3 -m twine upload --repository testpypi dist/*\n# python3 -m twine upload  dist/*\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fcloud_auth_tpm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fcloud_auth_tpm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fcloud_auth_tpm/lists"}