diff --git a/.env.tpl b/.env.tpl new file mode 100755 index 000000000..0be8702d4 --- /dev/null +++ b/.env.tpl @@ -0,0 +1,31 @@ +SKIP_PREFLIGHT_CHECK=true +LOCAL_LOGIN=true +attachmentsBucketName=op://mdct_devs/carts_secrets/attachmentsBucketName +fiscalYearTemplateBucketName=op://mdct_devs/carts_secrets/fiscalYearTemplateBucketName +loggingBucket=op://mdct_devs/carts_secrets/loggingBucket +acsTableName=local-acs +fmapTableName=local-fmap +uploadsTableName=local-uploads +stateTableName=local-state +stateStatusTableName=local-state-status +sectionBaseTableName=local-section-base +sectionTableName=local-section +stageEnrollmentCountsTableName=local-stg-enrollment-counts +DYNAMODB_URL=http://localhost:8000 +COGNITO_USER_POOL_ID=op://mdct_devs/carts_secrets/COGNITO_USER_POOL_ID +COGNITO_USER_POOL_CLIENT_ID=op://mdct_devs/carts_secrets/COGNITO_USER_POOL_CLIENT_ID +POST_SIGNOUT_REDIRECT=op://mdct_devs/carts_secrets/POST_SIGNOUT_REDIRECT +API_URL=http://localhost:3030/local +S3_LOCAL_ENDPOINT=http://localhost:4569 +S3_ATTACHMENTS_BUCKET_NAME=op://mdct_devs/carts_secrets/S3_ATTACHMENTS_BUCKET_NAME +URL=http://localhost/3000 +docraptorApiKey=op://mdct_devs/carts_secrets/docraptorApiKey #pragma: allowlist secret +iamPath=/ +iamPermissionsBoundary="bound" +SLS_INTERACTIVE_SETUP_ENABLE=1 + +#needed for e2e tests +CYPRESS_ADMIN_USER_EMAIL=op://mdct_devs/carts_secrets/msssqm4kzbmrwhihjtgwozcv5u +CYPRESS_ADMIN_USER_PASSWORD=op://mdct_devs/carts_secrets/CYPRESS_ADMIN_USER_PASSWORD #pragma: allowlist secret +CYPRESS_STATE_USER_EMAIL=op://mdct_devs/carts_secrets/sn6trfrct3cl5sac3pkh2zcjp4 +CYPRESS_STATE_USER_PASSWORD=op://mdct_devs/carts_secrets/CYPRESS_STATE_USER_PASSWORD #pragma: allowlist secret \ No newline at end of file diff --git a/.env_example b/.env_example deleted file mode 100644 index 97856a478..000000000 --- a/.env_example +++ /dev/null @@ -1,24 +0,0 @@ -SKIP_PREFLIGHT_CHECK=true -LOCAL_LOGIN=true -attachmentsBucketName=uploads-local.AttachmentsBucketName -fiscalYearTemplateBucketName=fiscalYearBucket -loggingBucket=log-bucket -acsTableName=local-acs -fmapTableName=local-fmap -uploadsTableName=local-uploads -stateTableName=local-state -stateStatusTableName=local-state-status -sectionBaseTableName=local-section-base -sectionTableName=local-section -stageEnrollmentCountsTableName=local-stg-enrollment-counts -DYNAMODB_URL=http://localhost:8000 -COGNITO_USER_POOL_ID=us-east-1_placeholder -COGNITO_USER_POOL_CLIENT_ID=placeholder -POST_SIGNOUT_REDIRECT=http://localhost:3000/ -API_URL=http://localhost:3030/local -S3_LOCAL_ENDPOINT=http://localhost:4569 -S3_ATTACHMENTS_BUCKET_NAME=local-uploads -URL=http://localhost/3000 -docraptorApiKey=YOUR_API_KEY_HERE #pragma: allowlist secret -iamPath=/ -iamPermissionsBoundary="bound" diff --git a/README.md b/README.md index d8ca50f8c..25de551ef 100644 --- a/README.md +++ b/README.md @@ -32,11 +32,9 @@ Before starting the project install some tools TODO: Fix the phone a friend instructions below 1. Clone the repo -2. In the root directory copy the .env_example file and name it .env -3. In the services/ui-src directory copy the .env_example file and name it .env -4. Overwrite the values here with an example from another developer -5. In the root directory run `pre-commit install` -6. Also in the root of the project run `./run local` +2. Ensure you either have a 1Password account and have 1Password CLI installed. Alternatively, reach out to the team for an example of .env files +3. In the root directory run `pre-commit install` +4. Also in the root of the project run `./run local --update-env` or if you do not have a 1Password account you can simply run `./run local` to use a static .env file ### Logging in @@ -193,7 +191,7 @@ This repository uses 3 webhooks to publish to 3 different channels all in CMS S ## GitHub Actions Secret Management - Secrets are added to GitHub secrets by GitHub Admins -- Upon editing and adding new secrets Admins should also update the encypted `/github/secret-list` SSM parameter in the CARTS AWS Production Account. +- Development secrets are maintained in a 1Password vault ## Architecture diff --git a/run b/run index c222ebbab..38d4722cd 100755 --- a/run +++ b/run @@ -43,11 +43,34 @@ if [ "yarn.lock" -nt ".yarn_install" ]; then touch .yarn_install fi -# if .env doesn't exist, copy .env_example there -if [ ! -f .env ]; then - cp .env_example .env +# Parse arguments +UPDATE_ENV=false +ARGS=() + +for arg in "$@"; do + case $arg in + --update-env) + UPDATE_ENV=true + ;; + *) + ARGS+=("$arg") + ;; + esac +done + +# Inject secrets to .env if the flag is set +if [ "$UPDATE_ENV" = true ]; then + # Check if 1Password CLI is installed + if ! which op > /dev/null; then + echo "The MDCT team uses 1Password to store and retrieve development credentials. If you do not have a 1Password account please request one." + exit 1 + fi + + # call 1password vault to retrieve secrets + op inject -i .env.tpl -o .env -f + op inject -i services/ui-src/.env.tpl -o services/ui-src/.env -f fi # build and run run.ts # tsc is configured to build what we expect in tsconfig.json -./node_modules/.bin/tsc && node ./build_dev/run.js "$@" \ No newline at end of file +./node_modules/.bin/tsc && node ./build_dev/run.js "${ARGS[@]}" \ No newline at end of file diff --git a/services/ui-src/.env.tpl b/services/ui-src/.env.tpl new file mode 100755 index 000000000..17f9915e9 --- /dev/null +++ b/services/ui-src/.env.tpl @@ -0,0 +1,18 @@ +LOCAL_LOGIN=true +API_REGION=op://mdct_devs/carts_secrets/AWS_DEFAULT_REGION +API_URL=http://localhost:3030/local +COGNITO_REGION=op://mdct_devs/carts_secrets/AWS_DEFAULT_REGION +COGNITO_IDENTITY_POOL_ID=op://mdct_devs/carts_secrets/COGNITO_IDENTITY_POOL_ID +COGNITO_USER_POOL_ID=op://mdct_devs/carts_secrets/COGNITO_USER_POOL_ID +COGNITO_USER_POOL_CLIENT_ID=op://mdct_devs/carts_secrets/COGNITO_USER_POOL_CLIENT_ID +COGNITO_USER_POOL_CLIENT_DOMAIN=op://mdct_devs/carts_secrets/COGNITO_USER_POOL_CLIENT_DOMAIN +COGNITO_REDIRECT_SIGNIN=http://localhost:3000/ +COGNITO_REDIRECT_SIGNOUT=http://localhost:3000/ +POST_SIGNOUT_REDIRECT=op://mdct_devs/carts_secrets/POST_SIGNOUT_REDIRECT +S3_ATTACHMENTS_BUCKET_REGION=op://mdct_devs/carts_secrets/AWS_DEFAULT_REGION +S3_ATTACHMENTS_BUCKET_NAME=op://mdct_devs/carts_secrets/S3_ATTACHMENTS_BUCKET_NAME +S3_LOCAL_ENDPOINT=http://localhost:4569 +BRANCH_NAME=placeholder +REACT_APP_LD_SDK_CLIENT=op://mdct_devs/carts_secrets/REACT_APP_LD_SDK_CLIENT # pragma: allowlist secret +LD_PROJECT_KEY=op://mdct_devs/carts_secrets/LD_PROJECT_KEY +STAGE=local diff --git a/services/ui-src/.env_example b/services/ui-src/.env_example deleted file mode 100644 index c642d7bed..000000000 --- a/services/ui-src/.env_example +++ /dev/null @@ -1,19 +0,0 @@ -LOCAL_LOGIN=true -API_REGION=us-east-1 -API_URL=placeholder -COGNITO_REGION=placeholder -COGNITO_IDENTITY_POOL_ID=placeholder -COGNITO_USER_POOL_ID=us-east-1_placeholder -COGNITO_USER_POOL_CLIENT_ID=placeholder -COGNITO_USER_POOL_CLIENT_DOMAIN=placeholder -COGNITO_REDIRECT_SIGNIN=placeholder -COGNITO_REDIRECT_SIGNOUT=placeholder -POST_SIGNOUT_REDIRECT=placeholder -S3_ATTACHMENTS_BUCKET_REGION=placeholder -S3_ATTACHMENTS_BUCKET_NAME=placeholder -S3_LOCAL_ENDPOINT=http://localhost:4569 -BRANCH_NAME=placeholder -API_POSTGRES_URL=placeholder -REACT_APP_LD_SDK_CLIENT=63581e76df884e59436475a2 # pragma: allowlist secret -LD_PROJECT_KEY=mdct-carts -STAGE=local \ No newline at end of file diff --git a/services/ui-src/env.sh b/services/ui-src/env.sh index 6954416a4..628538156 100755 --- a/services/ui-src/env.sh +++ b/services/ui-src/env.sh @@ -4,9 +4,9 @@ rm -rf ./public/env-config.js touch ./public/env-config.js -# if .env doesn't exist, copy .env_example there +# if .env doesn't exist, copy .env.tpl there if [ ! -f .env ]; then - cp .env_example .env + cp .env.tpl .env fi # Add assignment diff --git a/src/run.ts b/src/run.ts index 60509e3e7..17c972f7c 100644 --- a/src/run.ts +++ b/src/run.ts @@ -2,10 +2,26 @@ import yargs from "yargs"; import * as dotenv from "dotenv"; import LabeledProcessRunner from "./runner.js"; import { ServerlessStageDestroyer } from "@stratiformdigital/serverless-stage-destroyer"; +import { execSync } from "child_process"; // load .env dotenv.config(); +// Function to update .env files using 1Password CLI +function updateEnvFiles() { + try { + execSync("op inject -i .env.tpl -o .env -f", { stdio: "inherit" }); + execSync( + "op inject -i services/ui-src/.env.tpl -o services/ui-src/.env -f", + { stdio: "inherit" } + ); + } catch (error) { + // eslint-disable-next-line no-console + console.error("Failed to update .env files using 1Password CLI."); + process.exit(1); + } +} + // run_db_locally runs the local db async function run_db_locally(runner: LabeledProcessRunner) { await runner.run_command_and_output( @@ -136,5 +152,13 @@ yargs(process.argv.slice(2)) }, destroy_stage ) + .command( + "update-env", + "update environment variables using 1Password", + () => {}, + () => { + updateEnvFiles(); + } + ) .scriptName("run") .demandCommand(1, "").argv; // this prints out the help if you don't call a subcommand diff --git a/tests/cypress/README.md b/tests/cypress/README.md index 0d826df96..4e04afe3c 100644 --- a/tests/cypress/README.md +++ b/tests/cypress/README.md @@ -4,6 +4,8 @@ ## Getting Started +You will need an updated .env from either using 1Password or by contacting the team directly for a filled in .env file. + 1. The `scripts` section defines 2 jobs: - `yarn test` - runs two parallel processes: diff --git a/tests/cypress/cypress.config.js b/tests/cypress/cypress.config.js index 107a1f6fa..38cd69c4e 100644 --- a/tests/cypress/cypress.config.js +++ b/tests/cypress/cypress.config.js @@ -3,6 +3,7 @@ const preprocessor = require("@badeball/cypress-cucumber-preprocessor"); const browserify = require("@badeball/cypress-cucumber-preprocessor/browserify"); const { lighthouse } = require("@cypress-audit/lighthouse"); const { pa11y, prepareAudit } = require("@cypress-audit/pa11y"); +require("dotenv").config({ path: "../../.env" }); module.exports = defineConfig({ redirectionLimit: 20, @@ -14,8 +15,12 @@ module.exports = defineConfig({ downloadsFolder: "downloads", types: ["cypress", "cypress-axe"], env: { - STATE_USER_EMAIL: "stateuser2@test.com", - ADMIN_USER_EMAIL: "cypressadminuser@test.com", + STATE_USER_EMAIL: process.env.CYPRESS_STATE_USER_EMAIL, + // pragma: allowlist nextline secret + STATE_USER_PASSWORD: process.env.CYPRESS_STATE_USER_PASSWORD, + ADMIN_USER_EMAIL: process.env.CYPRESS_ADMIN_USER_EMAIL, + // pragma: allowlist nextline secret + ADMIN_USER_PASSWORD: process.env.CYPRESS_ADMIN_USER_PASSWORD, }, e2e: { baseUrl: "http://localhost:3000/", diff --git a/tests/cypress/package.json b/tests/cypress/package.json index 75c507c36..b79ff30f3 100644 --- a/tests/cypress/package.json +++ b/tests/cypress/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { + "cypress": "cypress open", "start": "cd ../../ && ./run local && cd -", "test:ci": "cypress install && cypress run --browser chrome --headless", - "cypress": "cypress open", "test": "concurrently --kill-others \"npm start\" \"npm run cypress\"" }, "author": "", @@ -19,7 +19,8 @@ "concurrently": "^7.6.0", "cypress": "^12.15.1", "cypress-axe": "^1.3.0", - "cypress-file-upload": "^5.0.8" + "cypress-file-upload": "^5.0.8", + "dotenv": "^16.4.5" }, "cypress-cucumber-preprocessor": { "nonGlobalStepDefinitions": true, diff --git a/tests/cypress/yarn.lock b/tests/cypress/yarn.lock index f26c6574d..cdc47b667 100644 --- a/tests/cypress/yarn.lock +++ b/tests/cypress/yarn.lock @@ -2648,6 +2648,11 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"