AWSTemplateFormatVersion: '2010-09-09'
Description: >
  AWS Cost and Usage Report (CUR) 2.0 Export Configuration with support for S3 bucket and IAM Role creation. 
  Note: This stack must be run in a US Region as billing services data export is supported only in the US regions.

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "Data Export Creation - CUR Reports"
        Parameters:
          - ExportName
          - S3BucketName
      - Label:
          default: "Role Creation"
        Parameters:
          - RoleName
    ParameterLabels:
      S3BucketName:
        default: "S3 Bucket Name"
      ExportName:
        default: "Export Name for CUR"
      RoleName:
        default: "Role Name"

Parameters:

  S3BucketName:
    Type: String
    Description: "S3 bucket name to store CUR Files generated by AWS."
    AllowedPattern: "[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]"
    ConstraintDescription: "Bucket name must contain only letters, numbers, and hyphens"
    Default: "onelens-customername-cur-bucket"
    MinLength: 3
    MaxLength: 63

  ExportName:
    Type: String
    Description: "Name for the CUR export definition"
    Default: "OneLens-Standard-CUR-Export"
    MinLength: 3
    MaxLength: 75

  RoleName:
    Type: String
    Description: 'Name of the IAM Role with aplhanumeric unique id'
    Default: "OneLens-<10-char-alphanumeric-unique-id-2>"

Resources:
  S3ClientBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref S3BucketName
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration:
        Rules:
          - Id: TransitionToIA
            Status: Enabled
            Transitions:
              - TransitionInDays: 90
                StorageClass: STANDARD_IA
      Tags:
        - Key: onelens:provider
          Value: onelens

  S3ClientBucketAccessPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3BucketName
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - billingreports.amazonaws.com
                - bcm-data-exports.amazonaws.com
            Action:
              - s3:PutObject
              - s3:GetBucketPolicy
            Resource:
              - !Sub arn:aws:s3:::${S3BucketName}
              - !Sub arn:aws:s3:::${S3BucketName}/*
            Condition:
              StringLike:
                aws:SourceArn:
                  - !Sub arn:aws:cur:${AWS::Region}:${AWS::AccountId}:definition/*
                  - !Sub arn:aws:bcm-data-exports:${AWS::Region}:${AWS::AccountId}:export/*
                aws:SourceAccount: !Sub ${AWS::AccountId}

  CURReportDefinition:
    DependsOn: S3ClientBucketAccessPolicy
    Type: AWS::BCMDataExports::Export
    Properties:
      Export:
        DataQuery:
          QueryStatement: >
            SELECT bill_bill_type, bill_billing_entity, bill_billing_period_end_date, bill_billing_period_start_date, bill_invoice_id, bill_invoicing_entity, bill_payer_account_id, bill_payer_account_name, cost_category, discount, discount_bundled_discount, discount_total_discount, identity_line_item_id, identity_time_interval, line_item_availability_zone, line_item_blended_cost, line_item_blended_rate, line_item_currency_code, line_item_legal_entity, line_item_line_item_description, line_item_line_item_type, line_item_net_unblended_cost, line_item_net_unblended_rate, line_item_normalization_factor, line_item_normalized_usage_amount, line_item_operation, line_item_product_code, line_item_resource_id, line_item_tax_type, line_item_unblended_cost, line_item_unblended_rate, line_item_usage_account_id, line_item_usage_account_name, line_item_usage_amount, line_item_usage_end_date, line_item_usage_start_date, line_item_usage_type, pricing_currency, pricing_lease_contract_length, pricing_offering_class, pricing_public_on_demand_cost, pricing_public_on_demand_rate, pricing_purchase_option, pricing_rate_code, pricing_rate_id, pricing_term, pricing_unit, product, product_comment, product_fee_code, product_fee_description, product_from_location, product_from_location_type, product_from_region_code, product_instance_family, product_instance_type, product_instancesku, product_location, product_location_type, product_operation, product_pricing_unit, product_product_family, product_region_code, product_servicecode, product_sku, product_to_location, product_to_location_type, product_to_region_code, product_usagetype, reservation_amortized_upfront_cost_for_usage, reservation_amortized_upfront_fee_for_billing_period, reservation_availability_zone, reservation_effective_cost, reservation_end_time, reservation_modification_status, reservation_net_amortized_upfront_cost_for_usage, reservation_net_amortized_upfront_fee_for_billing_period, reservation_net_effective_cost, reservation_net_recurring_fee_for_usage, reservation_net_unused_amortized_upfront_fee_for_billing_period, reservation_net_unused_recurring_fee, reservation_net_upfront_value, reservation_normalized_units_per_reservation, reservation_number_of_reservations, reservation_recurring_fee_for_usage, reservation_reservation_a_r_n, reservation_start_time, reservation_subscription_id, reservation_total_reserved_normalized_units, reservation_total_reserved_units, reservation_units_per_reservation, reservation_unused_amortized_upfront_fee_for_billing_period, reservation_unused_normalized_unit_quantity, reservation_unused_quantity, reservation_unused_recurring_fee, reservation_upfront_value, resource_tags, savings_plan_amortized_upfront_commitment_for_billing_period, savings_plan_end_time, savings_plan_instance_type_family, savings_plan_net_amortized_upfront_commitment_for_billing_period, savings_plan_net_recurring_commitment_for_billing_period, savings_plan_net_savings_plan_effective_cost, savings_plan_offering_type, savings_plan_payment_option, savings_plan_purchase_term, savings_plan_recurring_commitment_for_billing_period, savings_plan_region, savings_plan_savings_plan_a_r_n, savings_plan_savings_plan_effective_cost, savings_plan_savings_plan_rate, savings_plan_start_time, savings_plan_total_commitment_to_date, savings_plan_used_commitment, split_line_item_actual_usage, split_line_item_net_split_cost, split_line_item_net_unused_cost, split_line_item_parent_resource_id, split_line_item_public_on_demand_split_cost, split_line_item_public_on_demand_unused_cost, split_line_item_reserved_usage, split_line_item_split_cost, split_line_item_split_usage, split_line_item_split_usage_ratio, split_line_item_unused_cost FROM COST_AND_USAGE_REPORT
          TableConfigurations:
            COST_AND_USAGE_REPORT:
              INCLUDE_RESOURCES: "TRUE"
              INCLUDE_SPLIT_COST_ALLOCATION_DATA: "TRUE"
              TIME_GRANULARITY: "HOURLY"
        DestinationConfigurations:
          S3Destination:
            S3Bucket: !Ref S3BucketName
            S3Region: 'us-east-1'
            S3Prefix: "cur/"
            S3OutputConfigurations:
              Compression: "PARQUET"
              Format: "PARQUET"
              OutputType: "CUSTOM"
              Overwrite: "OVERWRITE_REPORT"
        Name: !Ref ExportName
        RefreshCadence:
          Frequency: "SYNCHRONOUS"

  OneLensCURPolicy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: !Sub 'OneLensCURPolicy-${AWS::StackName}'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: 'S3CurAccess'
            Effect: Allow
            Action:
              - s3:Get*
              - s3:List*
            Resource:
              - !Sub 'arn:aws:s3:::${S3BucketName}'
              - !Sub 'arn:aws:s3:::${S3BucketName}/*'

  OneLens:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: !Ref RoleName
      Description: "Role for OneLens CUR data access"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            #Astuto Account ID to assume role
            Principal:
              AWS: !Sub 'arn:aws:iam::471112871310:root'
            Action: 
              - "sts:AssumeRole"
              - "sts:TagSession"
      ManagedPolicyArns:
        - !Ref OneLensCURPolicy
      Tags:
        - Key: Purpose
          Value: OneLensCURAccess

Outputs:
  S3BucketName:
    Description: "Name of the S3 bucket storing CUR data"
    Value: !Ref S3BucketName

  IAMRoleArn:
    Description: "IAM Role ARN for the specified account"
    Value: !GetAtt OneLens.Arn

