2
votes

I'm trying to get an AWS secret in my cypress test but I keep getting a CredentialsError

Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1

I do have a ~/.aws/credentials file with my aws_access_key_id and aws_secret_access_key set.

In my code I've exported all my env variables to a text file and I can see values for AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN.

I've also tried setting an env variable AWS_SDK_LOAD_CONFIG=1 but still get the same message.

Do I need the ~/.aws/credentials or can I do it all through env variables?

Can anyone see what I'm missing: (99% of the code is what Amazon provide on the secrets manager page I'm just trying to wrap the response up in a Cypress object. I've removed my AWS details and replaced them with REMOVED)

Cypress.Commands.add("aws_secret", () => {
  // Use this code snippet in your app.
  // If you need more information about configurations or implementing the sample code, visit the AWS docs:
  // https://aws.amazon.com/developers/getting-started/nodejs/

  cy.exec(`printenv >> envs.txt`);

  // Load the AWS SDK
  var AWS = require("aws-sdk"),
    region = “REMOVED”,
    secretName = “REMOVED”,
    secret,
    decodedBinarySecret;

  // Create a Secrets Manager client
  var client = new AWS.SecretsManager({
    region: region,
  });

  // In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
  // See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
  // We rethrow the exception by default.

  client.getSecretValue({ SecretId: secretName }, function (err, data) {
    if (err) {
      if (err.code === "DecryptionFailureException")
        // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw err;
      else if (err.code === "InternalServiceErrorException")
        // An error occurred on the server side.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw err;
      else if (err.code === "InvalidParameterException")
        // You provided an invalid value for a parameter.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw err;
      else if (err.code === "InvalidRequestException")
        // You provided a parameter value that is not valid for the current state of the resource.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw err;
      else if (err.code === "ResourceNotFoundException")
        // We can't find the resource that you asked for.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw err;
    } else {
      // Decrypts secret using the associated KMS CMK.
      // Depending on whether the secret is a string or binary, one of these fields will be populated.
      if ("SecretString" in data) {
        secret = data.SecretString;
        cy.log("the secret is " + secret);
      } else {
        let buff = new Buffer(data.SecretBinary, "base64");
        decodedBinarySecret = buff.toString("ascii");
        cy.log("the decodedBinarySecret is " + decodedBinarySecret);
      }
    }

    // Your code goes here.
    cy.wrap(
      client.getSecretValue({ SecretId: "REMOVED" }).promise()
    ).as("key1");
  });
});
2
Wrapping the promise does not look right. client.getSecretValue(...).promise().then(key => cy.wrap(key).as("key1") )?Hiram K. Hackenbacker
I just give it a try but I still get the same error Uncaught (in promise) CredentialsError: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1Doctor Who

2 Answers

0
votes

You don't need to set AWS_SDK_LOAD_CONFIG. env run through that process doesn't guarantee to have all the same environment variables set. How are you setting your environment variables when you run this script.

You can actually test this before loading the AWS SDK, add

console.log('AccessKey: ', process.env.AWS_ACCESS_KEY_ID);

And verify that they are being printed. To pass as environment variables in your node process, execute as: export AWS_ACCESS_KEY_ID=VALUE; node ./script.js

Docs on setting up Cypress environment variables

Prefix with CYPRESS to import:

export CYPRESS_AWS_ACCESS_KEY_ID=VALUE
0
votes

Cypress has a plugins entrypoint, which runs within Cypress server-side, namely with node, and lets you tap onto Cypress events and config. The spec files run within Cypress client-side, namely in the browser, hence no access to the filesystem in order to get these variables from ~/.aws/credentials, so even if you set the client-side with AWS_SDK_LOAD_CONFIG=1, the SDK won't be able to get it since it's running on the client-side. This means, you have to use the plugins entrypoint in order to attach any variables that are not already on process.env (AWS credentials do not appear to be there from my experience). Any variable you'll pass into config.env, should then be available with Cypress.env('my-variable').

// <project-root>/cypress/plugins/index.js

import dotenv from 'dotenv';

dotenv.config({ path: '~/.aws/credentials' });

module.exports = (on: any, config: any) => {
  config.env = { ...process.env };
});