The rolesanywhere-credential-helper implements the signing process for the AWS IAM Roles Anywhere CreateSession API. It returns temporary credentials in a standard JSON format compatible with the credential_process feature available across AWS SDKs. For more information, see the AWS IAM Roles Anywhere documentation.
Installation
Dependencies
To build the source code, you need git, gcc, GNU make, and golang.
Linux
On Debian-based systems, install the dependencies:
For other Linux distributions, use the appropriate package manager.
MacOS
If you don’t have Apple clang, download it from the Apple Developer website. Install other dependencies using Homebrew:
brew install git make go
Windows
Get GCC on Windows using MinGW-w64. Install Golang through the installer. Install git and make using Chocolatey:
choco install git make
Build
After installing the tools and adding them to your PATH, build the package from the package root:
make release
You will find the aws_signing_helper binary for your system in build/bin/aws_signing_helper.
Docker Image
The AWS IAM Roles Anywhere Credential Helper is also available as a Docker image, providing a containerized deployment option for environments like Kubernetes, Docker Compose, or other container orchestration platforms.
When to Use the Docker Image
The Docker image is recommended when:
Container environments: You’re deploying in Kubernetes, Docker Swarm, or other container orchestration platforms
Consistent runtime: You need a consistent, reproducible runtime environment across different systems. Particularly useful for environments where glibc is not available (ex. alpine linux)
This repository follows 3 tagging schemas for images:
latest: Offers the latest image for both amd64 and arm64 images.
latest-<platform>: Offers the latest image for a specified platform
<version>-<platform>-<timestamp>: Offers a specific, immutable image with a precise version number, platform architecture, and build timestamp.
Supported Architectures
OS/Arch: Linux, ARM 64, x86-64
Image Verification
For security-conscious deployments, you can verify the authenticity of Docker images using notation. See the image verification guide for detailed instructions on setting up and using notation to verify image signatures and attestations.
Troubleshooting
You might need to set the GOPROXY environment variable: export GOPROXY="direct"
Use serve to provide temporary credentials through a local endpoint compatible with IMDSv2. Note that any process that can reach 127.0.0.1 can retrieve AWS credentials from the credential helper.
The AWS IAM Roles Anywhere Credential Helper is also available as a Docker image, providing a containerized deployment option for environments like Kubernetes, Docker Compose, or other container orchestration platforms.
When to Use the Docker Image
The Docker image is recommended when:
Container environments: You’re deploying in Kubernetes, Docker Swarm, or other container orchestration platforms
Consistent runtime: You need a consistent, reproducible runtime environment across different systems. Particularly useful for environments where glibc is not available (ex. Alpine Linux)
This repository follows 3 tagging schemas for images:
latest: Offers the latest image for both AMD64 and ARM64 images.
latest-<platform>: Offers the latest image for a specified platform
<version>-<platform>-<timestamp>: Offers a specific, immutable image with a precise version number, platform architecture, and build timestamp.
Supported Architectures
OS/Arch: Linux, ARM 64, x86-64
Image Verification
For security-conscious deployments, you can verify the authenticity of Docker images using notation. See the image verification guide for detailed instructions on setting up and using notation to verify image signatures and attestations.
Diagnostic Command Tools
To retrieve credentials from the server:
# Get a token
TOKEN=$(curl -X PUT "http://localhost:1338/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# Get the role name
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://localhost:1338/latest/meta-data/iam/security-credentials/
# Get the credentials
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://localhost:1338/latest/meta-data/iam/security-credentials/default
When using serve, AWS SDKs can discover the credentials using their credential providers without code changes. To make the credentials available to the SDK, set the AWS_EC2_METADATA_SERVICE_ENDPOINT environment variable to http://localhost:1338.
Getting Credentials from Secure Stores
On Windows or macOS, the credential helper supports using private keys and certificates from OS-specific secure stores. Use the --cert-selector flag to specify the certificate for the CreateSession API call. The credential helper delegates signing operations to the keys in those stores, without the keys leaving the stores.
If more than one certificate matches the --cert-selector within the secure store, the credential-process command will fail. To find the list of certificates that match a given --cert-selector parameter, use this flag with the read-certificate-data command.
Searching for a Certificate and Private Key
The --cert-selector flag supports searching for a specific certificate and its associated private key by the certificate Subject, Issuer, and Serial Number. The corresponding keys are x509Subject, x509Issuer, and x509Serial, respectively. You can specify these either through a JSON file or command line.
In these examples, the subject and Issuer each contain a single RDN.
To securely store keys for use with IAM Roles Anywhere, we recommend creating a dedicated Keychain that only the credential helper can access. This approach enhances security by isolating these sensitive credentials. The credential helper will search for credentials only from Keychains on the search list.
Ensure the new Keychain is included in the system’s search list. This command extracts existing Keychains in the search list and adds the newly created Keychain to the top of it.
Finally, add your PFX file (containing your client certificate and associated private key) to the Keychain. Replace \path\to\identity.pfx with the actual path to your PFX file.
You might need to specify your Keychain password for signing operations or choose to always allow the credential helper to use the Keychain item.
Important Considerations
Note that since the credential helper isn’t signed, it isn’t trusted by macOS by default. As a result, you may need to enter the Keychain password each time the credential helper performs a signing operation. If you prefer not to enter the password repeatedly, you can choose to “always allow” the credential helper to use the Keychain item. However, carefully consider the security implications of this setting in your specific environment.
Alternative Methods
These steps can also be performed using macOS Keychain APIs or through the Keychain Access application. Choose the method that best fits your workflow and security requirements.
Windows CNG
The credential helper for IAM Roles Anywhere is designed to work exclusively with the user’s “MY” certificate store on Windows. This integration allows for secure key management through Windows CNG (Cryptography API: Next Generation).
To use your keys with IAM Roles Anywhere, you need to import your certificate and its associated private key into your user’s “MY” certificate store.
Using Command Prompt
To import a PFX file containing your certificate and private key, open Command Prompt and run:
Replace \path\to\identity.pfx with the actual path to your PFX file. The %UNWRAPPING_PASSWORD% environment variable should contain the password to decrypt the PFX file.
Alternative Methods
You can also import your certificate using a PowerShell cmdlet or Windows CNG/Cryptography APIs.
Importing Certificates into the User’s “MY” Store
To secure keys through Windows CNG, import your certificate into your user’s “MY” certificate store:
The credential helper supports using a PKCS#11 URI instead of a filename to use certificates and keys from hardware or software PKCS#11 tokens/HSMs. For help with URIs, consult this documentation or use the read-certificate-data command. Most Linux systems use p11-kit to provide configuration of PKCS#11 providers. If your system lacks p11-kit, use the --pkcs11-lib parameter to specify a provider library.
PKCS#11 Examples
These examples show how to use the aws_signing_helper credential-process command with different PKCS#11 configurations.
# Using a certificate from a PKCS#11 token
aws_signing_helper credential-process \
--certificate 'pkcs11:manufacturer=piv_II;id=%01' \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--trust-anchor-arn arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/abcdef1234567890
# Using both certificate and key from a PKCS#11 token
aws_signing_helper credential-process \
--certificate 'pkcs11:object=My%20RA%20key' \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--trust-anchor-arn arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/abcdef1234567890
# Using a certificate from a file but the key from a PKCS#11 token
aws_signing_helper credential-process \
--certificate client-cert.pem \
--private-key 'pkcs11:model=SoftHSM%20v2;object=My%20RA%20key' \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--trust-anchor-arn arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/abcdef1234567890
The --reuse-pin parameter is useful when the private key object has CKA_ALWAYS_AUTHENTICATE set and the CKU_CONTEXT_SPECIFIC PIN matches the CKU_USER PIN. If --reuse-pin isn’t set, you will be prompted to enter the PIN in the console. If --reuse-pin is set, but the CKU_USER PIN is different from the CKU_CONTEXT_SPECIFIC PIN, the credential helper will prompt you to enter the CKU_CONTEXT_SPECIFIC PIN. This is helpful for unattended workloads.
Unattended Workloads Limitation
The credential helper doesn’t currently support specifying the CKU_CONTEXT_SPECIFIC PIN programmatically. For unattended workloads, this presents a challenge when the CKU_CONTEXT_SPECIFIC PIN of the private key object differs from the CKU_USER PIN of its token. In such cases, the system will always prompt for the PIN, making unattended operations impossible
Trusted Platform Module (TPMv2)
The credential helper supports private key files containing a TPM wrapped key in the -----BEGIN TSS2 PRIVATE KEY----- format. You can use such a file as you would any plain key file:
The credential helper requires a TPM key password on the child key by default. If you don’t use a child key, add the --no-tpm-key-password option.
Limitations
The current implementation of TSS private key format support has these limitations:
Password authentication on parent keys (and hierarchies)
Use of a persistent handle as a parent
Importable keys
TPM Policy / AuthPolicy
Sealed keys
We’re working on addressing these limitations. Future releases may include support for some or all of these features. For the latest updates on feature support, refer to our release notes or documentation.
Workaround for Parent Key Password Authentication
To work around the parent key password authentication limitation:
Load the signing key into the TPM using external tools. This process requires you to provide your parent key password.
Reference the loaded key’s handle in your credential helper command.
This approach allows you to use the signing key without the credential helper needing to handle the parent key password authentication directly.
Important: If your TPM’s owner hierarchy is not yet initialized, configure it with a high-entropy password. The owner hierarchy lacks dictionary attack protections, making a strong password crucial for security.
This command creates a primary key in the TPM owner hierarchy with the password specified in ${TPM_PRIMARY_KEY_PASSWORD}.
Note: If your TPM’s owner hierarchy doesn’t have a password (not recommended), omit the -P option from the command.
Once you have your CSR, you can provide it to a CA so that it can issue a client certificate for you. The client certificate and TPM key can then be used with the credential helper application as follows:
You are responsible for clearing persistent and temporary objects from the TPM when no longer needed.
Failure to do so might allow others with machine access to escalate privileges.
Non-password-protected keys loaded into the TPM can be used by anyone with machine access.
Alternative: Using a TPM Key PEM File
You can use a TPM key PEM file with the credential helper. This approach:
Loads the wrapped private key as a transient object in the TPM.
Automatically flushes the key from the TPM after signing.
Reloads the key for each signing operation.
Limitation: The parent of the signing key cannot be password-protected, as there’s currently no way to pass this password to the credential helper.
For the TPM key PEM file format, refer to: TPM2 Key Format Specification
Example: Using the Credential Helper with a TPM Key File
To use the credential helper with a TPM key file, run the following command:
Replace the placeholder values with your specific file paths and ARNs.
Password-Encrypted Private Keys
You can pass a password-encrypted private key to the credential helper for signing the request. The credential helper supports two formats of PKCS#8 private key files:
This command encrypts a PEM file containing an unencrypted private key in PKCS#8 format using the AES-256-CBC cipher with the password “password”. The encrypted key is saved to a PEM file. Supported ciphers include:
AES-128-CBC
AES-192-CBC
AES-256-CBC
You can also encrypt the key using a different pseudorandom function (PRF):
If you don’t specify a cipher or PRF, the key is converted to PKCS#8 format using PKCS#5 v2.0 with AES-256-CBC and HMACWithSHA256.
The credential helper supports decrypting PKCS#8-encrypted private keys using PBES2, as defined in PKCS#5 (RFC 8018), with the options mentioned earlier. The key derivation function is PBKDF2, as specified in RFC 8018.
To enhance key protection, you can use scrypt to secure the PKCS#8-encoded key. Scrypt, defined in RFC 7914, is a memory-intensive KDF that improves resistance to attacks.
To encrypt a key using scrypt with OpenSSL:
This command uses the default scrypt parameters: N=16,384, r=8, and p=1.
After obtaining the encrypted key in a PEM file, pass it to the credential helper along with the password as the value for the --pkcs8-password option during signing. Note the following:
If you don’t want to encrypt a private key and are using OpenSSL, use the -nocrypt flag.
Zero-length passwords are treated as no password.
Only UTF-8-encoded passwords are supported.
YubiKey and Attestation Certificates
YubiKeys with PIV support automatically generate attestation certificates for key pairs in Slot 9a (PIV authentication) and Slot 9c (digital signature). These attestation certificates cannot be deleted
Handling Multiple Certificates in PIV Slots
When using a PKCS#11 URI with CKA_ID (id path attribute) to identify a certificate, two matching certificates will be found (user certificate and attestation certificate). This duplication occurs in slots 9a and 9c due to the presence of attestation certificates
Using CKA_LABEL for Certificate Identification
To distinguish between user and attestation certificates, use CKA_LABEL (the object path attribute) in your PKCS#11 URI. Attestation certificates in either of these two slots can be identified through the hard-coded labels:
AWS IAM Roles Anywhere Credential Helper
The
rolesanywhere-credential-helperimplements the signing process for the AWS IAM Roles Anywhere CreateSession API. It returns temporary credentials in a standard JSON format compatible with thecredential_processfeature available across AWS SDKs. For more information, see the AWS IAM Roles Anywhere documentation.Installation
Dependencies
To build the source code, you need
git,gcc, GNUmake, andgolang.Linux
On Debian-based systems, install the dependencies:
For other Linux distributions, use the appropriate package manager.
MacOS
If you don’t have Apple clang, download it from the Apple Developer website. Install other dependencies using Homebrew:
Windows
Get GCC on Windows using MinGW-w64. Install Golang through the installer. Install git and make using Chocolatey:
Build
After installing the tools and adding them to your
PATH, build the package from the package root:You will find the
aws_signing_helperbinary for your system inbuild/bin/aws_signing_helper.Docker Image
The AWS IAM Roles Anywhere Credential Helper is also available as a Docker image, providing a containerized deployment option for environments like Kubernetes, Docker Compose, or other container orchestration platforms.
When to Use the Docker Image
The Docker image is recommended when:
Quick Start
The official Docker image is available from the AWS ECR Public Gallery at gallery.ecr.aws/rolesanywhere/credential-helper. See the Docker image documentation for more information.
Image Tags
This repository follows 3 tagging schemas for images:
latest: Offers the latest image for both amd64 and arm64 images.latest-<platform>: Offers the latest image for a specified platform<version>-<platform>-<timestamp>: Offers a specific, immutable image with a precise version number, platform architecture, and build timestamp.Supported Architectures
OS/Arch: Linux, ARM 64, x86-64
Image Verification
For security-conscious deployments, you can verify the authenticity of Docker images using notation. See the image verification guide for detailed instructions on setting up and using notation to verify image signatures and attestations.
Troubleshooting
You might need to set the GOPROXY environment variable:
export GOPROXY="direct"Usage
aws_signing_helpersupports these commands:For full command documentation, including available environment variables, see theCredential helper reference.
Getting Temporary Credentials
Use
credential-processto vend temporary credentials.credential-processsends a CreateSession request to the IAM Roles Anywhere service.Example usage of credential-process command
For more information about the signing process, see Signing process for IAM Roles Anywhere.
Serving Temporary Credentials
Use
serveto provide temporary credentials through a local endpoint compatible with IMDSv2. Note that any process that can reach 127.0.0.1 can retrieve AWS credentials from the credential helper.Example usage of serve command
Command:
Output:
Docker Image
The AWS IAM Roles Anywhere Credential Helper is also available as a Docker image, providing a containerized deployment option for environments like Kubernetes, Docker Compose, or other container orchestration platforms.
When to Use the Docker Image
The Docker image is recommended when:
Quick Start
The official Docker image is available from the AWS ECR Public Gallery at gallery.ecr.aws/rolesanywhere/credential-helper. See the Docker image documentation for more information.
Image Tags
This repository follows 3 tagging schemas for images:
latest: Offers the latest image for both AMD64 and ARM64 images.latest-<platform>: Offers the latest image for a specified platform<version>-<platform>-<timestamp>: Offers a specific, immutable image with a precise version number, platform architecture, and build timestamp.Supported Architectures
OS/Arch: Linux, ARM 64, x86-64
Image Verification
For security-conscious deployments, you can verify the authenticity of Docker images using notation. See the image verification guide for detailed instructions on setting up and using notation to verify image signatures and attestations.
Diagnostic Command Tools
To retrieve credentials from the server:
When using
serve, AWS SDKs can discover the credentials using their credential providers without code changes. To make the credentials available to the SDK, set theAWS_EC2_METADATA_SERVICE_ENDPOINTenvironment variable tohttp://localhost:1338.Getting Credentials from Secure Stores
On Windows or macOS, the credential helper supports using private keys and certificates from OS-specific secure stores. Use the
--cert-selectorflag to specify the certificate for the CreateSession API call. The credential helper delegates signing operations to the keys in those stores, without the keys leaving the stores.Using the –cert-selector Flag
If more than one certificate matches the
--cert-selectorwithin the secure store, thecredential-processcommand will fail. To find the list of certificates that match a given--cert-selectorparameter, use this flag with theread-certificate-datacommand.Searching for a Certificate and Private Key
The
--cert-selectorflag supports searching for a specific certificate and its associated private key by the certificate Subject, Issuer, and Serial Number. The corresponding keys arex509Subject,x509Issuer, andx509Serial, respectively. You can specify these either through a JSON file or command line.In these examples, the subject and Issuer each contain a single RDN.
Using a JSON File
Create a file called
selector.json:Use it with:
Using Command Line Parameters
Operating-System Specific Credential Stores
MacOS Keychain
To securely store keys for use with IAM Roles Anywhere, we recommend creating a dedicated Keychain that only the credential helper can access. This approach enhances security by isolating these sensitive credentials. The credential helper will search for credentials only from Keychains on the search list.
Creating and Configuring a New Keychain
Ensure the new Keychain is included in the system’s search list. This command extracts existing Keychains in the search list and adds the newly created Keychain to the top of it.
Finally, add your PFX file (containing your client certificate and associated private key) to the Keychain. Replace
\path\to\identity.pfxwith the actual path to your PFX file.Troubleshooting
Important Considerations
Note that since the credential helper isn’t signed, it isn’t trusted by macOS by default. As a result, you may need to enter the Keychain password each time the credential helper performs a signing operation. If you prefer not to enter the password repeatedly, you can choose to “always allow” the credential helper to use the Keychain item. However, carefully consider the security implications of this setting in your specific environment.
Alternative Methods
These steps can also be performed using macOS Keychain APIs or through the Keychain Access application. Choose the method that best fits your workflow and security requirements.
Windows CNG
The credential helper for IAM Roles Anywhere is designed to work exclusively with the user’s “MY” certificate store on Windows. This integration allows for secure key management through Windows CNG (Cryptography API: Next Generation). To use your keys with IAM Roles Anywhere, you need to import your certificate and its associated private key into your user’s “MY” certificate store.
Using Command Prompt
To import a PFX file containing your certificate and private key, open Command Prompt and run:
Replace
\path\to\identity.pfxwith the actual path to your PFX file. The%UNWRAPPING_PASSWORD%environment variable should contain the password to decrypt the PFX file.Alternative Methods
You can also import your certificate using a PowerShell cmdlet or Windows CNG/Cryptography APIs.
Importing Certificates into the User’s “MY” Store
To secure keys through Windows CNG, import your certificate into your user’s “MY” certificate store:
Platform-Independent Cryptographic Token Interface (PKCS#11)
The credential helper supports using a PKCS#11 URI instead of a filename to use certificates and keys from hardware or software PKCS#11 tokens/HSMs. For help with URIs, consult this documentation or use the
read-certificate-datacommand. Most Linux systems use p11-kit to provide configuration of PKCS#11 providers. If your system lacks p11-kit, use the--pkcs11-libparameter to specify a provider library.PKCS#11 Examples
These examples show how to use the
aws_signing_helper credential-processcommand with different PKCS#11 configurations.The
--reuse-pinparameter is useful when the private key object hasCKA_ALWAYS_AUTHENTICATEset and theCKU_CONTEXT_SPECIFICPIN matches the CKU_USER PIN. If--reuse-pinisn’t set, you will be prompted to enter the PIN in the console. If--reuse-pinis set, but theCKU_USERPIN is different from theCKU_CONTEXT_SPECIFICPIN, the credential helper will prompt you to enter theCKU_CONTEXT_SPECIFICPIN. This is helpful for unattended workloads.Unattended Workloads Limitation
The credential helper doesn’t currently support specifying the
CKU_CONTEXT_SPECIFICPIN programmatically. For unattended workloads, this presents a challenge when theCKU_CONTEXT_SPECIFICPIN of the private key object differs from theCKU_USERPIN of its token. In such cases, the system will always prompt for the PIN, making unattended operations impossibleTrusted Platform Module (TPMv2)
The credential helper supports private key files containing a TPM wrapped key in the
-----BEGIN TSS2 PRIVATE KEY-----format. You can use such a file as you would any plain key file:You can also use a TPM key handle:
The credential helper requires a TPM key password on the child key by default. If you don’t use a child key, add the
--no-tpm-key-passwordoption.Limitations
The current implementation of TSS private key format support has these limitations:
We’re working on addressing these limitations. Future releases may include support for some or all of these features. For the latest updates on feature support, refer to our release notes or documentation.
Workaround for Parent Key Password Authentication
To work around the parent key password authentication limitation:
This approach allows you to use the signing key without the credential helper needing to handle the parent key password authentication directly.
Creating and Using TPM Keys
Requirements:
Important: If your TPM’s owner hierarchy is not yet initialized, configure it with a high-entropy password. The owner hierarchy lacks dictionary attack protections, making a strong password crucial for security.
This command creates a primary key in the TPM owner hierarchy with the password specified in
${TPM_PRIMARY_KEY_PASSWORD}. Note: If your TPM’s owner hierarchy doesn’t have a password (not recommended), omit the-Poption from the command.You will be prompted for your password (
TPM_CHILD_KEY_PASSWORD).Security Considerations
When using TPM persistent objects:
Alternative: Using a TPM Key PEM File
You can use a TPM key PEM file with the credential helper. This approach:
Limitation: The parent of the signing key cannot be password-protected, as there’s currently no way to pass this password to the credential helper. For the TPM key PEM file format, refer to: TPM2 Key Format Specification
Example: Using the Credential Helper with a TPM Key File
To use the credential helper with a TPM key file, run the following command:
Replace the placeholder values with your specific file paths and ARNs.
Password-Encrypted Private Keys
You can pass a password-encrypted private key to the credential helper for signing the request. The credential helper supports two formats of PKCS#8 private key files:
-----BEGIN PRIVATE KEY----------BEGIN ENCRYPTED PRIVATE KEY-----(using PBES2)To encrypt a plaintext private key stored on disk, you can use
openssl:This command encrypts a PEM file containing an unencrypted private key in PKCS#8 format using the AES-256-CBC cipher with the password “password”. The encrypted key is saved to a PEM file. Supported ciphers include:
You can also encrypt the key using a different pseudorandom function (PRF):
Supported PRFs include:
If you don’t specify a cipher or PRF, the key is converted to PKCS#8 format using PKCS#5 v2.0 with AES-256-CBC and HMACWithSHA256. The credential helper supports decrypting PKCS#8-encrypted private keys using PBES2, as defined in PKCS#5 (RFC 8018), with the options mentioned earlier. The key derivation function is PBKDF2, as specified in RFC 8018. To enhance key protection, you can use scrypt to secure the PKCS#8-encoded key. Scrypt, defined in RFC 7914, is a memory-intensive KDF that improves resistance to attacks. To encrypt a key using scrypt with OpenSSL:
This command uses the default scrypt parameters: N=16,384, r=8, and p=1. After obtaining the encrypted key in a PEM file, pass it to the credential helper along with the password as the value for the
--pkcs8-passwordoption during signing. Note the following:-nocryptflag.YubiKey and Attestation Certificates
YubiKeys with PIV support automatically generate attestation certificates for key pairs in Slot 9a (PIV authentication) and Slot 9c (digital signature). These attestation certificates cannot be deleted
Handling Multiple Certificates in PIV Slots
When using a
PKCS#11 URIwithCKA_ID(id path attribute) to identify a certificate, two matching certificates will be found (user certificate and attestation certificate). This duplication occurs in slots 9a and 9c due to the presence of attestation certificatesUsing CKA_LABEL for Certificate Identification
To distinguish between user and attestation certificates, use
CKA_LABEL(the object path attribute) in yourPKCS#11 URI. Attestation certificates in either of these two slots can be identified through the hard-coded labels:X.509 Certificate for PIV Attestation 9aX.509 Certificate for PIV Attestation 9cSecurity
See CONTRIBUTING.md for more information.
License
This project is licensed under the Apache License 2.0.