serverless: Profile [profilename] does not exist. Using Cross account roles. credentials_source=EcsContainer

This is a Bug Report

Description

Hi, I am trying to use --aws-profile feature to deploy lambda functions using crossaccount role specified in aws/credentials file.

  • What went wrong? sls deploy --aws-profile [profilename]

    Error --------------------------------------------------

    Profile [profilename] does not exist

  • What did you expect should have happened? Project should be deployed to corresponding account.

  • What was the config you used? My credentials file looks like this:

[playground]
role_arn=somecrossaccountrolearn
credential_source=EcsContainer

[dev]
role_arn=somecrossaccountrolearn
credential_source=EcsContainer

[test]
role_arn=somecrossaccountrolearn
credential_source=EcsContainer

[qa]
role_arn=somecrossaccountrolearn
credential_source=EcsContainer]

  • What stacktrace or error message from your provider did you see?

  Error --------------------------------------------------

  Profile playground does not exist

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Stack Trace --------------------------------------------

Error: Profile [profilename] does not exist
    at Object.addProfileCredentials (/usr/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:86:15)
    at AwsProvider.getCredentials (/usr/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:310:12)
    at AwsProvider.request (/usr/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:197:30)
    at createDeployment.then (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/createStack.js:39:61)
From previous event:
    at AwsDeploy.create (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/createStack.js:39:36)
From previous event:
    at AwsDeploy.BbPromise.bind.then.catch (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/createStack.js:88:14)
From previous event:
    at AwsDeploy.createStack (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/createStack.js:81:13)
From previous event:
    at Object.aws:deploy:deploy:createStack [as hook] (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:102:10)
    at BbPromise.reduce (/usr/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55)
From previous event:
    at PluginManager.invoke (/usr/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22)
    at PluginManager.spawn (/usr/lib/node_modules/serverless/lib/classes/PluginManager.js:408:17)
    at AwsDeploy.BbPromise.bind.then (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:95:48)
From previous event:
    at Object.deploy:deploy [as hook] (/usr/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:91:10)
    at BbPromise.reduce (/usr/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55)
From previous event:
    at PluginManager.invoke (/usr/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22)
    at PluginManager.run (/usr/lib/node_modules/serverless/lib/classes/PluginManager.js:421:17)
    at variables.populateService.then.then (/usr/lib/node_modules/serverless/lib/Serverless.js:157:33)
    at runCallback (timers.js:789:20)
    at tryOnImmediate (timers.js:751:5)
    at processImmediate [as _immediateCallback] (timers.js:722:5)
From previous event:
    at Serverless.run (/usr/lib/node_modules/serverless/lib/Serverless.js:144:8)
    at serverless.init.then (/usr/lib/node_modules/serverless/bin/serverless:43:50)
    at <anonymous>

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information -----------------------------
     OS:                     
     Node Version:           8.9.3
     Serverless Version:     

Additional Data

  • Serverless Framework Version you’re using: 1.32.0
  • Operating System: linux
  • Stack Trace:
  • Provider Error messages:

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 4
  • Comments: 38 (7 by maintainers)

Most upvoted comments

Any update with this?

@micsafi I’m not sure what the previous issue one user was having but AWS_SDK_LOAD_CONFIG=1 as an env var worked for me using a cross-account IAM role

@ghinks does it work if you set the aws-sdk’s AWS_SDK_LOAD_CONFIG env var option?

While using ~/.aws/credentials file make sure aws_secret_key and aws_secret_access_key are written in lowercase.

not a real solution but a workaround for now. In my case, I ended up running a bash script that fetches temp credentials and sets them as environment variables. Prerequisite for running the script: jq installed

#!/bin/bash

CREDS=$(aws sts assume-role --role-arn $1 --role-session-name $2)
RETURN_VAL=$?

if [ "$RETURN_VAL" -eq "0" ]; then

   KEYID=`      echo $CREDS | jq -r '.Credentials.AccessKeyId'`
   SECRETKEY=`  echo $CREDS | jq -r '.Credentials.SecretAccessKey'`
   TOKEN=`      echo $CREDS | jq -r '.Credentials.SessionToken'`

   export AWS_ACCESS_KEY_ID=$KEYID
   export AWS_SECRET_ACCESS_KEY=$SECRETKEY
   export AWS_SESSION_TOKEN=$TOKEN
else
  echo "Failed to set credentials"
fi

As far as my research goes, serverless or aws js-sdk does not support my use case.

I’m adding my 2 cents worth that when I use a simple export of the aws secret and key it does work but if I specify a profile

provider:
  name: aws
  runtime: nodejs8.10
  profile: lamba

when these are specified in the ~/.aws/config and credentials the named profile is not found when using serverless.

This was showing up for me because I was running serverless deploy within a script that I was running as sudo. In that case, it couldn’t find my profile because my account had the ~/.aws/credentials profile, but the root user didn’t. Not saying this shouldn’t have been obvious, just wanted to post my feedback in case anyone else is banging their head on the same wall as me.

Closing since this is something which needs to be fixed in the AWS SDK codebase Serverless depends on…

I did some digging & debugging and the issue is due to the AWS Javascript SDK, which serverless uses behind the scenes to get the credentials. At the moment the implementation for the shared ini file (i.e. ~/.aws/credentials) only supports a source_profile, not a credential_source.

See from shared_ini_file_credentials.js in function loadRoleProfile:

  loadRoleProfile: function loadRoleProfile(creds, roleProfile, callback) {
    ...
    var self = this;
    var roleArn = roleProfile['role_arn'];
    var roleSessionName = roleProfile['role_session_name'];
    var externalId = roleProfile['external_id'];
    var mfaSerial = roleProfile['mfa_serial'];
    var sourceProfileName = roleProfile['source_profile'];

    if (!sourceProfileName) {
      throw AWS.util.error(
        new Error('source_profile is not set using profile ' + this.profile),
        { code: 'SharedIniFileCredentialsProviderFailure' }
      );
    }
   ...

Maybe one can try to do a workaround in the serverless code, but I think this is best addressed in the SDK itself. It is currently an open feature request there https://github.com/aws/aws-sdk-js/issues/1916.

I’m quite interested in trying to debug the issue. I’ll look at the serverless code to see when/and/or what the order of precedence is as it happily picks up the exported key and secret but does not see the profile. Hints to where to look first accepted 😃

Ok, I’ve found a solution to this at least on Windows.

If you’re sure that you have the AWS folder in ~/.aws make sure that your HOME and USERPROFILE environment variables point to the same location.

In our case, HOME was pointing to C:\ and USERPROFILE to C:\Users\<username>.

After making them point to the same location and that location is where the .aws folder is, we could deploy using the --aws-profile flag correctly.

I had the same problems as many others with this issue and burnt a lot of time on it.

Locally, I was able to get it to work OK, and couldn’t figure out why it didn’t work on jenkins build agents after a lot of trial and error.

The problem is that the aws-sdk v2 does not support using credential_source=Ec2InstanceMetadata along with source_profile and role_arn. There seems to have been support added to version 3, but this is not used by serverless yet, so that upgrade is not an option.

You can have a source profile which is referenced by a child profile, as long as the source profile sets aws credentials directly. You can’t however assume a second role by using the IAM role attached to the EC2 instance or container.

You can also generate temporary credentials using the AWS CLI, and set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY directly in the environment. This solution would work so long as you are not using profile names directly in the serverless config.

For us, we are using --aws-profile and profile names in the serverless config, so the best solution I could find was to create a user that was able to assume the roles needed, and then set that up as the source_profile. This isn’t exactly what I wanted (which was no shared credentials on build agents) but was a good enough interim step.

~/.aws/credentials

[assume-role-user]
aws_access_key_id = xxxxxx
aws_secret_access_key = xxxx

~/.aws/config

[profile serverless-deployments-dev]
role_arn = arn:aws:iam::ACCOUNT_ID:role/my-serverless-deployments-role
source_profile =  assume-role-user
role_session_name =  serverless-deploy
region = eu-west-2

...

To test it works in the CLI:

aws sts assume-role --profile serverless-deployments-dev

Then with serverless:

AWS_SDK_LOAD_CONFIG=1  sls deploy --aws-profile=serverless-deployments-dev

You can then have any number of profiles in the config file assume various roles in different accounts, but just one source profile and one shared key. The source profile will need something like this too, along with an appropriate policy for the role being assumed:

{
    "Version" : "2012-10-17",
    "Statement" : [
      {
        "Effect" : "Allow",
        "Action" : [
          "sts:AssumeRole",
          "sts:TagSession"
        ]
        "Resource" : [
          "arn:aws:iam::ACCOUNT_ID:role/my-serverless-deployments-role",
        ]
      }
    ]
  }

Ran across a similar problem, I haven’t implemented many of the fixes here, but we had success using the AWS CLI to STS assume role and immediately assume it in a temporary bash_env. (Headsup, this was designed for a CI/CD flow and wouldn’t be a great fit for local development)

            aws sts assume-role \
            --role-arn << parameters.role-arn >> \
            --role-session-name << parameters.role-session-name >> \
            --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
            --output text | \
            awk '{print "export AWS_ACCESS_KEY_ID=\""$1"\"","\nexport AWS_SECRET_ACCESS_KEY=\""$2"\"","\nexport AWS_SESSION_TOKEN=\""$3"\""}' \
            >> $BASH_ENV && source $BASH_ENV

Having those 3 environment variables populated as the role you’d like to assume immediately before running performs subsequent actions as the assumed role.

For me, I have my “~/.aws/credentials” like this: (notice the “[default]” name)

[default]
aws_access_key_id = XXX
aws_secret_access_key = XXX

I ran the deploy command like this serverless deploy --aws-profile default (“default” is the profile name). Hope it helps!

I had this same issue and was able to solve it without the need to set the AWS_SDK_LOAD_CONFIG environment variable. My issue was that my credentials file was setting the access key ID for aws in all capital letters, i.e. AWS_ACCESS_KEY_ID=<access key>, however my understanding is that the aws-sdk loads the keys from your credentials file as all lower case. (reference: https://github.com/aws/aws-sdk-js/blob/c2ad3ef8fd486bb58edc225f74152dda51f9f2fe/lib/credentials/shared_ini_file_credentials.js#L138)

Before making all the variables lowercase, this.accessKeyId was evaluating as undefined, thus triggering the Profile [profilename] does not exist error inside of awsProvider.js. After the change, this.accessKeyId evaluated to the correct value and my profile was recognized with no further problems.

TL;DR: change all of your credential variables from all uppercase to all lowercase i.e. AWS_ACCESS_KEY_ID=<key> -> aws_access_key_id=<key>

This may or may not be the recommended fix, I personally don’t see a problem with it. I just wanted to share what worked for me!

Is this issue really solved? I am trying to accomplish the same cross-account scenario as the original author (@pawel-miszkurka-cko ), with using AWS profiles with only role_arn and credential_source configured. I am getting the same Profile ‘xxx’ does not exist error.

In my scenario I am running sls commands from Jenkins CI/CD pipeline which is hosted in a EC2 instance. Using access keys in such cross-account scenario would be really step backwards, since AWS provides the assume role functionality specifically for this kind of use cases.

I’m adding my 2 cents worth that when I use a simple export of the aws secret and key it does work but if I specify a profile

provider:
  name: aws
  runtime: nodejs8.10
  profile: lamba

when these are specified in the ~/.aws/config and credentials the named profile is not found when using serverless.

@ghinks thank you so much! missing to disable this simple setting took me hours without any success. this finally solved the issue!

Thanks for checking @ghinks, #5432 might give you some ideas of where to start looking. It’s the PR that clued me into that env var seems related since it’s loading a profile from config.