AWSTemplateFormatVersion: "2010-09-09"
Description: "DDB Table and IAM Managed Policies/Role for AWS KMS Hierarchical Keyring Testing"

Parameters:
  TableName:
    Type: String
    Description: Test Table Name
    Default: HierarchicalKeyringTestTable
  KeyStoreTable:
    Type: String
    Description: Key Store Test Table Name
    Default: KeyStoreTestTable
  KeyStoreDdbTable:
    Type: String
    Description: Key Store DynamoDB Table Name
    Default: KeyStoreDdbTable
  KeyStoreStaticTable:
    Type: String
    Description: Key Store Static Table Name
    Default: KeyStoreStaticTable
  ProjectName:
    Type: String
    Description: A prefix that will be applied to any names
    # This must remain ESDK-Dafny, or several GHWs will break
    Default: ESDK-Dafny
  GitHubRepo:
    Type: String
    Description: GitHub Repo that invokes CI
    Default: aws/private-aws-encryption-sdk-dafny-staging

Resources:
  KeyStoreTestTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "branch-key-id"
          AttributeType: "S"
        - AttributeName: "type"
          AttributeType: "S"
        - AttributeName: "status"
          AttributeType: "S"
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: "branch-key-id"
          KeyType: "HASH"
        - AttributeName: "type"
          KeyType: "RANGE"
      TableName: !Ref KeyStoreTable
      GlobalSecondaryIndexes:
        - IndexName: !Sub "Active-Keys"
          KeySchema:
            - AttributeName: "branch-key-id"
              KeyType: "HASH"
            - AttributeName: "status"
              KeyType: "RANGE"
          Projection:
            ProjectionType: "ALL"
        - IndexName: !Sub "Active-Keys-KeyStoreTestTable"
          KeySchema:
            - AttributeName: "branch-key-id"
              KeyType: "HASH"
            - AttributeName: "status"
              KeyType: "RANGE"
          Projection:
            ProjectionType: "ALL"

  KeyStoreTestDdbTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "branch-key-id"
          AttributeType: "S"
        - AttributeName: "type"
          AttributeType: "S"
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: "branch-key-id"
          KeyType: "HASH"
        - AttributeName: "type"
          KeyType: "RANGE"
      TableName: !Ref KeyStoreDdbTable

  HierarchicalKeyringTestTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "branch-key-id"
          AttributeType: "S"
        - AttributeName: "version"
          AttributeType: "S"
        - AttributeName: "status"
          AttributeType: "S"
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: "branch-key-id"
          KeyType: "HASH"
        - AttributeName: "version"
          KeyType: "RANGE"
      TableName: !Ref TableName
      GlobalSecondaryIndexes:
        - IndexName: "Active-Keys"
          KeySchema:
            - AttributeName: "status"
              KeyType: "HASH"
            - AttributeName: "branch-key-id"
              KeyType: "RANGE"
          Projection:
            ProjectionType: "ALL"

  # Static Key Store table for storing static branch keys
  KeyStoreTestStaticTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "branch-key-id"
          AttributeType: "S"
        - AttributeName: "type"
          AttributeType: "S"
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: "branch-key-id"
          KeyType: "HASH"
        - AttributeName: "type"
          KeyType: "RANGE"
      TableName: !Ref KeyStoreStaticTable

  StaticKeyStoreTableReadOnly:
    Type: "AWS::IAM::ManagedPolicy"
    Properties:
      Description: "Allow Read-Only access to Static Key Store Table"
      ManagedPolicyName: !Sub "${ProjectName}-DDB-${KeyStoreStaticTable}-ReadOnly-${AWS::Region}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - dynamodb:DescribeTable
              - dynamodb:GetItem
              - dynamodb:Query
              - dynamodb:BatchGetItem
              - dynamodb:Scan
            Resource:
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${KeyStoreStaticTable}"
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${KeyStoreStaticTable}/index/*"

  # This policy SHOULD be given to:
  #  - aws/private-aws-encryption-sdk-dafny-staging
  #  - ToolsDevelopment
  HierarchicalKeyringTestTableUsage:
    Type: "AWS::IAM::ManagedPolicy"
    Properties:
      Description: "Allow Read, Write, and Delete of Items in HierarchicalKeyringTestTable"
      ManagedPolicyName: !Sub "${ProjectName}-DDB-ReadWriteDelete-${AWS::Region}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - dynamodb:DescribeTable
              - dynamodb:CreateTable
              - dynamodb:PutItem
              - dynamodb:DeleteItem
              - dynamodb:GetItem
              - dynamodb:Query
              - dynamodb:ConditionCheckItem
              - dynamodb:UpdateItem
              - dynamodb:BatchGetItem
              - dynamodb:Scan
            Resource:
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${KeyStoreDdbTable}"
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${KeyStoreDdbTable}/index/*"
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${KeyStoreTestTable}"
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${KeyStoreTestTable}/index/*"
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${HierarchicalKeyringTestTable}"
              - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${HierarchicalKeyringTestTable}/index/*"

  HierarchicalGitHubKMSKeyID:
    Type: "AWS::KMS::Key"
    Properties:
      Description: KMS Key for GitHub Action Workflow
      Enabled: true
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"

  HierarchicalGitHubKMSKeyIDTwo:
    Type: "AWS::KMS::Key"
    Properties:
      Description: Another KMS Key for GitHub Action Workflow
      Enabled: true
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"

  KmsKeyForHV1ReEncryptStrategy:
    Type: "AWS::KMS::Key"
    Properties:
      Description: KMS Key for GitHub Action Workflow for HV1 Only Branch Keys
      Enabled: true
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"

  KmsKeyForHV2Only:
    Type: "AWS::KMS::Key"
    Properties:
      Description: KMS Key for GitHub Action Workflow for HV2 Only Branch Keys
      Enabled: true
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"

  KeyStoreAdminSystemKeyKmsSymEnc:
    Type: "AWS::KMS::Key"
    Properties:
      Description: KMS Key for System Key
      Enabled: true
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"
  EccP256:
    Type: "AWS::KMS::Key"
    Properties:
      Description: ECC Key with P-256
      KeySpec: ECC_NIST_P256
      KeyUsage: SIGN_VERIFY
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"
  EccP384:
    Type: "AWS::KMS::Key"
    Properties:
      Description: ECC Key with P-384
      KeySpec: ECC_NIST_P384
      KeyUsage: SIGN_VERIFY
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"
  EccP521:
    Type: "AWS::KMS::Key"
    Properties:
      Description: ECC Key with P-521
      KeySpec: ECC_NIST_P521
      KeyUsage: SIGN_VERIFY
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"

  KMSUsage:
    Type: "AWS::IAM::ManagedPolicy"
    Properties:
      PolicyDocument: !Sub |
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:GenerateDataKey",
                "kms:GenerateDataKeyWithoutPlaintext",
                "kms:ReEncrypt*",
                "kms:DescribeKey",
                "kms:CreateGrant",
                "kms:ListGrant",
                "kms:RevokeGrant"
              ],
              "Resource": [
                "arn:aws:kms:*:${AWS::AccountId}:key/${HierarchicalGitHubKMSKeyID}",
                "arn:aws:kms:*:${AWS::AccountId}:key/${HierarchicalGitHubKMSKeyIDTwo}"
              ]
            },
            {
              "Effect": "Allow",
              "Action": [
                "kms:ReEncrypt*",
                "kms:GenerateDataKeyWithoutPlaintext",
                "kms:Decrypt"
              ],
              "Resource": [
                "arn:aws:kms:*:${AWS::AccountId}:key/${KmsKeyForHV1ReEncryptStrategy}"
              ]
            }, 
            {
              "Effect": "Allow",
              "Action": [
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:GenerateDataKey"
              ],
              "Resource": [
                "arn:aws:kms:*:${AWS::AccountId}:key/${KeyStoreAdminSystemKeyKmsSymEnc}",
                "arn:aws:kms:*:${AWS::AccountId}:key/${KmsKeyForHV2Only}"
              ]
            },            
            {
              "Effect": "Allow",
              "Action": [
                "kms:*"
              ],
              "Resource": [
                "arn:aws:kms:*:${AWS::AccountId}:key/${EccP256}",
                "arn:aws:kms:*:${AWS::AccountId}:key/${EccP384}",
                "arn:aws:kms:*:${AWS::AccountId}:key/${EccP521}"
              ]
            },
            {
              "Effect": "Allow",
              "Action": [
                "kms:GenerateRandom"
              ],
              "Resource": [
                "*"
              ]
            }   
          ]
        }
      ManagedPolicyName: Hierarchical-GitHub-KMS-Key-Policy

  RSAGitHubKMSKeyID:
    Type: "AWS::KMS::Key"
    Properties:
      Description: KMS RSA Key for GitHub Action Workflow
      Enabled: true
      KeyPolicy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"
      KeySpec: "RSA_2048"
      KeyUsage: "ENCRYPT_DECRYPT"
      MultiRegion: true

  RSAKMSUsage:
    Type: "AWS::IAM::ManagedPolicy"
    Properties:
      PolicyDocument: !Sub |
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:Generate*",
                "kms:GetPublicKey",
                "kms:DescribeKey"
              ],
              "Resource": "arn:aws:kms:*:${AWS::AccountId}:key/${RSAGitHubKMSKeyID}"
            }
          ]
        }
      ManagedPolicyName: RSA-GitHub-KMS-Key-Policy

  # The MPL-Dafny Repo get access to everything here
  # via the CI.yaml#GitHubCIRole
  GitHubCIRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "GitHub-CI-${ProjectName}-Role-${AWS::Region}"
      Description: "Access DDB, KMS, Resources for CI from GitHub"
      ManagedPolicyArns:
        - "arn:aws:iam::370957321024:policy/KMS-Public-CMK-EncryptDecrypt-Key-Access"
        - "arn:aws:iam::370957321024:policy/Github-ECDH-KMS"
        - "arn:aws:iam::370957321024:policy/PolymorphTestModels-KMS-us-west-2"
        - !Ref KMSUsage
        - !Ref RSAKMSUsage
        - "arn:aws:iam::370957321024:policy/PolymorphTestModels-DDB-ReadWriteDelete-us-west-2"
        - !Ref HierarchicalKeyringTestTableUsage
        - !Ref StaticKeyStoreTableReadOnly
      AssumeRolePolicyDocument: !Sub |
        {
          "Version": "2012-10-17",   
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": { "Federated": "arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com" },
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                  "token.actions.githubusercontent.com:sub": "repo:${GitHubRepo}:*"
                }
              }
            },
            {
              "Effect": "Allow",
              "Principal": { "AWS": "arn:aws:iam::${AWS::AccountId}:role/ToolsDevelopment" },
              "Action": "sts:AssumeRole"
            }
          ]
        }

  RestrictedKMSHKeyOneOnly:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "Restricted-KMS-HKey-One-Only"
      Description: "Restricted to only KMS Key One"
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "kms:CreateGrant"
                  - "kms:Decrypt"
                  - "kms:DescribeKey"
                  - "kms:Encrypt"
                  - "kms:GenerateDataKeyWithoutPlaintext"
                  - "kms:ListGrant"
                  - "kms:RevokeGrant"
                Resource: !Sub "arn:aws:kms:*:${AWS::AccountId}:key/${HierarchicalGitHubKMSKeyID}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com"
            Action: "sts:AssumeRoleWithWebIdentity"
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: "sts.amazonaws.com"
              StringLike:
                token.actions.githubusercontent.com:sub:
                  - "repo:aws/private-aws-encryption-sdk-dafny-staging:*"
                  - "repo:aws/aws-encryption-sdk-dafny:*"
                  - "repo:aws/aws-cryptographic-material-providers-library:*"
                  - "repo:aws/private-aws-cryptographic-material-providers-library-dafny-staging:*"
          - Effect: Allow
            Principal:
              AWS:
                - !Sub "arn:aws:iam::${AWS::AccountId}:role/ToolsDevelopment"
                - "arn:aws:iam::648638458147:role/AVP-14101"
                - !GetAtt GitHubCIRole.Arn
                - "arn:aws:iam::370957321024:role/GitHub-CI-MPL-Dafny-Role-us-west-2"
            Action: "sts:AssumeRole"

  RestrictedKMSHKeyTwoOnly:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "Restricted-KMS-HKey-Two-Only"
      Description: "Restricted to only KMS Key Two"
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "kms:CreateGrant"
                  - "kms:Decrypt"
                  - "kms:DescribeKey"
                  - "kms:Encrypt"
                  - "kms:GenerateDataKeyWithoutPlaintext"
                  - "kms:ListGrant"
                  - "kms:RevokeGrant"
                Resource: !Sub "arn:aws:kms:*:${AWS::AccountId}:key/${HierarchicalGitHubKMSKeyIDTwo}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com"
            Action: "sts:AssumeRoleWithWebIdentity"
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: "sts.amazonaws.com"
              StringLike:
                token.actions.githubusercontent.com:sub:
                  - "repo:aws/private-aws-encryption-sdk-dafny-staging:*"
                  - "repo:aws/aws-encryption-sdk-dafny:*"
                  - "repo:aws/aws-cryptographic-material-providers-library:*"
                  - "repo:aws/private-aws-cryptographic-material-providers-library-dafny-staging:*"
          - Effect: Allow
            Principal:
              AWS:
                - !Sub "arn:aws:iam::${AWS::AccountId}:role/ToolsDevelopment"
                - "arn:aws:iam::648638458147:role/AVP-14101"
                - !GetAtt GitHubCIRole.Arn
                - "arn:aws:iam::370957321024:role/GitHub-CI-MPL-Dafny-Role-us-west-2"
            Action: "sts:AssumeRole"
