alexa / ask-cli

Alexa Skills Kit Command Line Interface

Home Page:https://developer.amazon.com/en-US/docs/alexa/smapi/ask-cli-intro.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot Access Alexa-Hosted Skill Repository When AWS Profile Linked

jsetton opened this issue · comments

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request 
[ ] Other... Please describe: 

Expected Behavior

The ASK CLI should be able to access an Alexa-hosted repository when an AWS profile is linked to an ASK profile.

Current Behavior

When trying to create a new or clone an Alexa-hosted skill, the ASK CLI cannot access its repository, returning error to "Failed to fetch a LWA access token".

$ ask new

Please follow the wizard to start your Alexa skill project ->
? Choose the programming language you will use to code your skill:  NodeJS
? Choose a method to host your skill's backend resources:  Alexa-hosted skills
  Host your skill code by Alexa (free).
? Choose the default region for your skill:  us-east-1
? Please type in your skill name:  Hello World Skill
? Please type in your folder name for the skill project (alphanumeric):  HelloWorldSkill

Project directory for Hello World Skill created at
        <path>/HelloWorldSkill
  Cloning Alexa Hosted Skill...Username for 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/<repoId>': 
Password for 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/<repoId>': <path>/ask-cli/lib/clients/git-client.js:221
                throw new CLiError(`${ex}`);
                ^

CliError: Error: Command failed: git fetch --all --quiet
warning: invalid credential line: Failed to fetch a LWA access token.
fatal: Authentication failed for 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/<repoId>/'
error: Could not fetch origin

    at GitClient._execCommands (<path>/ask-cli/lib/clients/git-client.js:221:23)
    at GitClient.fetchAll (<path>/ask-cli/lib/clients/git-client.js:81:14)
    at _gitCloneWorkflow (<path>/ask-cli/lib/controllers/hosted-skill-controller/clone-flow.js:89:15)
    at Object.cloneProjectFromGit (<path>/ask-cli/lib/controllers/hosted-skill-controller/clone-flow.js:62:5)
    at <path>/ask-cli/lib/controllers/hosted-skill-controller/index.js:68:23
    at <path>/ask-cli/lib/controllers/hosted-skill-controller/index.js:104:13
    at <path>/ask-cli/lib/clients/smapi-client/index.js:169:21
    at _normalizeSmapiResponse (<path>/ask-cli/lib/clients/smapi-client/index.js:189:5)
    at <path>/ask-cli/lib/clients/smapi-client/index.js:168:17
    at Request._callback (<path>/ask-cli/lib/clients/http-client.js:64:16)

Steps to Reproduce (for bugs)

  1. Configure an ASK profile with a linked AWS profile
  2. Create a new Alexa-hosted skill and use all default values

Possible Solution

Looking closer at the code, this error is generated by the ~/.ask/scripts/git-credential-helper script which includes a regex to extract the relevant refresh token from ~/.ask/cli_config which doesn't seem to account for the aws_profile property and therefore fails to extract that information.

I would have submitted a PR to fix that regex but unfortunately that script seems to actually be downloaded by the ASK CLI, each time it is called, from this location and isn't part of this repository. So, the only workaround is to create a separate profile with no AWS linked profile.

ASK CLI config profile with linked AWS profile

{
  "profiles": {
    "default": {
      "aws_profile": "default",
      "token": {
        "access_token": "<accessToken>",
        "refresh_token": "<refreshToken>",
        "token_type": "bearer",
        "expires_in": 3600,
        "expires_at": "2021-07-22T20:45:03.639Z"
      },
      "vendor_id": "<vendorId>"
    }
  },
  "machine_id": "<machineId>",
  "share_usage": false
}

Proposed patch fix

--- ~/.ask/scripts/git-credential-helper    2021-07-22 17:37:45.386851195 -0400
+++ ~/.ask/scripts/git-credential-helper.new        2021-07-22 17:34:59.959849286 -0400
@@ -7,7 +7,7 @@
 skillId=$2
 configFile=~/.ask/cli_config
 if [ -f "${configFile}" ]; then
-    configOp="s/.*${profile}\":{\"token\":{\"[^{]*\",\"refresh_token\":\"\([^{]*\)\"/\1/p"
+    configOp="s/.*${profile}\":{[^{]*\"token\":{\"[^{]*\",\"refresh_token\":\"\([^{]*\)\"/\1/p"
     askRefreshToken=$(tr -d '\n' <  "${configFile}" | tr -d ' ' | sed -n "${configOp}" | sed 's/".*//')
 fi

Before:

$ ~/.ask/scripts/git-credential-helper default <skillId>
Failed to fetch a LWA access token.

After:

$ ~/.ask/scripts/git-credential-helper.new default <skillId>
username=<username>
password=<password>

Your Environment and Context

  • ask-cli version: 2.22.4

Struggling with the same issue - only "worse", as even the workaround doesn't seem to work for me (recreated my ask profile while not linking it to my AWS account - still no luck with even creating a new skill project:

λ ask new
Please follow the wizard to start your Alexa skill project ->
? Choose the programming language you will use to code your skill: NodeJS
? Choose a method to host your skill's backend resources: Alexa-hosted skills
Host your skill code by Alexa (free).
? Choose the default region for your skill: eu-west-1
? Please type in your skill name: Hello World
? Please type in your folder name for the skill project (alphanumeric): HelloWorld
[Error]: Error: getaddrinfo ENOTFOUND ask-tools-core-content.s3-us-west-2.amazonaws.com

C:_Frank\alexa\skills
λ ask --version
2.24.1

Seems that the whole set-up is making a number of assumptions that don't work with the choices given in the configuration process. Any suggestion on how to get even the most straight forward "hello world" to work as indicated in the documentation? Your help would be appreciated. Thanks.

commented

any chance you have an AntiVirus installed like AVG? We have tracked AVG as being the cause of this error in the past.

@doiron is this a question related to my original bug report or @fwornle's issue which I believe isn't related?

commented

correct @fwornle's issues seems different than this. the Error in question that we identified as an issue with a customer's AVG installation was

CliError: Error: Command failed: git fetch --all --quiet
warning: invalid credential line: Failed to fetch a LWA access token.
fatal: Authentication failed for 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/<repoId>/'
error: Could not fetch origin

I don't run AVG in my environment. What is the actual root cause for the use case you mentioned?

commented

so it was preventing the cli code to properly execute and run the git-credential-helper script within the same env context. This script is downloaded locally from S3 during the install, i.e. ~/.ask/scripts/git-credential-helper.

configured here:

const credentialScriptPath = path.join(os.homedir(),

this usually resolves to some configuration like ~/.ask/scripts/git-credential-helper default amzn1.ask.skill...<your skillId>

and executed here :

configureCredentialHelper(credentialScriptExecution, hostUrl) {

Understood. What part of the git-credential-helper script fails to execute in this instance?

I am trying to compare to the analysis I originally provided. The "Failed to fetch a LWA access token" error message is generated when it fails to get an access token from the LWA API.

In my case, it was a regex issue preventing the refresh token from being extracted.

#!/bin/bash
# ask tools git-credential-helper

source ~/.ask/auth_info

profile=$1
skillId=$2
configFile=~/.ask/cli_config
if [ -f "${configFile}" ]; then
    configOp="s/.*${profile}\":{\"token\":{\"[^{]*\",\"refresh_token\":\"\([^{]*\)\"/\1/p"
    askRefreshToken=$(tr -d '\n' <  "${configFile}" | tr -d ' ' | sed -n "${configOp}" | sed 's/".*//')
fi

refreshToken="${ASK_REFRESH_TOKEN:-$askRefreshToken}"
lwaAPI="${ASK_LWA_TOKEN_HOST:-$ask_lwa_api}"
smapiAPI="${ASK_SMAPI_SERVER_BASE_URL:-$ask_smapi_api}"
clientID="${ASK_LWA_CLIENT_ID:-$ask_client_id}"
clientSecret="${ASK_LWA_CLIENT_CONFIRMATION:-$ask_client_confirmation}"

token=$(curl -f -s -d grant_type=refresh_token -d client_id="${clientID}" -d client_secret="${clientSecret}" -d refresh_token="${refreshToken}" \
 "${lwaAPI}"/auth/O2/token)
accessToken=$(tr -d '\n'  <<< "${token}" | tr -d ' ' | sed 's/.*"access_token":"\([^{]*\)","refresh_token".*/\1/') 
if [[ -z "${accessToken}" ]]; then
    echo "Failed to fetch a LWA access token."
    exit 1
fi
[...]
commented

it was reported that token was null when attempting to run the script manually line by line. So potentially something here with the curl command to LWA.

token=$(curl -f -s -d grant_type=refresh_token -d client_id="${clientID}" -d client_secret="${clientSecret}" -d refresh_token="${refreshToken}" \
 "${lwaAPI}"/auth/O2/token)

But once the AVG was uninstalled everything worked as expected. Note: disabling the antivirus did not fix the issue, there were some instance where it worked somehow?? but still getting that error fairly consistently.

commented

oh interesting that the regex was not fetching the right info. hmmm it seems the order of which the cli_config file properties matter in this case.

I can test with the original regex with a slight modification to your cli_config example.

{
  "profiles": {
    "default": {
          <<<--- moved aws_profile from here this made token the first item under default profile. 
      "token": {
        "access_token": "<accessToken>",
        "refresh_token": "<refreshToken>",
        "token_type": "bearer",
        "expires_in": 3600,
        "expires_at": "2021-07-22T20:45:03.639Z"
      },
      "vendor_id": "<vendorId>",
      "aws_profile": "default"      <<<--- moved to here 
    }
  },
  "machine_id": "<machineId>",
  "share_usage": false
}

The regex changes you made would make this less error prone to someone manually editing the file.

So potentially something here with the curl command to LWA.

It is highly likely the curl command is getting blocked by the AVG malware protection agent. Disabling it should be sufficient though. This forum post seems to indicate it did.

it seems the order of which the cli_config file properties matter in this case.

Exactly. My proposed solution is to remove that unnecessary restriction.

The regex changes you made would make this less error prone to someone manually editing the file.

To be clear, the error I highlighted isn't due to manually editing the file. The aws_profile property would be at the top if you create a new ASK profile with a linked AWS profile.

commented

So potentially something here with the curl command to LWA.

It is highly likely the curl command is getting blocked by the AVG malware protection agent. Disabling it should be sufficient though. This forum post seems to indicate it did.

This appears to be the same person we were working with to solve the issue. It had for a few requests but then the error started coming up again and the only thing that really solved the issue was to uninstall it. :(

The regex changes you made would make this less error prone to someone manually editing the file.

To be clear, the error I highlighted isn't due to manually editing the file. The aws_profile property would be at the top if you create a new ASK profile with a linked AWS profile.

Interesting that the ask-cli wrote that profile like that. I use AWS profiles all the time and they always show up at the bottom. Eitherway, I think your solution fixes this and we should not need to worry about the order of the json blob... will work on uploading an update to the script.

So I just realized that my proposed regex is too greedy when multiple profiles are configured.

I have updated the regex to now be: .*${profile}\":{[^{]*\"token\":{\"[^{]*\",\"refresh_token\":\"\([^{]*\)\".

commented

script changes are now live. thanks for reporting and all the help identifying this and providing working solutions.

I noticed the refresh_token was also relying on a comma before it, so also removed that and ended up with

configOp="s/.*\"${profile}\":{[^{]*\"token\":{[^{]*\"refresh_token\":\"\([^{]*\)\"/\1/p"

should allow for token and refresh_token to be anywhere within the object.

Feel free to re-open if you this doesn't resolve your issue.

In case this helps anyone else, I am using Avast anti-virus on Windows 11. I tried a # of other things until I found this post, and when I temporarily disabled my AVG shields and retried the CLI operations, all worked as expected.

It'd be nice to know if there was some configuration I could add/set in AVG that would allow-list the CLI and its operations so I didn't have to disable it.