chef/knife-ec2

Support for MFA

Opened this issue · 1 comments

Version:

0.9.16

Environment:

OS: macOS 10.14
Ruby: 2.3.0p0
ChefDK: 3.8.14

Scenario:

Due to compliance/regulatory requirements, some organizations enforce the requirement that programmatic access to AWS APIs use Multi-Factor Authentication (MFA). With the AWS Command Line Interface (AWS CLI), users are automatically prompted to provide their MFA token when making API calls. New session credentials are generated by AWS Security Token Service (AWS STS) and cached locally. The user is then prompted again when the credentials have expired. Currently, knife-ec2 does not "bubble up" this token request, instead failing with the following (having specified knife[:aws_config_file] and knife[:aws_profile] in knife.rb).

$ knife ec2 server create -r 'role[testrole]' -I ami-0080e4c5bc078760e -f t2.micro --ssh-key my_key
ERROR: You did not provide a valid 'AWS Access Key Id' value.
ERROR: You did not provide a valid 'AWS Secret Access Key' value.

Steps to Reproduce:

  1. Create a new AWS Identity and Access Management (AWS IAM) user.
  2. Configure MFA for the user.
  3. Create a role that can be assumed by said user.
  4. Add this user as a new profile in ~/.aws/config.
  5. Add a second profile for the role to be assumed, using the user profile as source_profile.
  6. Update knife.rb to include knife[:aws_config_file] and knife[:aws_profile].
  7. Specify the role profile as knife[:aws_profile] (not the user profile).
  8. Attempt to run a command such as knife ec2 create.

The AWS credentials configuration file should information similar to the following:

[profile mfauser]
region=us-east-1
aws_access_key_id=AKIAEXAMPLE1234
aws_secret_access_key=EXAMPLESECRETKEY12345
output=json

[profile adminrole]
source_profile=mfauser
role_arn=arn:aws:iam::123456789012:role/adminrole
output=json
mfa_serial=arn:aws:iam::123456789012:mfa/mfauser

Expected Result:

On the final step, the user should be prompted for their MFA token. This is in line with the result of running a similar AWS CLI command.

$ aws ec2 describe-instances --profile roleprofile
Enter MFA code for arn:aws:iam::123456789012:mfa/mfauser:

Actual Result:

See below output:

$ knife ec2 server create -r 'role[testrole]' -I ami-0080e4c5bc078760e -f t2.micro --ssh-key my_key
ERROR: You did not provide a valid 'AWS Access Key Id' value.
ERROR: You did not provide a valid 'AWS Secret Access Key' value.

Current workaround:

  1. Create new session credentials by running aws sts get-session-token.

    aws sts get-session-token \
    --serial-number MFA_DEVICE_ARN \
    --token-code MFA_DEVICE_TOKEN \
    --profile mfauser
  2. Update knife.rb. Use the output values from the above command.

    • Remove knife[:aws_config_file] and knife[:aws_profile].
    • Add knife[:aws_access_key_id], knife[:aws_secret_access_key], and knife[:aws_session_token].
  3. Any time credentials expire, repeat above steps.