Sceptre / sceptre

Build better AWS infrastructure
https://docs.sceptre-project.org
Other
1.48k stars 313 forks source link

AWS profile with role_arn does not appear to work. #643

Closed edstafford closed 5 years ago

edstafford commented 5 years ago

My apologies for raising this as an issue as I'm not sure if this is intended or if I've lost the plot somewhere.

Given an IAM user in a group with a policy of trusted account roles (which works on switching accounts and assuming roles on the cli) I then have a 2nd service role for cloudformation which I'm attempting to use for stack creation.

My assumption is that by specifying the profile and setting the role_arn for a given cfn template that the combination would be effective. I can confirm that using the aws cli with create-stack and passing in the specific role-arn along with the --profile flag works for me but not when using sceptre.

Can someone confirm for me if this is intended behaviour or if someone has another way that this path could be supported?

Thank you in advance for your time.

mobee-pdufresne commented 5 years ago

Hi there

I'm currently having the same issue. Attempting cross-account role based deployment.

I pass the profile name with --var "profile=profile_name" in the CLI. Regardless of the value passed, the profile (or something) is not taken into account it seems, the deployment is done in the same account as the EC2 instance instead of the intended destination account.

Using AWS CLI, can deploy a stack across accounts with the same template and profile defined in ~/.aws/config I'm attempting to pass to Sceptre.

Scepter does work with the profile defined in ~/.aws/config when I set the environment variable AWS_PROFILE. so I'm not sure if Im defining the string correctly for --var

I'm using Sceptre v1.4.2

bootc commented 5 years ago

It looks like I've run into the same issue. I have an IAM user that we use to drive Sceptre from our CI/CD setup; this user should use AssumeRole into the target account (which is different to the CI/CD user), and then launch stacks with yet another role for CloudFormation itself. The session output looks something like this:

$ sceptre --debug launch --yes audit/
[2019-04-10 17:50:22] - Adding yaml constructors for the entry point groups ['sceptre.hooks', 'sceptre.resolvers']
[2019-04-10 17:50:22] - Added constructor for <class 'sceptre.hooks.asg_scaling_processes.ASGScalingProcesses'> with node tag !asg_scheduled_actions
[2019-04-10 17:50:22] - Added constructor for <class 'sceptre.hooks.cmd.Cmd'> with node tag !cmd
[2019-04-10 17:50:22] - Added constructor for <class 'sceptre.resolvers.environment_variable.EnvironmentVariable'> with node tag !environment_variable
[2019-04-10 17:50:22] - Added constructor for <class 'sceptre.resolvers.file_contents.FileContents'> with node tag !file_contents
[2019-04-10 17:50:22] - Added constructor for <class 'sceptre.resolvers.stack_output.StackOutput'> with node tag !stack_output
[2019-04-10 17:50:22] - Added constructor for <class 'sceptre.resolvers.stack_output.StackOutputExternal'> with node tag !stack_output_external
[2019-04-10 17:50:22] - Reading in 'main/config.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'main', 'project_code': 'cfn', 'region': 'eu-west-1', 'require_version': '~2', 'template_bucket_name': 'sceptre.aws.example.com', 'role_arn': 'arn:aws:iam::111111111111:role/SceptreCloudFormationRole'}
[2019-04-10 17:50:22] - Reading in 'main/cfn-secret-provider.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'main', 'project_code': 'cfn', 'region': 'eu-west-1', 'require_version': '~2', 'template_bucket_name': 'sceptre.aws.example.com', 'role_arn': 'arn:aws:iam::111111111111:role/SceptreCloudFormationRole', 'template_path': 'cfn-secret-provider.yaml', 'parameters': {'UseKmsCustomerManagedKey': 'false'}}
[2019-04-10 17:50:22] - Reading in 'audit/config.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'audit', 'project_code': 'cfn', 'region': 'eu-west-2', 'require_version': '~2', 'profile': 'subacct', 'template_bucket_name': 'sceptre.aws.example.com', 'role_arn': 'arn:aws:iam::222222222222:role/SceptreCloudFormationRole'}
[2019-04-10 17:50:22] - Reading in 'audit/cloudtrail-bucket.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'audit', 'project_code': 'cfn', 'region': 'eu-west-2', 'require_version': '~2', 'profile': 'subacct', 'template_bucket_name': 'sceptre.aws.example.com', 'role_arn': 'arn:aws:iam::222222222222:role/SceptreCloudFormationRole', 'template_path': 'audit/cloudtrail-bucket.yaml', 'parameters': {'CloudTrailBucketName': 'cloudtrail.aws.example.com'}}
[2019-04-10 17:50:22] - Reading in 'main/monitoring-user.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'main', 'project_code': 'cfn', 'region': 'eu-west-1', 'require_version': '~2', 'template_bucket_name': 'sceptre.aws.example.com', 'role_arn': 'arn:aws:iam::111111111111:role/SceptreCloudFormationRole', 'template_path': 'monitoring-user.yaml', 'dependencies': ['main/cfn-secret-provider.yaml'], 'parameters': {'MonitoringRoleArn': <sceptre.resolvers.stack_output.StackOutput object at 0x7feedd44ab70>}}
[2019-04-10 17:50:22] - Reading in 'init/config.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'init', 'project_code': 'cfn', 'region': 'eu-west-1', 'require_version': '~2'}
[2019-04-10 17:50:22] - Reading in 'init/sceptre.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'init', 'project_code': 'cfn', 'region': 'eu-west-1', 'require_version': '~2', 'template_path': 'sceptre.yaml', 'parameters': {'TemplateBucketName': 'sceptre.aws.example.com', 'AllowAssumeRoles': 'arn:aws:iam::222222222222:role/SceptreRole'}}
[2019-04-10 17:50:22] - Reading in 'main/monitoring-role.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'main', 'project_code': 'cfn', 'region': 'eu-west-1', 'require_version': '~2', 'template_bucket_name': 'sceptre.aws.example.com', 'role_arn': 'arn:aws:iam::111111111111:role/SceptreCloudFormationRole', 'template_path': 'monitoring-role.yaml'}
[2019-04-10 17:50:22] - Reading in 'init-audit/config.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'init-audit', 'project_code': 'cfn', 'region': 'eu-west-2', 'require_version': '~2'}
[2019-04-10 17:50:22] - Reading in 'init-audit/sceptre.yaml' files...
[2019-04-10 17:50:22] - Config: {'project_path': '/home/example/sceptre', 'stack_group_path': 'init-audit', 'project_code': 'cfn', 'region': 'eu-west-2', 'require_version': '~2', 'template_path': 'sceptre-subacct.yaml', 'parameters': {'TemplateBucketName': 'sceptre-audit.aws.example.com', 'SceptreSourceArn': 'arn:aws:iam::111111111111:user/Sceptre'}}
[2019-04-10 17:50:22] - Generate edges for graph 
[2019-04-10 17:50:22] - Generate edges for graph 
[2019-04-10 17:50:22] - Generate edges for graph 
[2019-04-10 17:50:22] - Generate edges for graph 
[2019-04-10 17:50:22] - Generate edges for graph 
[2019-04-10 17:50:22] - Generate edges for graph 
[2019-04-10 17:50:22] - Added edge: None
[2019-04-10 17:50:22] - Added edge: None
[2019-04-10 17:50:22] - audit/cloudtrail-bucket - Launching Stack
[2019-04-10 17:50:22] - No cloudformation client found, creating one...
[2019-04-10 17:50:22] - Getting Boto3 session
[2019-04-10 17:50:22] - No Boto3 session found, creating one...
[2019-04-10 17:50:22] - Using cli credentials...
[2019-04-10 17:50:22] - Using credential set from explicit: {'AccessKeyId': '****************FL2A', 'SecretAccessKey': '****************************************', 'Region': 'eu-west-2'}
[2019-04-10 17:50:22] - Boto3 session created
[2019-04-10 17:50:22] - audit/cloudtrail-bucket - Stack is in the PENDING state
[2019-04-10 17:50:22] - audit/cloudtrail-bucket - Creating Stack
[2019-04-10 17:50:22] - cloudtrail-bucket - Uploading template to S3...
[2019-04-10 17:50:22] - cloudtrail-bucket - Attempting to find template bucket 'sceptre.aws.example.com'
[2019-04-10 17:50:22] - No s3 client found, creating one...
[2019-04-10 17:50:22] - Getting Boto3 session
[2019-04-10 17:50:23] - cloudtrail-bucket - Found template bucket 'sceptre.aws.example.com'
[2019-04-10 17:50:23] - cloudtrail-bucket - Uploading template to: 's3://sceptre.aws.example.com/audit/cloudtrail-bucket/2019-04-10-16-50-22-244747Z.json'
[2019-04-10 17:50:23] - cloudtrail-bucket - Template URL: 'https://sceptre.aws.example.com.s3.amazonaws.com/audit/cloudtrail-bucket/2019-04-10-16-50-22-244747Z.json'
An error occurred (AccessDenied) when calling the CreateStack operation: Cross-account pass role is not allowed

Can this be fixed? Alternatively, does anyone have a workaround?

anh072 commented 5 years ago

I have the same issue in Sceptre 2.1.0

ngfgrant commented 5 years ago

Ok thanks folks I am investigating

bootc commented 5 years ago

So after I posted my comment above I found a workaround. This is because of a deliberate behaviour in Sceptre: it will prefer ambient credentials to any role configured in the stack:

https://github.com/cloudreach/sceptre/blob/0b104db2e4f2e84522b1d2d3c81f2a8af1d97b12/sceptre/connection_manager.py#L120

In the end I created a wrapper script that takes the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and puts them into a temporary file, then points AWS_SHARED_CREDENTIALS_FILE at the temp file before running Sceptre. When it exits it cleans up. It's a nasty hack, but it works for me.

Here is my script in case it's helpful:

#!/bin/bash
# Sceptre will prefer ambient credentials to the profile name in its
# configuration, but we need to use the profile to assume-role into a different
# account. This wrapper will take the ambient credentials and stuff them into
# a temporary credentials file, then unset them from the environment.

set -euo pipefail

# Put the credentials in a temp file, and clean it up at exit
export AWS_SHARED_CREDENTIALS_FILE="$(mktemp)"
trap -- "rm -f ${AWS_SHARED_CREDENTIALS_FILE}" EXIT

# Put the values in the config file
cat <<EOF >"${AWS_SHARED_CREDENTIALS_FILE}"
[default]
aws_access_key_id=${AWS_ACCESS_KEY_ID}
aws_secret_access_key=${AWS_SECRET_ACCESS_KEY}
${AWS_SESSION_TOKEN:+aws_session_token=${AWS_SESSION_TOKEN}}
EOF

# Mask the environment variables for child processes
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN AWS_SECURITY_TOKEN

# Now run the wrapped command
cmd="$1"
shift
$cmd "$@"

You can use it like this:

./aws-wrap.sh sceptre launch --yes my_stacks
ngfgrant commented 5 years ago

as @bootc points out ambient env variables take priority over config. To use profile and cross account make sure your env is unset from any relevant AWS settings. I've tested the cross account functionality with clear env and it works fine.