---
# =============================================================================
# ZapStack Organization Onboarding Template (v1)
# =============================================================================
#
# PURPOSE:
# Single-template deployment that sets up ZapStack access across an entire
# AWS Organization. Deploy this ONCE to your management (payer) account.
#
# WHAT THIS TEMPLATE CREATES:
#   1. S3 bucket for Cost & Usage Reports (CUR) in management account
#   2. CUR report definition (hourly Parquet with resource-level data)
#   3. IAM role in management account for ZapStack to assume
#   4. StackSet that auto-deploys IAM roles to ALL member accounts
#   5. Lambda function to discover the Organization root ID
#   6. Notification to ZapStack backend when setup completes
#
# AUTO-DEPLOYMENT:
# The StackSet has AutoDeployment enabled, meaning:
#   - New accounts added to the Organization automatically get the IAM role
#   - Removed accounts automatically have the IAM role cleaned up
#   - No manual intervention needed for org membership changes
#
# =============================================================================
AWSTemplateFormatVersion: "2010-09-09"
Description: ZapStack organization onboarding - deploys to management and all member accounts

# =============================================================================
# PARAMETERS
# These values are provided by ZapStack during the onboarding flow.
# Do not modify ZapStackID - it's your unique tenant identifier.
# =============================================================================
Parameters:
  BucketName:
    Type: String
    MinLength: "1"
    Description: S3 bucket name for Cost and Usage Reports
  ReportName:
    Type: String
    MinLength: "1"
    Description: Cost and Usage Report name
  ZapStackID:
    Type: String
    MinLength: "1"
    Description: Your ZapStack tenant ID (do not modify)

# =============================================================================
# MAPPINGS
# Static configuration for ZapStack infrastructure.
# These values point to ZapStack's AWS resources that receive notifications
# and serve the member account template.
# =============================================================================
Mappings:
  ZapStackConfig:
    Account:
      # ZapStack's AWS account ID - used in IAM trust policies
      ID: "964607248450"
    SNS:
      # SNS topic that receives deployment notifications
      TopicName: zapstack-aws-connect
    Templates:
      # S3 bucket hosting the member account template (v1-member.yaml)
      BucketURL: https://zapstack-cfn-templates.s3.amazonaws.com/
    Version:
      # Template version - used for tracking deployed versions
      Current: "1.0"

Resources:
  # ===========================================================================
  # COST AND USAGE REPORT (CUR) - Management Account Only
  # ===========================================================================
  # The CUR is the primary data source for cost analysis. It provides:
  #   - Line-item billing data for every AWS resource
  #   - Resource IDs to correlate costs with specific resources
  #   - Split cost allocation for shared resources (containers, etc.)
  #
  # Configuration choices:
  #   - HOURLY: Granular time-based analysis, spot instance tracking
  #   - Parquet: Columnar format for efficient querying (Athena-optimized)
  #   - RESOURCES: Includes resource ARNs for cost attribution
  #   - SPLIT_COST_ALLOCATION_DATA: Breaks down shared costs (ECS, EKS)
  # ===========================================================================

  # S3 bucket to store CUR data
  # AWS delivers new reports here automatically (up to 3x daily for hourly reports)
  CURBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref BucketName
      AccessControl: Private
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        IgnorePublicAcls: true
        # BlockPublicPolicy: false required for billingreports service access
        BlockPublicPolicy: false
        RestrictPublicBuckets: false

  # Bucket policy granting access to:
  #   1. AWS billing service (to write CUR files)
  #   2. ZapStack IAM role (to read CUR files)
  CURBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref CURBucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          # AWS billing service needs to verify bucket ownership before writing
          - Sid: AllowBillingReportsService
            Effect: Allow
            Principal:
              Service: billingreports.amazonaws.com
            Action:
              - s3:GetBucketAcl
              - s3:GetBucketPolicy
            Resource: !Sub "arn:aws:s3:::${CURBucket}"
          # AWS billing service writes CUR Parquet files to this bucket
          - Sid: AllowBillingReportsPut
            Effect: Allow
            Principal:
              Service: billingreports.amazonaws.com
            Action: s3:PutObject
            Resource: !Sub "arn:aws:s3:::${CURBucket}/*"
          # ZapStack reads CUR data for cost analysis
          - Sid: AllowZapStackRead
            Effect: Allow
            Principal:
              AWS: !GetAtt ManagementAccountRole.Arn
            Action:
              - s3:GetObject
              - s3:GetObjectAcl
            Resource: !Sub "arn:aws:s3:::${CURBucket}/*"

  # CUR report definition - tells AWS what data to generate and where to put it
  CostAndUsageReport:
    Type: AWS::CUR::ReportDefinition
    DependsOn: CURBucketPolicy
    Properties:
      ReportName: !Ref ReportName
      S3Bucket: !Ref CURBucket
      S3Prefix: hourly-v1
      # CUR is only available in us-east-1 (billing API limitation)
      S3Region: us-east-1
      # HOURLY provides most granular data (vs DAILY/MONTHLY)
      TimeUnit: HOURLY
      # Parquet is columnar, efficient for Athena queries
      Format: Parquet
      Compression: Parquet
      # CREATE_NEW_REPORT: Each month gets a new report (vs overwriting)
      ReportVersioning: CREATE_NEW_REPORT
      # Update past reports when AWS issues credits/adjustments
      RefreshClosedReports: true
      AdditionalSchemaElements:
        # RESOURCES: Include resource ARNs for cost attribution
        - RESOURCES
        # SPLIT_COST_ALLOCATION_DATA: Break down shared costs (ECS tasks, etc.)
        - SPLIT_COST_ALLOCATION_DATA

  # ===========================================================================
  # MANAGEMENT ACCOUNT IAM ROLE
  # ===========================================================================
  # This role allows ZapStack to access billing data and inventory resources
  # in the management account. It's assumed cross-account using STS with
  # ExternalId for security.
  #
  # The role has read-only access to:
  #   - CUR S3 bucket (cost data)
  #   - Billing/Cost Explorer APIs
  #   - CloudWatch metrics (for resource utilization)
  #   - Resource inventory across all services
  #   - StackSet management (to add/remove member accounts)
  # ===========================================================================
  ManagementAccountRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ZapStackCrossAccountRole
      # Trust policy: Only ZapStack's account can assume this role
      # ExternalId prevents confused deputy attacks
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub
                - "arn:aws:iam::${ZapStackAccountId}:root"
                - ZapStackAccountId: !FindInMap [ZapStackConfig, Account, ID]
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                # ExternalId must match - prevents other ZapStack customers
                # from accidentally accessing your account
                sts:ExternalId: !Ref ZapStackID
      # AWS managed policy for broad read-only access
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess
      Path: "/"
      Policies:
        # ------------------------------------
        # CUR Bucket Access
        # ------------------------------------
        # Read access to the CUR S3 bucket for cost analysis
        - PolicyName: CURBucketAccess
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: ListCURBucket
                Effect: Allow
                Action:
                  - s3:ListBucket
                  - s3:GetBucketLocation
                Resource:
                  - !Sub "arn:aws:s3:::${CURBucket}"
                  - !Sub "arn:aws:s3:::${CURBucket}/*"
              - Sid: ReadCURObjects
                Effect: Allow
                Action: s3:GetObject
                Resource: !Sub "arn:aws:s3:::${CURBucket}/*"

        # ------------------------------------
        # Billing & Cost Data
        # ------------------------------------
        # Access to billing APIs for:
        #   - Cost Explorer queries (spend trends, forecasts)
        #   - Budget status
        #   - Savings Plans inventory
        #   - Organization structure (for multi-account analysis)
        - PolicyName: BillingData
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: ZapStackBillingReadOnly
                Effect: Allow
                Resource: "*"
                Action:
                  - account:GetAccountInformation
                  - budgets:Describe*
                  - budgets:View*
                  - ce:Get*
                  - ce:Describe*
                  - ce:List*
                  - cur:Describe*
                  - invoicing:List*
                  - invoicing:GetInvoice*
                  - pricing:*
                  - organizations:Describe*
                  - organizations:List*
                  - savingsplans:Describe*
                  # Simulate policies to check effective permissions
                  - iam:SimulatePrincipalPolicy

        # ------------------------------------
        # StackSet Management
        # ------------------------------------
        # Allows ZapStack to add/remove member account deployments
        # when you explicitly add/remove accounts from ZapStack
        # (separate from the automatic org-wide deployment)
        - PolicyName: StackSetManagement
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: ManageStackSetInstances
                Effect: Allow
                Action:
                  - cloudformation:CreateStackInstances
                  - cloudformation:DeleteStackInstances
                  - cloudformation:DescribeStackSetOperation
                  - cloudformation:ListStackInstances
                Resource:
                  - !Sub "arn:aws:cloudformation:*:${AWS::AccountId}:stackset/ZapStackOrgRoles:*"
                  - !Sub "arn:aws:cloudformation:*:${AWS::AccountId}:stackset-target/ZapStackOrgRoles:*"

        # ------------------------------------
        # CloudWatch Metrics
        # ------------------------------------
        # Read CloudWatch metrics to analyze resource utilization
        # (e.g., EC2 CPU usage, RDS connections, Lambda invocations)
        - PolicyName: QueryMetrics
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: QueryMetrics
                Effect: Allow
                Resource: "*"
                Action:
                  - cloudwatch:GetMetric*
                  - cloudwatch:ListMetrics

        # ------------------------------------
        # S3 Multipart Upload Detection
        # ------------------------------------
        # Detect incomplete/abandoned multipart uploads
        # (common source of hidden S3 costs)
        - PolicyName: S3ListMultipartUploads
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: MultipartUploads
                Effect: Allow
                Resource: "*"
                Action:
                  - s3:ListBucketMultipartUploads
                  - s3:ListParts

        # ------------------------------------
        # Extended Resource Inventory
        # ------------------------------------
        # ViewOnlyAccess doesn't cover all services. This policy adds
        # read access for additional services needed for complete
        # resource inventory and cost attribution.
        - PolicyName: ZapStackAdditionalResourceReadOnly
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Resource: "*"
                Action:
                  # Certificate Manager
                  - acm:Describe*
                  - acm:List*
                  - acm-pca:Describe*
                  - acm-pca:List*
                  # Amplify
                  - amplify:List*
                  # Auto Scaling
                  - application-autoscaling:Describe*
                  - applicationinsights:Describe*
                  - applicationinsights:List*
                  # AppStream
                  - appstream:Describe*
                  - appstream:List*
                  # AppSync & App Runner
                  - appsync:List*
                  - apprunner:List*
                  - apprunner:Describe*
                  - autoscaling-plans:Describe*
                  # Batch
                  - batch:Describe*
                  # Budgets (redundant with BillingData but explicit)
                  - budgets:Describe*
                  # Cost Explorer
                  - ce:Get*
                  # CloudHSM
                  - cloudhsm:List*
                  - cloudhsm:Describe*
                  # CloudSearch
                  - cloudsearch:Describe*
                  # CloudTrail
                  - cloudtrail:Describe*
                  - cloudtrail:Get*
                  - cloudtrail:List*
                  # CloudWatch
                  - cloudwatch:Describe*
                  # CloudFront
                  - cloudfront:Get*
                  # CodeBuild & CodePipeline
                  - codebuild:Describe*
                  - codebuild:Get*
                  - codebuild:List*
                  - codepipeline:List*
                  - codepipeline:Get*
                  - codestar:Describe*
                  # Connect
                  - connect:Describe*
                  # Data Exchange & DataSync
                  - dataexchange:List*
                  - datasync:Describe*
                  - datasync:List*
                  - datapipeline:Describe*
                  - datapipeline:List*
                  # Detective
                  - detective:List*
                  # Discovery & DMS
                  - discovery:Describe*
                  - dms:Describe*
                  # Directory Service
                  - ds:Describe*
                  - ds:List*
                  # EC2 extended
                  - ec2:Get*
                  - ec2:Search*
                  # ECR & EKS
                  - ecr:Describe*
                  - ecr:List*
                  - eks:Describe*
                  - eks:List*
                  # ElastiCache
                  - elasticache:List*
                  # Elastic Beanstalk
                  - elasticbeanstalk:Describe*
                  - elasticbeanstalk:List*
                  # EFS
                  - elasticfilesystem:Describe*
                  # EMR
                  - elasticmapreduce:Describe*
                  # Elemental
                  - elemental-appliances-software:List*
                  # Elasticsearch/OpenSearch
                  - es:Describe*
                  - es:List*
                  # EventBridge
                  - events:Describe*
                  - events:List*
                  # Kinesis Firehose
                  - firehose:Describe*
                  # FSx
                  - fsx:Describe*
                  - fsx:List*
                  # Grafana
                  - grafana:Describe*
                  - grafana:List*
                  # Glacier
                  - glacier:Describe*
                  # Global Accelerator
                  - globalaccelerator:Describe*
                  - globalaccelerator:List*
                  # Glue
                  - glue:List*
                  # GuardDuty
                  - guardduty:List*
                  # Health
                  - health:Describe*
                  # Image Builder
                  - imagebuilder:List*
                  # Import/Export
                  - importexport:List*
                  # Inspector
                  - inspector:Describe*
                  # IoT
                  - iot:Describe*
                  - iotanalytics:Describe*
                  - iotanalytics:List*
                  - iotsitewise:Describe*
                  - iotsitewise:List*
                  # MSK (Kafka)
                  - kafka:Describe*
                  - kafka:List*
                  # Kinesis
                  - kinesisanalytics:Describe*
                  - kinesisanalytics:List*
                  - kinesisvideo:Describe*
                  - kinesisvideo:List*
                  - kinesis:Describe*
                  - kinesis:List*
                  # KMS
                  - kms:Describe*
                  - kms:List*
                  # License Manager
                  - license-manager:List*
                  # CloudWatch Logs
                  - logs:List*
                  # Media Services
                  - mediaconvert:Describe*
                  - mediaconvert:List*
                  - mediapackage:List*
                  - mediapackage:Describe*
                  - medialive:List*
                  - medialive:Describe*
                  - mediaconnect:List*
                  - mediaconnect:Describe*
                  - mediapackage-vod:List*
                  - mediapackage-vod:Describe*
                  - mediastore:List*
                  - mediastore:Describe*
                  - mediatailor:List*
                  - mediatailor:Describe*
                  # Migration Hub
                  - mgh:Describe*
                  - mgh:List*
                  # Mobile Hub
                  - mobilehub:Describe*
                  - mobilehub:List*
                  - mobiletargeting:List*
                  # MQ
                  - mq:Describe*
                  - mq:List*
                  # OpsWorks
                  - opsworks-cm:List*
                  # Organizations
                  - organizations:Describe*
                  # Outposts
                  - outposts:List*
                  # Personalize
                  - personalize:Describe*
                  - personalize:List*
                  # Performance Insights
                  - pi:Describe*
                  # QLDB
                  - qldb:List*
                  # QuickSight
                  - quicksight:Describe*
                  - quicksight:List*
                  # Resource Access Manager
                  - ram:List*
                  # Rekognition
                  - rekognition:List*
                  # RDS
                  - rds:List*
                  # Redshift
                  - redshift:Describe*
                  # Resource Groups
                  - resource-groups:Get*
                  - resource-groups:List*
                  - resource-groups:Search*
                  # RoboMaker
                  - robomaker:Describe*
                  - robomaker:List*
                  # Route 53 Domains
                  - route53domains:Get*
                  # S3 Lifecycle
                  - s3:GetLifecycleConfiguration
                  # EventBridge Schemas
                  - schemas:Describe*
                  - schemas:List*
                  # Secrets Manager
                  - secretsmanager:List*
                  - secretsmanager:Describe*
                  # Security Hub
                  - securityhub:Describe*
                  - securityhub:List*
                  # Serverless Repo
                  - serverlessrepo:List*
                  # Service Catalog
                  - servicecatalog:Describe*
                  # Cloud Map
                  - servicediscovery:Get*
                  - servicediscovery:List*
                  # SES
                  - ses:Describe*
                  # Shield
                  - shield:Describe*
                  # Snowball
                  - snowball:Describe*
                  - snowball:List*
                  # SQS
                  - sqs:List*
                  # Systems Manager
                  - ssm:Describe*
                  - ssm:List*
                  # IAM Identity Center (SSO)
                  - sso:Describe*
                  - sso:List*
                  - sso:Search*
                  - sso-directory:Describe*
                  - sso-directory:List*
                  - sso-directory:Search*
                  # Step Functions
                  - states:List*
                  - states:Describe*
                  # Storage Gateway
                  - storagegateway:Describe*
                  - storagegateway:List*
                  # SWF
                  - swf:Describe*
                  # Synthetics (CloudWatch)
                  - synthetics:Describe*
                  - synthetics:List*
                  # Resource Tags
                  - tag:Get*
                  # Transfer Family
                  - transfer:Describe*
                  - transfer:List*
                  # Transcribe
                  - transcribe:List*
                  # WAF v2
                  - wafv2:Describe*
                  # WorkLink
                  - worklink:Describe*
                  - worklink:List*
                  # Resource Explorer
                  - resource-explorer-2:Search
                  - resource-explorer-2:List*

  # ===========================================================================
  # STACKSET FOR MEMBER ACCOUNTS
  # ===========================================================================
  # This StackSet automatically deploys the v1-member.yaml template to every
  # account in the Organization. Key features:
  #
  # SERVICE_MANAGED: Uses AWS Organizations integration (no IAM roles needed)
  # AutoDeployment: New accounts automatically get the stack
  # ManagedExecution: Parallel deployments for faster rollout
  #
  # The StackSet deploys to the Organization root, meaning ALL accounts
  # (except the management account itself, which uses the role above).
  # ===========================================================================
  MemberAccountStackSet:
    Type: AWS::CloudFormation::StackSet
    DependsOn: ManagementAccountRole
    Properties:
      StackSetName: ZapStackOrgRoles
      Description: ZapStack IAM roles for organization member accounts
      # SERVICE_MANAGED: AWS Organizations handles cross-account deployment
      # (no need for StackSetAdministrationRole/StackSetExecutionRole)
      PermissionModel: SERVICE_MANAGED
      CallAs: SELF
      Capabilities:
        - CAPABILITY_NAMED_IAM
      # Auto-deploy to new accounts, remove from deleted accounts
      AutoDeployment:
        Enabled: true
        RetainStacksOnAccountRemoval: false
      # Parallel execution for faster deployment
      ManagedExecution:
        Active: true
      # Deployment settings: tolerate some failures, deploy in batches
      OperationPreferences:
        FailureTolerancePercentage: 50
        MaxConcurrentPercentage: 25
      # Deploy to all accounts under the Organization root
      StackInstancesGroup:
        - DeploymentTargets:
            # Organization root ID (fetched by Lambda below)
            OrganizationalUnitIds:
              - !GetAtt OrganizationRootId.RootId
          Regions:
            # us-east-1 only - billing/CUR APIs are regional to us-east-1
            - us-east-1
      # Member account template hosted in ZapStack's S3 bucket
      TemplateURL: !Sub
        - "${BucketURL}v1-member.yaml"
        - BucketURL: !FindInMap [ZapStackConfig, Templates, BucketURL]
      # Parameters passed to each member account stack
      Parameters:
        - ParameterKey: ZapStackID
          ParameterValue: !Ref ZapStackID
        - ParameterKey: ZapStackAccount
          ParameterValue: !FindInMap [ZapStackConfig, Account, ID]
        - ParameterKey: ZapStackSnsTopicArn
          ParameterValue: !Sub
            - "arn:aws:sns:us-east-1:${AccountId}:${TopicName}"
            - AccountId: !FindInMap [ZapStackConfig, Account, ID]
              TopicName: !FindInMap [ZapStackConfig, SNS, TopicName]
        - ParameterKey: Version
          ParameterValue: !FindInMap [ZapStackConfig, Version, Current]
      Tags:
        - Key: zapstack:managed
          Value: "true"

  # ===========================================================================
  # ORGANIZATION ROOT ID DISCOVERY
  # ===========================================================================
  # CloudFormation doesn't have a built-in way to get the Organization root ID,
  # but we need it to target the StackSet at all accounts. This Lambda function
  # calls organizations:ListRoots and returns the root ID.
  #
  # This is a one-time lookup at stack creation/update time.
  # ===========================================================================
  OrganizationRootIdFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: ZapStackGetOrgRootId
      Runtime: python3.11
      Handler: index.handler
      Timeout: 30
      Role: !GetAtt OrganizationRootIdFunctionRole.Arn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          def handler(event, context):
              if event['RequestType'] == 'Delete':
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                  return
              try:
                  org = boto3.client('organizations')
                  roots = org.list_roots()['Roots']
                  root_id = roots[0]['Id'] if roots else ''
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, {'RootId': root_id})
              except Exception as e:
                  cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})

  # IAM role for the Lambda function - minimal permissions
  OrganizationRootIdFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: ListOrganizationRoots
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: organizations:ListRoots
                Resource: "*"

  # Custom resource that invokes the Lambda and captures the root ID
  OrganizationRootId:
    Type: Custom::OrganizationRootId
    Properties:
      ServiceToken: !GetAtt OrganizationRootIdFunction.Arn

  # ===========================================================================
  # ZAPSTACK NOTIFICATION
  # ===========================================================================
  # Sends a message to ZapStack's SNS topic when deployment completes.
  # This triggers ZapStack to:
  #   1. Record the management account details
  #   2. Start the initial CUR import job
  #   3. Begin resource scanning
  #
  # The SNS topic is configured as a CloudFormation custom resource handler,
  # so it responds with success/failure to CloudFormation.
  # ===========================================================================
  ZapStackNotifier:
    Type: AWS::CloudFormation::CustomResource
    DependsOn:
      - CostAndUsageReport
      - MemberAccountStackSet
    Properties:
      ServiceToken: !Sub
        - "arn:aws:sns:us-east-1:${AccountId}:${TopicName}"
        - AccountId: !FindInMap [ZapStackConfig, Account, ID]
          TopicName: !FindInMap [ZapStackConfig, SNS, TopicName]
      # Data sent to ZapStack
      AccountID: !Ref AWS::AccountId
      ZapStackID: !Ref ZapStackID
      RoleARN: !GetAtt ManagementAccountRole.Arn
      BucketName: !Ref CURBucket
      ReportName: !Ref ReportName
      Version: !FindInMap [ZapStackConfig, Version, Current]
      StackRegion: !Ref AWS::Region
      IsManagementAccount: "true"
    UpdateReplacePolicy: Delete

# =============================================================================
# OUTPUTS
# Values exported for reference and debugging
# =============================================================================
Outputs:
  ManagementAccountRoleArn:
    Value: !GetAtt ManagementAccountRole.Arn
    Description: Management account IAM role ARN
  CURBucketName:
    Value: !Ref CURBucket
    Description: Cost and Usage Report S3 bucket
  StackSetName:
    Value: !Ref MemberAccountStackSet
    Description: StackSet name for member account roles
  OrganizationRootId:
    Value: !GetAtt OrganizationRootId.RootId
    Description: Organization root ID used for StackSet deployment
