{"id":21354879,"url":"https://github.com/salrashid123/aws_hmac","last_synced_at":"2025-10-28T03:51:49.237Z","repository":{"id":57592230,"uuid":"373356590","full_name":"salrashid123/aws_hmac","owner":"salrashid123","description":"AWS Credentials for Hardware Security Modules and TPM based AWS_SECRET_ACCESS_KEY","archived":false,"fork":false,"pushed_at":"2024-09-12T13:10:20.000Z","size":1213,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-09-13T01:12:11.526Z","etag":null,"topics":["authentication","aws","aws-authentication","golang","hashicorp-vault","pkcs11","trusted-computing","trusted-platform-module"],"latest_commit_sha":null,"homepage":"","language":"Go","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":"2021-06-03T02:18:48.000Z","updated_at":"2024-09-12T13:11:41.000Z","dependencies_parsed_at":"2022-09-14T09:11:13.194Z","dependency_job_id":"3c67f65d-fd7f-4056-9125-e3b638c1fb4f","html_url":"https://github.com/salrashid123/aws_hmac","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Faws_hmac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Faws_hmac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Faws_hmac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Faws_hmac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/aws_hmac/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225839601,"owners_count":17532308,"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":["authentication","aws","aws-authentication","golang","hashicorp-vault","pkcs11","trusted-computing","trusted-platform-module"],"created_at":"2024-11-22T04:14:48.135Z","updated_at":"2025-10-28T03:51:44.203Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## AWS Credentials for Hardware Security Modules and TPM based AWS_SECRET_ACCESS_KEY\n\nLibrary to to **embed** AWS [Secret Access Keys](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) _inside_ an HSM device through [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11), [Trusted Platform Module](https://en.wikipedia.org/wiki/Trusted_Platform_Module) and [Hashicorp Vault](https://www.vaultproject.io/).\n\nThe critical feature is, once the `AWS_SECRET_ACCESS_KEY` checks in, it never checks out, like a roach motel.  You ask the HSM and TPM to issue HMAC signature you can ultimately use for AWS Signatures v4 or more commonly, to access AWS resources.\n\nThis repo provides four ways to protect the aws secret:\n\n1. Embed the secret into an `HSM` an access it via `PKCS11` `\"github.com/salrashid123/aws_hmac/pkcs\"`\n\n2. Embed the secret into an `TPM` an access it via `go-tpm`  `\"github.com/salrashid123/aws_hmac/tpm\"`\n\n3. Wrap the secret using `KMS` and access it via `TINK`. `\"github.com/salrashid123/aws_hmac/tink\"`\n\n\u003e\u003e NOTE: This code is NOT Supported by Google\n\n---\n\n\n* For TPM based process credentials, see [AWS Process Credentials for Trusted Platform Module (TPM)](https://github.com/salrashid123/aws-tpm-process-credential)\n* For HSM based process credentials, see [AWS Process Credentials for Hardware Security Module (HSM) with PKCS11](https://github.com/salrashid123/aws-pkcs-process-credential)\n  \n\nFor concrete usage see:\n\n- [example/tpm](example/tpm)\n- [example/pkcs](example/pkcs)\n- [example/rest](example/rest)\n- [example/tink](example/tink)\n\n---\n\n### AWS v4 Signing Protocol\n\nWhile you can embed many types of keys to hardware like `TPM` or `HSM` or software key management system like `Vault`, applying those embedded keys to authenticate to AWS requires some background on how AWS signatures work.\n\nThe [AWS Signing](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) protocol uses the `AWS_SECRET_ACCESS_KEY` to create an HMAC signature by first adding a small prefix (`AWS4`) to the key.\n\nWhat that means is if we can embed `AWS4$AWS_SECRET_ACCESS_KEY` into an HSM, we can ask it to perform an HMAC to kick off the first step in the whole signature process:\n\n- ![images/sign_protocol.png](images/sign_protocol.png)\n\nOnce we have the ability to generate an HMAC, we can ask the TPM for the first application and then perform the rest of the chain of operations outside.  The chain itself is shown in the diagram above and described [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html)\n\nThis repo provides two variations to access AWS:\n\n1.  Create a raw Signed AWS Request to access via REST\n2.  Create an AWS SDK `Credential` which uses the HMAC signer as a credential provider for any go SDK for AWS.\n\nBasically, this repo provides an `AWS Credential` _and_ a `Signerv4`.   You can use the former for any sdk operation and the later for standalone REST calls to AWS.\n\n#### STS SessionToken and AssumeRole\n\nAWS SDK's require an actual `AWS_SECRET_ACCESS_KEY` to perform its signature operation and cant' be 'given' a presigned URL to use.\n\nThis makes it a bit complicated on how to use an embedded key for an SDK which never sees the light of day outside of an HSM.\n\nThe workaround employed in this repo is a two step process to get a temporary  `AWS_SECRET_ACCESS_KEY` _derived_ from an initial Signerv4 request:\n\n1. use the HSM embedded HMAC key to generate an AWS API call for either:\n\n  * [sts.GetSessionToken()](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html)\n  * [sts.AssumeRole()](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html)\n\n2. [Both APIs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison) below will return a new temporary `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and for the assumerole, a session.\n\n3. Use these new keys as inputs to AWS Clients though a custom Credential object from this repo.\n\nTo use these samples end-to-end, you must hae an aws user, role and 'assumeRole\" permissions as shown in the appendix\n\n---\n\nYou can find example README files for each mode under `example/` folder.\n\n---\n\n### Usage: Signer with HTTP POST\n\nYou can use a signer to make an authenticate API calls directly.  \n\nTO use this mode, initialize any of the HSM backends.  The following uses KMS and Tink to sign a REST API for `GetCallerIdentity` endpoint\n\n```golang\n// import latest by first importing the schema\n// go get github.com/salrashid123/aws_hmac/stsschema@latest\n// go get github.com/salrashid123/aws_hmac/tink@latest\n\n\nimport (\n\t\"github.com/salrashid123/aws_hmac/stsschema\"\n\tgcpkms \"github.com/tink-crypto/tink-go-gcpkms/v2/integration/gcpkms\"\n\thmaccred \"github.com/salrashid123/aws_hmac/tink\"\n\thmacsigner \"github.com/salrashid123/aws_hmac/tink/signer\"\n\thmacsignerv4 \"github.com/salrashid123/aws_hmac/tink/signer/v4\"\n)\n\n\ttinkSigner, err := hmacsigner.NewTinkSigner(\u0026hmacsigner.TinkSignerConfig{\n\t\tTinkConfig: hmacsigner.TinkConfig{\n\t\t\tKmsBackend: backend,\n\t\t\tJSONBytes:  keysetbytes,    // this is the keyset bytes, i'm using json keyset\n\t\t},\n\t\tAccessKeyID: *accessKeyID,\n\t})\n\n\thmacSigner := hmacsignerv4.NewSigner()\n\n\tfmt.Println(\"-------------------------------- Calling HTTP GET on  GetCallerIdentity using Tink Signer\")\n\n\temptyBody := strings.NewReader(\"\")\n\tgetCallerIdentityRequest, err := http.NewRequest(http.MethodGet, \"https://sts.amazonaws.com?Action=GetCallerIdentity\u0026Version=2011-06-15\", emptyBody)\n\n\thmacSigner.SignHTTP(ctx, *tinkSigner, getCallerIdentityRequest, emptyPayloadHash, \"sts\", *awsRegion, time.Now())\n\n\tgetResponse, err := http.DefaultClient.Do(getCallerIdentityRequest)\n\n\tdefer getResponse.Body.Close()\n\n\tvar getCallerIdentityResponseStruct stsschema.GetCallerIdentityResponse\n\n\tgetResponseData, err := io.ReadAll(getResponse.Body)\n\n\terr = xml.Unmarshal(getResponseData, \u0026getCallerIdentityResponseStruct)\n\n\tlog.Printf(\"GetCallerIdentityResponse UserID %s\\n\", getCallerIdentityResponseStruct.CallerIdentityResult.UserId)\t\n```\n\n\n### Usage: AWS SDK Credentials from Signer \n\n```golang\n\t// first read the keyset from disk\n\tkeysetbytes, err := os.ReadFile(*in)\n\n\ttinkSigner, err := hmacsigner.NewTinkSigner(\u0026hmacsigner.TinkSignerConfig{\n\t\tTinkConfig: hmacsigner.TinkConfig{\n\t\t\tKmsBackend: backend,\n\t\t\tJSONBytes:  keysetbytes,\n\t\t},\n\t\tAccessKeyID: *accessKeyID,\n\t})\n\n\thmacSigner := hmacsignerv4.NewSigner()\n\n\tsessionCredentials, err := hmaccred.NewAWSTinkCredentials(hmaccred.TINKProvider{\n\t\tGetSessionTokenInput: \u0026sts.GetSessionTokenInput{\n\t\t\tDurationSeconds: aws.Int32(3600),\n\t\t},\n\t\tVersion:    \"2011-06-15\",\n\t\tRegion:     *awsRegion,\n\t\tTinkSigner: tinkSigner,\n\t})\n\n\tassumeRoleCredentials, err := hmaccred.NewAWSTinkCredentials(hmaccred.TINKProvider{\n\t\tAssumeRoleInput: \u0026sts.AssumeRoleInput{\n\t\t\tRoleArn:         aws.String(*roleARN),\n\t\t\tRoleSessionName: aws.String(roleSessionName),\n\t\t\tDurationSeconds: aws.Int32(3600),\n\t\t},\n\t\tVersion:    \"2011-06-15\",\n\t\tRegion:     *awsRegion,\n\t\tTinkSigner: tinkSigner,\n\t})\n\n// for sessiontokens:\n\n\tcfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(*awsRegion), config.WithCredentialsProvider(sessionCredentials))\n\n\tstssvc := sts.NewFromConfig(cfg, func(o *sts.Options) {\n\t\to.Region = *awsRegion\n\t})\n\n\tstsresp, err := stssvc.GetCallerIdentity(ctx, \u0026sts.GetCallerIdentityInput{})\n\n\tfmt.Printf(\"STS Identity from API %s\\n\", *stsresp.UserId)\n\n// for assume role and s3\n\n\tfmt.Println(\"-------------------------------- Calling s3 list buckets using Tink Signer with AssumeRole\")\n\n\ts3cfg2, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(*awsRegion), config.WithCredentialsProvider(assumeRoleCredentials))\n\n\ts3svc2 := s3.NewFromConfig(s3cfg2, func(o *s3.Options) {\n\t\to.Region = *awsRegion\n\t})\n\n\tresult2, err := s3svc2.ListBuckets(ctx, input)\n\n\tlog.Println(len(result2.Buckets))\n```\n\n---\n\n#### PKCS Usage Overview\n\nWith this, you are embedding the HMAC key *INTO* an HSM.  When you then need to access the secret, you ask the HSM to generate an HMAC for the AWS v4 signing process.   At no time does the client ever see the secret after it is embedded: the actual HMAC is done within the HSM. \n\nOnce the key is embedded into an HSM, you can access it to sign, verify, etc but the key is ever exposed\n\n```bash\n$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so  --list-objects --pin mynewpin\n\tSecret Key Object; unknown key algorithm 43\n\tlabel:      HMACKey\n\tID:         0100\n\tUsage:      verify\n\tAccess:     sensitive\n```\n\nThe big advantage of (2,3) is clear, the HSM owns the key and is not exportable:  nobody will see the raw key once thats done but yet you can use it to create an AWS s4 sign.\n\n#### TPM Usage Overview\n\nSimilar to PKCS but here you are not using the cumbersome overlay that PKCS requires and directly using the embedded token from a `Trusted Platform Module (TPM)`.\n\nTo use this mode, your AWS must already be encoded to the TPM.  \n\nYou can do this directly on the TPM\n\n- [Importing External HMAC and performing HMAC Signatures](https://github.com/salrashid123/tpm2/blob/master/hmac_import/README.md)\n\nor remotely through a process like duplicate:\n\n- [Duplicate an externally loaded HMAC key](https://github.com/salrashid123/tpm2/tree/master/tpm2_duplicate#duplicate-an-externally-loaded-hmac-key)\n\nPlease note the default signer here **requires** a persistentHandle.  If you would rather save/load from files, please file an issue (its relatively easy to adapt the import and signing), see\n\n* [tpm_hmac file import](https://github.com/salrashid123/tpm2/tree/master/hmac_import)\n\nYou can also pass through an authorized session incase you bound the key to a policy like `PCRPolicy` or `PasswordPolicy`\n\n\n#### TINK Usage Overview\n\nIn (4) you are using KMS to encrypt the Secret and save it in encrypted format.  When you need to access the Secret to make it generate an AWS v4 signing request, the raw Secret is automatically decrypted by TINK using KMS and made to HMAC sign.  The user will never need to \"see\" the secret but it is true that the key gets decrypted locally...  You will also need to have access to KMS in the first place so this example is a bit convoluted.   Use this if you already have access to another cloud providers KMS (eg GCP KMS), then use that decrypt the Key and then make it sign though the utility of this mechanism is limited since the hmac key is decrypted locally ultimately.\n\nThe encrypted Key would look like the following:\n\n```json\n{\n\t\"encryptedKeyset\": \"CiUAmT+VVWAVKQZfFW6UheHPI1E3VmvTFlv2C4cspNaqpbxc8YvEEqUBACsKZVI1IW8U+86r2Yset0WOKwnggDitP0hi0oUapgOrF4W7Pklrbso93gfMoNDVw2QCWW4HwJwKzElQRi3zWHuL6NJP4t/t2VtIWORgWLz76zpH7+JWn6IrlqA/M4sammN0kAn+ZcgiG6kCvoMXzczUz3jzyk96Uz6U2LIuZb+bFaCasMYyka2fpSndMQ2SxpmHbVSe2AvhBVMLhM29LOcio41D\",\n\t\"keysetInfo\": {\n\t\t\"primaryKeyId\": 2596996162,\n\t\t\"keyInfo\": [\n\t\t\t{\n\t\t\t\t\"typeUrl\": \"type.googleapis.com/google.crypto.tink.HmacKey\",\n\t\t\t\t\"status\": \"ENABLED\",\n\t\t\t\t\"keyId\": 2596996162,\n\t\t\t\t\"outputPrefixType\": \"RAW\"\n\t\t\t}\n\t\t]\n\t}\n}\n```\n---\n\n\n#### References\n\nSome references for TINK and PKCS11:\n\n- [Go PKCS11 Samples](https://github.com/salrashid123/go_pkcs11)\n- [Importing external HMAC as TINK EncryptedKeySet](https://github.com/salrashid123/tink_samples/tree/main/external_hmac)\n\n- User\n  ![images/svcacct1.png](images/svcacct1.png)\n\n- AWS Role\n  ![images/role.png](images/role.png)\n\n- AWS Assume Role Permissions\n  ![images/assume_role_permissions.png](images/assume_role_permissions.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Faws_hmac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Faws_hmac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Faws_hmac/lists"}