AWSTemplateFormatVersion: '2010-09-09'
Description: 'Dynatrace Data Acquisition AWS nested stackset roles  (v1.0.2 2026-03-05 11:57)'

Metadata:
  Version:
    Number: v1.0.2
    ReleaseDate: 2026-03-05 11:57

Parameters:
  pDynatraceEnvironmentId:
    Type: String
    Description: 'Your Dynatrace environment identifier (e.g. abc12345)'
    AllowedPattern: '^[a-z]{3}[a-z0-9]{5}$'

Resources:
  DynatraceStackSetExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub
        - 'DynatraceStackSetExecutionRole-${pDynatraceEnvironmentId}-${DeploymentHash}'
        - DeploymentHash: !Select [ 0, !Split [ '-', !Select [ 2, !Split [ '/', !Ref AWS::StackId ] ] ] ]
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !GetAtt DynatraceStackSetAdministrationRole.Arn
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: StackSetInstancesPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'events:ListTargetsByRule'
                  - 'events:DescribeRule'
                  - 'events:PutTargets'
                  - 'events:PutRule'
                  - 'events:DescribeApiDestination'
                  - 'events:CreateApiDestination'
                  - 'events:DescribeConnection'
                  - 'events:CreateConnection'
                  - 'events:UpdateConnection'
                  - 'events:DeleteConnection'
                  - 'events:DeleteApiDestination'
                  - 'events:DeleteRule'
                  - 'events:RemoveTargets'
                  - 'events:TagResource'
                  - 'events:UntagResource'
                Resource:
                  - 'arn:aws:events:*:*:rule/StackSet-DynatraceEvent*'
                  - 'arn:aws:events:*:*:rule/Dynatrace*'
                  - 'arn:aws:events:*:*:rule/*/StackSet-DynatraceEvent*'
                  - 'arn:aws:events:*:*:api-destination/DynatraceApiDestination*'
                  - 'arn:aws:events:*:*:connection/DynatraceConnection*'
              - Effect: Allow
                Action:
                  - 'secretsmanager:CreateSecret'
                Resource:
                  - !Sub 'arn:aws:secretsmanager:*:${AWS::AccountId}:secret:events!connection/DynatraceConnection-${pDynatraceEnvironmentId}-*'
              - Effect: Allow
                Action:
                  - 'secretsmanager:CreateSecret'
                Resource:
                  - !Sub 'arn:aws:secretsmanager:*:${AWS::AccountId}:secret:/dynatrace/*'
                Condition:
                  StringEquals:
                    'aws:RequestTag/dt:CreatedBy': 'Dynatrace'
                    'aws:RequestTag/dt:EnvironmentID': !Ref pDynatraceEnvironmentId
              - Effect: Allow
                Action:
                  - 'secretsmanager:DescribeSecret'
                  - 'secretsmanager:UpdateSecret'
                  - 'secretsmanager:GetSecretValue'
                  - 'secretsmanager:PutSecretValue'
                  - 'secretsmanager:TagResource'
                  - 'secretsmanager:DeleteSecret'
                Resource:
                  - !Sub 'arn:aws:secretsmanager:*:${AWS::AccountId}:secret:events!connection/DynatraceConnection-${pDynatraceEnvironmentId}-*'
              - Effect: Allow
                Action:
                  - 'secretsmanager:DescribeSecret'
                  - 'secretsmanager:UpdateSecret'
                  - 'secretsmanager:GetSecretValue'
                  - 'secretsmanager:PutSecretValue'
                  - 'secretsmanager:TagResource'
                  - 'secretsmanager:DeleteSecret'
                Resource:
                  - !Sub 'arn:aws:secretsmanager:*:${AWS::AccountId}:secret:/dynatrace/*'
                Condition:
                  StringEquals:
                    'aws:ResourceTag/dt:CreatedBy': 'Dynatrace'
                    'aws:ResourceTag/dt:EnvironmentID': !Ref pDynatraceEnvironmentId
              - Effect: Allow
                Action:
                  - 'logs:DescribeLogGroups'
                Resource: 'arn:aws:logs:*:*:log-group:/aws/datafirehose/dynatrace/*'
              - Effect: Allow
                Action:
                  - 'kms:CreateKey'
                Resource: '*'
                Condition:
                  StringEquals:
                    'aws:RequestTag/dt:CreatedBy': 'Dynatrace'
                    'aws:RequestTag/dt:EnvironmentID': !Ref pDynatraceEnvironmentId
              - Effect: Allow
                Action:
                  - 'kms:DescribeKey'
                  - 'kms:GetKeyPolicy'
                  - 'kms:PutKeyPolicy'
                  - 'kms:ScheduleKeyDeletion'
                  - 'kms:TagResource'
                  - 'kms:UntagResource'
                Resource: !Sub 'arn:aws:kms:*:${AWS::AccountId}:key/*'
                Condition:
                  StringEquals:
                    'aws:ResourceTag/dt:CreatedBy': 'Dynatrace'
                    'aws:ResourceTag/dt:EnvironmentID': !Ref pDynatraceEnvironmentId
              - Effect: Allow
                Action:
                  - 'kms:ListAliases'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'kms:CreateAlias'
                  - 'kms:DeleteAlias'
                Resource:
                  - !Sub 'arn:aws:kms:*:${AWS::AccountId}:alias/dynatrace/*'
              - Effect: Allow
                Action:
                  - 'kms:CreateAlias'
                  - 'kms:DeleteAlias'
                Resource:
                  - !Sub 'arn:aws:kms:*:${AWS::AccountId}:key/*'
                Condition:
                  StringEquals:
                    'aws:ResourceTag/dt:CreatedBy': 'Dynatrace'
                    'aws:ResourceTag/dt:EnvironmentID': !Ref pDynatraceEnvironmentId
              - Effect: Allow
                Action:
                  - 'cloudformation:CreateStack'
                  - 'cloudformation:DescribeStacks'
                  - 'cloudformation:UpdateStack'
                  - 'cloudformation:ListStacks'
                  - 'cloudformation:DescribeStackResources'
                  - 'cloudformation:DeleteStack'
                  - 'cloudformation:ListStackSetOperationResults'
                Resource:
                  - 'arn:aws:cloudformation:*:*:stack/StackSet-DynatraceLogIngest*/*'
                  - 'arn:aws:cloudformation:*:*:stack/StackSet-DynatraceEventIngest*/*'
                  - 'arn:aws:cloudformation:*:*:stackset/DynatraceLogIngest*:*'
                  - 'arn:aws:cloudformation:*:*:stackset/DynatraceEventIngest*:*'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:DeleteLogGroup'
                  - 'logs:DeleteLogStream'
                  - 'logs:CreateLogStream'
                  - 'logs:DescribeLogStreams'
                  - 'logs:PutRetentionPolicy'
                  - 'logs:TagResource'
                  - 'logs:ListTagsForResource'
                  - 'logs:DescribeIndexPolicies'
                  - 'logs:DescribeLogStreams'
                  - 'logs:AssociateKmsKey'
                  - 'logs:DisassociateKmsKey'
                Resource:
                  - 'arn:aws:logs:*:*:log-group:/aws/datafirehose/dynatrace/*'
              - Effect: Allow
                Action:
                  - 's3:DeleteBucket'
                  - 's3:CreateBucket'
                  - 's3:PutBucketTagging'
                  - 's3:PutLifecycleConfiguration'
                  - 's3:GetBucket*'
                  - 's3:GetAccelerateConfiguration'
                  - 's3:PutEncryptionConfiguration'
                Resource: !Sub 'arn:aws:s3:::dynatrace-logs-backup-${pDynatraceEnvironmentId}*'
              - Effect: Allow
                Action:
                  - 'firehose:DeleteDeliveryStream'
                  - 'firehose:UpdateDestination'
                  - 'firehose:CreateDeliveryStream'
                  - 'firehose:DescribeDeliveryStream'
                  - 'firehose:TagDeliveryStream'
                  - 'firehose:UntagDeliveryStream'
                  - 'firehose:ListTagsForDeliveryStream'
                  - 'firehose:StartDeliveryStreamEncryption'
                  - 'firehose:StopDeliveryStreamEncryption'
                Resource:
                  - 'arn:aws:firehose:*:*:deliverystream/StackSet-DynatraceLogIngest*'
                  - 'arn:aws:firehose:*:*:deliverystream/Dynatrace*'
              - Effect: Allow
                Action:
                  - 'iam:ListRolePolicies'
                  - 'iam:GetRole'
                  - 'iam:ListAttachedRolePolicies'
                  - 'iam:GetRolePolicy'
                  - 'iam:CreateRole'
                  - 'iam:DeleteRole'
                  - 'iam:PutRolePolicy'
                  - 'iam:DeleteRolePolicy'
                  - 'iam:TagRole'
                  - 'iam:UntagRole'
                  - 'iam:TagPolicy'
                  - 'iam:UntagPolicy'
                  - 'iam:PassRole'
                  - 'iam:UpdateRoleDescription'
                Resource:
                  - 'arn:aws:iam::*:policy/StackSet-DynatraceLog*'
                  - 'arn:aws:iam::*:role/StackSet-DynatraceLog*'
                  - 'arn:aws:iam::*:policy/StackSet-DynatraceEvent*'
                  - 'arn:aws:iam::*:role/StackSet-DynatraceEvent*'
                  - 'arn:aws:iam::*:role/Dynatrace*'
              - Effect: Allow
                Action:
                  - 'iam:GetServiceLinkedRoleDeletionStatus'
                  - 'iam:CreateServiceLinkedRole'
                Resource:
                  - 'arn:aws:iam::*:role/aws-service-role/apidestinations.events.amazonaws.com/AWSServiceRoleForAmazonEventBridgeApiDestinations'
      Tags:
        - Key: 'dt:CreatedBy'
          Value: 'Dynatrace'
        - Key: 'dt:EnvironmentID'
          Value: !Ref pDynatraceEnvironmentId

  DynatraceStackSetAdministrationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub
        - 'DynatraceStackSetAdministrationRole-${pDynatraceEnvironmentId}-${DeploymentHash}'
        - DeploymentHash: !Select [ 0, !Split [ '-', !Select [ 2, !Split [ '/', !Ref AWS::StackId ] ] ] ]
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: 'cloudformation.amazonaws.com'
            Action:
              - 'sts:AssumeRole'
      Path: /
      Tags:
        - Key: 'dt:CreatedBy'
          Value: 'Dynatrace'
        - Key: 'dt:EnvironmentID'
          Value: !Ref pDynatraceEnvironmentId

  DynatraceStackSetAdministrationRolePolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: AssumeExecutionRolePolicy
      Roles:
        - !Ref DynatraceStackSetAdministrationRole
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - 'sts:AssumeRole'
            Resource:
              - !GetAtt DynatraceStackSetExecutionRole.Arn
Outputs:
    StackSetExecutionRoleName:
        Value: !Ref DynatraceStackSetExecutionRole
    StackSetAdministrationRoleArn:
        Value: !GetAtt DynatraceStackSetAdministrationRole.Arn