Secrets Manager integration¶
This document describes how Floecat uses AWS Secrets Manager, the required IAM permissions, and optional hardening with per-account role assumption.
Overview¶
Floecat stores secret payloads in AWS Secrets Manager using a key format:
accounts/<accountId>/<secretType>/<secretId>
Each secret is tagged with:
AccountId= the account id passed by Floecat
These tags support ABAC-style policies.
Connector AuthCredentials and storage-authority source credentials are written to Secrets Manager and removed from the corresponding persisted resource records. Connector responses mask sensitive auth fields, and storage-authority resolution only returns client-safe config plus any temporary credentials minted for a specific table/location match.
Connector secrets are never used for Iceberg REST client credential vending. Storage-authority secrets are the only credential source used for client credential vending.
Configuration¶
Optional role assumption:
floecat.secrets.aws.role-arn(optional)
If set, Floecat assumes this role per account operation and tags the STS session with AccountId=<accountId>. If unset, Floecat uses its default AWS credentials for all operations.
Set via system property:
-Dfloecat.secrets.aws.role-arn=arn:aws:iam::123456789012:role/floecat-secrets
Or via environment variable:
export FLOECAT_SECRETS_AWS_ROLE_ARN=arn:aws:iam::123456789012:role/floecat-secrets
Required IAM permissions (base)¶
The IAM identity Floecat runs under must be allowed to call Secrets Manager APIs. A minimal base policy looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SecretsManagerBase",
"Effect": "Allow",
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:GetSecretValue",
"secretsmanager:PutSecretValue",
"secretsmanager:DeleteSecret",
"secretsmanager:TagResource"
],
"Resource": "*"
}
]
}
Quick start (AWS CLI validation)¶
Primary setup is granting the Floecat workload permissions to call Secrets Manager (see the IAM policy above). The commands here are a quick validation of access and the expected key format.
Set the identifiers and create a sample payload:
export ACCOUNT_ID=acct-123
export SECRET_TYPE=connectors # or storage-authorities
export SECRET_ID=conn-001 # or a storage authority id such as sa-001
export SECRET_NAME="accounts/${ACCOUNT_ID}/${SECRET_TYPE}/${SECRET_ID}"
printf 'example-secret-payload' > payload.bin
Create a secret (binary payload):
aws secretsmanager create-secret \
--name "$SECRET_NAME" \
--secret-binary fileb://payload.bin \
--tags Key=AccountId,Value="$ACCOUNT_ID"
Update the secret:
aws secretsmanager put-secret-value \
--secret-id "$SECRET_NAME" \
--secret-binary fileb://payload.bin
Read the secret:
aws secretsmanager get-secret-value \
--secret-id "$SECRET_NAME" \
--query 'SecretBinary' \
--output text | base64 --decode
Delete the secret:
aws secretsmanager delete-secret \
--secret-id "$SECRET_NAME" \
--recovery-window-in-days 7
Optional hardening: per-account ABAC with role assumption¶
When floecat.secrets.aws.role-arn is set, Floecat will assume that role and attach an STS session tag AccountId=<accountId> for each operation. This allows you to enforce that secrets can only be accessed when the caller's AccountId tag matches the secret's AccountId tag.
Role trust policy¶
The role referenced by floecat.secrets.aws.role-arn must trust the Floecat base identity and allow session tagging:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/floecat-base"
},
"Action": "sts:AssumeRole"
},
{
"Sid": "AllowSessionTags",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/floecat-base"
},
"Action": "sts:TagSession",
"Condition": {
"StringLike": {
"aws:RequestTag/AccountId": "*"
},
"ForAllValues:StringEquals": {
"aws:TagKeys": ["AccountId"]
}
}
}
]
}
This follows the AWS STS session-tagging model: sts:TagSession is a permissions action in the
trust policy, and tag constraints are expressed with condition keys such as aws:RequestTag/...
and aws:TagKeys.
Role permissions policy¶
Attach a policy that enforces tag alignment:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SecretsByAccountTag",
"Effect": "Allow",
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:GetSecretValue",
"secretsmanager:PutSecretValue",
"secretsmanager:DeleteSecret",
"secretsmanager:TagResource"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"secretsmanager:ResourceTag/AccountId": "${aws:PrincipalTag/AccountId}"
}
}
}
]
}
This prevents any caller from reading or writing secrets unless the secret is tagged with the same AccountId value as the session.