ワンクリックで
ipa-security
// Provision or update centralized security infrastructure (IAM roles) for an IPA project. Use when the user says 'security', 'set up security', 'IAM roles', or invokes /ipa-security.
// Provision or update centralized security infrastructure (IAM roles) for an IPA project. Use when the user says 'security', 'set up security', 'IAM roles', or invokes /ipa-security.
Compose a deployment from stack skills and generate executable artifacts (Makefiles, security disposition). Use when the user says 'compose', 'generate deployment', or invokes /ipa-compose.
Deploy a CodePipeline CI/CD pipeline with CodeBuild for automated build/test/deploy.
Deploy one-time prerequisite infrastructure from scripts/prepare.mk. Use when the user says 'prepare', 'deploy prerequisites', 'create ECR', or invokes /ipa-prepare.
Deploy a frontend tier stack: S3 static hosting + CloudFront distribution + OAC.
Deploy a centralized S3 log bucket for CloudFront, S3 access, and VPC flow logs.
[DEPRECATED] Use /ipa-compose codepipeline + /ipa-prepare instead.
| name | ipa-security |
| description | Provision or update centralized security infrastructure (IAM roles) for an IPA project. Use when the user says 'security', 'set up security', 'IAM roles', or invokes /ipa-security. |
| model | opus |
This skill provisions or updates centralized security infrastructure for an IPA project: IAM execution roles. It supports three configuration paths:
All paths produce one CloudFormation stack: {namespace}-{env}-security (IAM/roles). The resulting identifiers are written to .env for consumption by downstream IPA skills (/ipa-compose, /ipa-deploy, /ipa-codepipeline).
Initial security provisioning is triggered automatically on first /ipa-compose run. Direct invocation of /ipa-security is reserved for reviewing or updating an existing configuration.
AWS credential resolution: All
awsCLI commands must be prefixed withsource .env 2>/dev/null;to load credentials into the environment. Do NOT pass--profileor--regionflags explicitly.
The skill manages these variables in the .env file's # IPA Security Configuration block:
| Variable | Set By | Condition | Description |
|---|---|---|---|
APP_BUILDER_ROLE_ARN | Stack output or builder input | Always | Builder execution role ARN |
APP_CODEBUILD_ROLE_ARN | Stack output or builder input | Always (managed policy) / Optional (existing role) | CodeBuild execution role ARN |
APP_KMS_KEY_ARN | (removed — no longer prompted) | (legacy) | KMS key ARN — skill always uses SSE-S3 (AES-256); this variable is not written to .env |
Derived at runtime (not stored in
.env):
- Security stack name:
{APP_NAMESPACE}-{APP_ENV}-security(convention)- Managed policy: read from CloudFormation stack parameters via
describe-stacks
Security variables use standard KEY=VALUE format — no quotes, no export, no spaces around =. They are written as a group under the # IPA Security Configuration header comment, AFTER the existing # IPA Project Configuration block written by /ipa-init.
Validate every builder-provided value before proceeding. If validation fails, display the error message and re-prompt.
| Input | Pattern | Error Message |
|---|---|---|
| Managed policy (short name) | /^[A-Za-z][A-Za-z0-9+=,.@_-]{0,127}$/ | "Invalid policy name — must be a valid IAM policy name" |
| Managed policy (AWS ARN) | /^arn:aws:iam::aws:policy\/[A-Za-z0-9+=,.@_\/-]+$/ | "Invalid AWS managed policy ARN format" |
| Managed policy (custom ARN) | /^arn:aws:iam::\d{12}:policy\/[A-Za-z0-9+=,.@_\/-]+$/ | "Invalid customer managed policy ARN format" |
| Existing role ARN | /^arn:aws:iam::\d{12}:role\/[A-Za-z0-9+=,.@_\/-]+$/ | "Invalid role ARN — expected format: arn:aws:iam::{account}:role/{name}" |
| KMS key ARN | /^arn:aws:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9-]+$/ | "Invalid KMS key ARN format" |
Accept all three managed policy formats:
MyCustomPolicy → resolve to arn:aws:iam::aws:policy/MyCustomPolicyarn:aws:iam::aws:policy/ReadOnlyAccess → use as-isarn:aws:iam::123456789012:policy/CustomPolicy → use as-isBefore any prompting, verify prerequisites and determine execution flow.
.env PrerequisitesRead .env at the project root and check for these variables (written by /ipa-init):
APP_NAMESPACEAPP_ENVAWS_ACCOUNT_IDAWS_REGIONAWS_PROFILEIf any are missing: STOP with: "Cannot proceed — .env is missing required IPA variables. Run /ipa-init first to configure project defaults."
Check if .env contains APP_BUILDER_ROLE_ARN:
Compute the stack name: {APP_NAMESPACE}-{APP_ENV}-security
Run:
source .env 2>/dev/null; aws cloudformation describe-stacks \
--stack-name {APP_NAMESPACE}-{APP_ENV}-security \
--query 'Stacks[0].StackStatus' \
--output text
ROLLBACK_COMPLETE → route to Update Flow.ROLLBACK_COMPLETE → route to ROLLBACK_COMPLETE Recovery (see "Error Handling" section).Use AskUserQuestion with 1 question:
Security configuration (header: "IAM Roles", multiSelect: false)
Question: "How should IPA configure IAM execution roles?"
Options:
If the builder selects "Innovation Builder Stack" → proceed to Step 3c: Innovation Builder Stack.
If the builder selects "Managed policy" → proceed to Step 3a: Managed Policy Input.
If the builder selects "Existing role ARNs" → proceed to Step 3b: Existing Role ARN Input.
MyCustomPolicy or arn:aws:iam::123456789012:policy/MyPolicy).arn: prefix): resolve to arn:aws:iam::aws:policy/{name}.ManagedPolicyArn for template generation.source .env 2>/dev/null; aws iam get-role \
--role-name {role_name_extracted_from_arn}
{arn}. Check the ARN and try again." and re-prompt./ipa-codepipeline):"aws iam get-role check).APP_CODEBUILD_ROLE_ARN will be omitted from .env.After role validation, display:
Note: IPA cannot validate that these roles have sufficient permissions for your composed pattern. If deployments fail with permission errors, re-run
/ipa-securitywith a managed policy instead.
When the builder selects the Innovation Builder path, gather two inputs:
Use AskUserQuestion:
aws sts get-caller-identity"If "Use my current caller":
source .env 2>/dev/null; aws sts get-caller-identity --query Arn --output textarn:aws:sts::{acct}:assumed-role/{role}/{session}):
arn:aws:iam::{acct}:role/{role}{converted_arn} (converted from assumed-role session)"arn:aws:iam::{acct}:user/{name}) or root (arn:aws:iam::{acct}:root):
{arn}"If "Paste ARN":
^arn:aws:iam::\d{12}:(role|user)/.+$ or ^arn:aws:iam::\d{12}:root$Store the validated ARN as TRUSTED_PRINCIPAL_ARN.
Compute the default: today + 6 months.
date -v+6m +%Y-%m-%ddate -d "+6 months" +%Y-%m-%dPrompt: "Enter role expiration date (YYYY-MM-DD, default: {computed_default}):"
^\d{4}-\d{2}-\d{2}$ and must be > today.Store as ROLE_EXPIRATION_DATE.
Proceed to Step 5: Confirmation Summary with path = "Innovation Builder Stack".
Display a confirmation table before deployment. Adapt the content based on the chosen path.
┌──────────────────────┬─────────────────────────────────────────────────┬───────────────┐
│ Setting │ Value │ Source │
├──────────────────────┼─────────────────────────────────────────────────┼───────────────┤
│ Path │ Managed Policy │ prompted │
│ Managed Policy │ {builder's policy} │ prompted │
│ Builder Role │ (will be created) │ generated │
│ CodeBuild Role │ (will be created) │ generated │
│ Security Stack │ myproject-dev-security │ computed │
└──────────────────────┴─────────────────────────────────────────────────┴───────────────┘
┌──────────────────────┬─────────────────────────────────────────────────┬───────────────┐
│ Setting │ Value │ Source │
├──────────────────────┼─────────────────────────────────────────────────┼───────────────┤
│ Path │ Existing Role ARNs │ prompted │
│ Builder Role ARN │ arn:aws:iam::123456789012:role/my-builder │ prompted │
│ CodeBuild Role ARN │ (skipped — deferred to /ipa-codepipeline) │ skipped │
│ Security Stack │ myproject-dev-security │ computed │
└──────────────────────┴─────────────────────────────────────────────────┴───────────────┘
┌──────────────────────┬─────────────────────────────────────────────────┬───────────────┐
│ Setting │ Value │ Source │
├──────────────────────┼─────────────────────────────────────────────────┼───────────────┤
│ Path │ Innovation Builder Stack │ prompted │
│ Trusted Principal │ arn:aws:iam::123456789012:role/MySSO │ detected │
│ Role Expiration │ 2026-11-07 │ default+6mo │
│ Builder Role │ (will be created: myproject-dev-builder) │ generated │
│ CodeBuild Role │ (will be created: myproject-dev-codebuild) │ generated │
│ SageMaker Role │ (will be created: myproject-dev-sagemaker) │ generated │
│ EC2 Builder Role │ (will be created: myproject-dev-ec2-builder) │ generated │
│ Security Stack │ myproject-dev-security │ computed │
└──────────────────────┴─────────────────────────────────────────────────┴───────────────┘
Use AskUserQuestion:
Question: "Deploy this security configuration?"
Header: "Deploy"
Options:
multiSelect: false
If "Yes, deploy" → proceed to Step 6: Generate and Deploy.
If "No, start over" → restart from Step 2.
Create the directory if it does not exist:
mkdir -p infra/cfn/generated
infra/cfn/generated/iam.ymlWrite infra/cfn/generated/iam.yml (IAM roles only, no log bucket):
AWSTemplateFormatVersion: "2010-09-09"
Description: "IPA Security Stack — IAM execution roles (managed policy path)"
Parameters:
Namespace:
Type: String
Environment:
Type: String
AccountId:
Type: String
ManagedPolicyArn:
Type: String
Resources:
BuilderExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${Namespace}-${Environment}-builder"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Sub "arn:aws:iam::${AccountId}:root"
Action: "sts:AssumeRole"
ManagedPolicyArns:
- !Ref ManagedPolicyArn
CodeBuildExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${Namespace}-${Environment}-codebuild"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: "sts:AssumeRole"
ManagedPolicyArns:
- !Ref ManagedPolicyArn
Outputs:
BuilderRoleArn:
Value: !GetAtt BuilderExecutionRole.Arn
Export:
Name: !Sub "${AWS::StackName}-BuilderRoleArn"
CodeBuildRoleArn:
Value: !GetAtt CodeBuildExecutionRole.Arn
Export:
Name: !Sub "${AWS::StackName}-CodeBuildRoleArn"
No template generated — roles already exist. Skip to Step 7.
No template generated — uses the existing vendored template at
infra/cfn/security/innovation-builder-security.yml (consumed as-is, never modified).
Deploy one CloudFormation stack: {APP_NAMESPACE}-{APP_ENV}-security.
source .env 2>/dev/null; aws cloudformation deploy \
--template-file infra/cfn/generated/iam.yml \
--stack-name {APP_NAMESPACE}-{APP_ENV}-security \
--parameter-overrides \
Namespace={APP_NAMESPACE} \
Environment={APP_ENV} \
AccountId={AWS_ACCOUNT_ID} \
ManagedPolicyArn={resolved_arn} \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
No security stack deployment needed (roles already exist). Skip to Step 8.
source .env 2>/dev/null; aws cloudformation deploy \
--template-file infra/cfn/security/innovation-builder-security.yml \
--stack-name {APP_NAMESPACE}-{APP_ENV}-security \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides \
TrustedPrincipalArn={TRUSTED_PRINCIPAL_ARN} \
RoleExpirationDate={ROLE_EXPIRATION_DATE} \
BoundaryPolicyName={APP_NAMESPACE}-{APP_ENV}-InnovationBuilderBoundary \
CodeBuildRoleName={APP_NAMESPACE}-{APP_ENV}-codebuild \
SageMakerRoleName={APP_NAMESPACE}-{APP_ENV}-sagemaker \
EC2BuilderRoleName={APP_NAMESPACE}-{APP_ENV}-ec2-builder \
BuilderRoleName={APP_NAMESPACE}-{APP_ENV}-builder \
--no-fail-on-empty-changeset
Monitor the deployment. If it fails, proceed to the Error Handling section.
If the deployment succeeds, proceed to Step 8: Write .env.
For paths A (Managed Policy) and C (Innovation Builder), read outputs from the security stack:
source .env 2>/dev/null; aws cloudformation describe-stacks \
--stack-name {APP_NAMESPACE}-{APP_ENV}-security \
--query 'Stacks[0].Outputs' \
--output json
Extract:
BuilderRoleArn → APP_BUILDER_ROLE_ARNCodeBuildRoleArn → APP_CODEBUILD_ROLE_ARNFor path B (Existing Role ARN), the builder provided the values directly.
# IPA Security Configuration
# Generated by /ipa-security — local only, do not commit
APP_BUILDER_ROLE_ARN={from stack output BuilderRoleArn}
APP_CODEBUILD_ROLE_ARN={from stack output CodeBuildRoleArn}
# IPA Security Configuration
# Generated by /ipa-security — local only, do not commit
APP_BUILDER_ROLE_ARN={builder-provided ARN}
Include APP_CODEBUILD_ROLE_ARN={builder-provided ARN} only if the builder provided a CodeBuild role ARN (not skipped).
# IPA Security Configuration
# Generated by /ipa-security — local only, do not commit
APP_BUILDER_ROLE_ARN={from stack output BuilderRoleArn}
APP_CODEBUILD_ROLE_ARN={from stack output CodeBuildRoleArn}
.env file.# IPA Security Configuration header line.# IPA Project Configuration block), non-IPA variables, comments, and blank lines MUST remain unchanged in their original positions.Display: "Security infrastructure deployed. .env updated with security variables."
Show a summary of written values:
Written to .env:
APP_BUILDER_ROLE_ARN={value}
APP_CODEBUILD_ROLE_ARN={value}
Stack deployed:
{APP_NAMESPACE}-{APP_ENV}-security (IAM roles)
If invoked as part of /ipa-compose (mode=init), return control to compose silently.
If invoked directly, display next steps:
Next steps:
• Run `/ipa-compose` to compose infrastructure and generate Makefiles
• Run `/ipa-security` again to review or update the configuration
This flow runs when pre-flight checks detect existing security configuration (Step 1.2 or 1.3).
.env: APP_BUILDER_ROLE_ARN, APP_CODEBUILD_ROLE_ARN (may be absent){APP_NAMESPACE}-{APP_ENV}-securitysource .env 2>/dev/null; aws cloudformation describe-stacks \
--stack-name {APP_NAMESPACE}-{APP_ENV}-security \
--output json
Stacks[0].StackStatus — verify it's a *_COMPLETE state (not ROLLBACK_COMPLETE)Stacks[0].Parameters — determine active path:
TrustedPrincipalArn parameter present → Innovation Builder path (C)ManagedPolicyArn parameter present → Managed Policy path (A)Stacks[0].Outputs — extract role ARNs (for display)Infrastructure context (optional):
Run:
source .env 2>/dev/null; aws cloudformation list-stacks \
--stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE \
--query "StackSummaries[?starts_with(StackName, '{APP_NAMESPACE}-{APP_ENV}')].{Name:StackName,Status:StackStatus,Updated:LastUpdatedTime}" \
--output table
If successful, display the output prefixed with:
Current Infrastructure ({APP_NAMESPACE}-{APP_ENV}):
{list-stacks output}
If the command fails, skip silently.
Security configuration table:
Display the configuration table using values from .env reads (role ARNs, KMS) and CloudFormation queries (path, managed policy, log bucket, stack name):
Current Security Configuration:
┌──────────────────────┬─────────────────────────────────────────────────┐
│ Setting │ Current Value │
├──────────────────────┼─────────────────────────────────────────────────┤
│ Path │ {from stack resources} │
│ Managed Policy │ {from stack parameter ManagedPolicyArn} │
│ Builder Role ARN │ {from .env APP_BUILDER_ROLE_ARN} │
│ CodeBuild Role ARN │ {from .env APP_CODEBUILD_ROLE_ARN} │
│ Security Stack │ {APP_NAMESPACE}-{APP_ENV}-security (computed) │
└──────────────────────┴─────────────────────────────────────────────────┘
Infer the current path from the stack's describe-stacks response:
TrustedPrincipalArn parameter present → "Innovation Builder Stack"ManagedPolicyArn parameter present → "Managed Policy"Pre-mark the active path in the three-way choice (Step 2) when the builder selects "Yes, update".
Use AskUserQuestion:
Question: "Would you like to update the security configuration?"
Header: "Update"
Options:
multiSelect: false
If "No, keep current": complete with "Security configuration is current. No changes needed."
If "Yes, update": proceed to Step 2 (Path Selection) to re-enter the full configuration flow.
If the builder is switching paths:
If CloudFormation returns "No updates are to be performed" during stack update:
.env from current stack outputs (in case .env was manually edited).If the security stack is in ROLLBACK_COMPLETE state:
{stack_name} is in ROLLBACK_COMPLETE state from a previous failed deployment."source .env 2>/dev/null; aws cloudformation delete-stack \
--stack-name {stack_name}
Wait for deletion to complete:
source .env 2>/dev/null; aws cloudformation wait stack-delete-complete \
--stack-name {stack_name}
Then proceed with the First-Time Flow (Step 2)./ipa-security."If CloudFormation deployment fails with an IAM permission error:
source .env 2>/dev/null; aws cloudformation describe-stack-events \
--stack-name {stack_name} \
--query 'StackEvents[?ResourceStatus==`CREATE_FAILED`].[LogicalResourceId,ResourceStatusReason]' \
--output table
iam:CreateRole and s3:CreateBucket permissions. Options: (a) use the existing-role-ARN path instead, (b) obtain the required permissions and retry."If CloudFormation fails with BucketAlreadyExists:
Display: "The log bucket name {bucket_name} already exists in S3 (bucket names are globally unique). This usually means another project or account owns this name. Consider changing your APP_NAMESPACE via /ipa-init to generate a different bucket name."
If CloudFormation fails because the managed policy does not exist:
AWS::IAM::Role failure.{policy} was not found. Check the policy name/ARN and try again."If .env does not exist or does not contain IPA init variables:
STOP with: "Cannot proceed — .env is missing or does not contain IPA project configuration. Run /ipa-init first."
.env security block is missing: Treat as an update scenario. Read stack outputs and re-populate .env..env has security variables but stack doesn't exist: Warn the builder that the stack may have been manually deleted. Offer to re-deploy or clear .env security variables.aws cloudformation list-stacks fails: Skip the infrastructure context display and proceed with the security-specific update flow using targeted describe-stacks calls. The infrastructure listing is informational, not blocking.