amplify-cli icon indicating copy to clipboard operation
amplify-cli copied to clipboard

[Feature Request] Amplify CLI support AWS SSO

Open v1pz3n opened this issue 5 years ago • 59 comments

Describe the bug

$ amplify env pull
⠦ Fetching updates to backend environment: dev from the cloud.(node:10308) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 169.254.169.254:80
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:10308) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:10308) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
⠋ Fetching updates to backend environment: dev from the cloud.

Amplify CLI Version 4.21.1

To Reproduce

  1. aws sso login --profile dev
  2. amplify pull or amplify env pull

Expected behavior Update my local development environment

Desktop

  • OS: Linux Mint 19.3
  • Node Version. v14.3.0

v1pz3n avatar Jun 07 '20 17:06 v1pz3n

I have a problem adding a new env with the Amplify CLI that uses a SSO profile. Getting

init failed
Error: connect ETIMEDOUT 169.254.169.254:80
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) {
  message: 'Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1',
  errno: 'ETIMEDOUT',
  code: 'CredentialsError',
  syscall: 'connect',
  address: '169.254.169.254',
  port: 80,
  time: 2020-06-08T05:08:14.592Z,
  originalError: {
    message: 'Could not load credentials from any providers',
    errno: 'ETIMEDOUT',
    code: 'CredentialsError',
    syscall: 'connect',
    address: '169.254.169.254',
    port: 80,
    time: 2020-06-08T05:08:14.592Z,
    originalError: {
      message: 'EC2 Metadata roleName request returned error',
      errno: 'ETIMEDOUT',
      code: 'ETIMEDOUT',
      syscall: 'connect',
      address: '169.254.169.254',
      port: 80,
      time: 2020-06-08T05:08:14.592Z,
      originalError: [Object]
    }
  }
}

ahansson89 avatar Jun 08 '20 05:06 ahansson89

I tried another way but I also had problems.

You must delete the "amplify" directory of your project

$ aws sso login --profile amplify

Attempting to automatically open the SSO authorization page in your default browser. If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.us-east-1.amazonaws.com/

Then enter the code:

XXXX-XXXX Successully logged into Start URL: https://amplify.awsapps.com/start

$ amplify pull

For more information on AWS Profiles, see: https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html

? Do you want to use an AWS profile? Yes ? Please choose the profile you want to use amplify

Error: connect EHOSTUNREACH 169.254.169.254:80
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) {
  message: 'Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1',
  errno: -113,
  code: 'CredentialsError',
  syscall: 'connect',
  address: '169.254.169.254',
  port: 80,
  time: 2020-06-13T22:09:10.614Z,
  originalError: {
    message: 'Could not load credentials from any providers',
    errno: -113,
    code: 'CredentialsError',
    syscall: 'connect',
    address: '169.254.169.254',
    port: 80,
    time: 2020-06-13T22:09:10.614Z,
    originalError: {
      message: 'EC2 Metadata roleName request returned error',
      errno: -113,
      code: 'EHOSTUNREACH',
      syscall: 'connect',
      address: '169.254.169.254',
      port: 80,
      time: 2020-06-13T22:09:10.614Z,
      originalError: [Object]
    }
  }
}

v1pz3n avatar Jun 13 '20 22:06 v1pz3n

Hi folks,

we also face a similar problem with slightly different error messages. I've tried to describe it here also for the 'amplify init' command:

Issue when AWS Profile unable to run amplify init

vgoetz avatar Jul 21 '20 15:07 vgoetz

You may be able to use aws-sso-credential-process with AWS_SDK_LOAD_CONFIG=1 set to enable AWS SSO credentials to be used.

If that doesn't work, there is a workaround, developed for the CDK (which has the same problem): https://github.com/aws/aws-cdk/issues/5455#issuecomment-713643500

benkehoe avatar Oct 21 '20 17:10 benkehoe

The aws2-wrap method referenced by @benkehoe is working absolutely fine for CDK. However, the amplify issue isn't getting resolved by it. Is there some other way that anyone has been able to get the amplify to work with sso credentials since the time this issue was first created?

nishitjain13 avatar Dec 09 '20 08:12 nishitjain13

Hey, folks, let me know if this helps, since I was facing a very similar problem and (I think) I "fixed" it: Setup

  • Multiple AWS Accounts in AWS Organization with AWS Single Sign-On enabled for those accounts;
  • Amplify with Angular (10) SPA - using basically (import) auth and (add) hosting; Issue: multiple profiles not working or amplify ends up publishing in the wrong (default) account.
$> amplify publish -c
× There was an error pulling the backend environment dev.
An error occurred during the push operation: The provided token has expired.

Fixing:

  1. Run $> aws configure sso (for each AWS Account/profile) ==> this will update (only) the ~/.aws/config (Linux & Mac) or %USERPROFILE%.aws\config (Windows) file;
  2. Copy the information from the SSO User Portal URL (repeat this step when the token expires) - command line or programmatic access (Option 2: Add a profile to your AWS credentials file) ==> user portal is something like 'https://xyz.awsapps.com/start#/'
  3. Edit the ~/.aws/credentials (Linux & Mac) or %USERPROFILE%.aws/credentials (Windows) and paste the information from #2. Save;
  4. Run the command again: success.

MFranca avatar Dec 30 '20 20:12 MFranca

@nishitjain13 Did you try the credential_process method using aws-sso-util instead of aws2-wrap? I have updated the documentation for it here.

Additionally, aws-export-credentials supports AWS SSO and allows you to inject environment variables with your credentials.

benkehoe avatar Dec 30 '20 21:12 benkehoe

In case like this one or other similar cases where AWS SSO result in incompatibilities with your library and you don't want to play with workarounds or complicated fixes, maybe you can also give a try to our open-source project: https://github.com/Noovolari/leapp. It deals with AWS SSO authentication and accounts/roles retrieval then it creates short-lived temporary credentials in .aws/credentials to maximize compatibility with third party tools / sdks.

urz9999 avatar Jan 14 '21 11:01 urz9999

Did you try the credential_process method using aws-sso-util instead of aws2-wrap? I have updated the documentation for it here.

@benkehoe Thank you. I solved the problem in my environment (aws-amplify/cli 4.41.2). I needed AWS_SDK_LOAD_CONFIG=1

pantone170145 avatar Jan 27 '21 06:01 pantone170145

I followed the above instructions with AWS_SDK_LOAD_CONFIG=1 using credential_process method with aws-sso-util. However it appears that the AWS CLI completely ignores the credential process as per this issue here: https://github.com/aws-amplify/amplify-cli/issues/6882

mrserverless avatar Oct 17 '21 10:10 mrserverless

Ok I figured out the issue. For this credential_process to work, all of the following conditions must be met:

  • Set AWS_SDK_LOAD_CONFIG=1
  • Set AWS_Profile={your profile}
  • Run amplify init and select the same {your profile} when prompted

mrserverless avatar Oct 17 '21 10:10 mrserverless

Also an (empty) ~/.aws/credentials file needed. https://github.com/aws-amplify/amplify-cli/issues/6882#issuecomment-950348362

tjmcewan avatar Oct 24 '21 15:10 tjmcewan

Bug is still relevant today (amplify version 9.2.1). When trying to run amplify init, using AWS profile as the authentication method and choosing the profile set up by AWS SSO, I get the error:

Failed to get profile: Cannot read property 'accessKeyId' of undefined

This is frustrating as using AWS SSO is considered best-practice instead of creating individual long-lived IAM users with permanent credentials.

Neither touch ~/.aws/credentials nor AWS_SDK_LOAD_CONFIG=1 amplify init solve the issue.

ari-becker avatar Aug 19 '22 06:08 ari-becker

I'm seeing the same issue as @ari-becker.

$ amplify version
10.0.0
$ AWS_SDK_LOAD_CONFIG=1
$ AWS_PROFILE=mapp01
$ amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project s3uploaderui
The following configuration will be applied:

Project information
| Name: s3uploaderui
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use mapp01
Failed to get profile: Cannot read property 'accessKeyId' of undefined

Is there a best practice on how to use amplify with SSO?

thomasliddledba avatar Sep 09 '22 09:09 thomasliddledba

I'm a little confused now. The AWS JavaScript SDK v2 added support for AWS SSO in v2.1093.0 and from what I can tell Amplify CLI requires v2.1113.0, so it seems like AWS SSO support should be present in the latest version of Amplify CLI.

benkehoe avatar Sep 09 '22 17:09 benkehoe

Running cli v10.3.0 I receive the same as the users above:

Failed to get profile: Cannot read property 'accessKeyId' of undefined

Is there an expected fix date for this?

karl-barbour avatar Oct 19 '22 13:10 karl-barbour

I've been stuck on this issue for 2 hours...how can something like this be broken and not fixed yet.

ameer2468 avatar Nov 26 '22 13:11 ameer2468

This is indeed broken as of now .

? Please choose the profile you want to use SB102
Failed to get profile: Cannot read property 'accessKeyId' of undefined

devops-amplify-app git:main ❯ amplify --version                                                                                                                                                                                                                                                                         ⏎
10.5.1

This was supposed to be a basic requirement as AWS already provides this SSO creds long back .

defyjoy avatar Nov 29 '22 05:11 defyjoy

Adding a role_arn to the profile configuration should solve the undefined 'accessKeyId' problem. Here is what I did in order to get it working on my computer:

I configured a profile in ~/.aws/config like this:

[profile myprofile]
region=<REGION>
role_arn=arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>
sso_start_url=https://<SUBDOMAIN>.awsapps.com/start
sso_region=<REGION>
sso_account_id=<ACCOUNT_ID>
sso_role_name=<ROLE_NAME>

I created the following script to login and export the credentials to the environment variables:

#!/bin/sh

profile_name="$1"

aws sso login --profile "${profile_name}"

credentials=$(aws-sso-util credential-process --profile "${profile_name}")

export AWS_ACCESS_KEY_ID="$(echo "${credentials}" | jq -r '.AccessKeyId')"
export AWS_SECRET_ACCESS_KEY="$(echo "${credentials}" | jq -r '.SecretAccessKey')"
export AWS_SESSION_TOKEN="$(echo "${credentials}" | jq -r '.SessionToken')"

This script must be sourced in order to keep the AWS envs (Make absolutely sure you're sourcing the script and not regularly executing it!). For example:

. ./configure-credentials-env.sh myprofile

First I executed the script. Then, after the login was successful, I executed amplify init. It then allowed me to choose "AWS profile" and within it "myprofile".

When your credentials run out, just source the script again to get new ones. The amplify cli (under these configurations) should recognize them.

Also, if you want to make sure the AWS profile configuration was done correctly, look inside the created amplify/.config/local-aws-info.json file. It should look something like this:

{
  "dev": {
    "configLevel": "project",
    "useProfile": true,
    "profileName": "myprofile"
  }
}

Hope this helps.

eligavril avatar Dec 03 '22 22:12 eligavril

I've found @benkehoe 's excellent aws-sso-util has solved this for me, on amplify v10.5.1.

  1. Install aws-sso-util

  2. Set up a profile (which goes in .aws/config) called 'myprofile' (substitute your own values) :

    aws-sso-util configure profile --sso-start-url 'https://myapp.awsapps.com/start#/' --account-id 987654321 --sso-region ap-southeast-2 --role-name AWSPowerUserAccess --region ap-southeast-2 myprofile
    

    Now whenever you need to login, you can just run: aws-sso-util login --all

    I have set up an alias in my .zshrc for this: alias awslogin="aws-sso-util login --all"

    and another one to launch the AWS web console: alias awsconsolebp="aws-sso-util console launch --account-id 987654321 --role-name AWSPowerUserAccess"

The resulting profile in ~/.aws/config looks like this; note the credential_process property :

[profile myprofile]
sso_start_url = https://myapp.awsapps.com/start#/
sso_region = ap-southeast-2
sso_account_id = 987654321
sso_role_name = AWSPowerUserAccess
region = ap-southeast-2
credential_process = aws-sso-util credential-process --profile myprofile

I think the credential_process is the special sauce which makes this work for us.

cunneen avatar Jan 12 '23 08:01 cunneen

A workaround I just got working was to make another profile with the credential_process set to call the sso login command, i.e.

[profile admin]
sso_start_url = https://xxxxxxxx.awsapps.com/start#/
sso_region = us-east-1
sso_account_id = xxxxxxxxxx
sso_role_name = AWSAdministratorAccess
region = us-east-1
output = json

[profile admin-amplify]
credential_process = aws sso login --profile admin

Note: you'll need to replace the values for the profile names, sso_start_url, sso_account_id for this to work for your situation

Then when using the amplify CLI set the profile to the amplify one, in this case: admin-amplify

seanWLawrence avatar Feb 23 '23 01:02 seanWLawrence

17:25:20 ~/ feature/lambda $ amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project xyz
The following configuration will be applied:

Project information
| Name: xyz
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use sso-session sami-sso
Failed to get profile: Cannot read property 'accessKeyId' of undefined

When is this issue expected to get resolves, I am using SSO-Login and SSO-profile?

sami-bt avatar Feb 27 '23 12:02 sami-bt

@cunneen made a great comment. but I used this npm package instead https://www.npmjs.com/package/aws-sso-cli just replace aws-sso-util with aws-sso-cli and it will work like a charm.

sami-bt avatar Feb 27 '23 15:02 sami-bt

still having issues after setup.

config file:

[profile account-sso-dev]
sso_start_url = https://*********.awsapps.com/start
sso_region = ca-central-1  
sso_account_id = ************
sso_role_name = ******Dev
region = ca-central-1
output = json

credentials file:

[account-sso-dev]
aws_access_key_id=*****************
aws_secret_access_key=***********************
aws_session_token=***********************

I've used aws sso login --profile <profile name> and re-logged in only to receive error:

✖ There was an error pulling the backend environment dev. 🛑 The provided token is malformed or otherwise invalid.

I've also used aws-vault exec <profile name> and same thing.

adcanis avatar Feb 28 '23 01:02 adcanis

@adcanis it looks like you're missing a line from your config file:

credential_process = aws sso login --profile account-sso-dev

cunneen avatar Feb 28 '23 01:02 cunneen

@cuneen thats fantastic! worked like a charm.

adcanis avatar Feb 28 '23 01:02 adcanis

@adcanis it looks like you're missing a line from your config file:

credential_process = aws sso login --profile account-sso-dev

This is the oddest solution, to me, considering credential_process is supposed to require that the process outputs to stdout a json blob in a very specific format. And aws sso login definitely does not do that. Some weirdness must be happening under the covers, an implementation detail that works for the moment, and not an actual solution to the problem...

lorengordon avatar Feb 28 '23 19:02 lorengordon

This is my workaround. My amplify-cli is v11.1.1. Almost all the same as https://github.com/aws-amplify/amplify-cli/issues/4488#issuecomment-1379987317 , but this way just depends on only aws-cli, jq, and POSIX shell commands.

example

~/.aws/config

# SSO session config, See: https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-token.html#sso-configure-profile-token-manual
[sso-session my-sso]
sso_start_url = ...
sso_region = ...
sso_registration_scopes = sso:account:access

# SSO profile for amplify-cli, See: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sourcing-external.html
# Please replace {{AWS_ACCOUNT_ID}} and {{SSO_ROLE_NAME}} to your own
[profile my-amplify]
credential_process = aws sso get-role-credentials --account-id {{AWS_ACCOUNT_ID}} --role-name {{SSO_ROLE_NAME}} --access-token $(ls -t ~/.aws/sso/cache/*.json | xargs -I{} jq -r '.accessToken' {} | grep -v 'null' | head -n 1) --output json --query 'roleCredentials.{Version:`1`,AccessKeyId:accessKeyId,SecretAccessKey:secretAccessKey,SessionToken:sessionToken,Expiration:expiration}'

usage:

$ aws sso login --sso-session my-sso

$ amplify init
...
? Select the authentication method you want to use: AWS profile
...
? Please choose the profile you want to use my-amplify
...

zagvym avatar May 02 '23 11:05 zagvym

How about adding a step to use aws-sdk-js#SsoCredentials in amplify-cli#getProfiledAwsConfig() ?

For example, aws-cdk that is a CLI tool depending on aws-sdk-js like amplify-cli, also use it like https://github.com/aws/aws-cdk/blob/v2.77.0/packages/aws-cdk/lib/api/aws-auth/awscli-compatible.ts#L81 .

zagvym avatar May 02 '23 11:05 zagvym

Thanks @benkehoe, the aws-sso-util has saved my life here.

noumanriazkhan avatar May 29 '23 15:05 noumanriazkhan