in source/controlplaneapi/infrastructure/stacks/chaliceapp.py [0:0]
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
##### START: DYNAMODB TABLES AND INDEXES #####
# System Configuration Table
self.system_table = ddb.Table(
self,
"System",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# ContentGroup Table
self.content_group_table = ddb.Table(
self,
"ContentGroup",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# Program Table
self.program_table = ddb.Table(
self,
"Program",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# Plugin Table
self.plugin_table = ddb.Table(
self,
"Plugin",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="Version",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# ReplayRequest Table
self.replayrequest_table = ddb.Table(
self,
"ReplayRequest",
partition_key=ddb.Attribute(
name="PK",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="ReplayId",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# Plugin Table: Name GSI
self.plugin_table.add_global_secondary_index(
index_name=PLUGIN_NAME_INDEX,
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
)
)
# Plugin Table: Version GSI
self.plugin_table.add_global_secondary_index(
index_name=PLUGIN_VERSION_INDEX,
partition_key=ddb.Attribute(
name="Version",
type=ddb.AttributeType.STRING
)
)
# Profile Table
self.profile_table = ddb.Table(
self,
"Profile",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# Model Table
self.model_table = ddb.Table(
self,
"Model",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="Version",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# Model Table: Name GSI
self.model_table.add_global_secondary_index(
index_name=MODEL_NAME_INDEX,
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
)
)
# Model Table: Version GSI
self.model_table.add_global_secondary_index(
index_name=MODEL_VERSION_INDEX,
partition_key=ddb.Attribute(
name="Version",
type=ddb.AttributeType.STRING
)
)
# Event Table
self.event_table = ddb.Table(
self,
"Event",
partition_key=ddb.Attribute(
name="Name",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="Program",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# Event Table: Channel GSI
self.event_table.add_global_secondary_index(
index_name=EVENT_CHANNEL_INDEX,
partition_key=ddb.Attribute(
name="Channel",
type=ddb.AttributeType.STRING
),
projection_type=ddb.ProjectionType.KEYS_ONLY
)
# Event Table: ProgramId GSI
self.event_table.add_global_secondary_index(
index_name=EVENT_PROGRAMID_INDEX,
partition_key=ddb.Attribute(
name="ProgramId",
type=ddb.AttributeType.STRING
),
projection_type=ddb.ProjectionType.KEYS_ONLY
)
# Event Table: ContentGroup GSI
self.event_table.add_global_secondary_index(
index_name=EVENT_CONTENT_GROUP_INDEX,
partition_key=ddb.Attribute(
name="ContentGroup",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="Start",
type=ddb.AttributeType.STRING
)
)
# Event Table: Pagination key
self.event_table.add_global_secondary_index(
index_name=EVENT_PAGINATION_INDEX,
partition_key=ddb.Attribute(
name="PaginationPartition",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="Start",
type=ddb.AttributeType.STRING
)
)
# WorkflowExecution Table
self.workflow_exec_table = ddb.Table(
self,
"WorkflowExecution",
partition_key=ddb.Attribute(
name="PK",
type=ddb.AttributeType.STRING
),
sort_key=ddb.Attribute(
name="ChunkNumber",
type=ddb.AttributeType.NUMBER
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
# CurrentEvents Table
self.current_events_table = ddb.Table(
self,
"CurrentEvents",
partition_key=ddb.Attribute(
name="EventId",
type=ddb.AttributeType.STRING
),
billing_mode=ddb.BillingMode.PAY_PER_REQUEST,
removal_policy=cdk.RemovalPolicy.DESTROY
)
##### END: DYNAMODB TABLES AND INDEXES #####
##### START: S3 BUCKETS #####
# MRE Access Log Bucket
self.access_log_bucket = s3.Bucket(
self,
'MreAccessLogsBucket',
enforce_ssl=True,
encryption=s3.BucketEncryption.S3_MANAGED
)
# MRE Data Export Bucket
self.data_export_bucket = s3.Bucket(
self,
'MreDataExportBucket',
enforce_ssl=True,
encryption=s3.BucketEncryption.S3_MANAGED
)
# MediaLive S3 Destination Bucket
self.medialive_s3_dest_bucket = s3.Bucket(
self,
"MediaLiveDestinationBucket",
enforce_ssl=True,
server_access_logs_bucket=self.access_log_bucket,
server_access_logs_prefix='mre-medialive-logs',
encryption=s3.BucketEncryption.S3_MANAGED
)
# Lambda Layer S3 bucket
self.lambda_layer_bucket = s3.Bucket(
self,
"LambdaLayerBucket",
enforce_ssl=True,
server_access_logs_bucket=self.access_log_bucket,
server_access_logs_prefix='mre-lambdalayer-logs',
encryption=s3.BucketEncryption.S3_MANAGED
)
# Bucket for housing output artifacts such as HLS manifests, MP4, HLS clips etc.
self.mre_media_output_bucket = s3.Bucket(
self,
"MreMediaOutputBucket",
enforce_ssl=True,
server_access_logs_bucket=self.access_log_bucket,
server_access_logs_prefix='mre-mediaconvert-logs',
encryption=s3.BucketEncryption.S3_MANAGED
)
# Cloudfront Distro for Media Output
self.mre_media_output_distro = cloudfront.Distribution(self, "mre-media-output",
default_behavior={
"origin": origins.S3Origin(
self.mre_media_output_bucket),
"viewer_protocol_policy": cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
"cache_policy": cloudfront.CachePolicy(self,
id="mre-cache-policy",
cache_policy_name=f"mre-cache-policy-{cdk.Aws.ACCOUNT_ID}-{cdk.Aws.REGION}",
cookie_behavior=cloudfront.CacheCookieBehavior.all(),
query_string_behavior=cloudfront.CacheQueryStringBehavior.all(),
header_behavior=cloudfront.CacheHeaderBehavior.allow_list(
'Origin',
'Access-Control-Request-Method',
'Access-Control-Request-Headers'),
enable_accept_encoding_brotli=True,
enable_accept_encoding_gzip=True
),
"origin_request_policy": cloudfront.OriginRequestPolicy(
self, id="mre-origin-request-policy",
origin_request_policy_name=f"mre-origin-request-policy-{cdk.Aws.ACCOUNT_ID}-{cdk.Aws.REGION}",
cookie_behavior=cloudfront.OriginRequestCookieBehavior.all(),
query_string_behavior=cloudfront.OriginRequestQueryStringBehavior.all(),
header_behavior=cloudfront.OriginRequestHeaderBehavior.allow_list(
'Origin', 'Access-Control-Request-Method',
'Access-Control-Request-Headers')
)
}
)
##### END: S3 BUCKETS #####
##### START: LAMBDA LAYERS #####
# Upload all the zipped Lambda Layers to S3
self.layer_deploy = s3_deploy.BucketDeployment(
self,
"LambdaLayerZipDeploy",
destination_bucket=self.lambda_layer_bucket,
sources=[
s3_deploy.Source.asset(
path="lambda_layers"
)
],
memory_limit=512
)
# timecode Layer
self.timecode_layer = _lambda.LayerVersion(
self,
"TimeCodeLayer",
layer_version_name="aws_mre_timecode",
description="Layer containing the TimeCode Lib",
code=_lambda.Code.from_bucket(
bucket=self.lambda_layer_bucket,
key="timecode/timecode.zip"
),
compatible_runtimes=[
_lambda.Runtime.PYTHON_3_6,
_lambda.Runtime.PYTHON_3_7,
_lambda.Runtime.PYTHON_3_8
]
)
# Deploy timecode_layer after layers_deploy
self.timecode_layer.node.add_dependency(self.layer_deploy)
# ffmpeg Layer
self.ffmpeg_layer = _lambda.LayerVersion(
self,
"FFMpegLayer",
layer_version_name="aws_mre_ffmpeg",
description="Layer containing the ffmpeg binary and ffmpeg-python library",
code=_lambda.Code.from_bucket(
bucket=self.lambda_layer_bucket,
key="ffmpeg/ffmpeg.zip"
),
compatible_runtimes=[
_lambda.Runtime.PYTHON_3_6,
_lambda.Runtime.PYTHON_3_7,
_lambda.Runtime.PYTHON_3_8
]
)
# Deploy ffmpeg_layer after layers_deploy
self.ffmpeg_layer.node.add_dependency(self.layer_deploy)
# ffprobe Layer
self.ffprobe_layer = _lambda.LayerVersion(
self,
"FFProbeLayer",
layer_version_name="aws_mre_ffprobe",
description="Layer containing the ffprobe binary",
code=_lambda.Code.from_bucket(
bucket=self.lambda_layer_bucket,
key="ffprobe/ffprobe.zip"
),
compatible_runtimes=[
_lambda.Runtime.PYTHON_3_6,
_lambda.Runtime.PYTHON_3_7,
_lambda.Runtime.PYTHON_3_8
]
)
# Deploy ffprobe_layer after layers_deploy
self.ffprobe_layer.node.add_dependency(self.layer_deploy)
# MediaReplayEngineWorkflowHelper Layer
self.mre_workflow_helper_layer = _lambda.LayerVersion(
self,
"MediaReplayEngineWorkflowHelperLayer",
layer_version_name="MediaReplayEngineWorkflowHelper",
description="Layer containing the helper library (and its runtime dependencies) used by the Media Replay Engine internal lambda functions to interact with the control plane",
code=_lambda.Code.from_bucket(
bucket=self.lambda_layer_bucket,
key="MediaReplayEngineWorkflowHelper/MediaReplayEngineWorkflowHelper.zip"
),
compatible_runtimes=[
_lambda.Runtime.PYTHON_3_8
]
)
# Deploy MediaReplayEngineWorkflowHelper after layers_deploy
self.mre_workflow_helper_layer.node.add_dependency(self.layer_deploy)
# MediaReplayEnginePluginHelper Layer
self.mre_plugin_helper_layer = _lambda.LayerVersion(
self,
"MediaReplayEnginePluginHelperLayer",
layer_version_name="MediaReplayEnginePluginHelper",
description="Layer containing the helper library (and its runtime dependencies) to aid the development of custom plugins for the Media Replay Engine",
code=_lambda.Code.from_bucket(
bucket=self.lambda_layer_bucket,
key="MediaReplayEnginePluginHelper/MediaReplayEnginePluginHelper.zip"
),
compatible_runtimes=[
_lambda.Runtime.PYTHON_3_8
]
)
# Deploy MediaReplayEnginePluginHelper after layers_deploy
self.mre_plugin_helper_layer.node.add_dependency(self.layer_deploy)
##### END: LAMBDA LAYERS #####
# EventBridge Event Bus for MRE
self.eb_event_bus = events.EventBus(
self,
"AWSMREEventBus",
event_bus_name="aws-mre-event-bus"
)
##### START: LAMBDA FUNCTIONS AND ASSOCIATED IAM ROLES #####
### START: event-clip-generator LAMBDA ###
self.event_media_convert_role = iam.Role(
self,
"MREMediaConvertIamRole",
assumed_by=iam.ServicePrincipal("mediaconvert.amazonaws.com")
)
self.event_media_convert_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"s3:Get*",
"s3:Describe*",
"s3:List*",
"s3:Put*",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"cloudwatch:PutMetricAlarm",
"cloudwatch:DeleteAlarms",
"autoscaling:Describe*"
],
resources=["*"]
)
)
self.event_clip_gen_lambda_role = iam.Role(
self,
"MREEventClipGenIamRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
self.event_clip_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"mediaconvert:Describe*",
"mediaconvert:Get*",
"mediaconvert:Create*"
],
resources=["*"]
)
)
self.event_clip_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"events:DescribeEventBus",
"events:PutEvents"
],
resources=[
f"arn:aws:events:*:*:event-bus/{self.eb_event_bus.event_bus_name}"
]
)
)
self.event_clip_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
self.event_clip_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
self.event_clip_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"iam:PassRole"
],
resources=[
self.event_media_convert_role.role_arn
]
)
)
# Function: ClipGen
self.event_clip_generator_lambda = _lambda.Function(
self,
"Mre-ClipGenEventClipGenerator",
description="Generates Clips for MRE events",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/EventClipGenerator"),
handler="mre-event-clip-generator.GenerateClips",
role=self.event_clip_gen_lambda_role,
memory_size=512,
timeout=cdk.Duration.minutes(15),
environment={
"MediaConvertRole": self.event_media_convert_role.role_arn,
"OutputBucket": self.mre_media_output_bucket.bucket_name,
"MediaConvertMaxInputJobs": "150",
"EB_EVENT_BUS_NAME": self.eb_event_bus.event_bus_name
},
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
### END: event-clip-generator LAMBDA ###
### START: event-data_export-generator LAMBDA ###
self.event_data_export_lambda_role = iam.Role(
self,
"MREEventDataExportIamRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
self.event_data_export_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"events:DescribeEventBus",
"events:PutEvents"
],
resources=[
f"arn:aws:events:*:*:event-bus/{self.eb_event_bus.event_bus_name}"
]
)
)
self.event_data_export_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"s3:Get*",
"s3:Put*",
"s3:List*"
],
resources=["*"]
)
)
self.event_data_export_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
self.event_data_export_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
self.event_data_export_lambda = _lambda.Function(
self,
"Mre-EventDataExportGenerator",
description="Generates Mre data export",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/MreDataExport"),
handler="mre_data_exporter.GenerateDataExport",
role=self.event_data_export_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(15),
environment={
"ExportOutputBucket": self.data_export_bucket.bucket_name,
"EB_EVENT_BUS_NAME": self.eb_event_bus.event_bus_name
},
layers=[self.mre_workflow_helper_layer, self.mre_plugin_helper_layer]
)
### END: event-data_export-generator LAMBDA ###
### START: EventHlsGenerator LAMBDA ###
self.event_hls_gen_lambda_role = iam.Role(
self,
"MREEventHlsGeneratorIamRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
self.event_hls_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"mediaconvert:Describe*",
"mediaconvert:Get*",
"mediaconvert:Create*",
"s3:Get*",
"s3:Put*",
"s3:List*"
],
resources=["*"]
)
)
self.event_hls_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
self.event_hls_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
self.event_hls_create_manifest_lambda = _lambda.Function(
self,
"Mre-ClipGenEventHlsGenerator",
description="Generates Hls Manifest for MRE events",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/EventHlsManifestGenerator"),
handler="event_hls_manifest_gen.create_hls_manifest",
role=self.event_hls_gen_lambda_role,
memory_size=512,
timeout=cdk.Duration.minutes(15),
environment={
"MediaConvertRole": self.event_media_convert_role.role_arn,
"OutputBucket": self.mre_media_output_bucket.bucket_name,
"MediaConvertMaxInputJobs": "150"
},
layers=[self.mre_workflow_helper_layer]
)
self.event_hls_media_convert_job_status_lambda = _lambda.Function(
self,
"MreEventHlsMediaConvertJobStatus",
description="Checks if all MRE Media Convert Jobs for an event are complete",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/EventHlsManifestGenerator"),
handler="event_hls_manifest_gen.media_convert_job_status",
role=self.event_hls_gen_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(5),
environment={
"MediaConvertRole": self.event_media_convert_role.role_arn,
"OutputBucket": self.mre_media_output_bucket.bucket_name,
"MediaConvertMaxInputJobs": "150"
},
layers=[self.mre_workflow_helper_layer]
)
### END: EventHlsGenerator LAMBDA ###
### START: EventEdlGenerator LAMBDA ###
self.event_edl_gen_lambda_role = iam.Role(
self,
"MREEventEdlGeneratorIamRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
self.event_edl_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"s3:Get*",
"s3:Put*",
"s3:List*"
],
resources=["*"]
)
)
self.event_edl_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
self.event_edl_gen_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
self.event_edl_gen_lambda = _lambda.Function(
self,
"Mre-ClipGenEventEdlGenerator",
description="Generates EDL representation for Mre Event",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/EventEdlGenerator"),
handler="mre_event_edl_gen.generate_edl",
role=self.event_hls_gen_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(10),
environment={
"OutputBucket": self.mre_media_output_bucket.bucket_name
},
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer,
self.timecode_layer
]
)
### END: EventEdlGenerator LAMBDA ###
### START: EventScheduler LAMBDA ###
# MREEventSchedulerIamRole
self.event_scheduler_lambda_role = iam.Role(
self,
"MREEventSchedulerIamRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# MREEventSchedulerIamRole: CloudWatch Logs permissions
self.event_scheduler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
self.event_scheduler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"dynamodb:BatchGetItem",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:Query",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:ConditionCheckItem",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem"
],
resources=[
self.event_table.table_arn,
f"{self.event_table.table_arn}/index/*",
self.current_events_table.table_arn
]
)
)
self.event_scheduler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"events:DescribeEventBus",
"events:PutEvents"
],
resources=[
f"arn:aws:events:*:*:event-bus/{self.eb_event_bus.event_bus_name}"
]
)
)
# Function: TriggerMREWorkflow
self.event_scheduler_lambda = _lambda.Function(
self,
"MreEventScheduler",
description="Schedules Past/Future events for processing based in the Event Start time",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/EventScheduler"),
handler="mre_event_scheduler.schedule_events_for_processing",
role=self.event_scheduler_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(5),
environment={
"EVENT_SCHEDULER_BOOTSTRAP_TIME_IN_MINS": "5",
"EVENT_SCHEDULER_BUFFER_TIME_IN_MINS": "5",
"EVENT_SCHEDULER_TIME_TO_LIVE_STREAM_IN_MINS": "1",
"EVENT_SCHEDULER_PAST_EVENTS_IN_SCOPE": "TRUE",
"EVENT_SCHEDULER_FUTURE_EVENTS_IN_SCOPE": "FALSE",
"EVENT_SCHEDULER_PAST_EVENT_START_DATE_UTC": "%Y-%m-%d",
"EVENT_SCHEDULER_PAST_EVENT_END_DATE_UTC": "%Y-%m-%d",
"EVENT_SCHEDULER_CONCURRENT_EVENTS": "1",
"CURRENT_EVENTS_TABLE_NAME": self.current_events_table.table_name,
"EB_EVENT_BUS_NAME": self.eb_event_bus.event_bus_name,
"EVENT_TABLE_NAME": self.event_table.table_name
}
)
self.event_scheduler_lambda_cloudwatch_event = events.Rule(
self,
"Event-Scheduler-Lambda-Rule",
description=
"CloudWatch event trigger for MRE's Event Scheduler Lambda. Triggers every 1 Minute.",
enabled=True,
schedule=events.Schedule.rate(cdk.Duration.minutes(1)),
targets=[events_targets.LambdaFunction(handler=self.event_scheduler_lambda)])
### END: EventScheduler LAMBDA ###
### START: TriggerMREWorkflow LAMBDA ###
# Role: TriggerMREWorkflowLambdaRole
self.trigger_mre_lambda_role = iam.Role(
self,
"TriggerMREWorkflowLambdaRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# TriggerMREWorkflowLambdaRole: CloudWatch Logs permissions
self.trigger_mre_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
# TriggerMREWorkflowLambdaRole: SSM Parameter Store permissions
self.trigger_mre_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
# TriggerMREWorkflowLambdaRole: API Gateway Invoke permissions
self.trigger_mre_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
# TriggerMREWorkflowLambdaRole: State Machine execute permissions
self.trigger_mre_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"states:StartExecution"
],
resources=[
"arn:aws:states:*:*:stateMachine:*"
]
)
)
# Function: TriggerMREWorkflow
self.trigger_mre_workflow_lambda = _lambda.Function(
self,
"TriggerMREWorkflow",
description="Execute MRE StepFunction workflow for every HLS video segment (.ts) file stored by MediaLive in S3",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/TriggerMREWorkflow"),
handler="lambda_function.lambda_handler",
role=self.trigger_mre_lambda_role,
memory_size=128,
timeout=cdk.Duration.minutes(1),
layers=[self.mre_workflow_helper_layer]
)
# S3 Event Source for TriggerMREWorkflow Lambda
self.s3_event_source = _lambda_es.S3EventSource(
bucket=self.medialive_s3_dest_bucket,
events=[s3.EventType.OBJECT_CREATED],
filters=[s3.NotificationKeyFilter(suffix=".ts")]
)
# Map the S3 Event Source with TriggerMREWorkflow Lambda
self.trigger_mre_workflow_lambda.add_event_source(self.s3_event_source)
### END: TriggerMREWorkflow LAMBDA ###
### START: ProbeVideo LAMBDA ###
# Role: ProbeVideoLambdaRole
self.probe_video_lambda_role = iam.Role(
self,
"ProbeVideoLambdaRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# ProbeVideoLambdaRole: CloudWatch Logs permissions
self.probe_video_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
# ProbeVideoLambdaRole: SSM Parameter Store permissions
self.probe_video_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
# ProbeVideoLambdaRole: API Gateway Invoke permissions
self.probe_video_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
# Function: ProbeVideo
self.probe_video_lambda = _lambda.Function(
self,
"ProbeVideo",
description="Probe the HLS video segment (.ts) file to extract metadata about the video segment and all the key frames in it",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/ProbeVideo"),
handler="lambda_function.lambda_handler",
role=self.probe_video_lambda_role,
memory_size=1024,
timeout=cdk.Duration.minutes(15),
layers=[
self.ffmpeg_layer,
self.ffprobe_layer,
self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
### END: ProbeVideo LAMBDA ###
### START: MultiChunkHelper LAMBDA ###
# Role: MultiChunkHelperLambdaRole
self.multi_chunk_helper_lambda_role = iam.Role(
self,
"MultiChunkHelperLambdaRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# MultiChunkHelperLambdaRole: CloudWatch Logs permissions
self.multi_chunk_helper_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
# MultiChunkHelperLambdaRole: SSM Parameter Store permissions
self.multi_chunk_helper_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
# MultiChunkHelperLambdaRole: API Gateway Invoke permissions
self.multi_chunk_helper_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
# Function: MultiChunkHelper
self.multi_chunk_helper_lambda = _lambda.Function(
self,
"MultiChunkHelper",
description="Check the completion status of a Classifier/Optimizer plugin in the prior AWS Step Function workflow executions",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/MultiChunkHelper"),
handler="lambda_function.lambda_handler",
role=self.multi_chunk_helper_lambda_role,
memory_size=128,
timeout=cdk.Duration.minutes(1),
layers=[
self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
### END: MultiChunkHelper LAMBDA ###
### START: PluginOutputHandler LAMBDA ###
# Role: PluginOutputHandlerLambdaRole
self.plugin_output_handler_lambda_role = iam.Role(
self,
"PluginOutputHandlerLambdaRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# PluginOutputHandlerLambdaRole: CloudWatch Logs permissions
self.plugin_output_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
# PluginOutputHandlerLambdaRole: SSM Parameter Store permissions
self.plugin_output_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
# PluginOutputHandlerLambdaRole: API Gateway Invoke permissions
self.plugin_output_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
# Function: PluginOutputHandler
self.plugin_output_handler_lambda = _lambda.Function(
self,
"PluginOutputHandler",
description="Handle the output of a plugin based on its execution status",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/PluginOutputHandler"),
handler="lambda_function.lambda_handler",
role=self.plugin_output_handler_lambda_role,
memory_size=128,
timeout=cdk.Duration.minutes(1),
layers=[
self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
### END: PluginOutputHandler LAMBDA ###
### START: WorkflowErrorHandler LAMBDA ###
# Role: WorkflowErrorHandlerLambdaRole
self.workflow_error_handler_lambda_role = iam.Role(
self,
"WorkflowErrorHandlerLambdaRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# WorkflowErrorHandlerLambdaRole: CloudWatch Logs permissions
self.workflow_error_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
# WorkflowErrorHandlerLambdaRole: SSM Parameter Store permissions
self.workflow_error_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
# WorkflowErrorHandlerLambdaRole: API Gateway Invoke permissions
self.workflow_error_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
# WorkflowErrorHandlerLambdaRole: EventBridge permissions
self.workflow_error_handler_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"events:DescribeEventBus",
"events:PutEvents"
],
resources=[
f"arn:aws:events:*:*:event-bus/{self.eb_event_bus.event_bus_name}"
]
)
)
# Function: WorkflowErrorHandler
self.workflow_error_handler_lambda = _lambda.Function(
self,
"WorkflowErrorHandler",
description="Handle exceptions caught by the AWS Step Function workflow and optionally update the execution status of the Classifier plugin",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/WorkflowErrorHandler"),
handler="lambda_function.lambda_handler",
role=self.workflow_error_handler_lambda_role,
memory_size=128,
timeout=cdk.Duration.minutes(1),
layers=[
self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
],
environment={
"EB_EVENT_BUS_NAME": self.eb_event_bus.event_bus_name
}
)
### END: WorkflowErrorHandler LAMBDA ###
### START: EventCompletionHandler LAMBDA ###
# Role: EventCompletionHandlerLambdaRole
self.event_completion_handler_role = iam.Role(
self,
"EventCompletionHandlerLambdaRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
# EventCompletionHandlerLambdaRole: CloudWatch Logs permissions
self.event_completion_handler_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=["*"]
)
)
# EventCompletionHandlerLambdaRole: SSM Parameter Store permissions
self.event_completion_handler_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
# EventCompletionHandlerLambdaRole: API Gateway Invoke permissions
self.event_completion_handler_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
# EventCompletionHandlerLambdaRole: MediaLive permissions
self.event_completion_handler_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"medialive:List*",
"medialive:Describe*",
"medialive:Stop*"
],
resources=["*"]
)
)
# Function: EventCompletionHandler
self.event_completion_handler_lambda = _lambda.Function(
self,
"EventCompletionHandler",
description="Update the status of an MRE event to Complete based on the configured CloudWatch EventBridge triggers",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/EventCompletionHandler"),
handler="lambda_function.lambda_handler",
role=self.event_completion_handler_role,
memory_size=128,
timeout=cdk.Duration.minutes(1),
layers=[self.mre_workflow_helper_layer]
)
### END: EventCompletionHandler LAMBDA ###
##### END: LAMBDA FUNCTIONS AND ASSOCIATED IAM ROLES #####
# Step Function IAM Role
self.sfn_role = iam.Role(
self,
"StepFunctionRole",
assumed_by=iam.ServicePrincipal(service="states.amazonaws.com"),
description="Service role for the AWS MRE Step Functions"
)
# Step Function IAM Role: X-Ray permissions
self.sfn_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets"
],
resources=[
"*"
]
)
)
# Step Function IAM Role: Lambda permissions
self.sfn_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"lambda:InvokeFunction"
],
resources=[
"*"
]
)
)
# Step Function IAM Role: State Machine execute permissions
self.sfn_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"states:StartExecution"
],
resources=[
"arn:aws:states:*:*:stateMachine:*"
]
)
)
# Chalice IAM Role
self.chalice_role = iam.Role(
self,
"ChaliceRole",
assumed_by=iam.ServicePrincipal(service="lambda.amazonaws.com"),
description="Role used by the MRE Control Plane Chalice Lambda function"
)
# Chalice IAM Role: DynamoDB permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"dynamodb:BatchGetItem",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:Query",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:ConditionCheckItem",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem"
],
resources=[
self.replayrequest_table.table_arn,
self.system_table.table_arn,
self.content_group_table.table_arn,
self.program_table.table_arn,
self.plugin_table.table_arn,
f"{self.plugin_table.table_arn}/index/*",
self.profile_table.table_arn,
self.model_table.table_arn,
f"{self.model_table.table_arn}/index/*",
self.event_table.table_arn,
f"{self.event_table.table_arn}/index/*",
self.workflow_exec_table.table_arn,
self.current_events_table.table_arn
]
)
)
# Chalice IAM Role: CloudWatch Logs permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=[
"arn:*:logs:*:*:*"
]
)
)
# Chalice IAM Role: Step Function permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"states:CreateStateMachine",
"states:ListStateMachines",
"states:UpdateStateMachine",
"states:DeleteStateMachine",
"states:TagResource"
],
resources=[
"arn:aws:states:*:*:*"
]
)
)
# Chalice IAM Role: Step Function PassRole permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"iam:PassRole"
],
resources=[
self.sfn_role.role_arn
]
)
)
# Chalice IAM Role: CloudWatch Alarms permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"cloudwatch:PutMetricAlarm",
"cloudwatch:DeleteAlarms"
],
resources=[
f"arn:aws:cloudwatch:*:*:alarm:AWS_MRE*"
]
)
)
# Chalice IAM Role: S3 Read permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"s3:Get*",
"s3:List*"
],
resources=[
"*"
]
)
)
# Chalice IAM Role: MediaLive permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"medialive:List*",
"medialive:Describe*",
"medialive:StartChannel",
"medialive:UpdateChannel"
],
resources=[
"*"
]
)
)
# Chalice IAM Role: MediaTailor permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"mediatailor:List*",
"mediatailor:Describe*"
],
resources=[
"*"
]
)
)
# Chalice IAM Role: EventBridge permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"events:DescribeEventBus",
"events:PutEvents"
],
resources=[
f"arn:aws:events:*:*:event-bus/{self.eb_event_bus.event_bus_name}"
]
)
)
# SQS Queue used to harvest HLS Streams
self.sqs_event_to_harvest_queue = sqs.Queue(
self,
"MREEventHarvestingQueue",
retention_period=cdk.Duration.days(7),
visibility_timeout=cdk.Duration.minutes(5),
encryption=sqs.QueueEncryption.KMS_MANAGED
)
# SQS Queue used to Notify when Resource allocation to Harvest HLS Streams
self.sqs_event_harvest_failure_queue = sqs.Queue(
self,
"MREEventHarvestProcessFailureQueue",
retention_period=cdk.Duration.days(7),
visibility_timeout=cdk.Duration.minutes(5),
encryption=sqs.QueueEncryption.KMS_MANAGED
)
# EventBridge: MRE Event Scheduler Events Rule
self.mre_event_scheduler_events_rule = events.Rule(
self,
"MREEventSchedulerHarvestSoonRule",
description="Rule that captures Event Scheduler events (PAST_EVENT_TO_BE_HARVESTED, FUTURE_EVENT_TO_BE_HARVESTED). Tie this to Event Processing logic.",
enabled=True,
event_bus=self.eb_event_bus,
event_pattern=events.EventPattern(
source=["awsmre"],
detail={
"State": ["PAST_EVENT_TO_BE_HARVESTED", "FUTURE_EVENT_TO_BE_HARVESTED"]
}
)
)
# EventBridge: MRE Event Scheduler Events Rule
self.mre_event_scheduler_events_rule = events.Rule(
self,
"MREEventSchedulerHarvestNowRule",
description="Rule that captures Event Scheduler events (FUTURE_EVENT_HARVEST_NOW, PAST_EVENT_HARVEST_NOW) and outputs them to sqs_event_to_harvest_queue",
enabled=True,
event_bus=self.eb_event_bus,
event_pattern=events.EventPattern(
source=["awsmre"],
detail={
"State": ["FUTURE_EVENT_HARVEST_NOW", "PAST_EVENT_HARVEST_NOW"]
}
),
targets=[
events_targets.SqsQueue(
queue=self.sqs_event_to_harvest_queue
)
]
)
# Store the EventBridge Event Bus name in SSM Parameter Store
ssm.StringParameter(
self,
"MREEventBridgeBusName",
string_value=self.eb_event_bus.event_bus_name,
parameter_name="/MRE/EventBridge/EventBusName",
tier=ssm.ParameterTier.INTELLIGENT_TIERING,
description="[DO NOT DELETE] Parameter contains the Amazon EventBridge Event Bus name used by AWS MRE"
)
# SQS Queue to capture MRE Event deletion notifications
self.sqs_queue = sqs.Queue(
self,
"MREEventDeletionQueue",
retention_period=cdk.Duration.days(7),
visibility_timeout=cdk.Duration.minutes(20),
encryption=sqs.QueueEncryption.KMS_MANAGED
)
# Chalice IAM Role: SQS permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"sqs:SendMessage"
],
resources=[
f"arn:aws:sqs:*:*:{self.sqs_queue.queue_name}"
]
)
)
# Store the SQS Queue ARN in SSM Parameter Store
ssm.StringParameter(
self,
"MREEventDeletionQueueARN",
string_value=self.sqs_queue.queue_arn,
parameter_name="/MRE/ControlPlane/EventDeletionQueueARN",
tier=ssm.ParameterTier.INTELLIGENT_TIERING,
description="[DO NOT DELETE] Parameter contains the ARN of SQS Queue used by AWS MRE to send Event deletion notifications"
)
secret_cloudfront_private_key = secret_mgr.Secret(self, "MRE_CLOUDFRONT_COOKIE_PRIVATE_KEY",
secret_name="mre_cloudfront_cookie_private_key")
secret_cloudfront_private_key.grant_read(self.chalice_role)
secret_cloudfront_key_pair_id = secret_mgr.Secret(self, "MRE_CLOUDFRONT_KEY_PAIR_ID",
secret_name="mre_cloudfront_key_pair_id")
secret_cloudfront_key_pair_id.grant_read(self.chalice_role)
hsa_api_auth_secret = secret_mgr.Secret(self, "MRE_HSA_API_AUTH_SECRET", secret_name="mre_hsa_api_auth_secret")
hsa_api_auth_secret.grant_read(self.chalice_role)
# Chalice IAM Role: Secrets Manager permissions
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
resources=[
secret_cloudfront_private_key.secret_arn,
secret_cloudfront_key_pair_id.secret_arn,
hsa_api_auth_secret.secret_arn
]
)
)
self.chalice_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"secretsmanager:CreateSecret",
"secretsmanager:UpdateSecret",
"secretsmanager:DeleteSecret",
"secretsmanager:TagResource"
],
resources=[
"arn:aws:secretsmanager:*:*:secret:/MRE*"
]
)
)
# EventBridge: MediaLive STOPPED State Change Rule
self.medialive_eb_rule = events.Rule(
self,
"MediaLiveStoppedStateChangeRule",
description="Rule used by AWS MRE to update the status of an Event to Complete when the MediaLive channel is stopped",
enabled=True,
event_pattern=events.EventPattern(
source=["aws.medialive"],
detail_type=["MediaLive Channel State Change"],
detail={
"state": ["STOPPED"]
}
),
targets=[
events_targets.LambdaFunction(
handler=self.event_completion_handler_lambda
)
]
)
# EventBridge: MediaLive InputVideoFrameRate Metric Alarm Rule
self.medialive_alarm_rule = events.Rule(
self,
"MediaLiveMetricAlarmRule",
description="Rule used by AWS MRE to update the status of an Event to Complete based on the MediaLive InputVideoFrameRate CloudWatch metric alarm",
enabled=True,
event_pattern=events.EventPattern(
source=["aws.cloudwatch"],
detail_type=["CloudWatch Alarm State Change"],
detail={
"alarmName": [
{
"prefix": "AWS_MRE"
}
],
"state": {
"value": ["ALARM"]
}
}
),
targets=[
events_targets.LambdaFunction(
handler=self.event_completion_handler_lambda
)
]
)
# Get MediaConvert Regional Endpoint via an AWS SDK call
self.mediaconvert_endpoints = cr.AwsCustomResource(
self,
"MediaConvertCustomResource",
policy=cr.AwsCustomResourcePolicy.from_statements(
statements=[
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=["mediaconvert:DescribeEndpoints"],
resources=["arn:aws:mediaconvert:*:*:*"]
)
]
),
on_create=cr.AwsSdkCall(
action="describeEndpoints",
service="MediaConvert",
physical_resource_id=cr.PhysicalResourceId.of(id="MediaConvertCustomResourceAwsSdkCall")
),
on_update=cr.AwsSdkCall(
action="describeEndpoints",
service="MediaConvert",
physical_resource_id=cr.PhysicalResourceId.of(id="MediaConvertCustomResourceAwsSdkCall")
)
)
# Store the MediaConvert Regional endpoint in SSM Parameter Store
ssm.StringParameter(
self,
"MediaConvertRegionalEndpoint",
string_value=self.mediaconvert_endpoints.get_response_field(data_path="Endpoints.0.Url"),
parameter_name="/MRE/ClipGen/MediaConvertEndpoint",
tier=ssm.ParameterTier.INTELLIGENT_TIERING,
description="[DO NOT DELETE] Contains Media Convert Endpoint required for MRE Clip Generation"
)
# START: Step function definition for ClipGeneration
# Step Function IAM Role
self.sfn_clip_gen_role = iam.Role(
self,
"EventClipGenerationStepFunctionRole",
assumed_by=iam.ServicePrincipal(service="states.amazonaws.com"),
description="Service role for MRE Clip Generation Step Functions"
)
# Step Function IAM Role: X-Ray permissions
self.sfn_clip_gen_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets"
],
resources=[
"*"
]
)
)
# Step Function IAM Role: Lambda permissions
self.sfn_clip_gen_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"lambda:InvokeFunction",
"lambda:List*",
"lambda:Read*",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
resources=[
"*"
]
)
)
self.sfn_clip_gen_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"iam:PassRole"
],
resources=[
self.event_media_convert_role.role_arn
]
)
)
generateClipsTask = tasks.LambdaInvoke(
self,
"GenerateClips",
lambda_function=_lambda.Function.from_function_arn(self, 'GenerateClipsLambda',
self.event_clip_generator_lambda.function_arn),
retry_on_service_exceptions=True,
result_path="$.ClipGen"
)
getJobStatusTask = tasks.LambdaInvoke(
self,
"GetJobStatus",
lambda_function=_lambda.Function.from_function_arn(self, 'GetJobStatusLambda',
self.event_hls_media_convert_job_status_lambda.function_arn),
result_path="$.JobStatus"
)
createHlsManifestTask = tasks.LambdaInvoke(
self,
"CreateHlsManifest",
lambda_function=_lambda.Function.from_function_arn(self, 'CreateHlsManifestLambda',
self.event_hls_create_manifest_lambda.function_arn),
result_path="$.ClipsGenerated"
)
waitTenSecondsTask = sfn.Wait(
self,
"wait_10_seconds",
time=sfn.WaitTime.duration(cdk.Duration.seconds(10))
)
doneTask = sfn.Pass(
self,
"Done",
)
definition = generateClipsTask.next(getJobStatusTask.next(sfn.Choice(
self,
"AreAllHLSJobsComplete"
).when(sfn.Condition.string_equals("$.JobStatus.Payload.Status", "Complete"),
createHlsManifestTask.next(doneTask)).otherwise(waitTenSecondsTask.next(getJobStatusTask))))
self.state_machine = sfn.StateMachine(
self,
'mre-Event-Clip-Generator-StateMachine',
definition=definition,
role=self.sfn_clip_gen_role
)
#self.event_edl_gen_lambda
self.mre_edlgen_events_rule = events.Rule(
self,
"MREEventEndRule",
description="Rule that captures the MRE Lifecycle Event EVENT_END",
enabled=True,
event_bus=self.eb_event_bus,
event_pattern=events.EventPattern(
source=["awsmre"],
detail={
"State": ["EVENT_END"]
}
),
targets=[
events_targets.LambdaFunction(
handler=self.event_edl_gen_lambda
)
]
)
self.mre_edlgen_events_rule.node.add_dependency(self.eb_event_bus)
self.mre_edlgen_events_rule.node.add_dependency(self.event_edl_gen_lambda)
#self.event_edl_gen_lambda
self.mre_event_data_export_rule = events.Rule(
self,
"MREEventDataExportRule",
description="Rule that captures the MRE Lifecycle Event CLIP_GEN_DONE and REPLAY_PROCESSED - Data Export",
enabled=True,
event_bus=self.eb_event_bus,
event_pattern=events.EventPattern(
source=["awsmre"],
detail={
"State": ["CLIP_GEN_DONE", "REPLAY_PROCESSED"]
}
),
targets=[
events_targets.LambdaFunction(
handler=self.event_data_export_lambda
)
]
)
self.mre_event_data_export_rule.node.add_dependency(self.eb_event_bus)
self.mre_event_data_export_rule.node.add_dependency(self.event_data_export_lambda)
# END: Step function definition for ClipGeneration
### START: CreateReplay LAMBDA ###
self.replay_lambda_role = iam.Role(
self,
"MREReplayIamRole",
assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)
self.replay_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"events:DescribeEventBus",
"events:PutEvents"
],
resources=[
f"arn:aws:events:*:*:event-bus/{self.eb_event_bus.event_bus_name}"
]
)
)
self.replay_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"mediaconvert:Describe*",
"mediaconvert:Get*",
"mediaconvert:Create*",
"s3:Get*",
"s3:Put*",
"s3:List*"
],
resources=["*"]
)
)
self.replay_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"execute-api:Invoke",
"execute-api:ManageConnections"
],
resources=["arn:aws:execute-api:*:*:*"]
)
)
self.replay_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"ssm:DescribeParameters",
"ssm:GetParameter*"
],
resources=["arn:aws:ssm:*:*:parameter/MRE*"]
)
)
self.replay_lambda_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"iam:PassRole"
],
resources=[
self.event_media_convert_role.role_arn
]
)
)
self.replay_media_convert_accelerated_queue = media_convert.CfnQueue(
self,
"mre-replay-hls-accelerated-queue",
description="Accelerated queue for MRE Replay HLS jobs",
name="mre-replay-hls-accelerated-queue")
self.replay_environment_config = {
"MediaConvertRole": self.event_media_convert_role.role_arn,
"OutputBucket": self.mre_media_output_bucket.bucket_name,
"MediaConvertMaxInputJobs": "150",
"MediaConvertAcceleratorQueueArn": self.replay_media_convert_accelerated_queue.attr_arn,
"EB_EVENT_BUS_NAME": self.eb_event_bus.event_bus_name
}
# Function: CreateReplay
self.create_replay_lambda = _lambda.Function(
self,
"MRE-replay-CreateReplay",
description="MRE - Creates Replay for MRE events",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.CreateReplay",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(15),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: GetEligibleReplays
self.get_eligible_replays_lambda = _lambda.Function(
self,
"MRE-replay-GetEligibleReplays",
description="MRE - Gets eligible replays for an MRE event",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.GetEligibleReplays",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(6),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: MarkReplayComplete
self.mark_replay_complete_lambda = _lambda.Function(
self,
"MRE-replay-MarkReplayComplete",
description="MRE - Mark a Replay status as Complete",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.mark_replay_complete",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(6),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: GenerateMasterPlaylist
self.generate_master_playlist_lambda = _lambda.Function(
self,
"MRE-replay-GenerateMasterPlaylist",
description="MRE - Creates a HLS Master Playlist manifest",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.generate_master_playlist",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(14),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: GenerateHlsClips
self.generate_hls_clips_lambda = _lambda.Function(
self,
"MRE-replay-GenerateHlsClips",
description="MRE - Creates HLS Clips",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.generate_hls_clips",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(14),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: check_Hls_job_status
self.check_Hls_job_status_lambda = _lambda.Function(
self,
"MRE-replay-CheckHlsJobsStatus",
description="MRE - Checks ths status of HLS Jobs",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.check_Hls_job_status",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(14),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: GenerateHlsClips
self.generate_mp4_clips_lambda = _lambda.Function(
self,
"MRE-replay-GenerateMp4Clips",
description="MRE - Creates MP4 replay Clips",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.generate_mp4_clips",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(15),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: check_mp4_job_status
self.check_mp4_job_status_lambda = _lambda.Function(
self,
"MRE-replay-CheckMp4JobsStatus",
description="MRE - Checks the status of Mp4 replay Jobs",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.check_mp4_job_status",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(15),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Function: Update replay with MP4 location
self.update_replay_with_mp4_loc_lambda = _lambda.Function(
self,
"MRE-replay-UpdateReplayWithMp4Loc",
description="MRE - Updates the replay request with the location of MP4 video",
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset("lambda/Replay"),
handler="replay_lambda.update_replay_with_mp4_location",
role=self.replay_lambda_role,
memory_size=256,
timeout=cdk.Duration.minutes(5),
environment=self.replay_environment_config,
layers=[self.mre_workflow_helper_layer,
self.mre_plugin_helper_layer
]
)
# Start: MRE Replay generation Step Function Definition
self.replay_sfn_role = iam.Role(
self,
"ReplayGenStepFunctionRole",
assumed_by=iam.ServicePrincipal(service="states.amazonaws.com"),
description="Service role for the Replay Generation Step Functions"
)
# Step Function IAM Role: X-Ray permissions
self.replay_sfn_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets"
],
resources=[
"*"
]
)
)
# Step Function IAM Role: Lambda permissions
self.replay_sfn_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"lambda:InvokeFunction"
],
resources=[
"*"
]
)
)
getEligibleReplaysTask = tasks.LambdaInvoke(
self,
"GetEligibleReplays",
lambda_function=_lambda.Function.from_function_arn(self, 'GetEligibleReplaysLambda',
self.get_eligible_replays_lambda.function_arn),
retry_on_service_exceptions=True,
result_path="$.ReplayResult"
)
createReplayTask = tasks.LambdaInvoke(
self,
"CreateReplay",
lambda_function=_lambda.Function.from_function_arn(self, 'CreateReplayLambda',
self.create_replay_lambda.function_arn),
retry_on_service_exceptions=True,
result_path="$.CurrentReplayResult"
)
generateHlsClipsTask = tasks.LambdaInvoke(
self,
"CreateHlsJobs",
lambda_function=_lambda.Function.from_function_arn(self, 'GenerateHlsClipsLambda',
self.generate_hls_clips_lambda.function_arn),
result_path="$.CreateHlsJobsResult",
retry_on_service_exceptions=True
)
checkHlsJobStatusTask = tasks.LambdaInvoke(
self,
"CheckHlsJobStatus",
lambda_function=_lambda.Function.from_function_arn(self, 'CheckHlsJobStatusLambda',
self.check_Hls_job_status_lambda.function_arn),
result_path="$.CheckHlsJobStatusResult",
retry_on_service_exceptions=True
)
generateMasterPlaylistTask = tasks.LambdaInvoke(
self,
"GenerateMasterPlaylist",
lambda_function=_lambda.Function.from_function_arn(self, 'GenerateMasterPlaylistLambda',
self.generate_master_playlist_lambda.function_arn),
retry_on_service_exceptions=True
)
completeReplayTask = tasks.LambdaInvoke(
self,
"CompleteReplay",
lambda_function=_lambda.Function.from_function_arn(self, 'MarkReplayCompleteLambda',
self.mark_replay_complete_lambda.function_arn),
retry_on_service_exceptions=True
)
updateReplayWithMp4Task = tasks.LambdaInvoke(
self,
"UpdateReplayWithMp4Loc",
lambda_function=_lambda.Function.from_function_arn(self, 'UpdateReplayWithMp4LocLambda',
self.update_replay_with_mp4_loc_lambda.function_arn),
retry_on_service_exceptions=True
)
waitFiveSecondsTask = sfn.Wait(
self,
"wait_5_seconds",
time=sfn.WaitTime.duration(cdk.Duration.seconds(5))
)
waitFiveSecondsTaskMp4 = sfn.Wait(
self,
"wait_5_seconds_mp4",
time=sfn.WaitTime.duration(cdk.Duration.seconds(5))
)
allOkTask = sfn.Pass(
self,
"AllOk",
)
generateMp4ClipsTask = tasks.LambdaInvoke(
self,
"CreateMp4Jobs",
lambda_function=_lambda.Function.from_function_arn(self, 'GenerateMp4ClipsLambda',
self.generate_mp4_clips_lambda.function_arn),
result_path="$.CreateMp4JobsResult",
retry_on_service_exceptions=True
)
checkMp4JobStatusTask = tasks.LambdaInvoke(
self,
"CheckMp4JobStatus",
lambda_function=_lambda.Function.from_function_arn(self, 'CheckMp4JobStatusLambda',
self.check_mp4_job_status_lambda.function_arn),
result_path="$.CheckMp4JobStatusResult",
retry_on_service_exceptions=True
)
mapTask = sfn.Map(
self,
"Map",
parameters={
"detail.$": "$.detail",
"ReplayRequest.$": "$$.Map.Item.Value"
},
items_path="$.ReplayResult.Payload.AllReplays",
result_path="$.MapResult"
)
replay_definition = getEligibleReplaysTask.next(
mapTask.iterator(
createReplayTask.next(sfn.Choice(
self,
"GenerateReplayVideoOutput?"
).when(
sfn.Condition.and_(sfn.Condition.boolean_equals("$.ReplayRequest.CreateHls", True),
sfn.Condition.string_equals("$.CurrentReplayResult.Payload.Status",
"Replay Processed")),
generateHlsClipsTask.next(
checkHlsJobStatusTask.next(
sfn.Choice(self, "AreAllHlsJobsComplete?")
.when(
sfn.Condition.string_equals("$.CheckHlsJobStatusResult.Payload.Status", "Complete"),
generateMasterPlaylistTask.next(allOkTask))
.otherwise(waitFiveSecondsTask.next(checkHlsJobStatusTask)))))
.when(
sfn.Condition.and_(sfn.Condition.boolean_equals("$.ReplayRequest.CreateMp4", True),
sfn.Condition.string_equals("$.CurrentReplayResult.Payload.Status",
"Replay Processed")),
generateMp4ClipsTask.next(
checkMp4JobStatusTask.next(
sfn.Choice(self, "AreAllMp4JobsComplete?")
.when(
sfn.Condition.string_equals("$.CheckMp4JobStatusResult.Payload.Status", "Complete"),
updateReplayWithMp4Task.next(allOkTask))
.otherwise(waitFiveSecondsTaskMp4.next(checkMp4JobStatusTask)))))
.otherwise(allOkTask)
)
).next(completeReplayTask)
)
self.replay_state_machine = sfn.StateMachine(
self,
'MRE-ReplayGenerationStateMachine',
definition=replay_definition,
role=self.replay_sfn_role
)
# EventBridge: ClipGen Events Rule
self.mre_replay_events_rule = events.Rule(
self,
"MREReplayLifecycleEventsRule",
description="Rule that captures all the MRE Lifecycle Events (Segmentation Status, Optimization Status, Event Status) and outputs them to Replay StateFunction",
enabled=True,
event_bus=self.eb_event_bus,
event_pattern=events.EventPattern(
source=["awsmre"],
detail={
"State": ["OPTIMIZED_SEGMENT_END", "SEGMENT_END", "EVENT_END", "REPLAY_CREATED"]
}
),
targets=[
events_targets.SfnStateMachine(
machine=self.replay_state_machine
)
]
)
self.mre_replay_events_rule.node.add_dependency(self.eb_event_bus)
self.mre_replay_events_rule.node.add_dependency(self.replay_state_machine)
# End: MRE Replay Step Function Definition
self.chalice = Chalice(
self,
"ChaliceApp",
source_dir=RUNTIME_SOURCE_DIR,
stage_config={
"environment_variables": {
"FRAMEWORK_VERSION": FRAMEWORK_VERSION,
"SYSTEM_TABLE_NAME": self.system_table.table_name,
"CONTENT_GROUP_TABLE_NAME": self.content_group_table.table_name,
"PROGRAM_TABLE_NAME": self.program_table.table_name,
"PLUGIN_TABLE_NAME": self.plugin_table.table_name,
"PLUGIN_NAME_INDEX": PLUGIN_NAME_INDEX,
"PLUGIN_VERSION_INDEX": PLUGIN_VERSION_INDEX,
"PROFILE_TABLE_NAME": self.profile_table.table_name,
"MODEL_TABLE_NAME": self.model_table.table_name,
"MODEL_NAME_INDEX": MODEL_NAME_INDEX,
"MODEL_VERSION_INDEX": MODEL_VERSION_INDEX,
"EVENT_TABLE_NAME": self.event_table.table_name,
"EVENT_CHANNEL_INDEX": EVENT_CHANNEL_INDEX,
"EVENT_CONTENT_GROUP_INDEX": EVENT_CONTENT_GROUP_INDEX,
"EVENT_PAGINATION_INDEX": EVENT_PAGINATION_INDEX,
"EVENT_PROGRAMID_INDEX": EVENT_PROGRAMID_INDEX,
"WORKFLOW_EXECUTION_TABLE_NAME": self.workflow_exec_table.table_name,
"REPLAY_REQUEST_TABLE_NAME": self.replayrequest_table.table_name,
"MEDIALIVE_S3_BUCKET": self.medialive_s3_dest_bucket.bucket_name,
"PROBE_VIDEO_LAMBDA_ARN": self.probe_video_lambda.function_arn,
"MULTI_CHUNK_HELPER_LAMBDA_ARN": self.multi_chunk_helper_lambda.function_arn,
"PLUGIN_OUTPUT_HANDLER_LAMBDA_ARN": self.plugin_output_handler_lambda.function_arn,
"WORKFLOW_ERROR_HANDLER_LAMBDA_ARN": self.workflow_error_handler_lambda.function_arn,
"SFN_ROLE_ARN": self.sfn_role.role_arn,
"EB_EVENT_BUS_NAME": self.eb_event_bus.event_bus_name,
"SQS_QUEUE_URL": self.sqs_queue.queue_url,
"HLS_HS256_API_AUTH_SECRET_KEY_NAME": "mre_hsa_api_auth_secret",
"CLOUDFRONT_COOKIE_PRIVATE_KEY_NAME": "mre_cloudfront_cookie_private_key",
"CLOUDFRONT_COOKIE_KEY_PAIR_ID_NAME": "mre_cloudfront_key_pair_id",
"HLS_STREAM_CLOUDFRONT_DISTRO": self.mre_media_output_distro.domain_name,
"CURRENT_EVENTS_TABLE_NAME": self.current_events_table.table_name,
"CLIP_GENERATION_STATE_MACHINE_ARN": self.state_machine.state_machine_arn
},
"tags": {
"Project": "MRE"
},
"manage_iam_role": False,
"iam_role_arn": self.chalice_role.role_arn
}
)
# Store the API Gateway endpoint output of Chalice in SSM Parameter Store
ssm.StringParameter(
self,
"MREControlPlaneEndpointParam",
string_value=self.chalice.sam_template.get_output("EndpointURL").value,
parameter_name="/MRE/ControlPlane/EndpointURL",
tier=ssm.ParameterTier.INTELLIGENT_TIERING,
description="[DO NOT DELETE] Parameter contains the AWS MRE ControlPlane APIEndpoint URL used by the MRE Workflow helper library"
)
# Store the Workflow Execution DDB table ARN in SSM Parameter Store
ssm.StringParameter(
self,
"MREWorkflowExecutionTableARN",
string_value=self.workflow_exec_table.table_arn,
parameter_name="/MRE/ControlPlane/WorkflowExecutionTableARN",
tier=ssm.ParameterTier.INTELLIGENT_TIERING,
description="[DO NOT DELETE] Parameter contains the ARN of the Workflow Execution DDB table used by the cleanup process following an Event deletion"
)
# Required for Updating the Content Security Policy for MRE Frontend
ssm.StringParameter(
self,
"MREMediaOutputBucketName",
string_value=self.mre_media_output_bucket.bucket_name,
parameter_name="/MRE/ControlPlane/MediaOutputBucket",
tier=ssm.ParameterTier.INTELLIGENT_TIERING,
description="[DO NOT DELETE] Parameter contains the AWS MRE MediaOutput Bucket Name"
)