AWS IAM Authenticator
The AWS IAM Authenticator (IAM Authenticator) allows an AWS resource to use its AWS IAM role to authenticate with Conjur. This approach enables EC2 instances and Lambda functions to access credentials stored in Conjur.
To learn more, see IAM roles in the AWS Documentation.
Configure the IAM Authenticator
This section describes how to set up the IAM Authenticator.
-
Define the IAM Authenticator policy
-
Create a policy that defines the IAM Authenticator, for example prod.
# policy id needs to match the convention `conjur/authn-iam/<service ID>` - !policy id: conjur/authn-iam/prod body: - !webservice - !group clients - !permit role: !group clients privilege: [ read, authenticate ] resource: !webservice
-
Save the policy as authn-iam.yml, and load it to root:
conjur policy load -b root -f /path/to/file/authn-iam.yml
-
-
Define an application identity (
host
) in Conjur for the AWS resourceIn this step you define the Conjur application identity (
host
) for the AWS resource and grant it access to secrets and permission to authenticate using IAM Authenticator.-
Create an application policy to provide a database username and password to an AWS service.
In the following example:
-
the IAM role is 011915987442:MyApp
-
The application identity (
host id
) in Conjur is composed of prefix/namespace, followed by the AWS account ID, followed by the name of the IAM role. The AWS Account ID and name of the role are extracted by the IAM Authenticator from the getCallerIdentity.
- !policy id: myspace body: - &variables - !variable database/username - !variable database/password # Create a group that will have permission to retrieve variables - !group secrets-users # Give the `secrets-users` group permission to retrieve variables - !permit role: !group secrets-users privilege: [ read, execute ] resource: *variables # Create a layer to hold this application's hosts - !layer # The host ID needs to match the AWS ARN of the role we wish to authenticate - !host 011915987442/MyApp # Add our host into our layer - !grant role: !layer member: !host 011915987442/MyApp # Give the host in our layer permission to retrieve variables - !grant member: !layer role: !group secrets-users # Give the host permission to authenticate using the IAM Authenticator - !grant role: !group conjur/authn-iam/prod/clients member: !host myspace/011915987442/MyApp
-
-
Save the policy as authn-iam-host.yml, and load it to root:
conjur policy load -b root -f /path/to/file/authn-iam-host.yml
-
-
Enable the IAM Authenticator
To enable the IAM Authenticator you need to allowlist it in Conjur. For example, to allowlist the conjur/authn-iam/prod endpoint, allowlist authn-iam/prod (exclude the conjur/ prefix).
For more information, see Configure authenticators.
Authentication flow
After you have configured the IAM Authenticator and have granted permissions, let's explore the authentication flow of an EC2 instance or a Lambda function:
-
The instance or function starts, assuming the IAM role was provided.
-
From the instance or function, generate a signed request to the STS service to get the identity of the requestor. This request is signed using the instance or function's access key. The signed request is valid for five minutes.
The example below shows how a signed request is generated (using Ruby):
require 'aws-sigv4' require 'aws-sdk' request = Aws::Sigv4::Signer.new( service: 'sts', region: 'us-east-1', credentials_provider: Aws::InstanceProfileCredentials.new ).sign_request( http_method: 'GET', url: 'https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15' ).headers
-
Using the signed request, the instance or function authenticates with a Conjur using the following:
require 'conjur-api' Conjur.configuration.account = 'my-account' Conjur.configuration.appliance_url = 'https://conjur.mydomain.com/authn-iam/prod' Conjur.configuration.cert_file = '<cert>/<path>/conjur-yourorg.pem' Conjur.configuration.apply_cert_config! conjur = Conjur::API.new_from_key 'host/aws/011915987442:assumed-role/MyApp', request.to_json
-
When Conjur receives this authentication request, it performs the following:
-
Validates the host,
myspace/011915987442/MyApp
, has permission to authenticate using the prod IAM Authenticator. -
Extracts the signed request from the POST body.
-
Creates a request to the AWS STS service, using the provided signed request as its header.
-
If the STS request is successful, the requesting instance or function's IAM role is returned. The role is validated against the requesting role. If the two roles match, an access token is returned.
Below is an example of a successful STS response:
<GetCallerIdentityResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-15/\"> <GetCallerIdentityResult> <Arn>arn:aws:sts::011915987442:MyApp/i-0a5702a5a078e1a00</Arn> <UserId>AROAJYAZ7DBLU2PE4DWOW:i-0a5702a5a078e1a00</UserId> <Account>011915987442</Account> </GetCallerIdentityResult> <ResponseMetadata> <RequestId>88278d14-4f3e-11e8-88a1-a9dc7b9cbe6c</RequestId> </ResponseMetadata> </GetCallerIdentityResponse>
-
Troubleshooting AWS IAM authentication
Authentication may fail for any of the following reasons - in each case, a 401 Unauthorized response is returned:
-
Signed request is invalid (signed by an unknown AWS Access Key or on that is older than 5 minutes)
-
Role ARN from the signed request does not match the Conjur
host
ARN -
Conjur
host
does not have permission to authenticate using the IAM Authenticator