Recommended setup
If you followed the steps in my previous post, you have:
- IAM users than can only assume a role
- AWS access keys for those users stored in Jenkins (using AWS Credentials plugin)
- An MFA device assigned to each user
- A condition that forces MFA when assuming roles
Example pipeline
With all this, we can now run a pipeline that takes advantage of this settings. Something like:
def getAWSUser() { wrap([$class: "BuildUser"]) { return env.BUILD_USER_ID } } def getCredentialsId() { wrap([$class: "BuildUser"]) { return env.BUILD_USER_ID } } def assumeRole(String credentials, String userName, String accountId = "YOUR_AWS_ACCOUNT_ID", String role = "role_to_be_assumed") { def String trustedAccount = "YOUR_AWS_ACCOUNT_ID" def mfa = input( message: "Enter MFA Token", parameters: [[$class: 'StringParameterDefinition', name: 'mfa', trim: true]] ) withCredentials([[ $class: 'AmazonWebServicesCredentialsBinding', credentialsId: "${credentials}", accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY' ]]) { return sh(script: """ aws sts assume-role \ --role-arn arn:aws:iam::${accountId}:role/${role} \ --serial-number arn:aws:iam::${trustedAccount}:mfa/${userName} \ --query 'Credentials' \ --token-code ${mfa} \ --role-session-name ${userName} """, returnStdout: true) } } pipeline { agent any stages { stage('Setup') { steps { script { AWSUser = getAWSUser() credentialsId = getCredentialsId() } } } stage('Get credentials') { steps { script { jsonCreds = assumeRole("${credentialsId}", "${AWSUser}") creds = readJSON text: "${jsonCreds}" } } } stage('Use credentials') { steps { withEnv([ "AWS_ACCESS_KEY_ID=${creds.AccessKeyId}", "AWS_SECRET_ACCESS_KEY=${creds.SecretAccessKey}", "AWS_SESSION_TOKEN=${creds.SessionToken}" ]) { sh """ aws sts get-caller-identity """ } } } } }
When running the pipeline, Jenkins will ask you to enter your MFA code in order to assume the desired role:
And after that, use those credentials to perform whatever AWS-related stuff:
Key points
- If you followed my advice, your IAM user name and credentials ID will be the same as your Jenkins user name. Otherwise, you’ll have to modify getAWSUser and/or getCredentialsId functions accordingly.
- This example assumes a privileged role in the same account as the IAM user, but the setup can be used to assume a role in another account. Just pass the destination account ID as a parameter to the assumeRole function call.
I hope you’ve enjoyed this post and I encourage you to check our blog for other posts that you might find helpful, such as “What is the cloud?“. Do not hesitate to contact us if you would like us to help you on your projects.
See you on the next post!
3 Responses
Hi,
Thank you for script first of all.
I have changed in the script account id and assumed role.
After typing mfa , getting this issue: ERROR: Could not find credentials entry with ID ‘anonymous’
Could you please advice?
I have solved first issue: Now this one is appears: hudson.remoting.ProxyException: net.sf.json.JSONException: Invalid JSON String
Without more information, it looks like
readJSON text: “${jsonCreds}”
is trying to parse a non-json response. Can you take a look at the result of the “aws sts assume-role” command in your environment?