How to assume an iam role in a makefile?

I tried:

deploy-non-prod:
    aws --version
    eval $(aws sts assume-role --role-arn arn:aws:iam::xxx:role/rl-some-role --role-session-name test | jq -r '.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"')

This worked in bash, but not in the makefile. It seems it isn't keeping the session. I also tried with environment variables but no luck either.


This is the default behavior of Make: each line in the "recipe" is executed by a separate shell, so nothing carries from one line to another.

GNU Make provides the .ONESHELL special target, which instructs Make to use a single shell for each recipe. The drawback of this is that it applies to the entire Makefile, so you don't have the option of individual execution.

You could use a backslash to combine multiple lines:

mytarget:
    aws --version ; \
    eval $(aws sts assume-role ... ) ; \
    aws sts get-caller-identity

If you do this, it's important to put the semi-colon after every command. You could also use a conditional operation like &&, to ensure that each line succeeds before invoking the next.

You could also as a variable to hold your access vars, and insert them in each line where you invoke an AWS operation:

ACCESS_VARS != aws sts assume-role --role-arn arn:aws:iam::123456789012:role/SomeRole --role-session-name test | jq -r '.Credentials | "AWS_ACCESS_KEY_ID=\(.AccessKeyId) AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey) AWS_SESSION_TOKEN=\(.SessionToken)"'

test:
    $(ACCESS_VARS) aws sts get-caller-identity

Note that the JQ command is different from the one in your quesion: if you set environment variables as part of a command, you don't use export.

IMO, however, the best solution is to write a script to do your work, and invoke that script from the Makefile. This will let you test the script independently, and enable full shell features without the additional constraints applied by Make.