Skip to content

Commit 9d6d8a4

Browse files
authored
Prepare for integration with infra template (#40)
1 parent 4474a89 commit 9d6d8a4

File tree

11 files changed

+85
-36
lines changed

11 files changed

+85
-36
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ If you have previously installed this template and would like to update your pro
6161
1. Run the [update script](./template-only-bin/update-template) in your project's root directory and pass in the branch, commit hash, or release that you want to update to, followed by the name of your application directory (e.g. `app-rails`).
6262
6363
```bash
64-
curl https://raw.githubusercontent.com/navapbc/template-application-rails/main/template-only-bin/download-and-install-template | bash -s -- <commit_hash> <app_name>
64+
curl https://raw.githubusercontent.com/navapbc/template-application-rails/main/template-only-bin/update-template | bash -s -- <commit_hash> <app_name>
6565
```
6666
6767
This script will:

app-rails/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ db-up: ## Run just the database container
144144
db-migrate: ## Run database migrations
145145
$(RAILS_RUN_CMD) db:migrate
146146

147+
db-rollback: ## Rollback a database migration
148+
$(RAILS_RUN_CMD) db:rollback
149+
147150
db-test-prepare: ## Prepare the test database
148151
$(RAILS_RUN_CMD) db:test:prepare
149152

app-rails/app/adapters/auth/cognito_adapter.rb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def initialize(client: Aws::CognitoIdentityProvider::Client.new)
1414
def create_account(email, password)
1515
begin
1616
response = @client.sign_up(
17-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
17+
client_id: ENV["COGNITO_CLIENT_ID"],
1818
secret_hash: get_secret_hash(email),
1919
username: email,
2020
password: password,
@@ -47,7 +47,7 @@ def create_account(email, password)
4747
def forgot_password(email)
4848
begin
4949
response = @client.forgot_password(
50-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
50+
client_id: ENV["COGNITO_CLIENT_ID"],
5151
secret_hash: get_secret_hash(email),
5252
username: email
5353
)
@@ -64,7 +64,7 @@ def forgot_password(email)
6464
def confirm_forgot_password(email, code, password)
6565
begin
6666
@client.confirm_forgot_password(
67-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
67+
client_id: ENV["COGNITO_CLIENT_ID"],
6868
secret_hash: get_secret_hash(email),
6969
username: email,
7070
confirmation_code: code,
@@ -84,7 +84,7 @@ def confirm_forgot_password(email, code, password)
8484
def change_email(uid, new_email)
8585
begin
8686
response = @client.admin_update_user_attributes(
87-
user_pool_id: ENV["AWS_COGNITO_USER_POOL_ID"],
87+
user_pool_id: ENV["COGNITO_USER_POOL_ID"],
8888
username: uid,
8989
user_attributes: [
9090
{
@@ -114,8 +114,8 @@ def change_email(uid, new_email)
114114
def initiate_auth(email, password)
115115
begin
116116
response = @client.admin_initiate_auth(
117-
user_pool_id: ENV["AWS_COGNITO_USER_POOL_ID"],
118-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
117+
user_pool_id: ENV["COGNITO_USER_POOL_ID"],
118+
client_id: ENV["COGNITO_CLIENT_ID"],
119119
auth_flow: "ADMIN_USER_PASSWORD_AUTH",
120120
auth_parameters: {
121121
"USERNAME" => email,
@@ -151,7 +151,7 @@ def initiate_auth(email, password)
151151
def resend_verification_code(email)
152152
begin
153153
@client.resend_confirmation_code(
154-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
154+
client_id: ENV["COGNITO_CLIENT_ID"],
155155
secret_hash: get_secret_hash(email),
156156
username: email
157157
)
@@ -163,8 +163,8 @@ def resend_verification_code(email)
163163
def respond_to_auth_challenge(code, challenge = {})
164164
begin
165165
response = @client.admin_respond_to_auth_challenge(
166-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
167-
user_pool_id: ENV["AWS_COGNITO_USER_POOL_ID"],
166+
client_id: ENV["COGNITO_CLIENT_ID"],
167+
user_pool_id: ENV["COGNITO_USER_POOL_ID"],
168168
challenge_name: "SOFTWARE_TOKEN_MFA",
169169
session: challenge[:session],
170170
challenge_responses: {
@@ -184,7 +184,7 @@ def respond_to_auth_challenge(code, challenge = {})
184184
def verify_account(email, code)
185185
begin
186186
@client.confirm_sign_up(
187-
client_id: ENV["AWS_COGNITO_CLIENT_ID"],
187+
client_id: ENV["COGNITO_CLIENT_ID"],
188188
secret_hash: get_secret_hash(email),
189189
username: email,
190190
confirmation_code: code
@@ -242,7 +242,7 @@ def verify_software_token(code, access_token)
242242
def disable_software_token(uid)
243243
begin
244244
@client.admin_set_user_mfa_preference(
245-
user_pool_id: ENV["AWS_COGNITO_USER_POOL_ID"],
245+
user_pool_id: ENV["COGNITO_USER_POOL_ID"],
246246
username: uid,
247247
software_token_mfa_settings: {
248248
enabled: false,
@@ -265,8 +265,8 @@ def get_auth_result(response)
265265
end
266266

267267
def get_secret_hash(username)
268-
message = username + ENV["AWS_COGNITO_CLIENT_ID"]
269-
key = ENV["AWS_COGNITO_CLIENT_SECRET"]
268+
message = username + ENV["COGNITO_CLIENT_ID"]
269+
key = ENV["COGNITO_CLIENT_SECRET"]
270270
Base64.strict_encode64(OpenSSL::HMAC.digest("sha256", key, message))
271271
end
272272

app-rails/config/environments/development.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
config.cache_store = :null_store
3737
end
3838

39-
config.active_storage.service = ENV["AWS_BUCKET_NAME"] ? :amazon : :local
39+
config.active_storage.service = ENV["BUCKET_NAME"] ? :amazon : :local
4040

4141
config.action_mailer.delivery_method = ENV["SES_EMAIL"] ? :sesv2 : :letter_opener
4242

app-rails/config/environments/production.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
5555
config.force_ssl = true
5656

57+
# Exclude healthcheck endpoint from force SSL since healthchecks should not go through
58+
# the reverse proxy.
59+
# See https://api.rubyonrails.org/classes/ActionDispatch/SSL.html
60+
config.ssl_options = { redirect: { exclude: -> request { /health/.match?(request.path) } } }
61+
5762
# Log to STDOUT by default
5863
config.logger = ActiveSupport::Logger.new(STDOUT)
5964
.tap { |logger| logger.formatter = ::Logger::Formatter.new }

app-rails/config/storage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ local:
88

99
amazon:
1010
service: S3
11-
bucket: <%= ENV.fetch("AWS_BUCKET_NAME") { nil } %>
11+
bucket: <%= ENV.fetch("BUCKET_NAME") { nil } %>
1212

1313

1414
# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)

app-rails/db/migrate/20240613000011_enable_extension_for_uuid.rb

Lines changed: 0 additions & 9 deletions
This file was deleted.

app-rails/db/schema.rb

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app-rails/local.env.example

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,20 @@ AWS_ACCESS_KEY_ID=<FILL ME IN>
1919
AWS_SECRET_ACCESS_KEY=<FILL ME IN>
2020
AWS_DEFAULT_REGION=<FILL ME IN>
2121

22+
############################
23+
# File storage
24+
############################
25+
2226
# Uncomment and fill in an AWS S3 bucket name to use S3 for file storage
23-
# AWS_BUCKET_NAME=<FILL ME IN>
27+
# BUCKET_NAME=<FILL ME IN>
2428

2529
############################
2630
# Auth
2731
############################
2832

29-
AWS_COGNITO_USER_POOL_ID=<FILL ME IN>
30-
AWS_COGNITO_CLIENT_ID=<FILL ME IN>
31-
AWS_COGNITO_CLIENT_SECRET=<FILL ME IN>
33+
COGNITO_USER_POOL_ID=<FILL ME IN>
34+
COGNITO_CLIENT_ID=<FILL ME IN>
35+
COGNITO_CLIENT_SECRET=<FILL ME IN>
3236

3337
############################
3438
# Database
@@ -37,4 +41,4 @@ AWS_COGNITO_CLIENT_SECRET=<FILL ME IN>
3741
DB_HOST=127.0.0.1
3842
DB_NAME=app_rails
3943
DB_USER=app_rails
40-
DB_PASSWORD=secret123
44+
DB_PASSWORD=secret123

docs/app-rails/technical-foundation.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ We have are using [UUIDs for primary keys](https://guides.rubyonrails.org/active
4040

4141
- ⚠️ Using ActiveRecord functions like `Foo.first` and `Foo.last` have unreliable results
4242
- Generating new models or scaffolds requires passing the `--primary-key-type=uuid` flag. For instance, `make rails-generate GENERATE_COMMAND="model Foo --primary-key-type=uuid"`
43-
- `pgcrypto` is a required dependency
4443

4544
#### Enums
4645

@@ -61,9 +60,9 @@ To preview email views in the browser, visit: `/rails/mailers`
6160

6261
To test AWS SES email sending locally:
6362

64-
1. Set the `AWS_*` env var in your `.env` file
65-
1. Set the `SES_EMAIL` env var to a verified sending identity
66-
1. Restart the server
63+
1. Set the "AWS services" environment variables in your `.env` file.
64+
1. Add an `SES_EMAIL` environment variable to a verified sending identity.
65+
1. Restart the server.
6766

6867
### 🎭 Authentication
6968

template-only-docs/Deployment.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Deployment to cloud environments
2+
3+
## Requirements
4+
5+
- External service access: The application must be able to make network calls to the public internet.
6+
- AWS Cognito: The application comes with AWS Cognito enabled by default, so AWS Cognito must be set up before deploying the application.
7+
- Custom domain name with HTTPS support: AWS Cognito requires HTTPS for callback urls to function.
8+
- Access to write to temporary directory: Rails needs to be able to write out temporary files.
9+
- Environment variables: You must provide the application with the environment variables listed in [local.env.example](/app-rails/local.env.example).
10+
- Secrets: You must provide the application with a secret `SECRET_KEY_BASE`. For more information, see the [Rails Guide on Security](https://guides.rubyonrails.org/v7.1/security.html#environmental-security).
11+
12+
## Deploying using the Platform Infrastructure Template
13+
14+
*Note: The following will be true once https://github.com/navapbc/template-infra/pull/650 is merged.*
15+
16+
This template can be deployed using the [Nava Platform Infrastructure Template](https://github.com/navapbc/template-infra). Using the infrastructure template will handle creating and configuring all of the resources required in AWS.
17+
18+
While following the [infrastructure template installation instructions](https://github.com/navapbc/template-infra?tab=readme-ov-file#installation) and [setup instructions](https://github.com/navapbc/template-infra/blob/main/infra/README.md), use the following configuration:
19+
20+
1. Rename `/infra/app` to `/infra/<APP_NAME>` so that it matches the directory name of your application. By default, this is `app-rails`.
21+
1. In `/infra/<APP_NAME>/app-config/main.tf`:
22+
1. Set `has_external_non_aws_service` to `true`.
23+
2. Set `enable_identity_provider` to `true`.
24+
1. In `/infra/<APP_NAME>/app-config/<ENVIRONMENT>.tf`:
25+
1. Set the `domain_name`.
26+
2. Set `enable_https` to `true`.
27+
3. Set `enable_command_execution` to `true`: This is necessary temporarily until a temporary file system can be enabled. Otherwise, ECS will run with read-only root filesystem, which will cause rails to error.
28+
1. In `/infra/<APP_NAME>/app-config/env-config/environment-variables.tf`:
29+
1. Add an entry to `secrets`:
30+
```terraform
31+
SECRET_KEY_BASE = {
32+
manage_method = "generated"
33+
secret_store_name = "/${var.app_name}-${var.environment}/service/rails-secret-key-base"
34+
}
35+
```
36+
1. In `/infra/networks/main.tf`:
37+
1. Modify the `app_config` module to change the path to match the directory name of your application. By default, this is `app-rails`.
38+
```terraform
39+
module "app_config" {
40+
source = "../<APP_NAME>/app-config"
41+
}
42+
```
43+
1. Follow the infrastructure template instructions to configure [custom domains](https://github.com/navapbc/template-infra/blob/main/docs/infra/set-up-custom-domains.md) and [https support](https://github.com/navapbc/template-infra/blob/main/docs/infra/https-support.md).
44+
45+
## Deploying using another method
46+
47+
- AWS Cognito requires a lot of configuration to work correctly. See the Nava Platform infrastructure template for example configuration.
48+
- If you are deploying using AWS ECS, but don't want to use the Platform infrastructure template, pass in environment variables and secrets using the ECS task definition. Use the `environment` key for environment variables and the `secrets` key with `valueFrom` for secrets.

0 commit comments

Comments
 (0)