Skip to content

Commit

Permalink
Make environment file completely optional for development
Browse files Browse the repository at this point in the history
Also, move the documentation for the environment file to a
separate page.
  • Loading branch information
lpsinger committed Aug 24, 2023
1 parent 704738b commit 4c6bba1
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 59 deletions.
21 changes: 21 additions & 0 deletions __tests__/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,26 @@ describe('getOrigin', () => {
})
})

describe('getSessionSecret', () => {
const key = 'SESSION_SECRET'

beforeAll(() => {
setEnv('ARC_SANDBOX', JSON.stringify({ ports: { http: 1234 } }))
})

test('gets sandbox value when SESSION_SECRET is not defined', () => {
setEnv(key, undefined)
const { sessionSecret } = importEnv()
expect(sessionSecret).toBe('fallback-secret-for-dev')
})

test('gets env.SESSION_SECRET when SESSION_SECRET is defined', () => {
setEnv(key, 'xyzzy')
const { sessionSecret } = importEnv()
expect(sessionSecret).toBe('xyzzy')
})
})

describe('getHostname', () => {
test('returns localhost when ORIGIN is not defined', () => {
setEnv('ORIGIN', undefined)
Expand All @@ -134,6 +154,7 @@ describe('getEnvOrDieInProduction', () => {
// ORIGIN must be defined
beforeEach(() => {
setEnv('ORIGIN', 'http://example.gov')
setEnv('SESSION_SECRET', 'foobar')
})

test('returns undefined if the variable does not exist', () => {
Expand Down
5 changes: 5 additions & 0 deletions app/lib/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,14 @@ function getFeatures() {
)
}

function getSessionSecret() {
return getEnvOrDieInProduction('SESSION_SECRET') || 'fallback-secret-for-dev'
}

export const origin = /* @__PURE__ */ getOrigin()
export const hostname = /* @__PURE__ */ getHostname()
export const features = /* @__PURE__ */ getFeatures()
export const sessionSecret = /* @__PURE__ */ getSessionSecret()

/**
* Return true if the given feature flag is enabled.
Expand Down
6 changes: 3 additions & 3 deletions app/routes/_auth/auth.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { createArcTableSessionStorage } from '@remix-run/architect'
import memoizee from 'memoizee'
import { Issuer } from 'openid-client'

import { getEnvOrDie } from '~/lib/env.server'
import { getEnvOrDie, sessionSecret } from '~/lib/env.server'

// Short-lived session for storing the OIDC state and PKCE code verifier
export const oidcStorage = createArcTableSessionStorage({
Expand All @@ -19,7 +19,7 @@ export const oidcStorage = createArcTableSessionStorage({
// but that doesn't work on localhost for Safari
// https://web.dev/when-to-use-local-https/
secure: process.env.NODE_ENV === 'production',
secrets: [getEnvOrDie('SESSION_SECRET')],
secrets: [sessionSecret],
path: '/',
maxAge: 300,
httpOnly: true,
Expand All @@ -38,7 +38,7 @@ export const storage = createArcTableSessionStorage({
// but that doesn't work on localhost for Safari
// https://web.dev/when-to-use-local-https/
secure: process.env.NODE_ENV === 'production',
secrets: [getEnvOrDie('SESSION_SECRET')],
secrets: [sessionSecret],
path: '/',
maxAge: 3600,
httpOnly: true,
Expand Down
53 changes: 0 additions & 53 deletions app/routes/docs.contributing._index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,59 +72,6 @@ Here are instructions for getting the GCN site set up and running on your own co
npm install
```

</ProcessListItem>
<ProcessListItem>
<ProcessListHeading type="h3">
Write configuration file
</ProcessListHeading>

Create a file called `.env` in the root directory of the repository with the following contents to define the configuration of your local development GCN server:

```sh
# (Required) Signing key for session cookies.
# Fill in with a long, random string.
SESSION_SECRET=fill-me-in

# (Optional) OpenID Connect identity provider configuration for Cognito.
# If omitted, then we will use a built-in sandbox identity provider.
# COGNITO_USER_POOL_ID=fill-me-in
# OIDC_CLIENT_ID=fill-me-in
# OIDC_CLIENT_SECRET=fill-me-in

# (Optional) Google ReCAPTCHA configuration.
# For parts of the site that require authentication,
# these lines must be uncommented and filled in.
# RECAPTCHA_SITE_KEY=fill-me-in
# RECAPTCHA_SECRET_KEY=fill-me-in

# (Optional) Github Integrations
# For parts of the site that pull data using Github's content API (i.e. schema-browser)
# See https://github.com/settings/tokens to generate an API token
# Generate a Classic token with the expiration set to be as long as possible and
# no scopes set.
# GITHUB_API_TOKEN=fill-me-in

# (Optional) URL origin to be used for external redirects, email From
# addresses, and so on. Leave this unset for local development so that it
# defaults to http://localhost:3333.
# ORIGIN=https://gcn.nasa.gov

# (Optional) Zendesk configuration.
# * ZENDESK_TOKEN, ZENDESK_TOKEN_EMAIL:
# API token and user email address for the Zendesk API.
# * ZENDESK_EMAIL: forward emails from Amazon SES to Zendesk.
# See https://support.zendesk.com/hc/en-us/articles/4408886828698.
# [email protected]
# ZENDESK_TOKEN=fill-me-in
# [email protected]

# (Optional) Feature flags turn on parts of the web site that are under
# development. On the production web site (https://gcn.nasa.gov), all
# feature flags are disabled by default. Turn feature flags for local
# development by adding them to this comma-separated list.
# GCN_FEATURES=ANTIGRAVITY,TIME_TRAVEL,PYROKINESIS
```

</ProcessListItem>
<ProcessListItem>
<ProcessListHeading type="h3">
Expand Down
37 changes: 37 additions & 0 deletions app/routes/docs.contributing.configuration/components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*!
* Copyright © 2023 United States Government as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/

export function Key({
children,
...props
}: Omit<JSX.IntrinsicElements['th'], 'scope'>) {
return (
<th scope="row" data-label="Key" {...props}>
{children}
</th>
)
}

export function Description({
children,
...props
}: JSX.IntrinsicElements['td']) {
return (
<td data-label="Description" {...props}>
{children}
</td>
)
}

export function Default({ children, ...props }: JSX.IntrinsicElements['td']) {
return (
<td data-label="Default" {...props}>
{children}
</td>
)
}
114 changes: 114 additions & 0 deletions app/routes/docs.contributing.configuration/route.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
handle:
breadcrumb: Configuration
---

import { Table } from '@trussworks/react-uswds'

import { Default, Description, Key } from './components'

# Configuration

For both [local development](.) and [deployment](deployment), the configuration of the GCN web application is controlled by the environment variables. You can adjust the environment variables in any one of three ways:

- [**`.env` file:**](https://arc.codes/docs/en/reference/configuration/local-preferences#.env-file-support) Create a file called `.env` in the base directory of your project formatted like this:

```text
FOO=value_of_foo_for_local_testing
BAR=value_of_bar_for_local_testing
```

- [**`preferences.arc` file:**](https://arc.codes/docs/en/reference/configuration/local-preferences#%40env) Create a file called `.preferences.arc` in the base directory of your project formatted like this:

```text
@env
testing
FOO=value_of_foo_for_local_testing
BAR=value_of_bar_for_local_testing
production
FOO=value_of_foo_for_deployment
BAR=value_of_bar_for_deployment
```

- [**`arc env` command:**](https://arc.codes/docs/en/reference/cli/env) Adjust settings for production by running the following commands.

```text
arc env -e production --add FOO value_of_foo_for_deployment
arc env -e production --add BAR value_of_bar_for_deployment
```

## Supported environment variables

_All_ environment variables are _optional in local development_. _All_ environment variables with the exception of `GCN_FEATURES` are _required in production deployment_.

<Table bordered compact stackedStyle="headers">
<thead>
<tr>
<th scope="col">Key</th>
<th scope="col">Description</th>
<th scope="col">Default</th>
</tr>
</thead>
<tbody>
<tr>
<Key>`SESSION_SECRET`</Key>
<Description>
Signing key for session cookies. Should be a long, random string
</Description>
<Default>Hard-coded constant</Default>
</tr>
<tr>
<Key>`COGNITO_USER_POOL_ID`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`</Key>
<Description>
OpenID Connect identity provider configuration for [AWS
Cognito](https://aws.amazon.com/cognito/)
</Description>
<Default>Sandbox identity provider</Default>
</tr>
<tr>
<Key>`RECAPTCHA_SITE_KEY`, `RECAPTCHA_SECRET_KEY`</Key>
<Description>
[Google ReCAPTCHA](https://www.google.com/recaptcha/) configuration
</Description>
<Default>ReCAPTCHAs replaced with placeholder</Default>
</tr>
<tr>
<Key>`GITHUB_API_TOKEN`</Key>
<Description>
GitHub API token for the schema browser. In [GitHub
settings](https://github.com/settings/tokens), generate a Classic token
with the expiration as long as possible and no scopes selected
</Description>
<Default>Anonymous GitHub API requests with lower rate limits</Default>
</tr>
<tr>
<Key>`ORIGIN`</Key>
<Description>
URL origin for external redirects, email From addresses, etc.
</Description>
<Default>http://localhost:3333</Default>
</tr>
<tr>
<Key>`ZENDESK_EMAIL`</Key>
<Description>
Email address for [Zendesk
forwarding](https://support.zendesk.com/hc/en-us/articles/4408886828698)
</Description>
<Default>Forwarding disabled</Default>
</tr>
<tr>
<Key>`ZENDESK_TOKEN`, `ZENDESK_TOKEN_EMAIL`</Key>
<Description>Zendesk API token and user email address</Description>
<Default>Zendesk API disabled</Default>
</tr>
<tr>
<Key>`GCN_FEATURES`</Key>
<Description>
[Feature flags](feature-flags) (for example,
`ANTIGRAVITY,TIME_TRAVEL,PYROKINESIS`)
</Description>
<Default>No features</Default>
</tr>
</tbody>
</Table>
2 changes: 1 addition & 1 deletion app/routes/docs.contributing.feature-flags.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The GCN project uses [feature flags](https://www.atlassian.com/continuous-delive

On the production web site (https://gcn.nasa.gov), all feature flags are disabled by default.

Turn feature flags on in your local development environment by adding them to the `GCN_FEATURES` environment variable in your `.env` file (see [quick start instructions for local development](/docs/contributing#quick-start)). The format of this environment variable is a comma-separated list.
Turn feature flags on in your local development environment by adding them to the `GCN_FEATURES` [environment variable in your `.env` file](configuration). The format of this environment variable is a comma-separated list.

For example, if you set `GCN_FEATURES=ANTIGRAVITY,TIME_TRAVEL,PYROKINESIS`, then the features `ANTIGRAVITY`, `TIME_TRAVEL`, and `PYROKINESIS` are enabled.

Expand Down
6 changes: 6 additions & 0 deletions app/routes/docs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ export default function () {
<NavLink key="index" to="contributing" end>
Getting Started
</NavLink>,
<NavLink
key="configuration"
to="contributing/configuration"
>
Configuration
</NavLink>,
<NavLink
key="feature-flags"
to="contributing/feature-flags"
Expand Down
4 changes: 2 additions & 2 deletions app/routes/unsubscribe.$jwt/jwt.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { SignJWT, jwtVerify } from 'jose'
import invariant from 'tiny-invariant'

import { maxTokenAge } from './jwt.lib'
import { getEnvOrDie, origin as issuer } from '~/lib/env.server'
import { origin as issuer, sessionSecret } from '~/lib/env.server'

const key = new TextEncoder().encode(getEnvOrDie('SESSION_SECRET'))
const key = new TextEncoder().encode(sessionSecret)

type UnsubscribeOptions = {
email: string
Expand Down

0 comments on commit 4c6bba1

Please sign in to comment.