--- AWSTemplateFormatVersion: "2010-09-09" Description: Creates an S3 watchfolder and automated video conversion workflow Parameters: NotifcationEmail: Description: Email address for SNS notifications Type: String Default: elementalrodeo@gmail.com AllowedPattern: "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$" Mappings: SourceCode: General: S3Bucket: "rodeolabz" KeyPrefix: "vodtk/1a-mediaconvert-watchfolder" Resources: MediaConvertRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-MediaConvertRole" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - "mediaconvert.amazonaws.com" - "mediaconvert.us-east-1.amazonaws.com" - "mediaconvert.ap-northeast-1.amazonaws.com" - "mediaconvert.ap-southeast-1.amazonaws.com" - "mediaconvert.ap-southeast-2.amazonaws.com" - "mediaconvert.eu-central-1.amazonaws.com" - "mediaconvert.eu-west-1.amazonaws.com" - "mediaconvert.us-east-1.amazonaws.com" - "mediaconvert.us-west-1.amazonaws.com" - "mediaconvert.us-west-2.amazonaws.com" Action: - sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-MediaConvertPolicy" PolicyDocument: Statement: - Effect: "Allow" Action: - "s3:*" Resource: - "*" - Effect: "Allow" Action: - "autoscaling:Describe*" - "cloudwatch:*" - "logs:*" - "sns:*" Resource: - "*" LambdaRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-LambdaRole" AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-LambdaPolicy" PolicyDocument: Version: 2012-10-17 Statement: - Sid: Logging Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "*" - Sid: PassRole Effect: Allow Action: - iam:PassRole Resource: - !GetAtt MediaConvertRole.Arn - Sid: MediaConvertService Effect: Allow Action: - "mediaconvert:*" Resource: - "*" - Sid: InputBucket Effect: Allow Action: - "s3:*" Resource: "*" S3InvokeLambda: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt LambdaConvert.Arn Action: lambda:InvokeFunction Principal: s3.amazonaws.com SourceAccount: !Ref AWS::AccountId WatchFolder: Type: AWS::S3::Bucket Properties: LifecycleConfiguration: Rules: - Id: ExpireRule Status: Enabled ExpirationInDays: '7' NotificationConfiguration: LambdaConfigurations: - Function: !GetAtt LambdaConvert.Arn Event: "s3:ObjectCreated:*" Filter: S3Key: Rules: - Name: prefix Value: inputs/ DeletionPolicy: Retain LambdaConvert: Type: AWS::Lambda::Function Properties: FunctionName: !Sub ${AWS::StackName}-convert Description: Converts input video Handler: convert.handler Role: !GetAtt LambdaRole.Arn Code: S3Bucket: !Join ["-", [!FindInMap ["SourceCode", "General", "S3Bucket"], !Ref "AWS::Region"]] S3Key: !Join ["/", [!FindInMap ["SourceCode", "General", "KeyPrefix"], "lambda.zip"]] Environment: Variables: DestinationBucket: !Ref MediaBucket MediaConvertRole: !GetAtt MediaConvertRole.Arn Application: !Sub "${AWS::StackName}" Runtime: python3.7 Timeout: 120 MediaBucket: Properties: WebsiteConfiguration: IndexDocument: index.html CorsConfiguration: CorsRules: - AllowedHeaders: ['*'] AllowedMethods: [GET] AllowedOrigins: ['*'] ExposedHeaders: [Date] Id: myCORSRuleId1 MaxAge: '3600' LifecycleConfiguration: Rules: - Id: ExpireRule Status: Enabled ExpirationInDays: '7' DeletionPolicy: Retain Type: "AWS::S3::Bucket" MediaBucketPolicy: Properties: Bucket: !Ref MediaBucket PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: "*" Action: s3:GetObject Resource: !Sub "arn:aws:s3:::${MediaBucket}/*" Type: "AWS::S3::BucketPolicy" NotificationTopicPolicy: Type: AWS::SNS::TopicPolicy Properties: PolicyDocument: Version: '2012-10-17' Statement: - Sid: AllowCloudWatchEvents Effect: Allow Principal: Service: events.amazonaws.com Action: sns:Publish Resource: "*" #grant rights to all SNS topics (narrow it down if security is an issue) Topics: - !Ref NotificationSns NotificationSns: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: !Ref NotifcationEmail Protocol: email NotifyEventRule: Type: "AWS::Events::Rule" Properties: Description: catches MediaConvert Complete and Error events and sends to SNS topic State: "ENABLED" EventPattern: source: - "aws.mediaconvert" detail: status: - "COMPLETE" - "ERROR" userMetadata: application: - !Sub "${AWS::StackName}" Targets: - Arn: !Ref NotificationSns Id: "TargetSNS1" InputTransformer: InputPathsMap: jobId: "$.detail.jobId" region: "$.region" status: "$.detail.status" InputTemplate: '"Job finished with status . Job details: https://.console.aws.amazon.com/mediaconvert/home?region=#/jobs/summary/"' Outputs: MediaBucket: Value: !Ref MediaBucket MediaConvertRoleArn: Value: !GetAtt MediaConvertRole.Arn WatchFolderBucket: Value: !Ref WatchFolder LambdaRoleArn: Value: !GetAtt LambdaRole.Arn