Secrets Management#
Relevant controls: SC.03.07, SC.03.02, SC.01.19
Compliance reference
This document supports ITRA controls SC-03 Data Protection and SC-01 Access Management.
1. Secrets Inventory and Storage#
All secrets are stored in AWS SSM Parameter Store as SecureString values, encrypted with the account-default AWS KMS key (aws/ssm). No actual secret values are stored in source code, Docker images, or CI/CD logs.
Each MCP has two parameters per environment:
Currently 4 MCPs × 2 environments = 16 parameters in total. All rotate on a 24-month schedule and are owned by the AI connectors team.
Secrets are provisioned by Terraform (infra/modules/mcp_app_registration/ssm.tf). The module imports the Azure AD app registration, generates a client secret against it, and writes both values as SecureString parameters to SSM.
At runtime, ECS injects secrets into the container via the secrets block in the ECS task definition:
- The ECS execution role reads the SSM parameter at container startup.
- The secret value is injected as an environment variable inside the container only.
- The secret never appears in plaintext in the task definition — only the SSM ARN reference is stored.
# Example from ecs/env/prod.yml
secrets:
MCP_SERVER_AZURE_CLIENT_ID: arn:aws:ssm:eu-central-1:673034950531:parameter/aiconnectors/prod/sharepoint/client_id
MCP_SERVER_AZURE_CLIENT_SECRET: arn:aws:ssm:eu-central-1:673034950531:parameter/aiconnectors/prod/sharepoint/client_secret
2. Secret Access Controls#
Access to secrets is strictly controlled via IAM policies. Each MCP's execution role is scoped to only its own SSM parameter ARNs; no role has cross-MCP access. Full IAM role definitions and least-privilege policy details are in access-management.md.
3. Secret Rotation#
Scheduled Rotation#
Azure AD client secrets are configured with a 24-month expiry (set in Terraform at the time of generation). Rotation is performed by re-generating the secret via Terraform before expiry:
- Run
terragrunt applyininfra/initial/mcps/{name}/— Terraform generates a new client secret against the Azure AD app registration and writes the new value to SSM, replacing the old one. The old secret remains valid in Azure AD until its expiry date. - Trigger ECS redeployment — force a new deployment of the ECS service so containers pick up the new secret from SSM at next startup.
- Verify the MCP is functional with the new secret (health check passes, test tool call succeeds).
- Confirm expiry of the old secret in Azure AD after the new one is confirmed active.
Emergency Rotation (Suspected Compromise)#
If a secret is suspected to be compromised:
- Immediately disable the compromised secret in Azure AD (no ServiceNow ticket required — use the Azure AD portal directly).
- Run
terragrunt applyininfra/initial/mcps/{name}/to generate a new client secret and update SSM. - Trigger ECS redeployment and verify (steps 2–4 above).
- Investigate the breach vector and document in an incident report (see incident-response.md).
- Review audit logs (
/check-audit-logs) for any unauthorised activity during the exposure window.
4. No Hardcoded Secrets Policy#
The AI connectors platform enforces a strict policy that no secrets are stored in:
- Source code or config files committed to git — only SSM ARN references appear in ECS task definition YAML files; actual values are never committed
- Docker images — multi-stage builds copy only application code; secrets are injected at runtime via ECS/SSM integration
- Terraform state — client IDs and secrets flow through Terraform state during
initial/apply; state is stored in S3 with encryption at rest and access restricted to the Terraform OIDC role - CI/CD pipeline logs — GitHub Actions workflows do not have SSM read access; secrets are never printed in build output
Enforcement Mechanisms#
| Mechanism | Scope | Status |
|---|---|---|
| GitHub secret scanning | Repository-wide — detects known secret patterns in pushes | Enabled (GitHub Advanced Security) |
.env in .gitignore |
Prevents accidental commit of local env files | Active |
No COPY .env in Dockerfiles |
Ensures .env files never enter Docker image layers |
Enforced by code review |
ECS secrets block (SSM ARN refs) |
Secrets injected at container startup, not in task definition plaintext | Enforced by ECS task definition pattern |
Terraform SecureString type |
SSM parameters created as encrypted by default | Enforced in infra/modules/mcp_app_registration/ssm.tf |
Recommended Improvements#
- Add
gitleaksordetect-secretsas a pre-commit hook and CI check to catch accidental secret commits before they reach the repository.
5. Certificate Management#
TLS certificate provisioning, renewal, and expiry alerting are covered in data-storage-encryption.md §2.