{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Combined CloudFormation template for AWS Marketplace EventBridge rules, API destinations, and Salesforce S3 integration resources with added security configurations.",
    "Parameters": {
        "ClientID": {
            "Type": "String",
            "Description": "OAuth Client ID for authenticating with the Salesforce API."
        },
        "ClientSecret": {
            "Type": "String",
            "NoEcho": true,
            "Description": "OAuth Client Secret for authenticating with the Salesforce API."
        },
        "DomainURL": {
            "Type": "String",
            "Description": "URL of the Salesforce instance, used as the API endpoint."
        },
        "CustomEulaBucketName": {
            "Type": "String",
            "Description": "The name of the S3 bucket to store custom EULAs (End-User License Agreements) for Salesforce integration."
        },
        "SalesforceIAMUserName": {
            "Type": "String",
            "Description": "AWS IAM username dedicated to Salesforce integration tasks."
        },
        "PresignedUrlRoleName": {
            "Type": "String",
            "Default": "GeneratePresignedUrlRole",
            "Description": "Role name for generating presigned URLs for the S3 bucket."
        }
    },
    "Resources": {
        "KMSKey": {
            "Type": "AWS::KMS::Key",
            "Properties": {
                "Description": "KMS Key for encrypting resources such as EventBridge Dead Letter Queue.",
                "EnableKeyRotation": true,
                "KeyPolicy": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "AWS": {
                                    "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root"
                                }
                            },
                            "Action": "*",
                            "Resource": "*"
                        }
                    ]
                }
            }
        },
        "DeadLetterQueue": {
            "Type": "AWS::SQS::Queue",
            "Properties": {
                "QueueName": "APIDestinationDLQ",
                "KmsMasterKeyId": {
                    "Ref": "KMSKey"
                },
                "KmsDataKeyReusePeriodSeconds": 86400
            }
        },
        "EventBridgeRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "Description": "IAM Role for EventBridge to assume for invoking API destinations.",
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": "events.amazonaws.com"
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                }
            }
        },
        "EventBridgePolicy": {
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyName": "EventBridgeInvokeApiDestinationPolicy",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": "events:InvokeApiDestination",
                            "Resource": {
                                "Fn::Sub": "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:api-destination/*"
                            }
                        }
                    ]
                },
                "Roles": [
                    {
                        "Ref": "EventBridgeRole"
                    }
                ]
            }
        },
        "Rule0Connection0": {
            "Type": "AWS::Events::Connection",
            "Properties": {
                "AuthorizationType": "OAUTH_CLIENT_CREDENTIALS",
                "AuthParameters": {
                    "OAuthParameters": {
                        "ClientParameters": {
                            "ClientID": {
                                "Ref": "ClientID"
                            },
                            "ClientSecret": {
                                "Ref": "ClientSecret"
                            }
                        },
                        "AuthorizationEndpoint": {
                            "Fn::Join": [
                                "",
                                [
                                    {
                                        "Ref": "DomainURL"
                                    },
                                    "/services/oauth2/token"
                                ]
                            ]
                        },
                        "HttpMethod": "POST",
                        "OAuthHttpParameters": {
                            "BodyParameters": [
                                {
                                    "Key": "grant_type",
                                    "Value": "client_credentials"
                                }
                            ]
                        }
                    }
                },
                "Name": "AWS2SalesforceConnection",
                "Description": "Connection to Salesforce using OAuth Client Credentials for EventBridge API destinations."
            }
        },
        "Rule0ApiDestination0": {
            "Type": "AWS::Events::ApiDestination",
            "Properties": {
                "ConnectionArn": {
                    "Fn::GetAtt": ["Rule0Connection0", "Arn"]
                },
                "HttpMethod": "POST",
                "InvocationEndpoint": {
                    "Fn::Join": [
                        "",
                        [
                            {
                                "Ref": "DomainURL"
                            },
                            "/services/data/v54.0/sobjects/awsapn__AWS_Marketplace_Notification__c"
                        ]
                    ]
                },
                "InvocationRateLimitPerSecond": 300,
                "Name": "AWS2SalesforceAPIDestination",
                "Description": "API destination for EventBridge to send marketplace notifications to Salesforce."
            }
        },
        "EventRule0": {
            "Type": "AWS::Events::Rule",
            "Properties": {
                "EventBusName": "default",
                "EventPattern": {
                    "source": ["aws.marketplacecatalog"],
                    "detail-type": [
                        "Change Set Succeeded",
                        "Change Set Failed",
                        "Change Set Cancelled"
                    ]
                },
                "Name": "AWSMarketplaceChangeSetEventsRule",
                "State": "ENABLED",
                "Targets": [
                    {
                        "Id": "Id97b0de5f-74c5-4713-a695-7fe0c7f7e0a7",
                        "Arn": {
                            "Fn::GetAtt": ["Rule0ApiDestination0", "Arn"]
                        },
                        "RoleArn": {
                            "Fn::GetAtt": ["EventBridgeRole", "Arn"]
                        },
                        "InputTransformer": {
                            "InputPathsMap": {
                                "Name": "$.detail-type",
                                "awsapn__Account_Number__c": "$.account",
                                "awsapn__EntityId__c": "$.detail.ChangeSetId"
                            },
                            "InputTemplate": "{\n  \"Name\": <Name>,\n  \"awsapn__Account_Number__c\": <awsapn__Account_Number__c>,\n  \"awsapn__EntityId__c\": <awsapn__EntityId__c>,\n  \"awsapn__State__c\" : \"Not Processed\"\n}"
                        },
                        "DeadLetterConfig": {
                            "Arn": {
                                "Fn::GetAtt": ["DeadLetterQueue", "Arn"]
                            }
                        }
                    }
                ],
                "Description": "EventBridge rule for marketplace catalog changes (change set events) to trigger the API destination."
            }
        },
        "EventRule1": {
            "Type": "AWS::Events::Rule",
            "Properties": {
                "EventBusName": "default",
                "EventPattern": {
                    "source": ["aws.marketplacecatalog"],
                    "detail-type": ["Offer Released"]
                },
                "Name": "AWSMarketplaceOfferReleasedEventsRule",
                "State": "ENABLED",
                "Targets": [
                    {
                        "Id": "Iddb2e341c-ea2a-4914-afdb-d6263f2a7dc2",
                        "Arn": {
                            "Fn::GetAtt": ["Rule0ApiDestination0", "Arn"]
                        },
                        "RoleArn": {
                            "Fn::GetAtt": ["EventBridgeRole", "Arn"]
                        },
                        "InputTransformer": {
                            "InputPathsMap": {
                                "Name": "$.detail-type",
                                "awsapn__Account_Number__c": "$.account",
                                "awsapn__EntityId__c": "$.detail.offer.id",
                                "awsapn__Manufacturer_Account_Id__c": "$.detail.manufacturer.accountId",
                                "awsapn__Product_Id__c": "$.detail.product.id",
                                "awsapn__Seller_Account_Id__c": "$.detail.sellerOfRecord.accountId",
                                "awsapn__Offer_Name__c": "$.detail.offer.name"
                            },
                            "InputTemplate": "{\n  \"Name\": <Name>,\n  \"awsapn__Account_Number__c\": <awsapn__Account_Number__c>,\n  \"awsapn__EntityId__c\": <awsapn__EntityId__c>,\n  \"awsapn__Seller_Account_Id__c\": <awsapn__Seller_Account_Id__c>,\n  \"awsapn__Manufacturer_Account_Id__c\": <awsapn__Manufacturer_Account_Id__c>,\n  \"awsapn__Product_Id__c\": <awsapn__Product_Id__c>,\n  \"awsapn__Offer_Name__c\" : <awsapn__Offer_Name__c>\n}"
                        },
                        "DeadLetterConfig": {
                            "Arn": {
                                "Fn::GetAtt": ["DeadLetterQueue", "Arn"]
                            }
                        }
                    }
                ],
                "Description": "EventBridge rule for marketplace catalog offer release events to trigger the API destination."
            }
        },
        "CustomEulaBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName": {
                    "Ref": "CustomEulaBucketName"
                },
                "BucketEncryption": {
                    "ServerSideEncryptionConfiguration": [
                        {
                            "ServerSideEncryptionByDefault": {
                                "SSEAlgorithm": "AES256"
                            }
                        }
                    ]
                },
                "LoggingConfiguration": {
                    "DestinationBucketName": {
                        "Ref": "CustomEulaBucketName"
                    },
                    "LogFilePrefix": "logs/"
                },
                "VersioningConfiguration": {
                    "Status": "Enabled"
                },
                "PublicAccessBlockConfiguration": {
                    "BlockPublicAcls": true,
                    "IgnorePublicAcls": true,
                    "BlockPublicPolicy": true,
                    "RestrictPublicBuckets": true
                }
            }
        },
        "SFIntegrationUser": {
            "Type": "AWS::IAM::User",
            "Properties": {
                "UserName": {
                    "Ref": "SalesforceIAMUserName"
                },
                "Groups": [
                    {
                        "Ref": "SalesforceIAMGroup"
                    }
                ]
            }
        },
        "SalesforceIAMGroup": {
            "Type": "AWS::IAM::Group",
            "Properties": {
                "GroupName": "SalesforceIntegrationGroup",
                "ManagedPolicyArns": [
                    {
                        "Ref": "SalesforceIntegrationPolicy"
                    },
                    "arn:aws:iam::aws:policy/AWSMarketplaceSellerFullAccess"
                ]
            }
        },
        "SalesforceIntegrationPolicy": {
            "Type": "AWS::IAM::ManagedPolicy",
            "Properties": {
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": [
                                "s3:ListBucket",
                                "s3:PutObject",
                                "s3:PutObjectAcl",
                                "s3:GetObject",
                                "s3:GetObjectAcl"
                            ],
                            "Resource": [
                                {
                                    "Fn::Sub": "arn:aws:s3:::${CustomEulaBucketName}"
                                },
                                {
                                    "Fn::Sub": "arn:aws:s3:::${CustomEulaBucketName}/*"
                                }
                            ]
                        }
                    ]
                },
                "Description": "Managed policy for Salesforce integration, granting access to specified S3 resources."
            }
        },
        "SalesforceUserAccessKey": {
            "Type": "AWS::IAM::AccessKey",
            "Properties": {
                "UserName": {
                    "Ref": "SalesforceIAMUserName"
                }
            },
            "DependsOn": "SFIntegrationUser"
        },
        "GeneratePresignedUrlRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": {
                    "Ref": "PresignedUrlRoleName"
                },
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "AWS": {
                                    "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:user/${SalesforceIAMUserName}"
                                }
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "MaxSessionDuration": 7200,
                "Policies": [
                    {
                        "PolicyName": "GeneratePresignedUrlPolicy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Sid": "AllowCreatePresignedUrl",
                                    "Effect": "Allow",
                                    "Action": [
                                        "s3:PutObject",
                                        "s3:PutObjectAcl",
                                        "s3:GetObject",
                                        "s3:GetObjectAcl"
                                    ],
                                    "Resource": [
                                        {
                                            "Fn::Sub": "arn:aws:s3:::${CustomEulaBucketName}"
                                        },
                                        {
                                            "Fn::Sub": "arn:aws:s3:::${CustomEulaBucketName}/*"
                                        }
                                    ]
                                }
                            ]
                        }
                    }
                ],
                "Description": "IAM role for generating presigned URLs for custom EULA bucket."
            },
            "DependsOn": "SFIntegrationUser"
        }
    },
    "Outputs": {
        "CustomEulaBucketName": {
            "Value": {
                "Ref": "CustomEulaBucketName"
            },
            "Description": "Name of the S3 bucket for storing custom EULAs."
        },
        "SFIntegrationUserArn": {
            "Value": {
                "Fn::GetAtt": ["SFIntegrationUser", "Arn"]
            },
            "Description": "ARN of the IAM user for Salesforce integration."
        },
        "SalesforceUserAccessKeyId": {
            "Description": "Access Key ID for the Salesforce integration IAM user.",

            "Value": {
                "Ref": "SalesforceUserAccessKey"
            }
        },
        "SalesforceUserSecretAccessKey": {
            "Description": "Secret Access Key for the Salesforce integration IAM user.",
            "Value": {
                "Fn::GetAtt": ["SalesforceUserAccessKey", "SecretAccessKey"]
            }
        }
    }
}