Security, IAM & Secrets

This page describes how TLS, IAM roles and secrets are used to protect the services managed by this repository. It corresponds to the Security & Secrets diagram and focuses on the infra view rather than application logic.

Security & Secrets

The main concerns are:

  • TLS termination and OIDC authentication at the Application Load Balancer
  • IAM roles and policies for ECS tasks and Lambda functions
  • Secrets stored in AWS Secrets Manager (and related parameters) for Kinde, databases and other external services

TLS and entry-point security (overview)

From a networking point of view (see also Networking & Entry Points):

  • Cloudflare serves DNS for rocketclub.online and proxies traffic towards AWS.
  • CloudFront distributions front the Application Load Balancer for portal.rocketclub.online and pipelines.rocketclub.online.
  • The ALB terminates HTTPS/TLS and performs OIDC authentication with Kinde before routing traffic to ECS services for Backstage and Prefect.

TLS certificates for the ALB origin are managed via the acm-alb-origin module, and ALB resources, listeners and listener rules live under infra/platform/infra/modules/core/alb.

IAM roles and policies

IAM configuration for the core services is managed in the infra/platform/infra/modules/core/iam module and applied in infra/platform/infra/envs/prod.

At a high level:

  • ECS tasks for Backstage and Prefect have task roles that allow them to:
    • Read/write from S3 data buckets provisioned in this repo
    • Read application secrets from AWS Secrets Manager
    • Emit logs and metrics to CloudWatch and other AWS services as needed
  • Lambda functions (such as the .ork processor) have execution roles that allow them to:
    • Read .ork files from the design files bucket
    • Write processed data to Neo4j Aura and Cloudinary using credentials stored in Secrets Manager
  • CI/CD jobs (Terraform in CircleCI) use IAM roles with permissions scoped to manage the infrastructure resources defined in this repository.

The exact policies and role names are defined in Terraform under infra/platform/infra/modules/core/iam and wired into ECS and Lambda modules. This page does not attempt to document every statement; Terraform remains the source of truth.

Secrets Manager and Kinde OIDC configuration

Kinde is configured directly on the ALB using authenticate-oidc actions on HTTPS listener rules for both Backstage and Prefect:

  • Listener rules live in infra/platform/infra/modules/core/alb/listener_rules.tf.
  • The Kinde endpoints are derived from var.kinde_domain (for example ronaldhatcher.kinde.com).
  • The Kinde client ID comes from var.kinde_client_id.
  • The Kinde client secret is stored in AWS Secrets Manager and referenced via var.kinde_client_secret_arn.

In infra/platform/infra/envs/prod:

  • infra/platform/infra/envs/prod/variables.tf defines:
    • kinde_domain
    • kinde_client_id
    • kinde_client_secret_name (the Secrets Manager name/path)
  • infra/platform/infra/envs/prod/main.tf builds the full local.kinde_client_secret_arn from that name, region and account ID and passes it into the ALB module.

The ALB module then uses data.aws_secretsmanager_secret_version.kinde_client_secret in infra/platform/infra/modules/core/alb/security.tf to resolve the client secret at apply time.

Other application credentials (for example database passwords, Prefect tokens, Cloudinary and Neo4j credentials) are also stored in AWS Secrets Manager and consumed by ECS tasks and Lambda functions via IAM roles defined in the iam module.

Secrets and parameters follow these conventions:

  • Secrets Manager paths are typically ${environment}/service/thing, for example prod/backstage/database-url.
  • SSM Parameter Store paths are typically /${environment}/namespace/resource, for example /prod/blog-data/buckets/cache.

Where this page shows prod/..., replace prod with the appropriate environment name for non-prod environments.

Key secrets in AWS Secrets Manager

The table below lists the main Secrets Manager entries that application and infra code are expected to use directly. It is not a complete inventory; Terraform remains the source of truth.

Secret name (prod)PurposePrimary consumersOwned/defined by
prod/db/adminAurora admin credentials (JSON username / password)Aurora cluster (master_username / master_password); Backstage DB bootstrap/inspect tasks (DB_ADMIN_SECRET_JSON)Terraform: infra/platform/infra/modules/core/iam, infra/platform/infra/modules/core/aurora
prod/backstage/dbBackstage DB username/password (JSON)Backstage DB bootstrap task (BACKSTAGE_DB_SECRET_JSON)Terraform: infra/platform/infra/modules/core/iam; consumed by infra/platform/infra/modules/apps/backstage
prod/backstage/database-urlBackstage database connection URL (PostgreSQL)Backstage ECS task container (BACKSTAGE_DATABASE_URL env var)Secret container defined in infra/platform/infra/modules/core/iam; value set in infra/platform/infra/envs/prod
prod/backstage/session-secretBackstage auth session secretBackstage ECS task container (AUTH_SESSION_SECRET env var)Terraform: infra/platform/infra/modules/core/iam; consumed by infra/platform/infra/modules/apps/backstage
prod/github/pat/blog_data_ciShared GitHub PAT for Backstage catalog discovery and Prefect deployerBackstage backend (GITHUB_TOKEN env var); Prefect deployer ECS taskExternal secret in AWS Secrets Manager; value managed manually (not stored in Terraform state)
prod/circleci/pat/backstageCircleCI PAT used by the Backstage backendBackstage ECS task container (CIRCLECI_AUTH_TOKEN env var)External secret in AWS Secrets Manager; value managed manually (not stored in Terraform state)
prod/prefect/database-urlPrefect database connection URL (PostgreSQL)Prefect API ECS service container (PREFECT_API_DATABASE_CONNECTION_URL env var)Terraform: infra/platform/infra/modules/apps/prefect-api (+ env wiring in infra/platform/infra/envs/prod)
prod/prefect/api-authPrefect API authentication (for workers and CI)Prefect workers / CI when talking to the Prefect APIStored in AWS Secrets Manager (external / manually managed secret)
prod/kinde/client-secret-2pS4d3Kinde OIDC client secret used by the ALBALB OIDC authentication for Backstage and PrefectStored in AWS Secrets Manager; referenced via kinde_client_secret_name / kinde_client_secret_arn
blog-data/neo4j/credentialsNeo4j connection URI, username and passwordPrefect flows and the blog frontendStored in AWS Secrets Manager; referenced by pipeline code (outside infra root)
blog-data/cloudinary/credentialsCloudinary cloud name, API key and secretPrefect flows and the blog frontendStored in AWS Secrets Manager; referenced by pipeline code (outside infra root)

Note: In non-prod environments, replace the prod/ prefix with the environment name (for example dev/backstage/database-url).

Key parameters in AWS Systems Manager Parameter Store (SSM)

Terraform also publishes a small set of SSM parameters that other code (CI, Prefect deployer, ALB) reads at runtime. These are the ones developers are most likely to need:

Parameter name (prod)Purpose / valuePrimary consumersDefined in Terraform
/prod/shared/cf_alb_secretSecureString shared secret header for CloudFront -> ALB requestsALB + CloudFront modules (via cf_alb_secret_param_name)infra/platform/infra/modules/core/iam, infra/platform/infra/modules/core/alb, infra/platform/infra/modules/core/cloudfront-apps
/prod/blog-data/buckets/cacheS3 bucket name for the blog-data cache layerPrefect flows/toolsinfra/platform/infra/modules/core/s3-data/ssm-parameters.tf
/prod/blog-data/buckets/rawS3 bucket name for the blog-data raw layerPrefect flowsinfra/platform/infra/modules/core/s3-data/ssm-parameters.tf
/prod/blog-data/buckets/cleanS3 bucket name for the blog-data clean layerPrefect flowsinfra/platform/infra/modules/core/s3-data/ssm-parameters.tf
/prod/blog-data/buckets/design-filesS3 bucket name for the design files layerLambda .ork processor and toolinginfra/platform/infra/modules/core/s3-data/ssm-parameters.tf
/prod/infra/park_modeMarker for overall infra park mode: parked / unparkedCI/Terraform workflowsinfra/platform/infra/envs/prod/main.tf
/prod/infra/database_restore_modeAurora restore mode: from_final_snapshot / cleanCI/Terraform workflows (controls restore variables)infra/platform/infra/envs/prod/main.tf
/prod/prefect/deployer/cluster_arnECS cluster ARN used by the internal Prefect deployer taskCI/scripts that trigger the Prefect deployer ECS taskinfra/platform/infra/envs/prod/main.tf
/prod/prefect/deployer/task_definition_arnTask definition ARN for the Prefect deployerCI/scripts that trigger the Prefect deployer ECS taskinfra/platform/infra/envs/prod/main.tf
/prod/prefect/deployer/subnet_idsComma-separated list of private subnet IDs for the deployer taskCI/scripts that trigger the Prefect deployer ECS taskinfra/platform/infra/envs/prod/main.tf
/prod/prefect/deployer/security_group_idSecurity group ID for the Prefect deployer taskCI/scripts that trigger the Prefect deployer ECS taskinfra/platform/infra/envs/prod/main.tf

Kinde OIDC runbook (config & rotation)

When you need to change or rotate Kinde credentials:

  1. Update Kinde app: In the Kinde dashboard, update or rotate the client secret for the application used by portal.rocketclub.online and pipelines.rocketclub.online.
  2. Update Secrets Manager: In AWS Secrets Manager, update the secret whose name is given by var.kinde_client_secret_name with the new client secret value.
  3. Apply Terraform: Run a Terraform plan/apply for infra/platform/infra/envs/prod (typically via the terraform-prod CircleCI workflow). This refreshes the ALB listener rule configuration with the new client secret.
  4. Verify login: Hit https://portal.rocketclub.online and https://pipelines.rocketclub.online in a browser and confirm Kinde login works end-to-end (no redirect loops or 403s).

If authentication starts failing in production, this section plus the ALB and Kinde logs are the starting points for debugging.