---
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AWSTemplateFormatVersion: "2010-09-09"
Description: This template creates a portfolio that contains an Amazon RDS MySQL product with constraints and shares it with an AWS IAM group.
Resources:
  DatabasePortfolio:
    Type: "AWS::ServiceCatalog::Portfolio"
    Properties:
      Description: "A portfolio of self-service databases."
      DisplayName: "Database Portfolio"
      ProviderName: "IT"

  EngineeringGroup:
    Type: "AWS::IAM::Group"
    Properties:
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AWSServiceCatalogEndUserFullAccess
      
  DatabasePortfolioPrincipalAssociation:
    Type: "AWS::ServiceCatalog::PortfolioPrincipalAssociation"
    Properties:
      PortfolioId: !Ref DatabasePortfolio
      PrincipalARN: !GetAtt EngineeringGroup.Arn
      PrincipalType: "IAM"

  MySQLDatabaseProduct:
    Type: "AWS::ServiceCatalog::CloudFormationProduct"
    Properties: 
      Name: "MySQL Database"
      Description: "MySQL Database with corporate configuration."
      Distributor: "IT"
      Owner: "IT"
      SupportDescription: "Please call any time for support"
      SupportEmail: "info@example.com"
      SupportUrl: "https://www.example.com"
      ProvisioningArtifactParameters:
        -
          Name: "MySQL Database"
          Description: "MySQL Database"
          Info:
            LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/rds/sc-rds-mysql-ra.yml"

  PostgreSQLDatabaseProduct:
    Type: "AWS::ServiceCatalog::CloudFormationProduct"
    Properties: 
      Name: "PostgreSQL Database"
      Description: "PostgreSQL Database with corporate configuration."
      Distributor: "IT"
      Owner: "IT"
      SupportDescription: "Please call any time for support"
      SupportEmail: "info@example.com"
      SupportUrl: "https://www.example.com"
      ProvisioningArtifactParameters:
        -
          Name: "PostgreSQL Database"
          Description: "PostgreSQL Database"
          Info:
            LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/rds/sc-rds-postgresql-ra.yml"

  MicrosoftSQLDatabaseProduct:
    Type: "AWS::ServiceCatalog::CloudFormationProduct"
    Properties: 
      Name: "Microsoft SQL Database"
      Description: "Microsoft SQL Database with corporate configuration."
      Distributor: "IT"
      Owner: "IT"
      SupportDescription: "Please call any time for support"
      SupportEmail: "info@example.com"
      SupportUrl: "https://www.example.com"
      ProvisioningArtifactParameters:
        -
          Name: "Microsoft SQL Database"
          Description: "Microsoft SQL Database"
          Info:
            LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/rds/sc-rds-mssql-ra.yml"

  MySQLtoDatabasePortfolioProductAssociation:
    Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
    Properties:
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MySQLDatabaseProduct
  
  PostgreSQLtoDatabasePortfolioProductAssociation:
    Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
    Properties:
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref PostgreSQLDatabaseProduct

  MicrosoftSQLtoDatabasePortfolioProductAssociation:
    Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
    Properties:
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MicrosoftSQLDatabaseProduct

  DatabaseTagOption:
    Type: "AWS::ServiceCatalog::TagOption"
    Properties:
      Key: "ProductType"
      Value: "Database"

  DatabasePortfolioTagOptionAssociation:
    Type: "AWS::ServiceCatalog::TagOptionAssociation"
    Properties:
      ResourceId: !Ref DatabasePortfolio
      TagOptionId: !Ref DatabaseTagOption

  MySQLDatabaseTagOption:
    Type: "AWS::ServiceCatalog::TagOption"
    Properties:
      Key: "DatabaseType"
      Value: "MySQL"

  PostgreSQLDatabaseTagOption:
    Type: "AWS::ServiceCatalog::TagOption"
    Properties:
      Key: "DatabaseType"
      Value: "PostgreSQL"

  MicrosoftSQLDatabaseTagOption:
    Type: "AWS::ServiceCatalog::TagOption"
    Properties:
      Key: "DatabaseType"
      Value: "Micorosft SQL"

  MySQLDatabaseTagOptionAssociation:
    Type: "AWS::ServiceCatalog::TagOptionAssociation"
    Properties:
      ResourceId: !Ref MySQLDatabaseProduct
      TagOptionId: !Ref MySQLDatabaseTagOption

  PostgreSQLDatabaseTagOptionAssociation:
    Type: "AWS::ServiceCatalog::TagOptionAssociation"
    Properties:
      ResourceId: !Ref PostgreSQLDatabaseProduct
      TagOptionId: !Ref PostgreSQLDatabaseTagOption

  MicrosoftSQLDatabaseTagOptionAssociation:
    Type: "AWS::ServiceCatalog::TagOptionAssociation"
    Properties:
      ResourceId: !Ref MicrosoftSQLDatabaseProduct
      TagOptionId: !Ref MicrosoftSQLDatabaseTagOption

  MySQLDatabaseLaunchConstraint:
    Type: "AWS::ServiceCatalog::LaunchRoleConstraint"
    Properties:
      Description: "Allows the product to launch with the policies granted by the associated role."
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MySQLDatabaseProduct
      RoleArn: !GetAtt RDSLaunchConstraintRole.Arn
    DependsOn: MySQLtoDatabasePortfolioProductAssociation

  PostgreSQLDatabaseLaunchConstraint:
    Type: "AWS::ServiceCatalog::LaunchRoleConstraint"
    Properties:
      Description: "Allows the product to launch with the policies granted by the associated role."
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref PostgreSQLDatabaseProduct
      RoleArn: !GetAtt RDSLaunchConstraintRole.Arn
    DependsOn: PostgreSQLtoDatabasePortfolioProductAssociation

  MicrosoftSQLDatabaseLaunchConstraint:
    Type: "AWS::ServiceCatalog::LaunchRoleConstraint"
    Properties:
      Description: "Allows the product to launch with the policies granted by the associated role."
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MicrosoftSQLDatabaseProduct
      RoleArn: !GetAtt RDSLaunchConstraintRole.Arn
    DependsOn: MicrosoftSQLtoDatabasePortfolioProductAssociation

  RDSLaunchConstraintRole:
    Type: "AWS::IAM::Role"
    Properties:
      Path: "/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "servicecatalog.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: "AllowProductLaunch"
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Resource: '*'
                Effect: "Allow"
                Action:
                  # Permissions required for the provisioning of the database
                  - rds:*
                  - ec2:DescribeAccountAttributes
                  - ec2:DescribeSubnets
                  - ec2:DescribeVpcs
                  - ec2:DescribeSecurityGroups
                  - ec2:DescribeSecurityGroupReferences
                  - ec2:DescribeStaleSecurityGroups
                  - ec2:CreateSecurityGroup
                  - ec2:DeleteSecurityGroup
                  - ec2:AuthorizeSecurityGroupIngress
                  - ec2:AuthorizeSecurityGroupEgress
                  - ec2:UpdateSecurityGroupRuleDescriptionsIngress
                  - ec2:UpdateSecurityGroupRuleDescriptionsEgress
                  - ec2:RevokeSecurityGroupEgress
                  - ec2:RevokeSecurityGroupIngress
                  - ec2:CreateTags


                  # Permissions required by AWS Service Catalog to create stack                  
                  - cloudformation:GetTemplateSummary
                  - s3:GetObject
              - Resource:
                  - "arn:aws:cloudformation:*:*:stack/SC-*"
                  - "arn:aws:cloudformation:*:*:changeSet/SC-*"
                Effect: "Allow"
                Action:
                  # Permissions required by AWS Service Catalog to create stack  
                  - cloudformation:CreateStack
                  - cloudformation:DeleteStack
                  - cloudformation:DescribeStackEvents
                  - cloudformation:DescribeStacks
                  - cloudformation:SetStackPolicy
                  - cloudformation:ValidateTemplate
                  - cloudformation:UpdateStack
              - Resource: !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${EngineeringDatabaseCreatedTopic.TopicName}"
                Effect: "Allow"
                Action:
                  - sns:Publish

  EngineeringDatabaseCreatedTopic:
    Type: "AWS::SNS::Topic"
    Properties:
      DisplayName: "Engineering Database Created"

  MySQLDatabaseCreatedLaunchNotification:
    Type: "AWS::ServiceCatalog::LaunchNotificationConstraint"
    Properties:
      Description: "Publishes notifications when a database is provisioned."
      NotificationArns: 
        - !Ref EngineeringDatabaseCreatedTopic
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MySQLDatabaseProduct
    DependsOn: MySQLtoDatabasePortfolioProductAssociation

  PostgreSQLDatabaseCreatedLaunchNotification:
    Type: "AWS::ServiceCatalog::LaunchNotificationConstraint"
    Properties:
      Description: "Publishes notifications when a database is provisioned."
      NotificationArns: 
        - !Ref EngineeringDatabaseCreatedTopic
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref PostgreSQLDatabaseProduct
    DependsOn: PostgreSQLtoDatabasePortfolioProductAssociation

  MicrosoftSQLDatabaseCreatedLaunchNotification:
    Type: "AWS::ServiceCatalog::LaunchNotificationConstraint"
    Properties:
      Description: "Publishes notifications when a database is provisioned."
      NotificationArns: 
        - !Ref EngineeringDatabaseCreatedTopic
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MicrosoftSQLDatabaseProduct
    DependsOn: MicrosoftSQLtoDatabasePortfolioProductAssociation

  ConstrainMySQLDatabaseInstanceSize:
    Type: "AWS::ServiceCatalog::LaunchTemplateConstraint"
    Properties:
      Description: "Constrains the size of a database instance "
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MySQLDatabaseProduct
      Rules: >
        {
          "Rule1" : { 
            "Assertions" : [{ 
              "Assert" : {
                "Fn::Equals" : [
                  "true", 
                  {"Ref" : "MultiAZ"}
                ]
              }, 
              "AssertDescription" : "Databases must be deployed with the MultiAZ property enabled."
            }]
          }
        }
    DependsOn: MySQLtoDatabasePortfolioProductAssociation

  ConstrainPostgreSQLDatabaseInstanceSize:
    Type: "AWS::ServiceCatalog::LaunchTemplateConstraint"
    Properties:
      Description: "Constrains the size of a database instance "
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref PostgreSQLDatabaseProduct
      Rules: >
        {
          "Rule1" : { 
            "Assertions" : [{ 
              "Assert" : {
                "Fn::Equals" : [
                  "true", 
                  {"Ref" : "MultiAZ"}
                ]
              }, 
              "AssertDescription" : "Databases must be deployed with the MultiAZ property enabled."
            }]
          }
        }
    DependsOn: PostgreSQLtoDatabasePortfolioProductAssociation

  ConstrainMicrosoftSQLDatabaseInstanceSize:
    Type: "AWS::ServiceCatalog::LaunchTemplateConstraint"
    Properties:
      Description: "Constrains the size of a database instance"
      PortfolioId: !Ref DatabasePortfolio
      ProductId: !Ref MicrosoftSQLDatabaseProduct
      Rules: >
        {
          "Rule1" : { 
            "Assertions" : [{ 
              "Assert" : {
                "Fn::Equals" : [
                  "true", 
                  {"Ref" : "MultiAZ"}
                ]
              }, 
              "AssertDescription" : "Databases must be deployed with the MultiAZ property enabled."
            }]
          }
        }
    DependsOn: MicrosoftSQLtoDatabasePortfolioProductAssociation