Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: specify app settings as code #1294

Merged
merged 12 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/deployment/infrastructure.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Within the `CDT Digital CA` directory ([how to switch](https://learn.microsoft.c

All resources in these Resource Groups should be reflected in Terraform in this repository. The exceptions are:

- Secrets, such as values under [Key Vault](https://azure.microsoft.com/en-us/services/key-vault/) and [App Service application settings](https://docs.microsoft.com/en-us/azure/app-service/configure-common#configure-app-settings). [`prevent_destroy`](https://developer.hashicorp.com/terraform/tutorials/state/resource-lifecycle#prevent-resource-deletion) is used on these Resources.
- Secrets, such as values under [Key Vault](https://azure.microsoft.com/en-us/services/key-vault/). [`prevent_destroy`](https://developer.hashicorp.com/terraform/tutorials/state/resource-lifecycle#prevent-resource-deletion) is used on these Resources.
- [Things managed by DevSecOps](#ownership)

You'll see these referenced in Terraform as [data sources](https://developer.hashicorp.com/terraform/language/data-sources).
Expand Down
14 changes: 14 additions & 0 deletions docs/deployment/secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,17 @@ To set a secret by providing the path of a file containing the secret (useful fo
```bash
./file.sh <environment_letter> <secret_name> <file_path>
```

## Refreshing secrets

To make sure the Benefits application uses the latest secret values in Key Vault, you will need to make a change to the app service's configuration. If you don't do this step, the application will instead use cached values, which may not be what you expect. See the [Azure docs](https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references?tabs=azure-cli#rotation) for more details.

The steps are:

1. After setting new secret values, go to the App Service configuration in Azure Portal, and change the value of the setting named `change_me_to_refresh_secrets`.
1. Save your changes.

The effects of following those steps should be:

- A restart of the App Service is triggered.
- The next time that our Azure infrastructure pipeline is run, the value of `change_me_to_refresh_secrets` is set back to the value defined in our Terraform file for the App Service resource.
2 changes: 1 addition & 1 deletion docs/getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ docker compose down
[docker]: https://www.docker.com/products/docker-desktop
[sample-data]: https://github.com/cal-itp/benefits/tree/dev/benefits/core/migrations/0002_sample_data.py

[data-migration](https://github.com/cal-itp/benefits/tree/dev/benefits/core/migrations)
[data-migration]: (https://github.com/cal-itp/benefits/tree/dev/benefits/core/migrations)
81 changes: 79 additions & 2 deletions terraform/app_service.tf
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,87 @@ resource "azurerm_linux_web_app" "main" {
mount_path = "/home/calitp/app/config"
}

app_settings = {
# app setting used solely for refreshing secrets - see https://github.com/MicrosoftDocs/azure-docs/issues/79855#issuecomment-1265664801
"change_me_to_refresh_secrets" = "change me in the portal to refresh all secrets",

"DOCKER_ENABLE_CI" = "true",
"DOCKER_REGISTRY_SERVER_URL" = "https://ghcr.io/",
"WEBSITE_HTTPLOGGING_RETENTION_DAYS" = "99999",
"WEBSITE_TIME_ZONE" = "America/Los_Angeles",
"WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false",
"WEBSITES_PORT" = "8000",

"ANALYTICS_KEY" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=analytics-key)",
thekaveman marked this conversation as resolved.
Show resolved Hide resolved

# Django settings
"DJANGO_ADMIN" = (local.is_prod || local.is_test) ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-admin)",
"DJANGO_ALLOWED_HOSTS" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-allowed-hosts)",
"DJANGO_DEBUG" = local.is_prod ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-debug)",
"DJANGO_LOAD_SAMPLE_DATA" = "false",
"DJANGO_LOG_LEVEL" = "DEBUG",
thekaveman marked this conversation as resolved.
Show resolved Hide resolved
"DJANGO_MIGRATIONS_DIR" = "./config",

"DJANGO_RATE_LIMIT" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-rate-limit)",
"DJANGO_RATE_LIMIT_METHODS" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-rate-limit-methods)",
"DJANGO_RATE_LIMIT_PERIOD" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-rate-limit-period)",

"DJANGO_RECAPTCHA_SECRET_KEY" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-recaptcha-secret-key)",
"DJANGO_RECAPTCHA_SITE_KEY" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-recaptcha-site-key)",

"DJANGO_SECRET_KEY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-secret-key)",
"DJANGO_TRUSTED_ORIGINS" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=django-trusted-origins)",

"HEALTHCHECK_USER_AGENTS" = local.is_dev ? null : "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=healthcheck-user-agents)",

# Sentry
"SENTRY_DSN" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sentry-dsn)",
"SENTRY_ENVIRONMENT" = local.env_name,

# Environment variables for data migration
"MST_SENIOR_GROUP_ID" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=mst-senior-group-id)",
"MST_COURTESY_CARD_GROUP_ID" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=mst-courtesy-card-group-id)"
"SACRT_SENIOR_GROUP_ID" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sacrt-senior-group-id)"
"CLIENT_PRIVATE_KEY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=client-private-key)"
"CLIENT_PUBLIC_KEY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=client-public-key)"
"SERVER_PUBLIC_KEY_URL" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=server-public-key-url)"
"PAYMENT_PROCESSOR_CLIENT_CERT" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-client-cert)"
"PAYMENT_PROCESSOR_CLIENT_CERT_PRIVATE_KEY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-client-cert-private-key)"
"PAYMENT_PROCESSOR_CLIENT_CERT_ROOT_CA" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-client-cert-root-ca)"
"AUTH_PROVIDER_CLIENT_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=auth-provider-client-name)"
"AUTH_PROVIDER_CLIENT_ID" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=auth-provider-client-id)"
"AUTH_PROVIDER_AUTHORITY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=auth-provider-authority)"
"AUTH_PROVIDER_SCOPE" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=auth-provider-scope)"
"AUTH_PROVIDER_CLAIM" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=auth-provider-claim)"
"MST_OAUTH_VERIFIER_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=mst-oauth-verifier-name)"
"COURTESY_CARD_VERIFIER" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier)"
"COURTESY_CARD_VERIFIER_API_URL" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier-api-url)"
"COURTESY_CARD_VERIFIER_API_AUTH_HEADER" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier-api-auth-header)"
"COURTESY_CARD_VERIFIER_API_AUTH_KEY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier-api-auth-key)"
"COURTESY_CARD_VERIFIER_JWE_CEK_ENC" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier-jwe-cek-enc)"
"COURTESY_CARD_VERIFIER_JWE_ENCRYPTION_ALG" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier-jwe-encryption-alg)"
"COURTESY_CARD_VERIFIER_JWS_SIGNING_ALG" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=courtesy-card-verifier-jws-signing-alg)"
"SACRT_OAUTH_VERIFIER_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sacrt-oauth-verifier-name)"
"PAYMENT_PROCESSOR_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-name)"
"PAYMENT_PROCESSOR_API_BASE_URL" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-api-base-url)"
"PAYMENT_PROCESSOR_API_ACCESS_TOKEN_ENDPOINT" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-api-access-token-endpoint)"
"PAYMENT_PROCESSOR_API_ACCESS_TOKEN_REQUEST_KEY" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-api-access-token-request-key)"
"PAYMENT_PROCESSOR_API_ACCESS_TOKEN_REQUEST_VAL" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-api-access-token-request-val)"
"PAYMENT_PROCESSOR_CARD_TOKENIZE_URL" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-card-tokenize-url)"
"PAYMENT_PROCESSOR_CARD_TOKENIZE_FUNC" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-card-tokenize-func)"
"PAYMENT_PROCESSOR_CARD_TOKENIZE_ENV" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=payment-processor-card-tokenize-env)"
"MST_AGENCY_SHORT_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=mst-agency-short-name)"
"MST_AGENCY_LONG_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=mst-agency-long-name)"
"MST_AGENCY_JWS_SIGNING_ALG" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=mst-agency-jws-signing-alg)"
"SACRT_AGENCY_SHORT_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sacrt-agency-short-name)"
"SACRT_AGENCY_LONG_NAME" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sacrt-agency-long-name)"
"SACRT_AGENCY_MERCHANT_ID" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sacrt-agency-merchant-id)"
thekaveman marked this conversation as resolved.
Show resolved Hide resolved
"SACRT_AGENCY_JWS_SIGNING_ALG" = "@Microsoft.KeyVault(VaultName=KV-CDT-PUB-CALITP-${local.env_letter}-001;SecretName=sacrt-agency-jws-signing-alg)"
}

lifecycle {
prevent_destroy = true
# app_settings are managed manually through the portal since they contain secrets
ignore_changes = [app_settings, sticky_settings, tags]
ignore_changes = [tags]
}
}

Expand Down
2 changes: 2 additions & 0 deletions terraform/environment.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
locals {
is_prod = terraform.workspace == "default"
is_test = terraform.workspace == "test"
is_dev = !(local.is_prod || local.is_test)
env_name = local.is_prod ? "prod" : terraform.workspace
env_letter = upper(substr(local.env_name, 0, 1))
subscription_letter = local.is_prod ? "P" : "D"
Expand Down