## Cloud Auth Library using Trusted Platform Module (TPM)
Python library which supports TPM embedded credentials for various cloud providers.
on python pypi: [https://pypi.org/project/cloud-auth-tpm/](https://pypi.org/project/cloud-auth-tpm/)
> **>>WARNING<<**: This code is not affiliated with or supported by google
---
### Usage
You need to first embed an RSA key into a TPM thats readable by [python-tss](https://github.com/tpm2-software/tpm2-pytss) or openssl and accessed using [PEM formatted TPM Keys](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html). To do that, see the [Using RSA Keys on TPM](#using-rsa-keys-on-tpm) section for options.
##### **GCPCredentials**
```python
from google.cloud import storage
from cloud_auth_tpm.gcp.gcpcredentials import GCPCredentials
#### pip3 install cloud_auth_tpm[gcp]
pc = GCPCredentials(
tcti="device:/dev/tpmrm0",
keyfile='/path/to/key.pem', # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----
ownerpassword=None,
password=None,
policy_impl=None,
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)
```
##### **AWSCredentials**
```python
import boto3
from cloud_auth_tpm.aws.awscredentials import AWSCredentials
#### pip3 install cloud_auth_tpm[aws]
pc = AWSCredentials(
tcti="device:/dev/tpmrm0",
keyfile='/path/to/key.pem', # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----
ownerpassword=None,
password=None,
policy_impl=None,
public_certificate_file="certs/alice-cert.crt",
region="us-east-2",
duration_seconds=1000,
trust_anchor_arn='arn:aws:rolesanywhere:us-east-2:291738886522:trust-anchor/a545a1fc-5d86-4032-8f4c-61cdd6ff92ac',
session_name="foo",
role_arn="arn:aws:iam::291738886522:role/rolesanywhere1",
profile_arn="arn:aws:rolesanywhere:us-east-2:291738886522:profile/6f4943fb-13d4-4242-89c4-be367595c560")
session = pc.get_session()
s3 = session.resource('s3')
for bucket in s3.buckets.all():
print(bucket.name)
```
##### **AWSHMACCredentials**
```python
import boto3
from cloud_auth_tpm.aws.awshmaccredentials import AWSHMACCredentials
#### pip3 install cloud_auth_tpm[aws]
pc = AWSHMACCredentials(
tcti="device:/dev/tpmrm0",
keyfile='/path/to/key.pem', # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----
ownerpassword=None,
password=None,
policy_impl=None,
access_key="AWS_ACCESS_KEY_ID",
region="us-east-2",
duration_seconds=1000,
role_session_name="foo",
assume_role_arn="arn:aws:iam::291738886522:role/gcpsts")
session = pc.get_session()
s3 = session.resource('s3')
for bucket in s3.buckets.all():
print(bucket.name)
```
##### **AzureCredentials**
```python
from azure.storage.blob import BlobServiceClient
from cloud_auth_tpm.azure.azurecredentials import AzureCredentials
#### pip3 install cloud_auth_tpm[azure]
pc = AzureCredentials(
tcti="device:/dev/tpmrm0",
keyfile='/path/to/key.pem', # TPM KEY: -----BEGIN TSS2 PRIVATE KEY-----
ownerpassword=None,
password=None,
policy_impl=None,
tenant_id="45243fbe-b73f-4f7d-8213-a104a99e428e",
client_id="cffeaee2-5617-4784-8a4b-b647efd676e1",
certificate_path="certs/azclient.crt")
blob_service_client = BlobServiceClient(
account_url="https://$STORAGE_ACCOUNT.blob.core.windows.net",
credential=pc
)
container_client = blob_service_client.get_container_client('container_name')
blob_list = container_client.list_blobs()
for blob in blob_list:
print(blob.name)
```
---
### Configuration
| Option | Description |
|:------------|-------------|
| **`tcti`** | Path to TPM: (required; default: `device:/dev/tpmrm0`) |
| **`keyfile`** | Path to TPM PEM keyfile: (required; default: ``) |
| **`ownerpassword`** | Password for the OWNER hierarchy used by H2 template: (optional; default: ``) |
| **`password`** | Password for the Key (userAuth): (optional; default: ``) |
| **`policy_impl`** | Concrete implementation class for Policy: (optional; default: ``) |
| **`enc_key_name`** | Hex "name" for the TPM key to use for session encryption: (optional; default: ``) |
##### **GCPCredentials**
| Option | Description |
|:------------|-------------|
| **`email`** | ServiceAccount email (required; default: ``) |
| **`scopes`** | Signed Jwt Scopes (optional default: `"https://www.googleapis.com/auth/cloud-platform"`) |
| **`keyid`** | ServiceAccount keyid (optional; default: ``) |
| **`expire_in`** | Token expiration in seconds (optional; default: `3600`) |
##### **AWSCredentials**
| Option | Description |
|:------------|-------------|
| **`public_certificate_file`** | Path to public x509 (required; default: ``) |
| **`region`** | AWS Region (optional default: ``) |
| **`duration_seconds`** | Duration in seconds for the token lifetime (optional; default: `3600`) |
| **`trust_anchor_arn`** | RolesAnywhere Trust anchor ARN (required; default: ``) |
| **`role_arn`** | RolesAnywhere RoleArn (required; default: ``) |
| **`profile_arn`** | RolesAnywhere Profile Arn (Required; default: ``) |
| **`session_name`** | AWS Session Name (optional; default: ``) |
##### **AWSHMACCredentials**
| Option | Description |
|:------------|-------------|
| **`region`** | AWS Region (optional default: ``) |
| **`aws_access_key_id`** | AWS_ACCESS_KEY_ID if using HMAC based credentials (required; default: ``) |
| **`duration_seconds`** | Duration in seconds for the token lifetime (optional; default: `3600`) |
| **`get_session_token`** | If using GetSessionToken (optional; default: `False`) |
| **`assume_role_arn`** | AssumeRole ARN (required if AssumeRole set; default: ``) |
| **`role_session_name`** | RoleSessionName if AssumeRole set (optional; default: ``) |
##### **AzureCredentials**
| Option | Description |
|:------------|-------------|
| **`tenant_id`** | Azure TentantID (required; default: ``) |
| **`client_id`** | Azure Application (client) ID (required; default: ``) |
| **`certificate_path`** | x509 certificate to authenticate with (required; default ``) |
---
### Setup
This library uses the [Enhanced Systems API (ESAPI)](https://tpm2-pytss.readthedocs.io/en/latest/esys.html) provided through `tpm2_pytss`. If you are interested in a branch which uses the `Feature API (FAPI)`, see the [fapi](https://github.com/salrashid123/cloud_auth_tpm/tree/fapi) branch in this repo.
You need to first install [tpm2-tss](https://github.com/tpm2-software/tpm2-tss) `version>=4.1.0` (see [issue#596](https://github.com/tpm2-software/tpm2-pytss/issues/596))
```bash
## tpm2-tss > 4.1.0 https://github.com/tpm2-software/tpm2-tss
apt-get install libtss2-dev
python3 -m pip install tpm2-pytss
```
#### Using RSA Keys on TPM
You can initialize a TPM based RSA key and optional certificate in several ways:
1. create a key on the tpm
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 using [tpm2_tools](https://github.com/tpm2-software/tpm2-tools) and the ESAP utility functions in [util/](util).
For more info, see [oauth2/tpm2tokensource](https://github.com/salrashid123/oauth2?tab=readme-ov-file#usage)
For additional examples on using ESAPI with python to perform operations, see [salrashid123/tpm2/pytss](https://github.com/salrashid123/tpm2/tree/master/pytss)
First step is to acquire the private RSA keys for whichever provider you're interested in
- `GCP`
Uses [Service Account Self-signed JWT](https://google.aip.dev/auth/4111 ) with Scopes.
Extract the service account json's private key and embed into the TPM.
- `AWS`
Uses [IAM Roles Anywhere](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/introduction.html) which involves using a local RSA key to authenticate
This repo also supports `AWS HMAC Credentials` which you can embed into a TPM.
- `Azure`
Uses [Azure Certificate Credentials](https://learn.microsoft.com/en-us/entra/identity-platform/certificate-credentials)
Once 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.
Note, 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)
For 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`.
The example in this repo converts the TPM public/private blobs to PEM format using python. As mentioned, you can also directly use [tpm2genkey](https://github.com/salrashid123/tpm2genkey?tab=readme-ov-file#convert-tpm2b_public-tpm2b_private-with-tpmhtpermanent-h2-template----pem) or for simple keys [tpm2tss-genkey](https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md)
For details on how to import an RSA or HMAC key into the TPM see [KeyImport](#keyimport)
#### Setup - GCP
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)`.
Setup a new key and download the json
```bash
export PROJECT_ID=`gcloud config get-value core/project`
export SERVICE_ACCOUNT_EMAIL=jwt-access-svc-account@$PROJECT_ID.iam.gserviceaccount.com
gcloud iam service-accounts create jwt-access-svc-account --display-name "Test Service Account"
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 SERVICE_ACCOUNT_EMAIL=`cat jwt-access-svc-account.json | jq -r '.client_email'`
cat jwt-access-svc-account.json | jq -r '.private_key' > /tmp/rsakey.pem
```
At this point, you need to embed the _raw_ RSA key at `/tmp/rsakey.pem` into the TPM. See the section above in using the `util/load.py` script.
Once 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:
```bash
cd example/
pip3 install -r requirements-gcp.txt
### Password
python3 main_gcp.py --keyfile=rsa_auth.pem \
--email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \
--password=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI
### PCR
export PCR=23
python3 main_gcp.py --keyfile=rsa_pcr.pem \
--email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \
--pcr=$PCR --tcti=$TPM2TOOLS_TCTI
### PCR and password
export PCR=23
python3 main_gcp.py --keyfile=rsa_pcr_auth.pem \
--email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \
--pcr=$PCR --password=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI
```
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 ESAPI to make it "sign" data for the JWT.
#### Setup - AWS
[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.
The trusted client RSA or EC key is embedded within a TPM and that is used to sign the RolesAnywhere header values.
In 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`.
Copy `example/certs/alice-cert.key` to `rsakey.pem` and run through the [Using RSA Keys on TPM](#using-rsa-keys-on-tpm) load step
The specific certificate CA and private key is the same as described in the sample here:
* [AWA RolesAnywhere Signer](https://github.com/salrashid123/aws_rolesanywhere_signer)
When 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. If you want to use the script in this repo to embed the cert see the section above in using the `util/load.py` script
Then attempt to use the credentials and specify the specific ARN values
```bash
export CERTIFICATE="certs/alice-cert.crt"
export REGION="us-east-2"
export TRUST_ANCHOR_ARN="arn:aws:rolesanywhere:us-east-2:291738886522:trust-anchor/a545a1fc-5d86-4032-8f4c-61cdd6ff92ac"
export ROLE_ARN="arn:aws:iam::291738886522:role/rolesanywhere1"
export PROFILE_ARN="arn:aws:rolesanywhere:us-east-2:291738886522:profile/6f4943fb-13d4-4242-89c4-be367595c560"
pip3 install -r requirements-aws.txt
## Password
python3 main_aws.py --public_certificate_file=$CERTIFICATE \
--region=$REGION --trust_anchor_arn=$TRUST_ANCHOR_ARN \
--role_arn=$ROLE_ARN \
--profile_arn=$PROFILE_ARN \
--keyfile=rsa_auth.pem \
--password=$KEY_PASSWORD \
--tcti=$TPM2TOOLS_TCTI
### PCR
export PCR=23
python3 main_aws.py --public_certificate_file=$CERTIFICATE \
--region=$REGION --trust_anchor_arn=$TRUST_ANCHOR_ARN \
--role_arn=$ROLE_ARN \
--profile_arn=$PROFILE_ARN \
--keyfile=rsa_pcr.pem \
--pcr=$PCR \
--tcti=$TPM2TOOLS_TCTI
```
Currently ONLY `RSASSA` keys are supported (its easy enough to support others, TODO)
An 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).
##### AWS HMAC
AWS 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)
This 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
```bash
### first embed the hmac key
export AWS_ACCESS_KEY_ID=recacted
export AWS_SECRET_ACCESS_KEY=redacted
export TPM2TOOLS_TCTI="swtpm:port=2321"
export KEY_PASSWORD=passwd
## add the AWS4 prefix to the key per the signing protocol
export secret="AWS4$AWS_SECRET_ACCESS_KEY"
echo -n $secret > hmac.key
## create the h2 template
printf '\x00\x00' > unique.dat
tpm2_createprimary -C o -G ecc -g sha256 -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
# embed the hmac key
tpm2_import -C primary.ctx -G hmac -i hmac.key -u hmac.pub -r hmac.prv -p $KEY_PASSWORD
tpm2_load -C primary.ctx -u hmac.pub -r hmac.prv -c hmac.ctx
### now convert the pub/priv to a PEM
cd util/
python3 load.py --public=hmac.pub --private=hmac.prv --out=hmac.pem --keyPassword=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI
```
To use this, you need to specify the key file and the `AWS_ACCESS_KEY_ID`
```bash
export REGION="us-east-1"
pip3 install -r requirements-aws.txt
## for getsessiontoken
python3 main_aws_hmac.py --get_session_token=False \
--region=$REGION --aws_access_key_id=$AWS_ACCESS_KEY_ID \
--keyfile=hmac.pem \
--password=$KEY_PASSWORD \
--tcti=$TPM2TOOLS_TCTI
## for assumerole
export ASSUME_ROLE_ARN="arn:aws:iam::291738886548:role/gcpsts"
python3 main_aws_hmac.py --assume_role_arn=$ASSUME_ROLE_ARN --role_session_name=bar \
--region=$REGION --aws_access_key_id=$AWS_ACCESS_KEY_ID \
--keyfile=hmac.pem \
--password=$KEY_PASSWORD \
--tcti=$TPM2TOOLS_TCTI
```
#### Setup - Azure
Azure 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
The following example assumes you have set this up similar to
* [KMS, TPM and HSM based Azure Certificate Credentials](https://github.com/salrashid123/azsigner)
If 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
```bash
## this is just the public cert and key pem in one file
export CERTIFICATE_PATH_COMBINED_DER="certs/azclient-cert-key.pem"
## this is just the public cert
export CERTIFICATE_PATH="certs/azclient.crt"
export CLIENT_ID="cffeaee2-5617-4784-8a4b-b647efd676e1"
export TENANT_ID="45243fbe-b73f-4f7d-8213-a104a99e428e"
## test that you have the cert based auth working
az login --service-principal -u $CLIENT_ID -p $CERTIFICATE_PATH_COMBINED_DER --tenant=$TENANT_ID
az account get-access-token --scope="api://$CLIENT_ID/.default"
## if the principal has access to a storage container, test that
export STORAGE_ACCOUNT=your-storage-account
export CONTAINER=your-container
export AZURE_TOKEN=$(az account get-access-token --resource https://storage.azure.com/ --query accessToken -o tsv)
curl -s --oauth2-bearer "$AZURE_TOKEN" -H 'x-ms-version: 2017-11-09' \
"https://$STORAGE_ACCOUNT.blob.core.windows.net/$CONTAINER?restype=container&comp=list" | xmllint - --format
## now you're ready to test with the client using the embedded TPM key
pip3 install -r requirements-azure.txt
### Password
python3 main_azure.py --keyfile=rsa_auth.pem \
--certificate_path=$CERTIFICATE_PATH \
--client_id=$CLIENT_ID --tenant_id=$TENANT_ID \
--password=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI
### PCR
export PCR=23
python3 main_azure.py --keyfile=rsa_pcr.pem \
--certificate_path=$CERTIFICATE_PATH \
--client_id=$CLIENT_ID --tenant_id=$TENANT_ID \
--pcr=$PCR --tcti=$TPM2TOOLS_TCTI
```
Currently ONLY RSASSA keys are supported (its easy enough to support others, TODO)
#### KeyImport
The following details how you can import an RSA PEM key file into a given TPM.
The first stage loads the PEM and saves it as `(TPM2B_PUBLIC,TPM2B_PRIVATE)` binary structures
You would then convert it those to TPM PEM formatted files (`-----BEGIN TSS2 PRIVATE KEY-----`)
First step is to create an "H2 Template" primary key:
```bash
export TPM2TOOLS_TCTI="swtpm:port=2321" # for real tpm use device:/dev/tpmrm0
cd /tmp/
### create H2 template
printf '\x00\x00' > unique.dat
tpm2_createprimary -C o -G ecc -g sha256 \
-c primary.ctx \
-a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
```
Then depending on what constraints you have on the key:
##### No Auth
For a plain key
```bash
# import the key, note we're setting the password.
## Each provider has a different way to get this rsa private key; see examples below
tpm2_import -C primary.ctx -G rsa2048:rsassa:null \
-g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv
tpm2_load -C primary.ctx -u rsa.pub -r rsa.prv -c rsa.ctx
## convert pub/priv blobs to PEM (remember to specify the full path --public --private and --out)
### alternatives to this is: https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md
cd util/
python3 load.py --public=rsa.pub \
--private=rsa.prv --out=rsa_auth.pem --tcti=$TPM2TOOLS_TCTI
```
##### Password Auth
If 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
```bash
# import the key, note we're setting the password.
## Each provider has a different way to get this rsa private key; see examples below
tpm2_import -C primary.ctx -G rsa2048:rsassa:null \
-g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv -p $KEY_PASSWORD
tpm2_load -C primary.ctx -u rsa.pub -r rsa.prv -c rsa.ctx
## convert pub/priv blobs to PEM (remember to specify the full path --public --private and --out)
### alternatives to this is: https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md
cd util/
python3 load.py --public=rsa.pub \
--private=rsa.prv --out=rsa_auth.pem \
--keyPassword=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI
```
##### PCR Policy
To create a key with a PCR policy (i.,e a policy which enforces the key can only be used if certain PCR values exist)
```bash
export PCR=23
export HASH=sha256
export PCRBANK=$HASH:$PCR
## set a pcr policy trial session and import the key
tpm2_startauthsession -S session.dat
tpm2_pcrread "$PCRBANK" -o pcr23_val.bin
tpm2_policypcr -S session.dat -l "$PCRBANK" -L policy.dat -f pcr23_val.bin
tpm2_flushcontext session.dat
tpm2_import -C primary.ctx -G rsa2048:rsassa:null \
-g sha256 -i rsakey.pem -u rsa.pub -r rsa.prv -L policy.dat
tpm2_load -C primary.ctx -u rsa.pub -r rsa.prv -c .ctx
tpm2_readpublic -c rsa.ctx -o rsapub.pem -f PEM -Q
cat rsapub.pem
## convert pub/priv to PEM
cd util/
python3 load.py --public=rsa.pub \
--private=rsa.prv --out=rsa_pcr.pem --tcti=$TPM2TOOLS_TCTI
```
##### PCR and PolicyAuthValue
To create a key with a PCR policy and a password, use `tpm2_policyauthvalue`
```bash
export PCR=23
export HASH=sha256
export PCRBANK=$HASH:$PCR
export KEY_PASSWORD=passwd
tpm2_startauthsession -S session.dat
tpm2_pcrread sha256:23 -o pcr23_val.bin
tpm2_policypcr -S session.dat -l sha256:23 -L policy.dat -f pcr23_val.bin
tpm2_policyauthvalue -S session.dat -L policy.dat
tpm2_flushcontext session.dat
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
tpm2_import -C primary.ctx -G rsa2048:rsassa:null \
-g sha256 -i rsakey.pem \
-u rsa.pub -r rsa.prv -L policy.dat -p $KEY_PASSWORD
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
## convert pub/priv to PEM
cd util/
python3 load.py --public=/tmp/rsa.pub --private=/tmp/rsa.prv \
--out=rsa_pcr_auth.pem --tcti=$TPM2TOOLS_TCTI --keyPassword=$KEY_PASSWORD
```
#### Custom Policy Implementation
The built repo contains a helper function which fulfills a `PCR` policy (i.,e certain PCR values must be present to use the key).
You 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)
The way to do this is to implement an abstract class:
```python
from cloud_auth_tpm.policy.policy import PolicyEval
```
which requires you to pass in a policy json on init and then impelment whatever you need to do in `policy_callback(ectx)`, eg:
```python
class PolicyEval(object, metaclass=ABCMeta):
def __init__(self, policy: dict[str, any] , debug: bool):
@abstractmethod
def policy_callback(self, ectx: ESAPI):
pass
```
so for the built-in policy see [cloud_auth_tpm/policy/pcr.py](cloud_auth_tpm/policy/pcr.py).
Then to use it, fist import the policy (in this example, its the default `PCRPolicy`), supply it with the json format of the policy and specify it when invoking credentials.
eg, with
```bash
$ tpm2_pcrread sha256:23
sha256:
23: 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B
```
then define a pcr binding:
```python
from cloud_auth_tpm.policy import PCRPolicy
pol = {
"description": "Policy PCR 23 TPM2_ALG_SHA256",
"policy": [
{
"type": "POLICYPCR",
"pcrs": [
{
"pcr": 23,
"hashAlg": "TPM2_ALG_SHA256",
"digest": "F5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B"
}
]
}
]
}
pc = GCPCredentials(tcti=args.tcti,
keyfile=args.keyfile,
ownerpassword=args.ownerpassword,
password=args.password,
policy_impl=PCRPolicy(policy=pol),
email=args.email)
```
#### PEM Keyfile format
The 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).
You 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)
decoded keys on TPM are readable as:
```bash
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/
export TPM2OPENSSL_TCTI="swtpm:port=2321"
$ openssl rsa -provider tpm2 -provider default -in rsatpm.pem -text
Private-Key: (RSA 2048 bit, TPM 2.0)
Modulus:
00:ec:26:5b:93:c6:09:b9:11:60:aa:d6:8f:21:6c:
b5:6e:8a:52:30:b6:83:a1:0c:58:e7:61:ae:75:22:
0d:8a:c9:da:dc:98:d0:32:20:a3:05:17:f4:c1:5d:
06:f7:d7:05:09:81:e0:13:26:d7:be:74:53:4f:e0:
e1:35:79:6e:bc:72:07:23:61:41:69:63:18:16:f4:
27:8d:1c:33:31:59:61:6c:c1:76:f0:2c:e5:7c:e9:
d4:d0:93:2b:07:27:77:10:2f:ab:c1:01:78:1c:27:
68:e7:28:ba:ef:64:84:fe:62:2f:d4:f1:a8:ca:83:
df:27:51:50:a3:b8:51:78:0b:04:be:d5:b5:43:a1:
4c:89:fa:78:22:d6:45:50:f2:4a:1a:28:00:a5:6a:
15:84:1b:46:51:de:2d:3c:65:c2:8b:9c:93:1d:53:
da:4f:34:34:1f:b5:d3:d4:a7:81:aa:2b:44:80:b4:
ff:58:51:2c:e7:cb:d4:53:18:ad:a3:49:81:9b:51:
c5:4a:5d:f0:a7:7d:f7:eb:cc:00:89:13:9f:36:9e:
8f:4d:23:7e:f2:36:dd:cb:cc:e3:b6:7b:b1:b9:4d:
87:12:8a:33:2d:96:8c:c1:0a:6e:98:a3:54:29:98:
86:79:97:33:42:6d:ca:e1:61:7b:bc:20:0d:30:54:
92:3f
Exponent: 65537 (0x10001)
Object Attributes:
userWithAuth
sign / encrypt
Signature Scheme: PKCS1
Hash: SHA256
writing RSA key
-----BEGIN TSS2 PRIVATE KEY-----
MIICNQYGZ4EFCgEDoAMBAQECBEAAAAEEggEaARgAAQALAAQAQAAAABAAFAALCAAA
AQABAQDsJluTxgm5EWCq1o8hbLVuilIwtoOhDFjnYa51Ig2KydrcmNAyIKMFF/TB
XQb31wUJgeATJte+dFNP4OE1eW68cgcjYUFpYxgW9CeNHDMxWWFswXbwLOV86dTQ
kysHJ3cQL6vBAXgcJ2jnKLrvZIT+Yi/U8ajKg98nUVCjuFF4CwS+1bVDoUyJ+ngi
1kVQ8koaKAClahWEG0ZR3i08ZcKLnJMdU9pPNDQftdPUp4GqK0SAtP9YUSzny9RT
GK2jSYGbUcVKXfCnfffrzACJE582no9NI37yNt3LzOO2e7G5TYcSijMtlozBCm6Y
o1QpmIZ5lzNCbcrhYXu8IA0wVJI/BIIBAAD+ACDBg/cpGTl++OOHhFwz+nBvPvNm
qdSNg+gqEzF1Eu2gNgAQ1qv0VDvcnIwo0DlItYWKfL7i1QHVMjp85eVgOGC8Qc65
VollWVse/DhTZOXz8N6qJhvXbj9HuRK2wdxka4mVjbAbgqNQdJfWbpyJk0d52hJ7
d71zvOwild71OLe/lvBqQlV3Hrk6Zvaed4C/38K3yPmICFR6YOfsFeDIAirzT+wp
9WGF9fq9CNzlKZgXAMoYLA6ZthtHKWdUUUYyyK0+yCqeNb32E5jN3Mn3GVxX9tc5
m5OgWpXX8bLqlRLY38P5J3HZOStjYxNBj5I3PdkvD7DFdlb7ZrJZoUg=
-----END TSS2 PRIVATE KEY-----
```
As 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.
#### Session Encryption
To 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).
For example, the following prints the EKRSA Public "name" on the tpm.
```bash
tpm2_createek -c primary.ctx -G rsa -u ek.pub -Q
tpm2_readpublic -c primary.ctx -o ek.pem -n name.bin -f pem -Q
xxd -p -c 100 name.bin
000bc947113c66100e860949eaa17bd5aa2a66dac54b55816e459669ef3975bbc91e
```
so pass that in as
```bash
--enc_key_name=000bc947113c66100e860949eaa17bd5aa2a66dac54b55816e459669ef3975bbc91e
```
If you don't provide the name, the EKPub will get read in live and used as-is
#### 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 ../
## depending on the variant provider
# pip3 install -r requirements-gcp.txt
# pip3 install -r requirements-aws.txt
# pip3 install -r requirements-azure.txt
### to deploy/upload
# virtualenv env
# source env/bin/activate
# python3 -m pip install --upgrade build
# python3 -m pip install --upgrade twine
# python3 -m build
# python3 -m twine upload --repository testpypi dist/*
# python3 -m twine upload dist/*
```
#### 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"
## swtpm don't have resource manager so you'll see "out of memory for object contexts" often...to clear the contexts:
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
```
Raw data
{
"_id": null,
"home_page": "https://github.com/salrashid123/cloud_auth_tpm",
"name": "cloud-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/fb/11/1cb4ced8de448d71efd98448cc76d8b27baf8b0751daf5fd10a926724c3d/cloud_auth_tpm-0.6.4.tar.gz",
"platform": null,
"description": "## Cloud Auth Library using Trusted Platform Module (TPM)\n\nPython library which supports TPM embedded credentials for various cloud providers.\n\non python pypi: [https://pypi.org/project/cloud-auth-tpm/](https://pypi.org/project/cloud-auth-tpm/)\n\n> **>>WARNING<<**: 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 thats readable by [python-tss](https://github.com/tpm2-software/tpm2-pytss) or openssl and accessed using [PEM formatted TPM Keys](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html). To do that, see the [Using RSA Keys on TPM](#using-rsa-keys-on-tpm) section for options.\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\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`. If you are interested in a branch which uses the `Feature API (FAPI)`, see the [fapi](https://github.com/salrashid123/cloud_auth_tpm/tree/fapi) branch in this repo.\n\nYou need to first install [tpm2-tss](https://github.com/tpm2-software/tpm2-tss) `version>=4.1.0` (see [issue#596](https://github.com/tpm2-software/tpm2-pytss/issues/596))\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\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\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 using [tpm2_tools](https://github.com/tpm2-software/tpm2-tools) and the ESAP utility functions in [util/](util). \n\nFor more info, see [oauth2/tpm2tokensource](https://github.com/salrashid123/oauth2?tab=readme-ov-file#usage)\n\nFor additional examples on using ESAPI with python to perform operations, see [salrashid123/tpm2/pytss](https://github.com/salrashid123/tpm2/tree/master/pytss)\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\nThe example in this repo converts the TPM public/private blobs to PEM format using python. As mentioned, you can also directly use [tpm2genkey](https://github.com/salrashid123/tpm2genkey?tab=readme-ov-file#convert-tpm2b_public-tpm2b_private-with-tpmhtpermanent-h2-template----pem) or for simple keys [tpm2tss-genkey](https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md)\n\n\nFor details on how to import an RSA or HMAC key into the TPM see [KeyImport](#keyimport)\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' > /tmp/rsakey.pem\n```\n\nAt this point, you need to embed the _raw_ RSA key at `/tmp/rsakey.pem` into the TPM. See the section above in using the `util/load.py` script.\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\n### Password\npython3 main_gcp.py --keyfile=rsa_auth.pem \\\n --email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \\\n --password=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI\n\n### PCR\nexport PCR=23\npython3 main_gcp.py --keyfile=rsa_pcr.pem \\\n --email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \\\n --pcr=$PCR --tcti=$TPM2TOOLS_TCTI\n\n### PCR and password\nexport PCR=23\npython3 main_gcp.py --keyfile=rsa_pcr_auth.pem \\\n --email=$SERVICE_ACCOUNT_EMAIL --project_id=$PROJECT_ID \\\n --pcr=$PCR --password=$KEY_PASSWORD --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\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. If you want to use the script in this repo to embed the cert see the section above in using the `util/load.py` script\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\n## Password\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 --password=$KEY_PASSWORD \\\n --tcti=$TPM2TOOLS_TCTI\n\n### PCR\nexport PCR=23\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_pcr.pem \\\n --pcr=$PCR \\\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\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 > hmac.key\n\n## create the h2 template\nprintf '\\x00\\x00' > 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# 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\n### now convert the pub/priv to a PEM\ncd util/\npython3 load.py --public=hmac.pub --private=hmac.prv --out=hmac.pem --keyPassword=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI\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&comp=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\n### Password\npython3 main_azure.py --keyfile=rsa_auth.pem \\\n --certificate_path=$CERTIFICATE_PATH \\\n --client_id=$CLIENT_ID --tenant_id=$TENANT_ID \\\n --password=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI\n\n### PCR\nexport PCR=23\npython3 main_azure.py --keyfile=rsa_pcr.pem \\\n --certificate_path=$CERTIFICATE_PATH \\\n --client_id=$CLIENT_ID --tenant_id=$TENANT_ID \\\n --pcr=$PCR --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\ncd /tmp/\n### create H2 template\nprintf '\\x00\\x00' > 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 have on the key:\n\n##### No Auth\n\nFor a plain key\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\n\ntpm2_load -C primary.ctx -u rsa.pub -r rsa.prv -c rsa.ctx \n\n## convert pub/priv blobs to PEM (remember to specify the full path --public --private and --out)\n### alternatives to this is: https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md\ncd util/\npython3 load.py --public=rsa.pub \\\n --private=rsa.prv --out=rsa_auth.pem --tcti=$TPM2TOOLS_TCTI\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 \n\n## convert pub/priv blobs to PEM (remember to specify the full path --public --private and --out)\n### alternatives to this is: https://github.com/tpm2-software/tpm2-tss-engine/blob/master/man/tpm2tss-genkey.1.md\ncd util/\npython3 load.py --public=rsa.pub \\\n --private=rsa.prv --out=rsa_auth.pem \\\n --keyPassword=$KEY_PASSWORD --tcti=$TPM2TOOLS_TCTI\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 \n\ntpm2_readpublic -c rsa.ctx -o rsapub.pem -f PEM -Q \ncat rsapub.pem\n\n## convert pub/priv to PEM\ncd util/\npython3 load.py --public=rsa.pub \\\n --private=rsa.prv --out=rsa_pcr.pem --tcti=$TPM2TOOLS_TCTI\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 && tpm2_flushcontext -s && 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 && tpm2_flushcontext -s && tpm2_flushcontext -l \n\n## convert pub/priv to PEM\ncd util/\npython3 load.py --public=/tmp/rsa.pub --private=/tmp/rsa.prv \\\n --out=rsa_pcr_auth.pem --tcti=$TPM2TOOLS_TCTI --keyPassword=$KEY_PASSWORD\n```\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)`, 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):\n pass\n```\n\nso for the built-in policy see [cloud_auth_tpm/policy/pcr.py](cloud_auth_tpm/policy/pcr.py).\n\nThen to use it, fist import the policy (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\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#### 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\n## swtpm don't have resource manager so you'll see \"out of memory for object contexts\" often...to clear the contexts:\ntpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "Python TPM based Credentials for Cloud Providers",
"version": "0.6.4",
"project_urls": {
"Homepage": "https://github.com/salrashid123/cloud_auth_tpm"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2f6c5a2dcf7b22c488e1eea13faf6da8370d7809e5568be13d115efcb08e40fb",
"md5": "72131564fc1127952ac81f16b71a114e",
"sha256": "7328676fdc6db568a940ce712cc74cedc4432a91184db745dd6c9ba3c6e54c8b"
},
"downloads": -1,
"filename": "cloud_auth_tpm-0.6.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "72131564fc1127952ac81f16b71a114e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 29897,
"upload_time": "2024-09-23T18:01:31",
"upload_time_iso_8601": "2024-09-23T18:01:31.164367Z",
"url": "https://files.pythonhosted.org/packages/2f/6c/5a2dcf7b22c488e1eea13faf6da8370d7809e5568be13d115efcb08e40fb/cloud_auth_tpm-0.6.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "fb111cb4ced8de448d71efd98448cc76d8b27baf8b0751daf5fd10a926724c3d",
"md5": "56b1a689f80f84bcb40d578839b70a5b",
"sha256": "515382480096b9b8d45d331736ddd7fddaa111209142642083a9ea7c4268b22e"
},
"downloads": -1,
"filename": "cloud_auth_tpm-0.6.4.tar.gz",
"has_sig": false,
"md5_digest": "56b1a689f80f84bcb40d578839b70a5b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 34329,
"upload_time": "2024-09-23T18:01:32",
"upload_time_iso_8601": "2024-09-23T18:01:32.758116Z",
"url": "https://files.pythonhosted.org/packages/fb/11/1cb4ced8de448d71efd98448cc76d8b27baf8b0751daf5fd10a926724c3d/cloud_auth_tpm-0.6.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-23 18:01:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "salrashid123",
"github_project": "cloud_auth_tpm",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "cloud-auth-tpm"
}