# 600 Reference 33118ac4

> AWS CloudFormation Security - Reference

- Skill: `tools-only/600-reference-33118ac4` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/600-reference-33118ac4`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/600-reference-33118ac4/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/600-reference-33118ac4

---

# AWS CloudFormation Security - Reference

This reference guide contains detailed information about AWS CloudFormation resources and configurations for infrastructure security, encryption, and secrets management.

## AWS::KMS::Key

Creates a customer master key (CMK) in AWS Key Management Service.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| KeyPolicy | Json | Yes | The key policy document |
| Description | String | No | Description of the key |
| KeyUsage | String | No | Key usage (ENCRYPT_DECRYPT or SIGN_VERIFY) |
| EnableKeyRotation | Boolean | No | Enable automatic key rotation |
| PendingWindowInDays | Integer | No | Pending deletion window (7-30 days) |
| MultiRegion | Boolean | No | Enable multi-region key |

### Key Policy Structure

```yaml
KeyPolicy:
  Version: "2012-10-17"
  Id: "key-policy-identifier"
  Statement:
    - Sid: "EnableIAMPolicies"
      Effect: Allow
      Principal:
        AWS: "arn:aws:iam::account-id:role/role-name"
      Action:
        - kms:Create*
        - kms:Describe*
        - kms:Enable*
        - kms:List*
        - kms:Put*
        - kms:Update*
        - kms:Revoke*
        - kms:Disable*
        - kms:Get*
        - kms:Delete*
        - kms:TagResource
        - kms:UntagResource
      Resource: "*"
    - Sid: "AllowCryptographicOperations"
      Effect: Allow
      Principal:
        AWS: "arn:aws:iam::account-id:role/role-name"
      Action:
        - kms:Encrypt
        - kms:Decrypt
        - kms:GenerateDataKey*
        - kms:ReEncrypt*
      Resource: "*"
```

### Key Policy Conditions

```yaml
Conditions:
  - StringEquals:
      aws:PrincipalOrgID: "o-organization-id"
  - StringEquals:
      aws:SourceAccount: !Ref AWS::AccountId
  - ArnEquals:
      aws:SourceArn: "arn:aws:lambda:region:account:function:function-name"
```

### Example

```yaml
Resources:
  SecureKmsKey:
    Type: AWS::KMS::Key
    Properties:
      Description: "KMS Key for sensitive data encryption"
      KeyPolicy:
        Version: "2012-10-17"
        Id: "secure-key-policy"
        Statement:
          - Sid: "EnableIAMPolicies"
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:role/AdminRole"
            Action: kms:*
            Resource: "*"
          - Sid: "AllowCryptographicOperations"
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:role/AppRole"
            Action:
              - kms:Encrypt
              - kms:Decrypt
              - kms:GenerateDataKey*
            Resource: "*"
          - Sid: "AllowAWSServiceAccess"
            Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action:
              - kms:Encrypt
              - kms:Decrypt
              - kms:GenerateDataKey*
            Resource: "*"
            Condition:
              StringEquals:
                aws:SourceAccount: !Ref AWS::AccountId
      EnableKeyRotation: true
      PendingWindowInDays: 30
```

### Attributes

| Attribute | Description |
|-----------|-------------|
| Arn | The ARN of the key |
| KeyId | The unique identifier of the key |

## AWS::KMS::Alias

Creates an alias for a KMS key.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| AliasName | String | Yes | The alias name (must start with 'alias/') |
| TargetKeyId | String | Yes | The key ID to associate with the alias |

### Example

```yaml
Resources:
  KmsKeyAlias:
    Type: AWS::KMS::Alias
    Properties:
      AliasName: !Sub "alias/application-${Environment}"
      TargetKeyId: !Ref SecureKmsKey
```

## AWS::SecretsManager::Secret

Creates a secret in AWS Secrets Manager.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| Name | String | No | The name of the secret |
| Description | String | No | Description of the secret |
| SecretString | String | No | The secret value |
| SecretStringTemplate | String | No | JSON template for secret values |
| GenerateSecretString | SecretGenerator | No | Generate secret automatically |
| KmsKeyId | String | No | KMS key ID for encryption |
| RotationRules | RotationRules | No | Automatic rotation configuration |
| RotationLambdaARN | String | No | Lambda function ARN for rotation |
| ResourcePolicy | Json | No | Resource-based policy |

### SecretGenerator Structure

```yaml
GenerateSecretString:
  SecretStringTemplate: '{"username": "admin"}'
  GenerateSecretKey: "password"
  PasswordLength: 32
  ExcludeCharacters: '"@/'
  ExcludeLowercase: false
  ExcludeUppercase: false
  ExcludeNumbers: false
  ExcludePunctuation: true
```

### RotationRules Structure

```yaml
RotationRules:
  AutomaticallyAfterDays: 30
  Duration: 8h
  ScheduleExpression: "rate(30 days)"
```

### Resource Policy Example

```yaml
ResourcePolicy:
  Version: "2012-10-17"
  Statement:
    - Sid: "AllowLambdaAccess"
      Effect: Allow
      Principal:
        AWS: "arn:aws:iam::account-id:role/LambdaRole"
      Action:
        - secretsmanager:GetSecretValue
        - secretsmanager:DescribeSecret
      Resource: "*"
      Condition:
        StringEquals:
          aws:ResourceTag/Environment: "production"
```

### Example

```yaml
Resources:
  DatabaseSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: !Sub "${AWS::StackName}/database/credentials"
      Description: "Database credentials with automatic rotation"
      SecretString: !Sub |
        {
          "username": "${DBUsername}",
          "password": "${DBPassword}",
          "host": "${DBHost}",
          "port": "${DBPort}"
        }
      KmsKeyId: !Ref SecretsKmsKeyId
      RotationRules:
        AutomaticallyAfterDays: 30
      ResourcePolicy:
        Version: "2012-10-17"
        Statement:
          - Sid: "AllowAppAccess"
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:role/AppRole"
            Action:
              - secretsmanager:GetSecretValue
            Resource: "*"
```

### Attributes

| Attribute | Description |
|-----------|-------------|
| Arn | The ARN of the secret |
| Name | The name of the secret |

## AWS::SSM::Parameter

Creates a parameter in AWS Systems Manager Parameter Store.

### Parameter Types

| Type | Description |
|------|-------------|
| String | Plain text parameter |
| StringList | Comma-separated list |
| SecureString | Encrypted parameter |

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| Name | String | No | The parameter name |
| Type | String | Yes | Parameter type (String, StringList, SecureString) |
| Value | String | Yes | The parameter value |
| Description | String | No | Description of the parameter |
| AllowedPattern | String | No | Regex pattern for validation |
| NoEcho | Boolean | No | Hide value in console |

### Example

```yaml
Parameters:
  DBCredentials:
    Type: AWS::SSM::Parameter::Value<SecureString>
    NoEcho: true
    Description: Database credentials
    Value: "/app/database/credentials"

  ApiEndpoint:
    Type: AWS::SSM::Parameter::Value<String>
    Description: API endpoint URL
    Value: "https://api.example.com"

  AllowedIPs:
    Type: AWS::SSM::Parameter::Value<StringList>
    Description: List of allowed IP addresses
    Value: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"

Resources:
  CustomParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Name: !Sub "/${AWS::StackName}/custom/setting"
      Type: SecureString
      Value: "sensitive-value"
      Description: "Custom secure parameter"
      AllowedPattern: "^[a-zA-Z0-9_-]+$"
```

## AWS::IAM::Role

Creates an IAM role for AWS services or cross-account access.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| RoleName | String | No | The name of the role |
| AssumeRolePolicyDocument | Json | Yes | Trust policy document |
| ManagedPolicyArns | List | No | AWS managed policies |
| Policies | List | No | Inline policies |
| PermissionsBoundary | String | No | Permissions boundary ARN |
| MaxSessionDuration | Integer | No | Max session duration (3600-43200) |
| Description | String | No | Description of the role |

### Assume Role Policy Examples

```yaml
# Service role for Lambda
AssumeRolePolicyDocument:
  Version: "2012-10-17"
  Statement:
    - Effect: Allow
      Principal:
        Service: lambda.amazonaws.com
      Action: sts:AssumeRole
      Condition:
        StringEquals:
          aws:SourceAccount: !Ref AWS::AccountId

# Cross-account role
AssumeRolePolicyDocument:
  Version: "2012-10-17"
  Statement:
    - Effect: Allow
      Principal:
        AWS:
          - !Sub "arn:aws:iam::account-id:root"
      Action: sts:AssumeRole
      Condition:
        StringEquals:
          aws:PrincipalAccount: "trusted-account-id"
        Bool:
          aws:MultiFactorAuthPresent: true
```

### Example

```yaml
Resources:
  SecureRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-secure-role"
      Description: "IAM role with least privilege"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      MaxSessionDuration: 3600
      PermissionsBoundary: !Ref PermissionsBoundary
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: SecretsPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - secretsmanager:GetSecretValue
                Resource: !Ref SecretArn
```

### Attributes

| Attribute | Description |
|-----------|-------------|
| Arn | The ARN of the role |
| RoleName | The name of the role |

## AWS::EC2::SecurityGroup

Creates a security group for VPC resources.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| GroupName | String | No | The name of the security group |
| GroupDescription | String | Yes | Description of the group |
| VpcId | String | No | VPC ID (required for non-default VPC) |
| SecurityGroupIngress | List | No | Inbound rules |
| SecurityGroupEgress | List | No | Outbound rules |
| Tags | List | No | Tags for the group |

### Security Group Rule Structure

```yaml
SecurityGroupIngress:
  - IpProtocol: tcp
    FromPort: 443
    ToPort: 443
    CidrIp: 0.0.0.0/0
    Description: "HTTPS from internet"
  - IpProtocol: tcp
    FromPort: 5432
    ToPort: 5432
    SourceSecurityGroupId: !Ref AppSecurityGroup
    Description: "PostgreSQL from app tier"
```

### Example

```yaml
Resources:
  SecureSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${AWS::StackName}-secure-sg"
      GroupDescription: "Security group with restricted rules"
      VpcId: !Ref VPCId
      Tags:
        - Key: Environment
          Value: !Ref Environment
      SecurityGroupIngress:
        # HTTPS from ALB
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          SourceSecurityGroupId: !Ref ALBSecurityGroup
          Description: "HTTPS from ALB"

        # SSH from bastion only
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          SourceSecurityGroupId: !Ref BastionSecurityGroup
          Description: "SSH from bastion host"

      SecurityGroupEgress:
        # HTTPS outbound
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: "HTTPS outbound"
```

## AWS::CertificateManager::Certificate

Creates an SSL/TLS certificate in AWS Certificate Manager.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| DomainName | String | Yes | Primary domain name |
| SubjectAlternativeNames | List | No | Additional domain names |
| DomainValidationOptions | List | No | Domain validation settings |
| ValidationMethod | String | No | Validation method (DNS or EMAIL) |
| Options | CertificateOptions | No | Additional certificate options |

### CertificateOptions Structure

```yaml
Options:
  CertificateTransparencyLoggingPreference: ENABLED | DISABLED
```

### Example

```yaml
Resources:
  SSLCertificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: example.com
      SubjectAlternativeNames:
        - "*.example.com"
        - "api.example.com"
      ValidationMethod: DNS
      DomainValidationOptions:
        - DomainName: example.com
          Route53HostedZoneId: !Ref HostedZoneId
        - DomainName: "*.example.com"
          Route53HostedZoneId: !Ref HostedZoneId
      Options:
        CertificateTransparencyLoggingPreference: ENABLED
```

### Attributes

| Attribute | Description |
|-----------|-------------|
| Arn | The ARN of the certificate |
| DomainName | The primary domain name |

## AWS::WAFv2::WebACL

Creates a Web ACL for AWS WAF.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| Name | String | Yes | The name of the Web ACL |
| Scope | String | Yes | CLOUDFRONT or REGIONAL |
| DefaultAction | Action | Yes | Default action for unmatched requests |
| Rules | List | No | List of rules |
| VisibilityConfig | VisibilityConfig | Yes | CloudWatch metrics configuration |

### Rule Structure

```yaml
Rules:
  - Name: "RateLimitRule"
    Priority: 1
    Statement:
      RateBasedStatement:
        Limit: 2000
        EvaluationWindowSec: 60
        AggregationKeyType: IP
    Action:
      Block:
        CustomResponse:
          ResponseCode: 429
          ResponseBody: "Too many requests"
    VisibilityConfig:
      SampledRequestsEnabled: true
      CloudWatchMetricsEnabled: true
      MetricName: RateLimitRule
```

### Action Types

```yaml
Action:
  Block:
    CustomResponse:
      ResponseCode: 403
      ResponseBody: "Request blocked"
      ResponseHeaders:
        - Name: X-Frame-Options
          Value: DENY
  Allow:
    CustomRequestHandling:
      InsertHeaders:
        - Name: X-Content-Type-Options
          Value: nosniff
  Count: {}
```

### Example

```yaml
Resources:
  SecureWebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name: !Sub "${AWS::StackName}-waf"
      Scope: REGIONAL
      DefaultAction:
        Allow: {}
      Rules:
        - Name: BlockSQLInjection
          Priority: 1
          Statement:
            SqliMatchStatement:
              FieldToMatch:
                Body:
                  OversizeHandling: CONTINUE
              SensitivityLevel: HIGH
          Action:
            Block:
              CustomResponse:
                ResponseCode: 403
                ResponseBody: "Request blocked - SQL injection detected"
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: BlockSQLInjection

        - Name: BlockXSS
          Priority: 2
          Statement:
            XssMatchStatement:
              FieldToMatch:
                QueryString:
                  OversizeHandling: CONTINUE
          Action:
            Block:
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: BlockXSS

        - Name: ManagedRuleSet
          Priority: 3
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesCommonRuleSet
              Version: Version_1.0
              ExcludedRules:
                - Name: SizeRestrictions_BODY
          Action:
            Count: {}
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: ManagedRuleSet

      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: !Sub "${AWS::StackName}-WAF"
        SampledRequestsEnabled: true
```

## AWS::Logs::LogGroup

Creates a CloudWatch Logs log group.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| LogGroupName | String | Yes | The name of the log group |
| RetentionInDays | Integer | No | Retention period in days |
| KmsKeyId | String | No | KMS key ID for encryption |
| LogGroupClass | String | No | Log group class (STANDARD or INFREQUENT_ACCESS) |

### Example

```yaml
Resources:
  EncryptedLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/${AWS::StackName}/application"
      RetentionInDays: 30
      KmsKeyId: !Ref ApplicationKmsKey
      LogGroupClass: STANDARD
```

### Attributes

| Attribute | Description |
|-----------|-------------|
| Arn | The ARN of the log group |

## AWS::EC2::VPCEndpoint

Creates a VPC endpoint for private connectivity to AWS services.

### Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| VpcId | String | Yes | The VPC ID |
| ServiceName | String | Yes | The service name |
| VpcEndpointType | String | No | Interface or Gateway |
| Subnets | List | Cond | Subnets for interface endpoints |
| SecurityGroups | List | Cond | Security groups for interface endpoints |
| PrivateDnsEnabled | Boolean | No | Enable private DNS |

### Example

```yaml
Resources:
  SecretsManagerEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPCId
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.secretsmanager"
      VpcEndpointType: Interface
      Subnets:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      SecurityGroups:
        - !Ref AppSecurityGroup
      PrivateDnsEnabled: true

  S3Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPCId
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcEndpointType: Gateway
      RouteTableIds:
        - !Ref PrivateRouteTable1
        - !Ref PrivateRouteTable2
```

## Intrinsic Functions per Security

### !GetAtt for Security Resources

```yaml
# Get KMS key ARN
KmsKeyArn: !GetAtt ApplicationKmsKey.Arn

# Get secret ARN
SecretArn: !Ref DatabaseSecret

# Get security group ID
SecurityGroupId: !Ref ApplicationSecurityGroup

# Get log group ARN
LogGroupArn: !GetAtt EncryptedLogGroup.Arn
```

### !Sub with AWS Variables

```yaml
# Construct ARN with account and region
RoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/${RoleName}"

# Construct secret name
SecretName: !Sub "${AWS::StackName}/${Service}/${Environment}"
```

### !ImportValue per Cross-Stack References

```yaml
# Import from network stack
VPCId: !ImportValue !Sub "${NetworkStackName}-VPCId"

# Import with function
SecurityGroupId: !ImportValue
  Fn::Sub: "${NetworkStackName}-SecurityGroupId"
```

## Condition Functions per Security

```yaml
Conditions:
  IsProduction: !Equals [!Ref Environment, production]
  EnableDetailedMonitoring: !Equals [!Ref Environment, production]
  UseCustomKMS: !Not [!Equals [!Ref KMSKeyId, ""]]
  EnableCrossAccount: !Equals [!Ref EnableCrossAccountAccess, true]

Resources:
  # Conditional KMS key
  ConditionalKmsKey:
    Type: AWS::KMS::Key
    Condition: UseCustomKMS
    Properties:
      Description: "Conditional KMS key"
      KeyPolicy: !Ref KeyPolicy

  # Conditional encryption
  EncryptedResource:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: !If [UseCustomKMS, aws:kms, AES256]
              KMSMasterKeyID: !If [UseCustomKMS, !Ref CustomKmsKey, !Ref AWS::NoValue]
```

## KMS Key States

| State | Description |
|-------|-------------|
| Enabled | Key is available for use |
| Disabled | Key is not available for use |
| PendingDeletion | Key is scheduled for deletion |
| PendingImport | Key is being imported |
| Unavailable | Key is unavailable |

## Secrets Manager Limits

| Resource | Limit |
|----------|-------|
| Secrets per account | 500,000 |
| Secret size | 65,536 bytes |
| Version stages | 20 per version |
| Rotation attempts | 3 per day |

## Security Group Limits

| Resource | Limit |
|----------|-------|
| Rules per security group | 60 inbound + 60 outbound |
| Security groups per VPC | 2,500 |
| Security groups per instance | 5 |

## Common Security Tags

```yaml
Resources:
  SecureResource:
    Type: AWS::KMS::Key
    Properties:
      Tags:
        - Key: Environment
          Value: !Ref Environment
        - Key: Project
          Value: !Ref ProjectName
        - Key: ManagedBy
          Value: CloudFormation
        - Key: SecurityClassification
          Value: "confidential"
        - Key: Compliance
          Value: "SOC2,ISO27001"
        - Key: Owner
          Value: "security-team@example.com"
```

