Skip to content

Commit

Permalink
Setup proxy configuration (#1440)
Browse files Browse the repository at this point in the history
* Setup proxy configuration
* Update documentation for proxy changes
  • Loading branch information
danivovich authored Oct 9, 2024
1 parent 0d4ef47 commit 7393d6d
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 33 deletions.
50 changes: 21 additions & 29 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,35 @@ jobs:
- run: cp config/test.circleci.exs config/test.local.exs
- restore_cache:
keys:
- v4-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
- v4-yarn-cache-{{ .Branch }}
- v4-yarn-cache
- v5-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
- v5-yarn-cache-{{ .Branch }}
- v5-yarn-cache
- restore_cache:
keys:
- v4-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
- v4-mix-cache-{{ .Branch }}
- v4-mix-cache
- v5-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
- v5-mix-cache-{{ .Branch }}
- restore_cache:
keys:
- v4-build-cache-{{ .Branch }}
- v4-build-cache
- v5-build-cache-{{ .Branch }}
- run: mix do deps.get, compile
- run: cd assets && yarn && cd ..
- save_cache:
key: v4-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
key: v5-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
paths: "assets/node_modules"
- save_cache:
key: v4-yarn-cache-{{ .Branch }}
key: v5-yarn-cache-{{ .Branch }}
paths: "assets/node_modules"
- save_cache:
key: v4-yarn-cache-{{ .Branch }}
key: v5-yarn-cache-{{ .Branch }}
paths: "assets/node_modules"
- save_cache:
key: v4-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
key: v5-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
paths: "deps"
- save_cache:
key: v4-mix-cache-{{ .Branch }}
key: v5-mix-cache-{{ .Branch }}
paths: "deps"
- save_cache:
key: v4-mix-cache
paths: "deps"
- save_cache:
key: v4-build-cache-{{ .Branch }}
paths: "_build"
- save_cache:
key: v4-build-cache
key: v5-build-cache-{{ .Branch }}
paths: "_build"

lint:
Expand All @@ -69,11 +61,11 @@ jobs:
- run: mix local.rebar --force
- run: cp config/test.circleci.exs config/test.local.exs
- restore_cache:
key: v4-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
key: v5-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
- restore_cache:
key: v4-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
key: v5-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
- restore_cache:
key: v4-build-cache-{{ .Branch }}
key: v5-build-cache-{{ .Branch }}
- run: mix deps.get
- run: mix compile --force
- run: mix deps.audit --ignore-package-names sweet_xml
Expand Down Expand Up @@ -106,11 +98,11 @@ jobs:
- run: mix clean
- run: cp config/test.circleci.exs config/test.local.exs
- restore_cache:
key: v4-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
key: v5-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
- restore_cache:
key: v4-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
key: v5-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
- restore_cache:
key: v4-build-cache-{{ .Branch }}
key: v5-build-cache-{{ .Branch }}
- run:
name: Wait for DB
command: dockerize -wait tcp://localhost:5432 -timeout 1m
Expand All @@ -135,11 +127,11 @@ jobs:
- run: mix local.rebar --force
- run: cp config/test.circleci.exs config/test.local.exs
- restore_cache:
key: v4-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
key: v5-yarn-cache-{{ .Branch }}-{{ checksum "assets/yarn.lock" }}
- restore_cache:
key: v4-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
key: v5-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
- restore_cache:
key: v4-build-cache-{{ .Branch }}
key: v5-build-cache-{{ .Branch }}
- run: mix deps.get
- run: cd assets && yarn run build && cd ..
- run: mix phx.digest
Expand Down
5 changes: 3 additions & 2 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ config :challenge_gov, ChallengeGov.GovDelivery,
config :challenge_gov, ChallengeGov.Mailer,
from: System.get_env("MAILER_FROM_ADDRESS"),
adapter: Bamboo.SMTPAdapter,
server: "smtp-relay.gmail.com",
server: System.get_env("SMTP_SERVER"),
hostname: System.get_env("HOST"),
port: 25,
port: String.to_integer(System.get_env("SMTP_PORT") || "25"),
tls_verify: :verify_none,
tls: :never,
ssl: false,
retries: 1
Expand Down
4 changes: 4 additions & 0 deletions docs/cloud_gov.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ Learn more generally about [cloud.gov](https://cloud.gov/), and specifically und
The app will run database migrations and seeds when booting. Background tasks are processed with Quantum and do not require any additional running processes
## Proxy
This app expects the configuration of an egress proxy. The configuration is managed locally with a sidecar as well as through the deployment of an egress proxy application configured in the platform codebase https://github.com/GSA/Challenge_platform
## SSH
Disable SSH for any sensitive environment when not in use. This can be done through the cloud.gov web interface.
Expand Down
6 changes: 5 additions & 1 deletion docs/configuration_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
| AWS_ACCESS_KEY_ID | Access key for S3, provided as a Cloud.gov Service | |
| AWS_SECRET_ACCESS_KEY | Secret Access key for S3, provided as a Cloud.gov Service | |
| BUCKET_NAME | Bucket Name for S3, provided as a Cloud.gov Service | |
| CHALLENGE_OWNER_ASSUMED_TLDS | By default, only .gov email addresses are assumed to want the Challenge Manager role, this allows other government TLD values to also be considered as wanting the Challenge Manager role | .mil |
| CHALLENGE_OWNER_ASSUMED_TLDS | By default, only .gov email addresses are assumed to want the Challenge Manager role, this allows other government TLD values to also be considered as wanting the Challenge Manager role | .mil |
| DATABASE_URL | The standard formatted postgres URL composed from the components of username, password, hostname, and database name, as provided by the Cloud.gov RDS service | postgres://username:password@hostname:port/database |
| GOV_DELIVERY_ACCOUNT_CODE | The GovDelivery account code | |
| GOV_DELIVERY_API_PASSWORD | The password of the API account with admin permission for the API | |
Expand All @@ -22,6 +22,7 @@
| GOV_DELIVERY_TOPIC_SUBSCRIBE_URL | The URL that the topic code gets added to for each challenge to be subscribed to | |
| GOV_DELIVERY_URL | The base API url for the GovDelivery API | |
| HOST | The external DNS name of the running portal | portal.challenge.gov |
| LOCAL_PROXY_HOST | The local sidecar proxy that will relay to the egress proxy | 127.0.0.1 |
| LOGIN_CLIENT_ID | The login client ID for the application in Login.gov | urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:challenge_gov |
| LOGIN_PRIVATE_KEY_PASSWORD | The password to decrypt the private key used in the Login.gov OpenID connect flow | password |
| LOGIN_PUBLIC_KEY_PATH | The path within the code repository to the provide key for the application to use with Login.gov | environment_key.pem |
Expand All @@ -30,7 +31,10 @@
| LOG_RETENTION_IN_DAYS | Number of days of security audit logs to keep in the database | 90 |
| MAILER_FROM_ADDRESS | The from/reply-to address for transactional email sent by the system | support@challenge.gov |
| MIX_ENV | The environment mode for the running application, should always be prod | prod |
| PROXYROUTE | The fully qualified URL for the upstream egress proxy with protocol, authentication, domain, and port. Used by the caddy sidecar | |
| RECAPTCHA_SECRET_KEY | Google reCaptcha 3 secret key | |
| RECAPTCHA_SITE_KEY | Google reCaptcha 3 public site key | |
| SECRET_KEY_BASE | Random seed used to encrypt secrets (cookies) for session management between the application and the browser | |
| SESSION_TIMEOUT_IN_MINUTES | Amount of idle time before the system logs a user out | 15 |
| SMTP_SERVER | The DNS or IP address of the SMTP server to connect to. May be a TCP relay proxy | |
| SMTP_PORT | The port of the SMTP server to connect to. May be a TCP relay proxy | |
19 changes: 18 additions & 1 deletion lib/challenge_gov/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule ChallengeGov.Application do
# Start the PubSub system
{Phoenix.PubSub, name: ChallengeGov.PubSub},
ChallengeGov.Repo,
{Finch, name: ChallengeGov.HTTPClient},
finch_config(System.get_env("LOCAL_PROXY_HOST")),
Web.Endpoint,
ChallengeGov.Scheduler,
ChallengeGov.Telemetry,
Expand All @@ -34,4 +34,21 @@ defmodule ChallengeGov.Application do
defp oban_config do
Application.get_env(:challenge_gov, Oban)
end

defp finch_config(nil), do: {Finch, name: ChallengeGov.HTTPClient}
defp finch_config(""), do: {Finch, name: ChallengeGov.HTTPClient}

defp finch_config(proxy_host) do
{Finch,
name: ChallengeGov.HTTPClient,
pools: %{
:default => [
size: 5,
conn_opts: [
protocols: [:http1],
proxy: {:http, proxy_host, 8080, []}
]
]
}}
end
end
5 changes: 5 additions & 0 deletions manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ applications:
<<: *defaults
instances: 1
disk_quota: 6GB
sidecars:
- name: local-proxy
process_types: [ 'web' ]
command: ./proxy/sidecar_start.sh
memory: 64M
env:
MIX_ENV: prod
STACK: heroku-22
Expand Down
48 changes: 48 additions & 0 deletions proxy/.profile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/sh

# Despite the temptation to use #!/bin/bash, we want to keep this file as as
# POSIX sh-compatible as possible. This is to facilitate testing the .profile
# under Alpine, which doesn't have /bin/bash, but does have ash (which is itself
# a flavor of busybox).
ENABLE_ASH_BASH_COMPAT=1

set -e

# Ensure there's only one entry per line, and leave no whitespace
PROXY_DENY=$( echo -n "$PROXY_DENY" | sed 's/^\S/ &/' | sed 's/\ /\n/g' | sed '/^\s*$/d' )
PROXY_ALLOW=$( echo -n "$PROXY_ALLOW" | sed 's/^\S/ &/' | sed 's/\ /\n/g' | sed '/^\s*$/d' )

# Append to the appropriate files
echo -n "$PROXY_DENY" > deny.acl
echo -n "$PROXY_ALLOW" > allow.acl

# Newline Terminate Non-Empty File If Not Already aka ntnefina
# https://stackoverflow.com/a/10082466/17138235
#
# It's unclear if this works properly under Alpine because it uses ANSI-C
# quoting; that needs more testiing. However, if caddy complains about a blank
# in the file, you know why!
ntnefina() {
if [ -s "$1" ] && [ "$(tail -c1 "$1"; echo x)" != $'\nx' ]; then
echo "" >> "$1"
fi
}

ntnefina deny.acl
ntnefina allow.acl

# Make it easy to run curl tests on ourselves
https_proxy="https://$PROXY_USERNAME:$PROXY_PASSWORD@$(echo "$VCAP_APPLICATION" | jq .application_uris[0] | sed 's/"//g'):61443"
export https_proxy

# Make open ports configurable via the PROXY_PORTS environment variable.
# For example "80 443 22 61443". Default to 443 only.
if [ -z "${PROXY_PORTS}" ]; then
PROXY_PORTS="443"
fi
export PROXY_PORTS

echo
echo
echo "The proxy connection URL is:"
echo " $https_proxy"
25 changes: 25 additions & 0 deletions proxy/Caddyfile.local.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
debug
log {
format console
level INFO
}
auto_https off
}

:8888 {
route {
forward_proxy {
acl {
allow all
}
ports 80 443 61443
upstream $PROXYROUTE
}
}
log {
format json
level INFO
output stdout
}
}
Binary file added proxy/caddy
Binary file not shown.
Binary file added proxy/envsubst
Binary file not shown.
5 changes: 5 additions & 0 deletions proxy/sidecar_start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
echo "Updating Caddy config"
./proxy/envsubst < ./proxy/Caddyfile.local.tmpl > ./proxy/Caddyfile.local

echo "Starting Caddy"
exec ./proxy/caddy run --config ./proxy/Caddyfile.local

0 comments on commit 7393d6d

Please sign in to comment.