AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudWise Remediation Role — Grants CloudWise permission to execute ONLY specific cost-saving actions (stop idle resources, clean up waste, right-size infrastructure). Cannot create resources, access data, or modify IAM.'

Metadata:
  CloudWise:
    TemplateVersion: "1.30.0"
    LastUpdated: "2026-04-17"
    ChangeLog:
      - Version: "1.30.0"
        Date: "2026-04-17"
        Changes:
          - "Added globalaccelerator:ListListeners (read) for Global Accelerator pre-deletion listener verification"
          - "Added globalaccelerator:ListEndpointGroups (read) for Global Accelerator pre-deletion endpoint verification"
      - Version: "1.29.0"
        Date: "2026-04-16"
        Changes:
          - "Added elasticache:DecreaseReplicaCount (write) for ElastiCache replication waste remediation"
          - "Added elasticache:IncreaseReplicaCount (write) for ElastiCache replication rollback"
          - "Added elasticache:DescribeReplicationGroups (read) for ElastiCache replication group pre-checks"
          - "Added elasticache:ModifyReplicationGroup (write) for ElastiCache configuration changes"
          - "Added elasticache:ListTagsForResource (read) for ElastiCache environment tag detection"
      - Version: "1.28.0"
        Date: "2026-04-15"
        Changes:
          - "Added elasticbeanstalk:UpdateEnvironment (write) for Beanstalk environment type switching and instance type upgrades"
          - "Added elasticbeanstalk:DescribeConfigurationSettings (read) for Beanstalk environment configuration pre-checks"
      - Version: "1.27.0"
        Date: "2026-04-12"
        Changes:
          - "Added workspaces:DescribeTags (read) for WorkSpaces AutoStop deny-tag guardrail check"
      - Version: "1.26.0"
        Date: "2026-04-12"
        Changes:
          - "Added workspaces:ModifyWorkspaceProperties (write) for WorkSpaces AutoStop mode switch and bundle changes"
          - "Added workspaces:DescribeWorkspaceBundles, DescribeWorkspacesPools (read) for WorkSpaces rightsizing and pool capacity pre-checks"
      - Version: "1.25.0"
        Date: "2026-04-14"
        Changes:
          - "Added elasticmapreduce:ModifyInstanceGroups (write) for EMR over-provisioned cluster right-sizing"
          - "Added elasticmapreduce:PutAutoTerminationPolicy, RemoveAutoTerminationPolicy (write) for EMR auto-termination policy management"
          - "Added elasticmapreduce:AddInstanceGroups (write) for EMR Spot task instance group creation"
          - "Added elasticmapreduce:ListInstanceGroups, ListSteps (read) for EMR pre-checks"
      - Version: "1.24.0"
        Date: "2026-04-13"
        Changes:
          - "Added kinesis:UpdateStreamMode, kinesis:DeregisterStreamConsumer, kinesis:RegisterStreamConsumer for Kinesis billing mode switch and enhanced fan-out consumer management"
          - "Added kinesis:DescribeStreamConsumer, kinesis:ListStreamConsumers read actions for enhanced fan-out pre-checks"
          - "Added firehose:DeleteDeliveryStream, firehose:CreateDeliveryStream (write) and firehose:DescribeDeliveryStream, firehose:ListDeliveryStreams (read) for Firehose idle delivery stream remediation"
      - Version: "1.23.0"
        Date: "2026-04-05"
        Changes:
          - "Added iam:SimulatePrincipalPolicy for comprehensive dry-run permission verification (Troubleshoot Connection)"
      - Version: "1.22.0"
        Date: "2026-04-04"
        Changes:
          - "Added Lightsail remediation actions: ReleaseStaticIp, CreateDiskSnapshot, DeleteDisk, CreateDiskFromSnapshot, DeleteInstanceSnapshot, CreateLoadBalancer, DeleteLoadBalancer, CreateRelationalDatabaseSnapshot, StopRelationalDatabase, StartRelationalDatabase, DeleteRelationalDatabase"
          - "Added Lightsail read actions: GetStaticIp, GetDisk, GetInstanceSnapshot, GetLoadBalancer, GetRelationalDatabase"
      - Version: "1.21.0"
        Date: "2026-03-27"
        Changes:
          - "Added mq:CreateBroker for oversized MQ broker downsizing via broker recreation"
          - "Deduplicated mq:DeleteBroker and mq:DescribeBroker entries"
      - Version: "1.20.0"
        Date: "2026-03-26"
        Changes:
          - "Added rds:StopDBCluster, rds:StartDBCluster for Neptune idle cluster stop/start remediation"
          - "Neptune uses rds: IAM namespace — existing rds:ModifyDBCluster, rds:DeleteDBClusterSnapshot already cover oversized and old snapshot remediation"
      - Version: "1.19.0"
        Date: "2026-03-25"
        Changes:
          - "Added rds:ModifyDBCluster (write) for Aurora I/O-Optimized storage switching"
          - "Added rds:DescribeDBClusters (read) for Aurora cluster pre-checks"
      - Version: "1.18.0"
        Date: "2026-03-24"
        Changes:
          - "Added appsync:DeleteApiCache, appsync:UpdateApiCache (write) and appsync:GetApiCache (read) for AppSync idle cache remediation"
      - Version: "1.17.0"
        Date: "2026-03-21"
        Changes:
          - "Added rollback actions for Haiku 4.5 model remediation plans"
          - "EC2: CreateVpcEndpoints (rollback for VPC endpoint deletion)"
          - "ELB: CreateLoadBalancer, CreateTargetGroup (rollback for delete)"
          - "Glue: CreateJob, CreateDevEndpoint, CreateCrawler (rollback), BatchDeleteTableVersion (catalog cleanup)"
          - "Backup: CreateRecoveryPoint (rollback for delete)"
          - "Route53: CreateHostedZone (rollback), ChangeResourceRecordSets (DNS record management)"
          - "CloudWatch: PutDashboard (rollback for dashboard deletion)"
          - "RDS: DeleteDBSnapshot, DescribeDBSnapshots (snapshot management)"
          - "ECR: DescribeRepositories, DeleteLifecyclePolicy (lifecycle management)"
          - "EFS: DescribeFileSystems (pre-checks)"
          - "Step Functions: ListStateMachines, ListExecutions, DescribeExecution (pre-checks)"
          - "WorkSpaces: DescribeWorkspaces (pre-checks)"
          - "Added MSK (Kafka): DeleteCluster, DescribeCluster, UpdateBrokerType"
          - "Added MQ: DeleteBroker, DescribeBroker"
          - "RDS: CreateDBInstance (Neptune rollback via rds: namespace)"
          - "FSx: UpdateFileSystem (rightsizing)"
          - "Redshift: CreateCluster (rollback), ModifyClusterParameterGroup"
          - "OpenSearch: DeleteDomain, CreateDomain (rollback), DescribeReservedInstanceOfferings"
      - Version: "1.16.0"
        Date: "2026-03-20"
        Changes:
          - "Added es:UpdateDomainConfig for OpenSearch domain rightsizing remediation (EBS volume and instance type changes)"
          - "Added es:DescribeDomain, es:DescribeDomains for OpenSearch pre-checks"
      - Version: "1.15.0"
        Date: "2026-03-18"
        Changes:
          - "Added fsx:DeleteFileSystem, fsx:CreateBackup, fsx:DeleteBackup for FSx remediation (old backup cleanup, idle filesystem delete)"
          - "Added fsx:DescribeFileSystems, fsx:DescribeBackups for FSx pre-checks"
      - Version: "1.14.0"
        Date: "2026-03-18"
        Changes:
          - "Added rds:CreateDBClusterSnapshot, rds:DeleteDBClusterSnapshot for DocumentDB snapshot remediation (old snapshot cleanup)"
          - "Added rds:DescribeDBClusterSnapshots for DocumentDB snapshot pre-checks"
      - Version: "1.13.0"
        Date: "2026-03-16"
        Changes:
          - "Added backup:UpdateRecoveryPointLifecycle, backup:UpdateBackupPlan, backup:DeleteBackupSelection for AWS Backup waste remediation"
          - "Added backup:ListRecoveryPointsByBackupVault, backup:ListBackupVaults, backup:GetBackupPlan, backup:ListBackupSelections, backup:ListBackupPlans, backup:GetBackupSelection for Backup pre-checks"
      - Version: "1.12.0"
        Date: "2026-03-11"
        Changes:
          - "Added ecs:UpdateService, ecs:UpdateClusterSettings for ECS/Fargate remediation (idle services, Container Insights)"
          - "Added ecs:DescribeServices, ecs:DescribeClusters, ecs:DescribeTaskDefinition, ecs:ListServices, ecs:ListClusters for ECS pre-checks"
      - Version: "1.11.0"
        Date: "2026-03-11"
        Changes:
          - "Added transfer:UpdateServer for removing unused Transfer Family server protocols"
          - "Added transfer:DeleteWebApp for deleting idle Transfer Family Web Apps"
          - "Added transfer:DescribeWebApp, transfer:ListWebApps for Transfer Family Web App pre-checks"
      - Version: "1.10.0"
        Date: "2026-03-08"
        Changes:
          - "Added glue:UpdateJob for Glue job right-sizing (worker count and timeout adjustments)"
          - "Added glue:GetJobRuns, glue:GetDatabases, glue:GetTables for Glue waste detection pre-checks"
      - Version: "1.9.0"
        Date: "2026-03-08"
        Changes:
          - "Added s3:ListBucket for HeadBucket and ListObjectsV2 pre-checks (bucket existence verification and object sampling)"
      - Version: "1.8.0"
        Date: "2026-03-09"
        Changes:
          - "Added s3:PutIntelligentTieringConfiguration and s3:GetIntelligentTieringConfiguration for S3 storage class optimization"
          - "Added cloudwatch:GetMetricStatistics for S3 bucket size and growth metrics"
      - Version: "1.7.0"
        Date: "2026-02-24"
        Changes:
          - "Added sagemaker:UpdateNotebookInstance for previous-gen instance type upgrade remediation"
      - Version: "1.6.0"
        Date: "2026-02-22"
        Changes:
          - "Added ec2:AttachVolume and ec2:DetachVolume for EBS rollback volume restore"
      - Version: "1.5.0"
        Date: "2026-02-16"
        Changes:
          - "Added 19 rollback actions needed for Agentic AI undo/rollback capability"
          - "EC2: StartInstances, RunInstances, AllocateAddress, AssociateAddress, CreateVolume, CreateNatGateway"
          - "RDS: StartDBInstance"
          - "Logs: DeleteRetentionPolicy (undo retention policy changes)"
          - "Extended: RestoreSecret, CancelKeyDeletion, EnableKey, CreateStream, IncreaseStreamRetentionPeriod"
          - "Extended: StartInstance (Lightsail), StartNotebookInstance (SageMaker), StartServer (Transfer), StartWorkspaces"
          - "Removed RestoreSecret, RunInstances, CreateDBInstance, CreateFunction from deny list (needed for rollback)"
      - Version: "1.4.0"
        Date: "2026-02-14"
        Changes:
          - "Added ELB/ALB permissions (elasticloadbalancing) — fixes AccessDenied on DescribeLoadBalancers"
          - "Added VPC endpoint permissions (DeleteVpcEndpoints, DescribeVpcEndpoints)"
          - "Added 20 new service categories via RemediationPolicyExtended managed policy"
          - "Updated deny policy: replaced blanket kms:* and secretsmanager:* with specific denies"
      - Version: "1.3.0"
        Date: "2026-02-14"
        Changes:
          - "Added ec2:CreateTags — required by CreateSnapshot when TagSpecifications are included"
      - Version: "1.2.0"
        Date: "2026-02-14"
        Changes:
          - "Fixed S3 IAM action names: GetBucketLifecycleConfiguration→GetLifecycleConfiguration, PutBucketLifecycleConfiguration→PutLifecycleConfiguration (S3 IAM actions omit 'Bucket' prefix)"
          - "Added s3:ListBucketMultipartUploads and s3:ListMultipartUploadParts"
      - Version: "1.1.0"
        Date: "2026-02-14"
        Changes:
          - "Split trust policy into two statements: sts:AssumeRole (with ExternalId) and sts:TagSession (without ExternalId, as sts:ExternalId condition key is unavailable for TagSession evaluations)"
      - Version: "1.0.0"
        Date: "2026-02-13"
        Changes:
          - "Initial remediation role template"
          - "EC2, RDS, EBS, ELB, NAT Gateway, ElastiCache, Lambda, S3 remediation permissions"
          - "Explicit deny for IAM, VPC, KMS, security group modifications"
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "Security Settings (Pre-configured - Do Not Change)"
        Parameters:
          - CloudWiseAccountId
          - ExternalId
    ParameterLabels:
      CloudWiseAccountId:
        default: "CloudWise Service Account (Remediation)"
      ExternalId:
        default: "Security Key (Read-Only)"

Parameters:
  CloudWiseAccountId:
    Type: String
    Description: "CloudWise service account ID (DO NOT CHANGE - required for CloudWise to execute remediation actions)"
    Default: "513158236564"
    AllowedValues:
      - "513158236564"
    ConstraintDescription: This value cannot be changed

  ExternalId:
    Type: String
    Description: "Security key for CloudWise access (DO NOT CHANGE - pre-configured for security)"
    Default: "cloudwise-cost-access-2025"
    AllowedValues:
      - "cloudwise-cost-access-2025"
    NoEcho: true

Resources:
  # ============================================================================
  # IAM Role: CloudWiseRemediationRole
  # ============================================================================
  CloudWiseRemediationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: CloudWiseRemediationRole
      Description: |
        Allows CloudWise Agentic AI to execute approved remediation actions.
        Limited to cost-saving operations only. All actions require user approval.
      MaxSessionDuration: 3600  # 1-hour minimum (AWS requirement); CloudWise enforces 15-min cap on its side
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          # Statement 1: Allow assuming the role with ExternalId verification
          - Effect: Allow
            Principal:
              AWS: !Sub 'arn:aws:iam::${CloudWiseAccountId}:role/cloudwise-customer-access-service-role'
            Action: 'sts:AssumeRole'
            Condition:
              StringEquals:
                'sts:ExternalId': !Ref ExternalId
              # Require session tags for audit trail
              StringLike:
                'aws:RequestTag/cloudwise-approval-id': '*'
          # Statement 2: Allow session tagging (sts:ExternalId condition key
          # is only available for sts:AssumeRole, so TagSession needs its own statement)
          - Effect: Allow
            Principal:
              AWS: !Sub 'arn:aws:iam::${CloudWiseAccountId}:role/cloudwise-customer-access-service-role'
            Action: 'sts:TagSession'
            Condition:
              StringLike:
                'aws:RequestTag/cloudwise-approval-id': '*'
      Tags:
        - Key: Purpose
          Value: cloudwise-remediation
        - Key: ManagedBy
          Value: cloudwise

  # ============================================================================
  # IAM Policy: Remediation Actions (Cost Optimization Only)
  # ============================================================================
  RemediationPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: CloudWiseRemediationPolicy
      Roles:
        - !Ref CloudWiseRemediationRole
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          # ── EC2: Stop/terminate idle instances, manage EBS, EIPs ──
          # Includes rollback actions: StartInstances, RunInstances, AllocateAddress, AssociateAddress, CreateVolume, AttachVolume, DetachVolume, CreateNatGateway
          - Sid: EC2Remediation
            Effect: Allow
            Action:
              - ec2:StopInstances
              - ec2:StartInstances
              - ec2:TerminateInstances
              - ec2:RunInstances
              - ec2:ReleaseAddress
              - ec2:AllocateAddress
              - ec2:DisassociateAddress
              - ec2:AssociateAddress
              - ec2:DeleteVolume
              - ec2:CreateVolume
              - ec2:AttachVolume
              - ec2:DetachVolume
              - ec2:DeleteSnapshot
              - ec2:CreateSnapshot
              - ec2:CreateTags
              - ec2:ModifyVolume
              - ec2:DeleteNatGateway
              - ec2:CreateNatGateway
              - ec2:DeleteVpcEndpoints
              - ec2:CreateVpcEndpoint
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          - Sid: EC2Describe
            Effect: Allow
            Action:
              - ec2:DescribeInstances
              - ec2:DescribeVolumes
              - ec2:DescribeAddresses
              - ec2:DescribeSnapshots
              - ec2:DescribeNatGateways
              - ec2:DescribeVpcEndpoints
            Resource: '*'

          # ── RDS: Stop idle databases (+ StartDBInstance for rollback) ──
          - Sid: RDSRemediation
            Effect: Allow
            Action:
              - rds:StopDBInstance
              - rds:StartDBInstance
              - rds:ModifyDBInstance
              - rds:ModifyDBCluster
              - rds:StopDBCluster
              - rds:StartDBCluster
              - rds:CreateDBSnapshot
              - rds:DeleteDBSnapshot
              - rds:CreateDBInstance
              - rds:CreateDBClusterSnapshot
              - rds:DeleteDBClusterSnapshot
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          - Sid: RDSDescribe
            Effect: Allow
            Action:
              - rds:DescribeDBInstances
              - rds:DescribeDBClusters
              - rds:DescribeDBSnapshots
              - rds:DescribeDBClusterSnapshots
            Resource: '*'

          # ── S3: Lifecycle policies, abort multipart uploads, Intelligent-Tiering ──
          # Note: S3 IAM action names omit "Bucket" prefix (e.g. s3:GetLifecycleConfiguration, not s3:GetBucketLifecycleConfiguration)
          - Sid: S3Remediation
            Effect: Allow
            Action:
              - s3:AbortMultipartUpload
              - s3:ListBucket
              - s3:PutLifecycleConfiguration
              - s3:GetLifecycleConfiguration
              - s3:ListBucketMultipartUploads
              - s3:ListMultipartUploadParts
              - s3:PutIntelligentTieringConfiguration
              - s3:GetIntelligentTieringConfiguration
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── Lambda: Right-size memory, delete unused, manage Provisioned Concurrency ──
          - Sid: LambdaRemediation
            Effect: Allow
            Action:
              - lambda:UpdateFunctionConfiguration
              - lambda:DeleteFunction
              - lambda:GetFunctionConfiguration
              - lambda:DeleteProvisionedConcurrencyConfig
              - lambda:PutProvisionedConcurrencyConfig
              - lambda:ListProvisionedConcurrencyConfigs
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── CloudWatch Logs: Set retention, delete old groups, remove retention (rollback) ──
          - Sid: LogsRemediation
            Effect: Allow
            Action:
              - logs:PutRetentionPolicy
              - logs:DeleteRetentionPolicy
              - logs:DeleteLogGroup
              - logs:DescribeLogGroups
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── CloudWatch Dashboards: Delete unused ──
          - Sid: DashboardRemediation
            Effect: Allow
            Action:
              - cloudwatch:DeleteDashboards
              - cloudwatch:PutDashboard
              - cloudwatch:ListDashboards
              - cloudwatch:GetMetricStatistics
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── ECR: Clean old images, set lifecycle policy ──
          - Sid: ECRRemediation
            Effect: Allow
            Action:
              - ecr:BatchDeleteImage
              - ecr:PutLifecyclePolicy
              - ecr:DeleteLifecyclePolicy
              - ecr:DescribeImages
              - ecr:DescribeRepositories
              - ecr:GetLifecyclePolicy
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── EFS: Set lifecycle configuration ──
          - Sid: EFSRemediation
            Effect: Allow
            Action:
              - elasticfilesystem:PutLifecycleConfiguration
              - elasticfilesystem:DescribeLifecycleConfiguration
              - elasticfilesystem:DescribeFileSystems
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── DynamoDB: Update table (autoscaling, capacity) ──
          - Sid: DynamoDBRemediation
            Effect: Allow
            Action:
              - dynamodb:UpdateTable
              - dynamodb:DescribeTable
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── ElastiCache: Delete idle clusters, manage replicas ──
          - Sid: ElastiCacheRemediation
            Effect: Allow
            Action:
              - elasticache:DeleteCacheCluster
              - elasticache:CreateSnapshot
              - elasticache:DescribeCacheClusters
              - elasticache:ModifyCacheCluster
              - elasticache:DescribeReplicationGroups
              - elasticache:DecreaseReplicaCount
              - elasticache:IncreaseReplicaCount
              - elasticache:ListTagsForResource
              - elasticache:ModifyReplicationGroup
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── ELB/ALB: Delete idle load balancers (+ Create for rollback) ──
          - Sid: ELBRemediation
            Effect: Allow
            Action:
              - elasticloadbalancing:DeleteLoadBalancer
              - elasticloadbalancing:CreateLoadBalancer
              - elasticloadbalancing:DeleteTargetGroup
              - elasticloadbalancing:CreateTargetGroup
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          - Sid: ELBDescribe
            Effect: Allow
            Action:
              - elasticloadbalancing:DescribeLoadBalancers
              - elasticloadbalancing:DescribeTargetHealth
              - elasticloadbalancing:DescribeTargetGroups
            Resource: '*'

  # ============================================================================
  # IAM Policy: Extended Remediation (Additional Services)
  # ============================================================================
  RemediationPolicyExtended:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: CloudWiseRemediationPolicyExtended
      Roles:
        - !Ref CloudWiseRemediationRole
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          # ── Write actions across all extended services (require session tag) ──
          - Sid: ExtendedRemediation
            Effect: Allow
            Action:
              - kinesis:DeleteStream
              - kinesis:CreateStream
              - kinesis:UpdateShardCount
              - kinesis:DecreaseStreamRetentionPeriod
              - kinesis:IncreaseStreamRetentionPeriod
              - kinesis:UpdateStreamMode
              - kinesis:DeregisterStreamConsumer
              - kinesis:RegisterStreamConsumer
              # Firehose
              - firehose:DeleteDeliveryStream
              - firehose:CreateDeliveryStream
              - glue:DeleteDevEndpoint
              - glue:CreateDevEndpoint
              - glue:DeleteJob
              - glue:CreateJob
              - glue:DeleteCrawler
              - glue:CreateCrawler
              - glue:UpdateJob
              - glue:BatchDeleteTableVersion
              - states:DeleteStateMachine
              - backup:DeleteRecoveryPoint
              - backup:StartBackupJob
              - backup:UpdateRecoveryPointLifecycle
              - backup:UpdateBackupPlan
              - backup:DeleteBackupSelection
              - secretsmanager:DeleteSecret
              - secretsmanager:RestoreSecret
              - sagemaker:StopNotebookInstance
              - sagemaker:StartNotebookInstance
              - sagemaker:DeleteNotebookInstance
              - sagemaker:UpdateNotebookInstance
              - sagemaker:DeleteEndpoint
              - sagemaker:UpdateEndpoint
              - apigateway:DELETE
              - elasticbeanstalk:TerminateEnvironment
              - elasticbeanstalk:UpdateEnvironment
              - lightsail:StopInstance
              - lightsail:StartInstance
              - lightsail:DeleteInstance
              - lightsail:ReleaseStaticIp
              - lightsail:GetDisk
              - lightsail:CreateDiskSnapshot
              - lightsail:DeleteDisk
              - lightsail:CreateDiskFromSnapshot
              - lightsail:GetInstanceSnapshot
              - lightsail:DeleteInstanceSnapshot
              - lightsail:GetLoadBalancer
              - lightsail:CreateLoadBalancer
              - lightsail:DeleteLoadBalancer
              - lightsail:GetRelationalDatabase
              - lightsail:CreateRelationalDatabaseSnapshot
              - lightsail:StopRelationalDatabase
              - lightsail:StartRelationalDatabase
              - lightsail:DeleteRelationalDatabase
              - workspaces:TerminateWorkspaces
              - workspaces:StopWorkspaces
              - workspaces:StartWorkspaces
              - workspaces:ModifyWorkspaceProperties
              - transfer:StopServer
              - transfer:StartServer
              - transfer:DeleteServer
              - transfer:UpdateServer
              - transfer:DeleteWebApp
              - qldb:DeleteLedger
              - timestream:DeleteDatabase
              - timestream:DeleteTable
              - globalaccelerator:DeleteAccelerator
              - globalaccelerator:UpdateAccelerator
              - appsync:DeleteGraphqlApi
              - appsync:DeleteApiCache
              - appsync:UpdateApiCache
              - cloudfront:DeleteDistribution
              - cloudfront:UpdateDistribution
              - route53:DeleteHostedZone
              - route53:CreateHostedZone
              - route53:ChangeResourceRecordSets
              # MSK (Kafka)
              - kafka:DeleteCluster
              - kafka:UpdateBrokerType
              # Amazon MQ
              - mq:DeleteBroker
              - mq:CreateBroker
              - kms:ScheduleKeyDeletion
              - kms:DisableKey
              - kms:CancelKeyDeletion
              - kms:EnableKey
              - lambda:CreateFunction
              - elasticmapreduce:TerminateJobFlows
              - elasticmapreduce:ModifyInstanceGroups
              - elasticmapreduce:PutAutoTerminationPolicy
              - elasticmapreduce:RemoveAutoTerminationPolicy
              - elasticmapreduce:AddInstanceGroups
              - redshift:DeleteCluster
              - redshift:CreateCluster
              - redshift:PauseCluster
              - redshift:ResumeCluster
              - redshift:ResizeCluster
              - redshift:CreateClusterSnapshot
              - redshift:CreateScheduledAction
              - redshift:DeleteScheduledAction
              - redshift:ModifyClusterParameterGroup
              - ecs:UpdateService
              - ecs:UpdateClusterSettings
              # FSx
              - fsx:DeleteFileSystem
              - fsx:CreateBackup
              - fsx:DeleteBackup
              - fsx:UpdateFileSystem
              # OpenSearch
              - es:UpdateDomainConfig
              - es:DeleteDomain
              - es:CreateDomain
            Resource: '*'
            Condition:
              StringEquals:
                'aws:PrincipalTag/cloudwise-action': 'remediation'

          # ── Read-only pre-checks (no session tag needed) ──
          - Sid: ExtendedDescribe
            Effect: Allow
            Action:
              - kinesis:DescribeStream
              - kinesis:DescribeStreamConsumer
              - kinesis:ListStreamConsumers
              - firehose:DescribeDeliveryStream
              - firehose:ListDeliveryStreams
              - glue:GetDevEndpoint
              - glue:GetJob
              - glue:GetCrawler
              - glue:GetJobRuns
              - glue:GetDatabases
              - glue:GetTables
              - states:DescribeStateMachine
              - states:ListStateMachines
              - states:ListExecutions
              - states:DescribeExecution
              - backup:DescribeRecoveryPoint
              - backup:ListRecoveryPointsByBackupVault
              - backup:ListBackupVaults
              - backup:GetBackupPlan
              - backup:ListBackupPlans
              - backup:ListBackupSelections
              - backup:GetBackupSelection
              - secretsmanager:DescribeSecret
              - sagemaker:DescribeNotebookInstance
              - sagemaker:DescribeEndpoint
              - sagemaker:DescribeEndpointConfig
              - apigateway:GET
              - cloudtrail:DescribeTrails
              - cloudtrail:GetTrailStatus
              - elasticbeanstalk:DescribeEnvironments
              - elasticbeanstalk:DescribeConfigurationSettings
              - lightsail:GetInstance
              - lightsail:GetStaticIp
              - lightsail:GetDisk
              - lightsail:GetInstanceSnapshot
              - lightsail:GetLoadBalancer
              - lightsail:GetRelationalDatabase
              - workspaces:DescribeWorkspaces
              - workspaces:DescribeWorkspaceBundles
              - workspaces:DescribeWorkspacesPools
              - workspaces:DescribeTags
              - transfer:DescribeServer
              - transfer:ListServers
              - transfer:ListUsers
              - transfer:DescribeUser
              - transfer:DescribeWebApp
              - transfer:ListWebApps
              - qldb:DescribeLedger
              - timestream:DescribeDatabase
              - timestream:DescribeTable
              - globalaccelerator:DescribeAccelerator
              - globalaccelerator:ListListeners
              - globalaccelerator:ListEndpointGroups
              - appsync:GetGraphqlApi
              - appsync:GetApiCache
              - cloudfront:GetDistribution
              - route53:GetHostedZone
              - route53:ListResourceRecordSets
              # MSK (Kafka)
              - kafka:DescribeCluster
              # Amazon MQ
              - mq:DescribeBroker
              - kms:DescribeKey
              - elasticmapreduce:DescribeCluster
              - elasticmapreduce:ListClusters
              - elasticmapreduce:ListInstanceGroups
              - elasticmapreduce:ListSteps
              - redshift:DescribeClusters
              - redshift:DescribeClusterSnapshots
              - redshift:DescribeScheduledActions
              - ecs:DescribeServices
              - ecs:DescribeClusters
              - ecs:DescribeTaskDefinition
              - ecs:ListServices
              - ecs:ListClusters
              # FSx
              - fsx:DescribeFileSystems
              - fsx:DescribeBackups
              # OpenSearch
              - es:DescribeDomain
              - es:DescribeDomains
              - es:DescribeReservedInstanceOfferings
              # IAM policy simulation (dry-run permission verification)
              - iam:SimulatePrincipalPolicy
            Resource: '*'

  # ============================================================================
  # IAM Policy: Explicit Deny — Never Allow These
  # ============================================================================
  RemediationDenyPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: CloudWiseRemediationDeny
      Roles:
        - !Ref CloudWiseRemediationRole
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: DenyDangerousActions
            Effect: Deny
            Action:
              - iam:*
              - organizations:*
              - sts:*
              - kms:CreateKey
              - kms:CreateGrant
              - kms:CreateAlias
              - kms:Encrypt
              - kms:Decrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
              - kms:PutKeyPolicy
              - secretsmanager:GetSecretValue
              - secretsmanager:PutSecretValue
              - secretsmanager:CreateSecret
              - secretsmanager:UpdateSecret
              - ssm:*
              - cloudtrail:DeleteTrail
              - cloudtrail:StopLogging
              - config:DeleteConfigRule
              - config:StopConfigurationRecorder
              - guardduty:DeleteDetector
              - s3:DeleteBucket
              - ec2:DeleteVpc
              - ec2:DeleteSubnet
              - ec2:DeleteSecurityGroup
              - ec2:AuthorizeSecurityGroupIngress
              - ec2:AuthorizeSecurityGroupEgress
              - ec2:RevokeSecurityGroupIngress
              - ec2:RevokeSecurityGroupEgress
              - ec2:CreateSecurityGroup
              - rds:DeleteDBInstance
              - lambda:AddPermission
              - lambda:CreateEventSourceMapping
            Resource: '*'

Outputs:
  RoleArn:
    Description: ARN of the CloudWise Remediation Role — copy this to CloudWise Settings
    Value: !GetAtt CloudWiseRemediationRole.Arn
    Export:
      Name: !Sub '${AWS::StackName}-RoleArn'

  RoleName:
    Description: Name of the role created
    Value: !Ref CloudWiseRemediationRole

  Instructions:
    Description: Next steps
    Value: |
      1. Copy the Role ARN above
      2. Go to CloudWise → Settings → AWS Accounts → Edit
      3. Paste the Role ARN into the "Remediation Role ARN" field
      4. Click "Test Connection" to verify
      5. Enable Agentic AI in Settings → Remediation Policy
