aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.51k stars 3.85k forks source link

[notice] CDK CLI Authentication Issues #1656

Closed rix0rrr closed 3 years ago

rix0rrr commented 5 years ago

The CDK CLI has some limitations compared to the AWS CLI. If you are having authentication issues, they might be covered by one of the following issues. Please use this thread to discuss further.

CDK CLI will not read your region from your [default] profile

If your ~/.aws/config is set up like this:

[default]
region = us-east-1

[profile MyProfile]
role_arn = arn:aws:iam::123456789012:role/myprofile
source_profile = SomeOtherProfile

Even though your profile MyProfile does not contain a region, the AWS CLI will read the region from the [default] section. The AWS SDK for JavaScript that the CDK is built on does not do this, so the CDK does not support this. Make sure every profile section contains the region.

Cannot have a profile named "default" in the config file

The following will not work:

[default]
...

[profile default]
...

The AWS CLI seems to accept this, but the AWS SDK for JavaScript will fail to load the configuration file properly.

How to properly select AWS CLI profiles for your stacks/accounts

See issue #3961

vschumaker commented 5 years ago

I ran in to the case where a [profile default] of the following format

[default]
output = text
region = us-east-1

[profile default]
role_arn = arn:aws:iam::123456789012:role/myrole
source_profile = default

[profile dev]
source_profile = default
role_arn = arn:aws:iam::987654321012:role/myrole
region = us-east-1

caused the following error, even though my AWS_PROFILE environment variable was set to dev

cdk deploy
Need to perform AWS calls for account unknown-account, but no credentials found. Tried: default credentials.

Removing the [profile default] section allowed me to successfully cdk deploy my stack.

moofish32 commented 5 years ago

I'm trying to run npm run integ I have my assume role credentials sourced in the following env vars:

AWS_ACCESS_KEY_ID=xxxxx
AWS_SECRET_ACCESS_KEY=xxxx
AWS_SESSION_TOKEN=xxxx

Is there any reason I would still get an error like:

Trying to deploy ec2/integ.event-task.lit.js
[Error at /aws-ecs-integ-ecs/Vpc] Cannot determine scope for context provider availability-zones with props: account=undefined,region=us-west-2.

Is there a new process for running integ tests?

moofish32 commented 5 years ago

Answering my own question for the next person.

My issue was that at some point ~/.aws/config added a similar file to the example above. I deleted the ~/.aws/config because I no longer use it and set the AWS_DEFAULT_REGION=xxxx env var in my shell. After that everything started working. @rix0rrr actually found this. So if you have ~/.aws/credentials and ~/.aws/config they both can't have a default profile section.

0xdevalias commented 5 years ago

Another edge case, in case anyone else runs into it. Using aws-vault

⇒  aws-vault exec myprofile -- cdk diff
Need to perform AWS calls for account unknown-account, but no credentials found. Tried: default credentials.

Looking at ~/.aws/config I had an empty profile: [profile myprofile]

By changing it to include a region, the issue was resolved and cdk diff worked as expected:

[profile myprofile]
region=ap-southeast-2

Maybe updating the error message to be a bit more explicit in what the actual issue is would be helpful?

r-kuhr commented 5 years ago

Just to add on for MFA:

I am having this problem WITHOUT a [profile default] entry. Any idea why I am getting the same error?

[default]
region = eu-central-1

[profile int-server]
source_profile = default
role_arn = arn:aws:iam::121212121212:role/deployer
mfa_serial = arn:aws:iam::421212121212:mfa/me@mfa.eu

[profile prod-server]
source_profile = default
role_arn = arn:aws:iam::321212121212:role/deployer
mfa_serial = arn:aws:iam::421212121212:mfa/me@mfa.eu

error:

Setting "aws:cdk:toolkit:default-region" context to eu-central-1
Resolving default credentials
Unable to determine the default AWS account (did you configure "aws configure"?): { AccessDenied: Access denied
LechuckThePirate commented 5 years ago

Hello... I'm having another authentication issue...

We use a identity account and a governor account role with MFA enabled... my config file looks like this:

[profile default] region=eu-west-1 role_arn=arn:aws:iam::xxxxxxxxxxxxx:role/xxxxxxxx mfa_serial=arn:aws:iam::xxxxxxxxxxxx:mfa/xxxxxxxxx@xxxxxx.com source_profile=default

and I have a [default] credentials with my client and secret keys.

I'm running CDK from a AWS Workspace (I don't know if this can be the problem). I get an error saying that I didn't do aws configure ... I did, and I'm providing --profile default to be sure.

Any fix/workaround?

If I try to deploy the hello-cdk app I get this (with --verbose)

PS > cdk deploy --profile default -v
CDK toolkit version: 0.27.0 (build 7638a58)
Command line arguments: { _: [ 'deploy' ],
  trace: false,
  strict: false,
  'ignore-errors': false,
  ignoreErrors: false,
  json: false,
  j: false,
  verbose: true,
  v: true,
  ec2creds: undefined,
  i: undefined,
  'version-reporting': undefined,
  versionReporting: undefined,
  'path-metadata': true,
  pathMetadata: true,
  'asset-metadata': true,
  assetMetadata: true,
  ci: false,
  version: false,
  help: false,
  h: false,
  exclusively: false,
  e: false,
  profile: 'default',
  'role-arn': undefined,
  r: undefined,
  roleArn: undefined,
  'build-exclude': [],
  E: [],
  buildExclude: [],
  '$0': '..\\..\\..\\AppData\\Roaming\\npm\\node_modules\\aws-cdk\\bin\\cdk',
  app: undefined,
  context: undefined,
  plugin: undefined,
  rename: undefined,
  proxy: undefined,
  'toolkit-stack-name': undefined,
  'require-approval': undefined,
  STACKS: [] }
Determining whether we're on an EC2 instance.
cdk.json: {
  "app": "node bin/testapp.js"
}
Setting "aws:cdk:toolkit:default-region" context to undefined
Resolving default credentials
Looks like EC2 instance.
Looking up default account ID from STS
Unable to determine the default AWS account (did you configure "aws configure"?): { InvalidClientTokenId: The security token included in the request is invalid.
    at Request.extractError (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\protocol\query.js:50:29)
    at Request.callListeners (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
    at Request.emit (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
    at Request.emit (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\request.js:683:14)
    at Request.transition (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\request.js:22:10)
    at AcceptorStateMachine.runTo (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\state_machine.js:14:12)
    at D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\state_machine.js:26:10
    at Request.<anonymous> (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\request.js:38:9)
    at Request.<anonymous> (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\request.js:685:12)
    at Request.callListeners (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\node_modules\aws-sdk\lib\sequential_executor.js:116:18)
  message: 'The security token included in the request is invalid.',
  code: 'InvalidClientTokenId',
  time: 2019-04-01T10:23:27.706Z,
  requestId: '30626f19-5468-11e9-b302-4524a75e3687',
  statusCode: 403,
  retryable: false,
  retryDelay: 16.893920433979147 }
Setting "aws:cdk:toolkit:default-account" context to undefined
context: { 'aws:cdk:toolkit:default-region': undefined,
  'aws:cdk:toolkit:default-account': undefined,
  'aws:cdk:enable-path-metadata': true,
  'aws:cdk:enable-asset-metadata': true }
outdir: D:\xxxxxxxxxxxxxx\AppData\Local\Temp\cdkYL2v9X
outfile: D:\xxxxxxxxxxxxxx\AppData\Local\Temp\cdkYL2v9X\cdk.out
{ version: '0.19.0',
  artifacts: 
   { TestappStack: 
      { type: 'aws:cloudformation:stack',
        environment: 'aws://unknown-account/unknown-region',
        properties: [Object],
        metadata: [Object] } },
  runtime: 
   { libraries: 
      { '@aws-cdk/cdk': '0.27.0',
        '@aws-cdk/cx-api': '0.27.0',
        '@aws-cdk/aws-s3': '0.27.0',
        '@aws-cdk/aws-events': '0.27.0',
        '@aws-cdk/aws-iam': '0.27.0',
        '@aws-cdk/region-info': '0.27.0',
        '@aws-cdk/aws-kms': '0.27.0',
        '@aws-cdk/aws-s3-notifications': '0.27.0',
        '@aws-cdk/aws-codepipeline-api': '0.27.0',
        'jsii-runtime': 'node.js/v8.12.0' } },
  stacks: 
   [ { name: 'TestappStack',
       environment: [Object],
       template: [Object],
       metadata: [Object] } ] }
Removing outdir D:\xxxxxxxxxxxxxx\AppData\Local\Temp\cdkYL2v9X
The stack TestappStack already includes a CDKMetadata resource
Stack name not specified, so defaulting to all available stacks: TestappStack
Reading existing template for stack TestappStack.
Need to perform AWS calls for account unknown-account, but no credentials found. Tried: default credentials.
Error: Need to perform AWS calls for account unknown-account, but no credentials found. Tried: default credentials.
    at CredentialsCache.getCredentials (D:\xxxxxxxxxxxxxx\AppData\Roaming\npm\node_modules\aws-cdk\lib\api\util\sdk.ts:209:11)
    at <anonymous>
Sparkboxx commented 5 years ago

CDK not using the --profile setting

Is it expected behaviour that when a profile is configured in cdk.json that cdk uses your [default] credential profile if you don't give it an explicit --profile ? Or should it be safe to assume that if the profile is set in the cdk.json that when running a cdk command it uses the configured profile?

The story I forgot to include the --profile myProfile a bunch of times while creating my app and ended up creating infrastructure my [default] profile account. This of course is user error, but I think an error other people might make too.

In order to avoid the problem I now setup an empty [default] profile, so that if I forget to include --profile myProfile I get an error. (Which is probably a good thing for me to do anyway working with multiple profiles)

CDK is configured with:

{
  "app": "node bin/app.js",
  "profile": "myProfile"
}
kadishmal commented 5 years ago

I'm trying to deploy a CDK app from within a Lambda function. Now it complains with:

Need to perform AWS calls for account unknown-account, but no credentials found. Tried: default credentials.

Passing --role-arn doesn't seem to work. Why is CDK bound to ~/.aws/credentials and ~/.aws/config?

Lambda function itself already has a role that has all the permissions to deploy a CDK app. Is this even possible? The final resort is to duplicate CDK's cdk.js and remove the credential checker part which feels so unnecessary.

mrgrain commented 5 years ago

I have a CDK app which is deployed from a docker container inside an EC2 instance.

The EC2 instance has a role in the target account which does nothing but allow me to assume an other role.

I have a CDK plugin which handles assuming the role.

When I try to deploy via CDK, the app is loading the plugin, but is not requesting credentials from it. Instead CDK resolves and looks up "default credentials" for the account. Since the role is for the account, CDK moves on and subsequently fails as the instance role has no permissions.

Is there a way to tell CDK to not use this account, or better to just use my plugin?

AWS_EC2_METADATA_DISABLED won't work as the plugin is relying on metadata.

kadishmal commented 5 years ago

@mrgrain I went on with a different approach I described in this https://github.com/awslabs/aws-cdk/issues/2637#issuecomment-496291068. It might give you some ideas.

mrgrain commented 5 years ago

@kadishmal I found a solution for my issue. Since the problem came down to AWS CDK trying to use ec2 meta data credentials by default, we can disable that behaviour by setting --ec2creds false on the cli.

I guess what would be nice if that option is explicitly called out in the log. Something like

Looks like an EC2 instance. Trying ec2 meta data credentials (disable this behaviour with `--ec2creds false`).
zzenonn commented 5 years ago

I have two weird issues:

My config file is setup like this:

[default]
output = json
region = ap-southeast-1
role_arn = arn:aws:iam::123456789012:role/AdminRole
source_profile = default

[profile company]
region=ap-southeast-1
output=json
cli_follow_urlparam = false

[profile educate]
region=us-east-1
output=json

When I run cdk deploy,

My first issue is I get this error which uses a different region from my default (which is very strange).

My second issue is that the CDK also does not assume the role specified in the configuration.

User: arn:aws:iam::123456789012:user/zenon is not authorized to perform: cloudformation:GetTemplate on resource: arn:aws:cloudformation:us-east-2:123456789012:stack/hello-cdk-1/*
mbonig commented 5 years ago

Is there any verified way of leverage just the AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID (but no AWS_SESSION_TOKEN) environment variables?

skinny85 commented 5 years ago

Is there any verified way of leverage just the AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID (but no AWS_SESSION_TOKEN) environment variables?

I believe if you're not using temporary credentials like assumeRole, but something like an IAM User, you don't need to set AWS_SESSION_TOKEN.

kevinslin commented 5 years ago

for mfa, I use aws-mfa to make things a bit more bearable. it writes short term credentials into your .credentials file and works with cdk!

mbonig commented 5 years ago

Is there any verified way of leverage just the AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID (but no AWS_SESSION_TOKEN) environment variables?

I believe if you're not using temporary credentials like assumeRole, but something like an IAM User, you don't need to set AWS_SESSION_TOKEN.

So, just to round out the issue... I have been trying to run cdk synth inside a Jenkins pipeline that was given temp credentials from the AWS Credentials Jenkins plugin. However, CDK couldn't find the env variable creds properly. So, I just write them to a file first and then point AWS_SHARED_CREDENTIALS_FILE at it and now things are working fine.

jonnyyu commented 5 years ago
  1. using aws-cdk 1.3.0 on a EC2 AMI Linux 2 instance with role attached.
  2. run 'aws configure' with secret/access=None, region=us-west-2
  3. run 'cdk deploy myservice' failed with
    Need to perform AWS calls for account XXXXXXXXXXX, but no credentials found. 

    Detail logs:

    Tried: default credentials.
    Error: Need to perform AWS calls for account XXXXXXXXXXX, but no credentials found. Tried: default credentials.
    at CredentialsCache.getCredentials (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/lib/api/util/sdk.ts:261:11)
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
    at CredentialsCache.get (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/lib/api/util/sdk.ts:223:25)
    at SDK.cloudFormation (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/lib/api/util/sdk.ts:117:20)
    at CloudFormationDeploymentTarget.readCurrentTemplate (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/lib/api/deployment-target.ts:52:17)
    at CdkToolkit.deploy (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/lib/cdk-toolkit.ts:94:33)
    at main (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/bin/cdk.ts:192:16)
    at initCommandLine (/home/ec2-user/.nvm/versions/node/v12.7.0/lib/node_modules/aws-cdk/bin/cdk.ts:150:9)

    A workaround is to touch ~/.aws/credentials, then it can correctly retrieve credentials from EC2 metadata. But AWS CLI doesn't require ~/.aws/credentials exist

SteveHoggNZ commented 5 years ago

@kadishmal I got CDK running in a Lambda. Setting the a HOME environment variable to /tmp for the Lambda allows create the credentials files and use the Lambda's role.

The CDK CLI also needs --output /tmp/cdk.out

kadishmal commented 5 years ago

@SteveHoggNZ just like that? Set the HOME env to /tmp and CDK will stop using the credentials? Can you paste some sample code?

whilp commented 5 years ago

A workaround is to touch ~/.aws/credentials, then it can correctly retrieve credentials from EC2 metadata.

This workaround may feel slightly less painful if you use the AWS_SHARED_CREDENTIALS_FILE environment variable.

export AWS_SHARED_CREDENTIALS_FILE=/tmp/aws-cdk-1656-workaround
touch $AWS_SHARED_CREDENTIALS_FILE
helzich commented 5 years ago

Adding to the findings of @jonnyyu, AWS CDK does not only expect ~/.aws/credentials to exist, it also requires the profile information to reside in ~/.aws/config even if the environment variable AWS_CONFIG_FILE points elsewhere. The AWS CLI respects the environment variable, but AWS CDK does not (tested with 1.5.0 (build c020efa) in a docker container running "Amazon Linux 2").

konstantinj commented 4 years ago

Hi, I'm wondering how to have stacks of different accounts/regions in one app and synth them at the same time. Similar to #1035 and #290

I'm specifying accountId and region with cdk.StackProps.env but (of course) cdk doesn't have access to all accounts specified:

Need to perform AWS calls for account XXXXXXXXXXXX, but no credentials found. Tried: default credentials.

How is this supposed to work? @eladb @rix0rrr

For using aws cli I have my default profile that has access to our main account with access/secret keys and all other accounts have then cross-account roles.

konstantinj commented 4 years ago

looks like #3961 will solve this issue

NGL321 commented 4 years ago

_Appending other pinned auth issue here:

3961_

hupe1980 commented 4 years ago

We solved our authentication issues with a simple plugin that adds support for mfa and multi profiles/accounts: https://github.com/hupe1980/cdk-multi-profile-plugin

toleabivol commented 4 years ago

I had this issue that --profile paramater had no effect (always getting the default) and it was because of AWS system variables being set. Removed AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY system vars and it worked.

holmesjr commented 4 years ago

CDK doesn't support CLI v2 SSO.

mitchlloyd commented 4 years ago

The CDK credentials provider plugin continues to be the best option for my team because, as @hupe1980 showed, it is very flexible.

The two issues with the current plugin architecture I run into are:

  1. The env vars and default profile always take precedence over the plugin. People sometimes forget or don't realize that they have env vars or a default profile and have to troubleshoot. I wish I could fully delegate credentials work to the plugin.
  2. There is no good way to set the role to use for sts in the plugin. We assume a conventional role name (Admin), but sometimes teams use different role names and need to provide additional info in an environment variable. It would be nice if the stack env had an optional role parameter to pass to the plugin, but maybe there's a better place for this.

In practice these 2 issues aren't too bad if CDK is the primary way developers interact with AWS. However the myriad of other AWS credentials processes derail things.

ghost commented 4 years ago

Regarding MFA support, There are a couple of possible workarounds, either can be scripted to make life easier:

In the end, these are just workarounds, and it would be nice to get this into the product.

lrhazi commented 4 years ago

FYI, I was getting this error:

Need to perform AWS calls for account 9999-9999-9999, but no credentials found. Tried: default credentials.

and it turns out the dashes in the account number were the problem!

skorfmann commented 4 years ago

@kadishmal I found a solution for my issue. Since the problem came down to AWS CDK trying to use ec2 meta data credentials by default, we can disable that behaviour by setting --ec2creds false on the cli.

I guess what would be nice if that option is explicitly called out in the log. Something like

Looks like an EC2 instance. Trying ec2 meta data credentials (disable this behaviour with `--ec2creds false`).

This worked for us 💯 in a CI context on EC2 instances (in combination with running touch ~/.aws/credentials for some reason)

👍 for making this obvious in the log output, since it's not obvious that the metadata endpoint will have priority over credentials in the env. Comparing this to the Javascript SDK:

If more than one credential source is available to the SDK, the default precedence of selection is as follows:

- Credentials that are explicitly set through the service-client constructor
- Environment variables
- The shared credentials file
- Credentials loaded from the ECS credentials provider (if applicable)
- Credentials that are obtained by using a credential process specified in the shared AWS config file or the shared credentials file. 
- Credentials loaded from AWS IAM using the credentials provider of the Amazon EC2 instance (if configured in the instance metadata)

So, even better than logging and documentation this behaviour as it is right now, it would probably better to align it with the rest of the ecosystem.

cn-sws commented 4 years ago

I was getting either of these two errors depending on what I tried in the config/credentials files to get it working:

Unable to determine AWS region from environment or AWS configuration

Unable to determine the default AWS account (did you configure "aws configure"?)

In my case, the cause had nothing to do with the profile I was actually trying to use, i.e. --profile sbox-03. The cause was from a "pseudo" duplicate entry in the config file. I had these two entries:

[app]
region = ap-southeast-2
output = json
[profile app]
region = ap-southeast-2
output = json

This caused the error below when running this command:

cdk deploy -v --profile sbox-03

Note the "-v". Without the -v you just get a one line response:

Unable to resolve AWS account to use. It must be either configured when you define your CDK or through the environment

the error:

Unable to determine the default AWS account (did you configure "aws configure"?): TypeError: Cannot redefine property: app
    at Function.defineProperty (<anonymous>)
    at D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\shared-ini\ini-loader.js:11:14
    at Array.forEach (<anonymous>)
    at IniLoader.parseFile (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\shared-ini\ini-loader.js:8:26)
    at IniLoader.loadFrom (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\shared-ini\ini-loader.js:56:30)
    at Object.getProfilesFromSharedConfig (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\util.js:960:42)
    at SharedIniFileCredentials.load (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\credentials\shared_ini_file_credentials.js:96:31)
    at SharedIniFileCredentials.coalesceRefresh (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\credentials.js:205:12)
    at SharedIniFileCredentials.refresh (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\credentials\shared_ini_file_credentials.js:168:10)
    at SharedIniFileCredentials.get (D:\Data\CIT\sw projects\_app-support\node-v10.12.0-win-x64\node_modules\aws-cdk\node_modules\aws-sdk\lib\credentials.js:122:12)`

This code in 'ini-loader.js' generates the error:

Object.defineProperty(tmpContent, profileName, {
function parseFile(filename, isConfig) {
    var content = AWS.util.ini.parse(AWS.util.readFileSync(filename));
    var tmpContent = {};
    Object.keys(content).forEach(function(profileName) {
      var profileContent = content[profileName];
      profileName = isConfig ? profileName.replace(/^profile\s/, '') : profileName;
      Object.defineProperty(tmpContent, profileName, {
        value: profileContent,
        enumerable: true
      });
    });
    return tmpContent;
}

Notice, it is trying to redefine my "app" profile:

Cannot redefine property: app

Notice above I said "pseudo" duplicate. If you have an actual duplicate, i.e. [app] and [app] for profile names then there is no problem. It is just when you have [app] and [profile app].

thekevinbrown commented 4 years ago

I'm struggling with this because the behaviour I want is as follows:

Why? Because we work on many clients who have their own AWS accounts, and I want to be sure that we never deploy one client's setup to the wrong AWS account, especially in the case where there's a developer who has a [default] profile set to a different client but is doing something on this project for a bit or a potentially misconfigured CI build agent which has AWS creds configured when it shouldn't.

How can I ensure this happens? I feel like the easiest API here would be to be able to pass in the Access Key and Secret Key directly to the tool and have that always override whatever's in the various files and env vars.

john-tipper commented 4 years ago

@SteveHoggNZ how did you package up the CDK into the lambda please? Did you install as a layer and if so, how did you create this layer?

0xdevalias commented 4 years ago

@thekevinbrown I use https://github.com/99designs/aws-vault to store my credentials, and give each profile within it a meaningful name (eg. client name). Then in my package.json scripts I prefix all of the cdk/etc commands with aws-vault syntax for the relevant client. That way I never have to think about which client, or the differences, I just need to run the same script in each project (and have an appropriate profile for that client configured on my computer, if not, it will fail rather than deploy to the wrong account)

SteveHoggNZ commented 4 years ago

@SteveHoggNZ how did you package up the CDK into the lambda please? Did you install as a layer and if so, how did you create this layer?

@john-tipper we did package CDK in a Lambda. We use Python, so we also had to bundle in NodeJS in the Lambda. Here is a simplified version of what we did:

Dockerfile

FROM lambci/lambda:build-python3.7

ARG CDK_VERSION

# CDK requires NodeJS
RUN yum -y update && yum install -y gcc-c++ make && \
        curl -sL https://rpm.nodesource.com/setup_12.x | bash - && \
        yum install -y nodejs

RUN npm i -g aws-cdk@$CDK_VERSION

RUN mkdir -p /opt/bin /opt/lib && \
        cp -pR /usr/lib/node_modules /opt/lib && \
        cp -p /usr/bin/node /opt/bin && \
        strip /opt/bin/node && \
        ln -s /opt/lib/node_modules/npm/bin/npm-cli.js /opt/bin/npm && \
        sed -i 's|/usr/bin/env node|/opt/bin/node|' /opt/lib/node_modules/aws-cdk/bin/cdk

# CDK requires the AWS CLI
RUN pip install awscli --target /opt/python/lib/python3.7/site-packages

Docker Build

CDK_VERSION=v1.25.0
docker build layers/cdk --tag cdk-layer-builder:$CDK_VERSION --build-arg CDK_VERSION=$CDK_VERSION

Layer Build

mkdir -p layers/cdk/versions
docker run \
        -v ${PWD}/layers/cdk/versions:/versions \
        cdk-layer-builder:$CDK_VERSION \
        bash -c "cd /opt && zip -r /versions/cdk-$CDK_VERSION.zip . >/dev/null"

That will give you a zip file in layers/cdk/versions you can upload as a layer.

To get the Lambda to run CDK there are other requirements:

That should be it.

My boss has given me the go-ahead to do a blog article on this with more detail.

john-tipper commented 4 years ago

Thanks @SteveHoggNZ, particularly for pointing out the gotchas! I ended up coming up with a similar solution for packaging the CDK as a layer: https://stackoverflow.com/a/60399178/272023

FreeWillaert commented 4 years ago

FYI, I was getting this error:

Need to perform AWS calls for account 9999-9999-9999, but no credentials found. Tried: default credentials.

and it turns out the dashes in the account number were the problem!

Same here. Having a wrong/missing/bad value in the env.account property of StackProps causes this same error message. Very confusing.

misk0 commented 4 years ago

I'm having similar issues and after reading whole thread I couldn't do an initial deploy. My setup:

aws --version File association not found for extension .py aws-cli/1.16.310 Python/3.8.1 Windows/10 botocore/1.13.46

cdk --version 1.27.0 (build a98c0b3)

I created simple Java class following the documentation and I'm getting

cdk deploy Stack-east-1 Need to perform AWS calls for account testuser, but no credentials found. Tried: default credentials.

If I try to use "aws s3 ls" if works without any problem.

This is verbose output:

cdk deploy Stack-east-1 -v CDK toolkit version: 1.27.0 (build a98c0b3) Command line arguments: { _: [ 'deploy' ], v: true, verbose: true, 'ignore-errors': false, ignoreErrors: false, json: false, j: false, ec2creds: undefined, i: undefined, 'version-reporting': undefined, versionReporting: undefined, 'path-metadata': true, pathMetadata: true, 'asset-metadata': true, assetMetadata: true, 'role-arn': undefined, r: undefined, roleArn: undefined, staging: true, 'no-color': false, noColor: false, fail: false, 'build-exclude': [], E: [], buildExclude: [], ci: false, execute: true, force: false, f: false, '$0': 'C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\bin\cdk', STACKS: [ 'Stack-east-1' ], stacks: [ 'Stack-east-1' ] } Determining whether we're on an EC2 instance. cdk.json: { "app": "mvn -e -q exec:java" } cdk.context.json: { "@aws-cdk/core:enableStackNameDuplicates": "true", "aws-cdk:enableDiffNoFail": "true" } merged settings: { versionReporting: true, pathMetadata: true, output: 'cdk.out', app: 'mvn -e -q exec:java', context: {}, tags: [], assetMetadata: true, toolkitBucket: {}, staging: true } Setting "CDK_DEFAULT_REGION" environment variable to us-east-1 Resolving default credentials Does not look like EC2 instance. Retrieved account ID 201547469031 from disk cache Setting "CDK_DEFAULT_ACCOUNT" environment variable to 201547469031 context: { '@aws-cdk/core:enableStackNameDuplicates': 'true', 'aws-cdk:enableDiffNoFail': 'true', 'aws:cdk:enable-path-metadata': true, 'aws:cdk:enable-asset-metadata': true } outdir: cdk.out env: { CDK_DEFAULT_REGION: 'us-east-1', CDK_DEFAULT_ACCOUNT: '201547469031', CDK_CONTEXT_JSON: '{"@aws-cdk/core:enableStackNameDuplicates":"true","aws-cdk:enableDiffNoFail":"true","aws:cdk:enable-path-metadata":true,"aws:cdk:enable-asset-metadata":true}', CDK_OUTDIR: 'cdk.out', CDK_CLI_ASM_VERSION: '1.21.0', CDK_CLI_VERSION: '1.27.0' } Reading existing template for stack Stack-east-1. Need to perform AWS calls for account testuser, but no credentials found. Tried: default credentials. Error: Need to perform AWS calls for account testuser, but no credentials found. Tried: default credentials. at CredentialsCache.getCredentials (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\lib\api\util\sdk.ts:284:11) at processTicksAndRejections (internal/process/task_queues.js:97:5) at CredentialsCache.get (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\lib\api\util\sdk.ts:246:25) at SDK.service (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\lib\api\util\sdk.ts:154:20) at CloudFormationDeploymentTarget.readCurrentTemplate (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\lib\api\deployment-target.ts:57:17) at CdkToolkit.deploy (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\lib\cdk-toolkit.ts:114:33) at main (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\bin\cdk.ts:218:16) at initCommandLine (C:\Users\misko\AppData\Roaming\npm\node_modules\aws-cdk\bin\cdk.ts:168:9)

I don't have any environment variables set and only my config file is populated. Where could be the problem? Thanks.

jakebanks commented 4 years ago

I was also experiencing this with aws-vault. The working combination of calls for me was:

const amiId = StringParameter.fromStringParameterAttributes(this, 'amiId', {
      parameterName: '/my-ami-parameter',
    }).stringValue;

Then for my ASG: machineImage: new ec2.GenericLinuxImage({ [region]: amiId }), - note the brackets are significant.

EDIT: okay, that got me to synth, deploying is still resulting in Need to perform AWS calls for account <account>, but no credentials found. Tried: default credentials.

EDIT2: sorted. The trick was to not specify the account name or id here:

    const env = {
      account: process.env.AWS_DEFAULT_ACCOUNT, //undefined for my local environment, which works
      region: process.env.AWS_DEFAULT_REGION || context.account.Region, //region req'd for AMI lookup
    };

Or else it tried to look for a profile with the corresponding name in 'C:\Users\jake\.aws\credentials'

misk0 commented 4 years ago

Thanks @jakebanks this helped. I'm using Java classes and I followed instruction from AWS doc site. So your post gave me an idea that maybe I should not specify credentials but used the default one. And bang! it works. That's ok, but Amazon advises to use different profile for different deployment scenario so it should work. Here are my classes

package com.myorg;

import software.amazon.awscdk.core.App; import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.core.Environment; import software.amazon.awscdk.core.StackProps; import software.amazon.awscdk.services.s3.Bucket;

import java.util.Arrays;

public class SimpleCdkApp {

private static App app;

// Helper method to declare MyStacks in specific accounts/regions
private static SimpleCdkStack makeMyStack(final String name, final String account,
                                   final String region) {

    return new SimpleCdkStack(app, name, StackProps.builder()
            .env(Environment.builder()
                    .account(account)
                    .region(region)
                    .build())
            .build());
}
public static void main(final String[] args) {
    app = new App();

    //makeMyStack("Stack-east-1",   "testuser",   "us-east-1");

    new SimpleCdkStack(app, "SimpleCdkStack");

    app.synth();
}

}

and

package com.myorg;

import software.amazon.awscdk.core.Construct; import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.core.StackProps; import software.amazon.awscdk.services.s3.Bucket;

public class SimpleCdkStack extends Stack { public SimpleCdkStack(final Construct scope, final String id) {

    this(scope, id, null);
}

public SimpleCdkStack(final Construct scope, final String id, final StackProps props) {
    super(scope, id, props);

    // The code that defines your stack goes here
    Bucket.Builder.create(this, "MyFirstBucket")
            .versioned(true).build();
}

}

If I use default stack it works, if I use helper method and specify profile details that it doesn't work. Any ideas? Thanks

rcollette commented 4 years ago

The issue of --profile not overriding environment variables in https://github.com/aws/aws-cdk/issues/1656#issuecomment-558218200 by @toleabivol is a real PITA.

The behavior I was seeing was that stacks having a stack as their parent (not nested stacks mind you), would not get the assigned stackName but would appear with the default hashed stack name.

It was only after using the verbose option that I could see that what was actually happening was invalid credentials were being used. Of course, those credentials don't print out, which is a pain, and it took forever to figure it out by basically removing any other credential on my system except the profile I was using and realizing that it was the environment variable credentials that were being used.

This behavior is unlike the AWS CLI so it's very confusing.

evanderkoogh commented 4 years ago

Found another issues. Authentication doesn't work at all if there ~/.aws/credentials file does not exist, even though you set the environment variables which should take precedence.

aws-cli works just fine, the aws-sdk-js fails with: Error: ENOENT: no such file or directory, open '/Users/<username>/.aws/credentials', but cdk fails with a generic error message.

thekevinbrown commented 4 years ago

I don't want to use aws-vault, I want to be able to give credentials to the CDK without writing to files or using third party tools.

Does anyone have a solution for this use case?

julienlepine commented 4 years ago

Found a possible workaround to get the actual creds from the CLI directly into CDK. (you still need a .aws/credentials file, but it can be empty (as referenced by @evanderkoogh). This leverages the profiles, MFA, or SSO from the CLI, and runs CDK with the target environment set.

aws creds exec cdk deploy

devarpi-zz commented 4 years ago

This is stopping us from cross account deployment. And it has become blocker now. And it's failing our cross account deployment in our pipeline.

RicoToothless commented 4 years ago

I face another issue. I try cdk 1.32.2 & 1.33.0 version and show error.

The security token included in the request is invalid

I try those command work fine.

aws sts get-caller-identity
aws s3 ls

the workaround is use environment export AWS_ACCESS_KEY_ID=somekey export AWS_SECRET_ACCESS_KEY=somesecret

I think is relate AWS Cloud9 IDE environment. Because I worked fine in local. But I was work fine on AWS Cloud9 IDE before. So I am not sure is cdk or AWS Cloud9 IDE problem.

AWS Cloud9 OS: Ubuntu Server 18.04 TLS

tijoer commented 4 years ago

Having the same problem. I am using

poweruser:~/environment/cdktest/packages/repository $ cdk deploy --profile tijoer-dev-poweruser
Need to perform AWS calls for account 22222222222, but no credentials have been configured.
poweruser:~/environment/cdktest/packages/repository $ cat ~/.aws/credentials
[tijoer-idp]
aws_access_key_id = asdasdasdasdasdasdasdasdasdasd
aws_secret_access_key = qweqweqweqweqweqweqeqweqe

poweruser:~/environment/cdktest/packages/repository $ cat ~/.aws/config
[profile tijoer-idp]
region = eu-central-1

[profile tijoer-dev-poweruser]
role_arn = arn:aws:iam::22222222222:role/poweruser
source_profile = tijoer-idp
mfa_serial = arn:aws:iam::888888888888:mfa/tim
region = eu-central-1
tijoer commented 4 years ago

I nearly forgot to tell: My settings works fine with Amplify.

thedancollins commented 4 years ago

CDK doesn't support CLI v2 SSO.

FWIW I got the AWS CDK to work against an AWS account that was configured to authenticate via SSO. I am not sure of the exact steps because I have been dancing with this for two days, but what appears to have worked might require that you do not try to use the --profile flag and let the commands run against "default". Then you need to clear out any Windows Environment Variables, set the .aws/credentials file with the AWS Key ID, Secret Key AND Session Key and then run "aws configure sso" as normal.