932923ee99
Nova Slides Render / render (push) Failing after 22s
---ci--- project: acdl phase: 6 milestone: v1.29 status: complete ---/ci---
551 lines
16 KiB
Markdown
551 lines
16 KiB
Markdown
# Archived: Nova IdP CloudFormation Template (v1.28)
|
|
|
|
> **Archived at v1.29.0** — the active path is `terraform apply` in
|
|
> `nova-platform-ops`. Deletion is a follow-up after Terraform parity
|
|
> is verified (REQ-369 AC 3, spec §7.5). This template is read-only
|
|
> reference; do not modify it. The `nova idp setup --apply` command
|
|
> now delegates to `terraform apply` (see `nova/idp/setup.py`).
|
|
|
|
This is the verbatim output of `generate_template()` from
|
|
`core/lambda/nova_idp_cfn.py` (the composition of the DynamoDB snippet
|
|
from `core/lambda/nova_idp_auth_cfn.py` + the KMS signing key + the
|
|
three IdP Lambdas + their IAM roles + function URLs). It was the active
|
|
provisioning path through v1.28; from v1.29 the operator runs
|
|
`terraform apply` in the `nova-platform-ops` checkout and `nova idp
|
|
setup --apply` delegates to it. The CFN generation code is retained as
|
|
read-only reference and emits a `DeprecationWarning` when the CFN
|
|
fallback path is invoked (terraform absent from PATH).
|
|
|
|
```json
|
|
{
|
|
"Resources": {
|
|
"NovaUsersTable": {
|
|
"Type": "AWS::DynamoDB::Table",
|
|
"Properties": {
|
|
"TableName": "nova-users",
|
|
"BillingMode": "PAY_PER_REQUEST",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "user_id",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"AttributeDefinitions": [
|
|
{
|
|
"AttributeName": "user_id",
|
|
"AttributeType": "S"
|
|
},
|
|
{
|
|
"AttributeName": "email",
|
|
"AttributeType": "S"
|
|
}
|
|
],
|
|
"GlobalSecondaryIndexes": [
|
|
{
|
|
"IndexName": "email-index",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "email",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"Projection": {
|
|
"ProjectionType": "ALL"
|
|
}
|
|
}
|
|
],
|
|
"PointInTimeRecoverySpecification": {
|
|
"PointInTimeRecoveryEnabled": true
|
|
},
|
|
"AttributeShape": {
|
|
"user_id": "String",
|
|
"email": "String",
|
|
"password_hash": "String",
|
|
"owner": "String",
|
|
"roles": "List",
|
|
"created_at": "String"
|
|
}
|
|
}
|
|
},
|
|
"NovaSessionsTable": {
|
|
"Type": "AWS::DynamoDB::Table",
|
|
"Properties": {
|
|
"TableName": "nova-sessions",
|
|
"BillingMode": "PAY_PER_REQUEST",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "session_id",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"AttributeDefinitions": [
|
|
{
|
|
"AttributeName": "session_id",
|
|
"AttributeType": "S"
|
|
},
|
|
{
|
|
"AttributeName": "user_id",
|
|
"AttributeType": "S"
|
|
}
|
|
],
|
|
"GlobalSecondaryIndexes": [
|
|
{
|
|
"IndexName": "user_id-index",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "user_id",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"Projection": {
|
|
"ProjectionType": "ALL"
|
|
}
|
|
}
|
|
],
|
|
"TimeToLiveSpecification": {
|
|
"AttributeName": "expires_at",
|
|
"Enabled": true
|
|
},
|
|
"AttributeShape": {
|
|
"session_id": "String",
|
|
"user_id": "String",
|
|
"expires_at": "String (epoch seconds, TTL)",
|
|
"created_at": "String (ISO-8601)"
|
|
}
|
|
}
|
|
},
|
|
"NovaPasswordResetsTable": {
|
|
"Type": "AWS::DynamoDB::Table",
|
|
"Properties": {
|
|
"TableName": "nova-password-resets",
|
|
"BillingMode": "PAY_PER_REQUEST",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "reset_token",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"AttributeDefinitions": [
|
|
{
|
|
"AttributeName": "reset_token",
|
|
"AttributeType": "S"
|
|
}
|
|
],
|
|
"TimeToLiveSpecification": {
|
|
"AttributeName": "expires_at",
|
|
"Enabled": true
|
|
},
|
|
"AttributeShape": {
|
|
"reset_token": "String",
|
|
"user_id": "String",
|
|
"expires_at": "String (epoch seconds, TTL; 15 min)"
|
|
}
|
|
}
|
|
},
|
|
"NovaPatsTable": {
|
|
"Type": "AWS::DynamoDB::Table",
|
|
"Properties": {
|
|
"TableName": "nova-pats",
|
|
"BillingMode": "PAY_PER_REQUEST",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "jti",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"AttributeDefinitions": [
|
|
{
|
|
"AttributeName": "jti",
|
|
"AttributeType": "S"
|
|
},
|
|
{
|
|
"AttributeName": "sub",
|
|
"AttributeType": "S"
|
|
},
|
|
{
|
|
"AttributeName": "pat_hash",
|
|
"AttributeType": "S"
|
|
}
|
|
],
|
|
"GlobalSecondaryIndexes": [
|
|
{
|
|
"IndexName": "sub-index",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "sub",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"Projection": {
|
|
"ProjectionType": "ALL"
|
|
}
|
|
},
|
|
{
|
|
"IndexName": "pat_hash-index",
|
|
"KeySchema": [
|
|
{
|
|
"AttributeName": "pat_hash",
|
|
"KeyType": "HASH"
|
|
}
|
|
],
|
|
"Projection": {
|
|
"ProjectionType": "ALL"
|
|
}
|
|
}
|
|
],
|
|
"TimeToLiveSpecification": {
|
|
"AttributeName": "expires_at",
|
|
"Enabled": true
|
|
},
|
|
"AttributeShape": {
|
|
"jti": "String (PK)",
|
|
"sub": "String (GSI1; subject / user_id)",
|
|
"pat_hash": "String (GSI2; SHA-256 of the PAT for lookup)",
|
|
"status": "String (active|revoked)",
|
|
"issued_at": "String (ISO-8601)",
|
|
"expires_at": "String (epoch seconds, TTL)",
|
|
"revoked_at": "String (ISO-8601, present iff status=revoked)",
|
|
"claims": "Map (JWT claims payload)"
|
|
}
|
|
}
|
|
},
|
|
"NovaOidcSigningKey": {
|
|
"Type": "AWS::KMS::Key",
|
|
"Properties": {
|
|
"Description": "Nova OIDC token signing key (REQ-337, ECC_NIST_P256)",
|
|
"KeySpec": "ECC_NIST_P256",
|
|
"KeyUsage": "SIGN_VERIFY",
|
|
"KeyPolicy": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": {
|
|
"Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root"
|
|
}
|
|
},
|
|
"Action": "kms:*",
|
|
"Resource": "*"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"NovaOidcSigningKeyAlias": {
|
|
"Type": "AWS::KMS::Alias",
|
|
"Properties": {
|
|
"AliasName": "alias/nova-oidc-signing",
|
|
"TargetKeyId": {
|
|
"Fn::GetAtt": "NovaOidcSigningKey.Arn"
|
|
}
|
|
}
|
|
},
|
|
"NovaIdpAuthRole": {
|
|
"Type": "AWS::IAM::Role",
|
|
"Properties": {
|
|
"AssumeRolePolicyDocument": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"Service": {
|
|
"Fn::Sub": "lambda.${AWS::Region}.amazonaws.com"
|
|
}
|
|
},
|
|
"Action": "sts:AssumeRole"
|
|
}
|
|
]
|
|
},
|
|
"Policies": [
|
|
{
|
|
"PolicyName": "NovaIdpAuthPolicy",
|
|
"PolicyDocument": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"logs:CreateLogStream",
|
|
"logs:PutLogEvents"
|
|
],
|
|
"Resource": {
|
|
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
|
|
}
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"logs:CreateLogGroup"
|
|
],
|
|
"Resource": {
|
|
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*"
|
|
}
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"dynamodb:GetItem",
|
|
"dynamodb:PutItem",
|
|
"dynamodb:UpdateItem",
|
|
"dynamodb:Query",
|
|
"dynamodb:DeleteItem"
|
|
],
|
|
"Resource": [
|
|
{
|
|
"Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/nova-users"
|
|
},
|
|
{
|
|
"Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/nova-sessions"
|
|
},
|
|
{
|
|
"Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/nova-password-resets"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"NovaIdpTokenVendRole": {
|
|
"Type": "AWS::IAM::Role",
|
|
"Properties": {
|
|
"AssumeRolePolicyDocument": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"Service": {
|
|
"Fn::Sub": "lambda.${AWS::Region}.amazonaws.com"
|
|
}
|
|
},
|
|
"Action": "sts:AssumeRole"
|
|
}
|
|
]
|
|
},
|
|
"Policies": [
|
|
{
|
|
"PolicyName": "NovaIdpTokenVendPolicy",
|
|
"PolicyDocument": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"logs:CreateLogStream",
|
|
"logs:PutLogEvents"
|
|
],
|
|
"Resource": {
|
|
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
|
|
}
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"logs:CreateLogGroup"
|
|
],
|
|
"Resource": {
|
|
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*"
|
|
}
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"dynamodb:GetItem",
|
|
"dynamodb:PutItem",
|
|
"dynamodb:UpdateItem",
|
|
"dynamodb:Query",
|
|
"dynamodb:DeleteItem"
|
|
],
|
|
"Resource": [
|
|
{
|
|
"Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/nova-pats"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"kms:Sign",
|
|
"kms:GetPublicKey",
|
|
"kms:DescribeKey"
|
|
],
|
|
"Resource": {
|
|
"Fn::GetAtt": "NovaOidcSigningKey.Arn"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"NovaIdpJwksRole": {
|
|
"Type": "AWS::IAM::Role",
|
|
"Properties": {
|
|
"AssumeRolePolicyDocument": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"Service": {
|
|
"Fn::Sub": "lambda.${AWS::Region}.amazonaws.com"
|
|
}
|
|
},
|
|
"Action": "sts:AssumeRole"
|
|
}
|
|
]
|
|
},
|
|
"Policies": [
|
|
{
|
|
"PolicyName": "NovaIdpJwksPolicy",
|
|
"PolicyDocument": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"logs:CreateLogStream",
|
|
"logs:PutLogEvents"
|
|
],
|
|
"Resource": {
|
|
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
|
|
}
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"logs:CreateLogGroup"
|
|
],
|
|
"Resource": {
|
|
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*"
|
|
}
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"kms:Sign",
|
|
"kms:GetPublicKey",
|
|
"kms:DescribeKey"
|
|
],
|
|
"Resource": {
|
|
"Fn::GetAtt": "NovaOidcSigningKey.Arn"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"NovaIdpAuthFunction": {
|
|
"Type": "AWS::Lambda::Function",
|
|
"Properties": {
|
|
"Handler": "nova_idp_auth.lambda_handler",
|
|
"Runtime": "python3.12",
|
|
"MemorySize": 512,
|
|
"Timeout": 30,
|
|
"Role": {
|
|
"Fn::GetAtt": [
|
|
"NovaIdpAuthRole",
|
|
"Arn"
|
|
]
|
|
},
|
|
"Environment": {
|
|
"Variables": {
|
|
"NOVA_USERS_TABLE": "nova-users",
|
|
"NOVA_SESSIONS_TABLE": "nova-sessions",
|
|
"NOVA_PASSWORD_RESETS_TABLE": "nova-password-resets",
|
|
"NOVA_PATS_TABLE": "nova-pats"
|
|
}
|
|
},
|
|
"Code": {
|
|
"ZipFile": "def lambda_handler(event, context):\n return {}"
|
|
}
|
|
}
|
|
},
|
|
"NovaIdpTokenVendFunction": {
|
|
"Type": "AWS::Lambda::Function",
|
|
"Properties": {
|
|
"Handler": "nova_idp_token_vend.lambda_handler",
|
|
"Runtime": "python3.12",
|
|
"MemorySize": 512,
|
|
"Timeout": 30,
|
|
"Role": {
|
|
"Fn::GetAtt": [
|
|
"NovaIdpTokenVendRole",
|
|
"Arn"
|
|
]
|
|
},
|
|
"Environment": {
|
|
"Variables": {
|
|
"NOVA_USERS_TABLE": "nova-users",
|
|
"NOVA_SESSIONS_TABLE": "nova-sessions",
|
|
"NOVA_PASSWORD_RESETS_TABLE": "nova-password-resets",
|
|
"NOVA_PATS_TABLE": "nova-pats",
|
|
"NOVA_OIDC_KMS_KEY_ID": "alias/nova-oidc-signing"
|
|
}
|
|
},
|
|
"Code": {
|
|
"ZipFile": "def lambda_handler(event, context):\n return {}"
|
|
}
|
|
}
|
|
},
|
|
"NovaIdpJwksFunction": {
|
|
"Type": "AWS::Lambda::Function",
|
|
"Properties": {
|
|
"Handler": "nova_idp_jwks.lambda_handler",
|
|
"Runtime": "python3.12",
|
|
"MemorySize": 256,
|
|
"Timeout": 30,
|
|
"Role": {
|
|
"Fn::GetAtt": [
|
|
"NovaIdpJwksRole",
|
|
"Arn"
|
|
]
|
|
},
|
|
"Environment": {
|
|
"Variables": {
|
|
"NOVA_OIDC_KMS_KEY_ID": "alias/nova-oidc-signing"
|
|
}
|
|
},
|
|
"Code": {
|
|
"ZipFile": "def lambda_handler(event, context):\n return {}"
|
|
}
|
|
}
|
|
},
|
|
"NovaIdpAuthUrl": {
|
|
"Type": "AWS::Lambda::Url",
|
|
"Properties": {
|
|
"TargetFunction": {
|
|
"Ref": "NovaIdpAuthFunction"
|
|
},
|
|
"AuthType": "AWS_IAM"
|
|
}
|
|
},
|
|
"NovaIdpTokenVendUrl": {
|
|
"Type": "AWS::Lambda::Url",
|
|
"Properties": {
|
|
"TargetFunction": {
|
|
"Ref": "NovaIdpTokenVendFunction"
|
|
},
|
|
"AuthType": "AWS_IAM"
|
|
}
|
|
},
|
|
"NovaIdpJwksUrl": {
|
|
"Type": "AWS::Lambda::Url",
|
|
"Properties": {
|
|
"TargetFunction": {
|
|
"Ref": "NovaIdpJwksFunction"
|
|
},
|
|
"AuthType": "NONE"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
``` |