AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: Cribl Stream free deployment on x86_64 with AWS Cloudtrail logging (qs-1ti330r8h).

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: AWS CloudTrail configuration
        Parameters:
          - ExternalLogBucket
      - Label:
          default: Cribl configuration
        Parameters:
          - webAccessCidr
          - instanceType
      - Label:
          default: Network configuration
        Parameters:
          - AvailabilityZones
          - VPCCIDR
          - PrivateSubnet1CIDR
          - PrivateSubnet2CIDR
          - PublicSubnet1CIDR
          - PublicSubnet2CIDR
          - VPCTenancy
      - Label:
          default: AWS Partner Solution configuration
        Parameters:
          - QSS3BucketName
          - QSS3KeyPrefix
          - QSS3BucketRegion
    ParameterLabels:
      AvailabilityZones:
        default: Availability Zones
      PublicSubnet1CIDR:
        default: Public subnet 1 CIDR
      PublicSubnet2CIDR:
        default: Public subnet 2 CIDR
      PrivateSubnet1CIDR:
        default: Private subnet 1 CIDR
      PrivateSubnet2CIDR:
        default: Private subnet 2 CIDR
      VPCTenancy:
        default: VPC tenancy
      VPCCIDR:
        default: VPC CIDR
      QSS3BucketName:
        default: Partner Solution S3 bucket name
      QSS3KeyPrefix:
        default: Partner Solution S3 key prefix
      QSS3BucketRegion:
        default: Partner Solution S3 bucket Region
      webAccessCidr:
        default: Cribl Stream leader web-access CIDR
      instanceType:
        default: Cribl Stream leader EC2 instance type
      ExternalLogBucket:
        default: CloudTrail logs S3 bucket

Parameters:
  AvailabilityZones:
    Description: List of Availability Zones to use for the subnets in the VPC.
    Type: 'List<AWS::EC2::AvailabilityZone::Name>'
  PrivateSubnet1CIDR:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.0.0/19
    Description: CIDR block for private subnet 1, located in Availability Zone 1.
    Type: String
  PrivateSubnet2CIDR:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.32.0/19
    Description: CIDR block for private subnet 2, located in Availability Zone 2.
    Type: String
  PublicSubnet1CIDR:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.128.0/20
    Description: CIDR Block for the public subnet 1, located in Availability Zone 1.
    Type: String
  PublicSubnet2CIDR:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.144.0/20
    Description: CIDR Block for the public subnet 2, located in Availability Zone 2.
    Type: String
  VPCTenancy:
    AllowedValues:
      - default
      - dedicated
    Default: default
    Description: The allowed tenancy of instances launched into the VPC.
    Type: String
  VPCCIDR:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form "x.x.x.x/16-28".
    Default: 10.0.0.0/16
    Description: CIDR Block for the VPC.
    Type: String
  QSS3BucketName:
    AllowedPattern: ^[0-9a-z]+([0-9a-z-\.]*[0-9a-z])*$
    ConstraintDescription: >-
      The S3 bucket name can include numbers, lowercase letters,
      and hyphens (-), but it cannot start or end with a hyphen.
    Default: aws-quickstart
    Description: >-
      Name of the S3 bucket for your copy of the deployment assets. Keep the default
      name unless you are customizing the template. Changing the name updates code
      references to point to a new location.
    MinLength: 3
    MaxLength: 63
    Type: String
  QSS3KeyPrefix:
    AllowedPattern: ^([0-9a-zA-Z!-_\.\*'\(\)/]+/)*$
    ConstraintDescription: >-
      The S3 key prefix can include numbers, lowercase letters, uppercase letters,
      hyphens (-), underscores (_), periods (.), asterisks (*), single quotes ('),
      open parenthesis ((), close parenthesis ()), and forward slashes (/). End the
      prefix with a forward slash.
    Default: quickstart-cribl-cloudtrail/
    Description: >-
      S3 key prefix that is used to simulate a folder for your copy of the
      deployment assets. Keep the default prefix unless you are customizing
      the template. Changing the prefix updates code references to point to
      a new location.
    Type: String
  QSS3BucketRegion:
    Default: us-east-1
    Description: >-
      AWS Region where the S3 bucket (QSS3BucketName) is hosted. Keep
      the default Region unless you are customizing the template. Changing the Region
      updates code references to point to a new location. When using your own bucket,
      specify the Region.
    Type: String
  webAccessCidr:
    Type: String
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
    ConstraintDescription: CIDR block parameter must be in the form "x.x.x.x/x".
    Description: (Required) CIDR IP range permitted to access the Cribl Stream web console. We recommend you set this value to a trusted IP range.
    Default: 10.0.144.0/20
  instanceType:
    Description: EC2 instance type to provision the Cribl Stream leader instance.
    Type: String
    Default: c5.xlarge
    AllowedValues:
      - c5.large
      - c5.xlarge
      - c5d.large
      - c5d.xlarge
      - c5a.large
      - c5a.xlarge
      - c5ad.large
      - c5ad.xlarge
    ConstraintDescription: Must contain valid instance type.
  ExternalLogBucket:
    Description: >-
      (Optional) Name of an existing S3 bucket to store flow logs. If
      you leave this blank, the deployment creates an Amazon S3 bucket for you.
    Type: String
    Default: ''

Rules:
  SubnetsInVPC:
    Assertions:
      - Assert: !EachMemberIn
          - !ValueOfAll
            - AWS::EC2::Subnet::Id
            - VpcId
          - !RefAll "AWS::EC2::VPC::Id"
        AssertDescription: All subnets must in the VPC

Conditions:
  InternalBucket: !Equals
    - !Ref ExternalLogBucket
    - ''
  UsingDefaultBucket: !Equals
    - !Ref QSS3BucketName
    - 'aws-quickstart'

Resources:
  S3Bucket:
    Condition: InternalBucket
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/aws_s3bucket.template.yaml
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub 'aws-quickstart-${AWS::Region}'
            - !Ref 'QSS3BucketName'
          S3Region: !If
            - UsingDefaultBucket
            - !Ref 'AWS::Region'
            - !Ref 'QSS3BucketRegion'

  CloudTrail:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/aws_cloudtrail.template.yaml
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub 'aws-quickstart-${AWS::Region}'
            - !Ref 'QSS3BucketName'
          S3Region: !If
            - UsingDefaultBucket
            - !Ref 'AWS::Region'
            - !Ref 'QSS3BucketRegion'
      Parameters:
        BucketArn: !If
          - InternalBucket
          - !GetAtt S3Bucket.Outputs.S3BucketArn
          - !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref ExternalLogBucket
        BucketName: !If
          - InternalBucket
          - !GetAtt S3Bucket.Outputs.S3BucketName
          - !Ref ExternalLogBucket

  VPCStack:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub 'aws-quickstart-${AWS::Region}'
            - !Ref 'QSS3BucketName'
          S3Region: !If
            - UsingDefaultBucket
            - !Ref 'AWS::Region'
            - !Ref 'QSS3BucketRegion'
      Parameters:
        AvailabilityZones: !Join
          - ','
          - !Ref AvailabilityZones
        NumberOfAZs: '2'
        PrivateSubnet1ACIDR: !Ref PrivateSubnet1CIDR
        PrivateSubnet2ACIDR: !Ref PrivateSubnet2CIDR
        PublicSubnet1CIDR: !Ref PublicSubnet1CIDR
        PublicSubnet2CIDR: !Ref PublicSubnet2CIDR
        VPCCIDR: !Ref VPCCIDR
        VPCTenancy: !Ref VPCTenancy

  CriblStack:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/quickstart-cribl-logstream/templates/cribl-single-x86.workload.template.yaml
        - S3Bucket: aws-quickstart
          S3Region: us-east-1
      Parameters:
        instanceType: !Ref instanceType
        webAccessCidr: !Ref webAccessCidr
        vpcId: !GetAtt VPCStack.Outputs.VPCID
        subnetIds: !Join
          - ','
          - - !GetAtt VPCStack.Outputs.PublicSubnet1ID
            - !GetAtt VPCStack.Outputs.PublicSubnet2ID

  EmptyBucketLambda:
    Condition: InternalBucket
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/aws_lambda_emptybucket.template.yaml
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub 'aws-quickstart-${AWS::Region}'
            - !Ref 'QSS3BucketName'
          S3Region: !If
            - UsingDefaultBucket
            - !Ref 'AWS::Region'
            - !Ref 'QSS3BucketRegion'
      Parameters:
        BucketArn2Empty: !GetAtt S3Bucket.Outputs.S3BucketArn
        Bucket2Empty: !GetAtt S3Bucket.Outputs.S3BucketName

Outputs:
  StreamWebUrlPublic:
    Value: !GetAtt CriblStack.Outputs.logstreamWebUrlPublic
    Description: Cribl Stream web console URL.
  StreamWebAccessCreds:
    Value: !GetAtt CriblStack.Outputs.logstreamWebAccessCreds
    Description: Default Cribl Stream web console access credentials.
  S3SQSArn:
    Value: !GetAtt S3Bucket.Outputs.SQSArn
    Description: ARN of the SQS queue (used to configure S3 input in Cribl Stream).
    Condition: InternalBucket
  S3AccessRoleArn:
    Value: !GetAtt S3Bucket.Outputs.AccessRoleArn
    Description: ARN for the IAM Role to access the SQS queue and S3 bucket (used to configure the S3 input in Cribl Stream).
    Condition: InternalBucket
  S3BucketArn:
    Value: !GetAtt S3Bucket.Outputs.S3BucketArn
    Description: ARN for the S3 bucket used for storing CloudTrail data.
    Condition: InternalBucket