#Amplify Gen 2 - secret() function access in SSR NextJS or other method?

1 messages · Page 1 of 1 (latest)

maiden mesa
#

I'm looking for an explanation of the Amplify Gen 2 secret function.

As far as i can make out from the documentation:
https://docs.amplify.aws/react/deploy-and-host/fullstack-branching/secrets-and-vars/

Secrets can be set in the Amplify Web console per branch or shared for all branches
Secrets that are being used in a sandbox environment need to be set via npx ampx sandbox terminal command.

Once secrets are set they can be accessed via the function:

secret("NAME OF SECRET");

but only in the backend files in the amplify folder.
Specifically the resource.ts files like this:

export const processOrderHandler = defineFunction({
  // optionally specify a name for the Function (defaults to directory name)
  name: "process-order-handler",
  // optionally specify a path to your handler (defaults to "./handler.ts")
  entry: "./handler.ts",
  // add environment variables
  environment: {
    STRIPE_SECRET_KEY: secret("STRIPE_SECRET_KEY"), // Secrets must be set for each branch via Amplify web console and via Terminal for Sandbox environments.
    TEST_SECRET: secret("TEST_SECRET")
  },
});

Then the secrets can be accessed via the

import { env } from "$amplify/env/process-order-handler";

env.STRIPE_SECRET_KEY;
env.TEST_SECRET;

My question is how can i use a similar approach to the above to access a secret in NextJS SSR functions.

I have server code in locations like:
/app/api/route.js

and some server side functions in standard pages:
/app/contact/page.js

I can't access the secret() function in any NextJS code without running errors. And even if i manage to get it working without errors, I can only get back a BackendSecret type when calling this function.

I want to maintain the same approach to all secrets handling and store them all via SSM if possible.

NextJS docs suggest the .env file with NEXT_PUBLIC_ for public variables and all others are treated as server only and secure.
But this isn't safe using git tracking.

dreamy horizon
#

Hi @maiden mesa , short answer, you can't.
But you can read the secrets and set them on the .env file, so during the build time, nextjs will load these env vars.

#

I did this using this approach

#

eg: (amplify.yml file)

commands:
        - export LAMBDA_FUNCTION_NAME=$(aws ssm get-parameter --name "/amplify/shared/${AWS_APP_ID}/LAMBDA_FUNCTION_NAME" --with-decryption --query "Parameter.Value" --output text)
        - echo "LAMBDA_FUNCTION_NAME=${LAMBDA_FUNCTION_NAME}" >> .env
maiden mesa
#

Hi @dreamy horizon , thank you.
I have gone down some rabbit holes since posting, to find an answer and I'm sad to find out you are right. You can't access secrets automatically.
I wanted to have access to the secrets in process.env so I can develop locally in NextJS 14 SSR, server functions and API calls with secrets the .env.local then keep the code on deployment. Using NextJS recommended approach to secrets and variables, "NEXT_PUBLIC" or secret.

Expanding on your suggestion above I have developed this code to retrieve all secrets and shared secrets from the Amplify Secrets console to be made available to the process.env during build.
This is my amplify.yml file with new commands to install jq during preBuild and use aws ssm get-parameters-by-path at build time.

#
frontend:
  phases:
    preBuild:
      commands:
        #install jq, must be done as sudo or permissions error thrown
        - sudo yum -y install jq
    build:
      commands:
        #START SHARED SECRETS
        - sharedPath="/amplify/shared/${AWS_APP_ID}/"
        - sharedSecrets=$(aws ssm get-parameters-by-path --path $sharedPath --query "Parameters[*].{key:Name,value:Value}" --with-decryption --recursive)
        - echo ${sharedSecrets} | jq --arg sharedPath "${sharedPath}" -r 'map("\(.key|ltrimstr($sharedPath))=\(.value)")|.[]' >> .env
        #END SHARED SECRETS
        #START SECRETS
        - secretsPath="/amplify/${AWS_APP_ID}/"
        #call aws ssm get-parameters-by-path and decrypt the returned secrets
          #this will get all branches secrets main, dev, etc.
        #query the results to a key value pair { key:Name, value:Value }
        #recursive to get all secrets in the same path
        #send it's output to a string variable $()
        - branchSecrets=$(aws ssm get-parameters-by-path  --path $secretsPath --query "Parameters[*].{key:Name,value:Value}" --with-decryption --recursive)
        #use jq to parse the results
        #pass secretsPath argument in to jq
        #pass branch argument in to jq
        #raw input of string
        #map each item to key="value"
        #select only those secrets that are of the right branch with contains(/branchname-branch-)
        #sub regex the key name to find and replace with "" the path given branchname-branch-######## isn't known
        #.[] to output each mapped item as a seperate result
        #echo (expressions) >> .env to write each line to the .env file
        - echo ${branchSecrets} | jq --arg secretsPath "${secretsPath}" --arg branch "${AWS_BRANCH}" -r 'map(select(.key|contains("/" + $branch + "-branch-"))|"\(.key|sub($secretsPath + $branch + "-branch-\\w+/";""))=\(.value)")|.[]' >> .env
        #END SECRETS
        - npm run build
#

This saves the hassle of defining secrets in three places .env.loacal, Amplify Secrets console, and amplify.yml.
If the secret is defined in the Amplify Secrets console as shared or for your branch. It will be available to your code at build for SSR functions to use.

dreamy horizon
#

That's very good. I thought about using JQ to make it more dynamic, but I only had 1 secrect I wanted to share with nextjs 🙂
Thanks for sharing it.

humble river
#

Bumping this. The concept of a secret is good and I like how Amplify Gen2 is handling it -- but sometimes the SSR needs a secret as it is handling a request and it's really frustrating that it isn't available cleanly.

sterile drift
#

Is this still the best solution to date? Currently experiencing the same issue. I have a contact form that uses resend api key. I am having trouble accessing the key as it’s not in process.env. I am only using aws amplify to host my site