AWSTemplateFormatVersion: 2010-09-09 Description: Template to start the visual search blog Parameters: SageMakerGitURL: Type: String Description: The name of the Git repository Default: https://github.com/aws-samples/amazon-sagemaker-visual-search Resources: NotebookInstance: Type: AWS::SageMaker::NotebookInstance Properties: PlatformIdentifier: notebook-al2-v2 InstanceType: ml.t3.medium RoleArn: !GetAtt Role.Arn DefaultCodeRepository: !Ref SageMakerGitURL Role: Type: AWS::IAM::Role Properties: Policies: - PolicyName: CustomNotebookAccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "es:ESHttp*" Resource: - !Sub arn:aws:es:${AWS::Region}:${AWS::AccountId}:domain/* - Effect: Allow Action: - "s3:GetObject" - "s3:PutObject" - "s3:DeleteObject" - "s3:PutObjectAcl" Resource: - !Sub arn:aws:s3:::${s3BucketTraining}/* - !Sub arn:aws:s3:::${s3BucketHosting}/* ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess - arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - sagemaker.amazonaws.com Action: - "sts:AssumeRole" s3BucketTraining: Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "AES256" VersioningConfiguration: Status: Enabled s3BucketHosting: Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "AES256" VersioningConfiguration: Status: Enabled WebsiteConfiguration: IndexDocument: index.html ErrorDocument: error.html CloudFrontOAI: Type: AWS::CloudFront::CloudFrontOriginAccessIdentity Properties: CloudFrontOriginAccessIdentityConfig: Comment: !Sub "Allows CloudFront to access the S3 bucket: ${s3BucketHosting}" UpdateReplacePolicy: Delete DeletionPolicy: Delete SiteBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref s3BucketHosting PolicyDocument: Statement: - Action: s3:GetObject Effect: Allow Principal: CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId Resource: !Sub "${s3BucketHosting.Arn}/*" Version: "2012-10-17" CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CustomErrorResponses: - ErrorCachingMinTTL: 10 ErrorCode: 403 ResponseCode: 200 ResponsePagePath: /index.html DefaultCacheBehavior: CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 Compress: true TargetOriginId: vissearchcloudfrontmyDistOrigin157DA494D ViewerProtocolPolicy: allow-all Enabled: true HttpVersion: http2 IPV6Enabled: true Origins: - DomainName: !Sub "${s3BucketHosting}.s3.${AWS::Region}.${AWS::URLSuffix}" Id: vissearchcloudfrontmyDistOrigin157DA494D S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOAI}" Domain: Type: AWS::OpenSearchService::Domain Properties: EngineVersion: "OpenSearch_1.3" AccessPolicies: Version: 2012-10-17 Statement: - Effect: Allow Principal: AWS: !Ref AWS::AccountId Action: "es:*" Resource: !Sub arn:aws:es:${AWS::Region}:${AWS::AccountId}:domain/*/* ClusterConfig: InstanceType: "t3.small.search" EBSOptions: EBSEnabled: True VolumeSize: 10 VolumeType: gp3 Outputs: cfDomain: Description: The CloudFront domain name Value: !GetAtt CloudFrontDistribution.DomainName esHostName: Description: OpenSearch hostname Value: !GetAtt Domain.DomainEndpoint esDomainName: Description: OpenSearch domain name Value: !Ref Domain s3BucketTraining: Description: S3 bucket name for training Value: !Ref s3BucketTraining s3BucketHostingBucketName: Description: S3 bucket name for frontend hosting Value: !Ref s3BucketHosting S3BucketSecureURL: Value: !Sub https//${s3BucketHosting.DomainName}/ Description: Name of S3 bucket to hold website content SageMakerNotebookURL: Description: SageMaker Notebook Instance Value: !Sub "https://console.aws.amazon.com/sagemaker/home?region=${AWS::Region}#/notebook-instances/openNotebook/${NotebookInstance.NotebookInstanceName}?view=lab"