AWS for M&E Blog

Secure media streaming with private networking using AWS Media Services


Many organizations are seeking ways to control and secure their live media streams, which often contain sensitive information or intellectual property, within their corporate networks. At the same time, companies also want the flexibility to grant controlled access to these private streams. Accessing media services, or media assets stored in Amazon Simple Storage Service (S3), directly does not provide the access control mechanisms required by some customers. Moreover, internet facing services like Amazon CloudFront distribute these streams over the public internet to satisfy certain requirements such as low-latency delivery.

This blog post describes how to set up a streaming solution leveraging Amazon API Gateway and AWS Elemental MediaLive in conjunction with VPC Endpoints and AWS Client VPN. This combination allows restriction of private streams exclusively to a customer’s corporate network, with the ability to implement custom access control mechanisms, reducing any exposure to the public internet.

Solution overview

AWS helps broadcasters and content owners automate their media supply chain, streamline content distribution, and broadcast live content cost-effectively to a global audience. With AWS, you have the flexibility to scale your infrastructure as needed while only paying for the resources you use. This empowers you to build highly available and budget-friendly solutions for live video streaming. Additionally, many customers express the need to enhance control and privacy for their internal content, while still granting access to employees and third parties. This includes scenarios like internal conferences, or sharing test footage of new products, movies, and games.

This implementation offers a modification to the Live Streaming on AWS solution. While similar, it provides additional security measures to manage stream access and keep those streams within a private IP network, and does not use the public internet for media asset delivery.

solution overview showing flow of the media stream through private connectivity

Figure 1: solution overview showing flow of the media stream through private connectivity

You can set up this solution specifically for a live event. When streaming concludes, you can decommission the infrastructure to ensure you’re only charged for what you’ve used. Alternatively, you can repurpose this solution for other streaming events, but we recommend implementing automation to manage the infrastructure efficiently. Another option is to maintain it as a mechanism for ingesting media and broadcasting it on demand after conversion.

Solution features

  • Automatically configures Virtual Private Clouds (VPCs) with private subnets and VPC Endpoints for controlled connectivity.
  • Creates a MediaLive channel connected to an Amazon S3 bucket to encode and originate content for adaptive bitrate streaming across multiple screens via HTTP Live Streaming (HLS).
  • Creates and deploys an API Gateway to provide an elastic, highly available, private delivery mechanism. Amazon Cognito or AWS Lambda authorizers can also be added if an additional authentication layer is a requirement.
  • Builds an embedded video player app for testing purposes in a browser.
  • Creates a ClientVPN endpoint as a mechanism to access the private network components on AWS and enables the testing of streaming from and to a specific machine. However, if you have an existing site-to-site VPN or AWS Direct Connect, they can also be used. AWS Elemental MediaConnect can also be used as a connectivity option, as it provides additional stream encryption mechanisms.

Solution implementation

AWS CDK structure

AWS CDK is an open-source software development framework that lets you define your cloud application resources using familiar programming languages. For hands-on experience, please visit the AWS CDK introduction workshop.

For this project, we make use of the Python version of the AWS CDK. We will create a Python app using the AWS CDK, which abstracts the AWS CloudFormation stack and resource creation. The CDK has been created using a top-level and nested stack concept to allow for scoping of resources:

  • Root stack: this is our top-level stack, which initiates the deployment of the nested stacks.
  • Gateway nested stack: this contains the API Gateway definition
  • IAM nested stack: holds the roles and policies required to deploy and run the solution.
  • MediaLive nested stack: contains the definition of our MediaLive channel and other components of the media infrastructure to stream MP4 files.
  • Network nested stack: contains the definition of the private networking components.
  • Storage nested stack: contains the resource definition for the private streaming bucket.

Deploy the solution


For this deployment, you should have:

CDK deployment

    1. Copy the sample code to your environment: git clone
    2. Move into the new directory that has just been created:  cd protected-streaming-aws-medialive
    3. Follow this guide to generate certificates and upload them to AWS Certificate Manager to set up mutual authentication between your client device and the AWS VPN endpoint. Ensure you capture the ARNs of the certificates you upload. Certificate ARNs will follow the format: arn:aws:acm:<region>:<account-id>:certificate/<certificate-id>
    4. Open up the protected-streaming-aws-medialive/cdk/ file in your favorite code editor, and modify the my_client_vpn_cert_param and my_server_vpn_cert_param lines to add in your ARNs from the certificates you just uploaded to ACM.
    5. Make sure to activate the virtualenv environment and install the dependencies from, protected-streaming-aws-medialive/cdk using pip install -r requirements.txt
    6. Run cdk synth to synthesize the CloudFormation template for the code.
    7. Run cdk deploy to deploy the stack and its resources into your account. The stack takes about 10 minutes to deploy, so this is a good time to go stretch your legs or grab a coffee.
    8. Once the CDK has finished deploying the resources, navigate to the CloudFormation console via your browser. You should see the following stacks have been successfully been created:
The diagram shows what the CloudFormation output will look like once all the CDK stacks have been deployed. CloudFormation will deploy the ProtectedStreaming stack, which contains the Network, Security, Storage, Gateway, and MediaLive nested stacks, as well as some CDKMetadata needed for deployment.

Figure 2: CloudFormation output will look like this once all the CDK stacks have been deployed

  1. Next, navigate to the VPC dashboard in your region, and on the left-hand side menu, select Client VPN endpoints. Select the radio button for the Client VPN endpoint, and choose Download client configuration.
  2. Open the downloaded-client-config.ovpn file in your favorite editor and follow option 1 in this guide to add the path to the local client certificate information to enable the mutual authentication.
    NOTE: Do not connect to the ClientVPN yet as this will prevent you from configuring the next few steps. Connection to the ClientVPN will occur for the testing phase.
  3. Navigate to the API Gateway console and find a new API called Protected Media Streaming. Make a note of this Protected Stream API ID, you’ll need this later on.
  4. Navigate to the MediaLive console and then click on Inputs in the left-hand navigation bar. Select the protected_stream_input. Make a note of the first URL listed under Endpoints, which will have the following format: rtmp://xx.xx.xx.xx:1935:protected_stream_app/protected_stream_appinst1

Deploy the video player

Back in our local repository, let’s deploy the video player, which will be embedded into the browser and display live stream footage.

  1. Navigate to the video player directory
    1. cd videoplayer
  2. Still in your virtual environment, install the Node dependencies with
    1. npm install
  3. Build the video player code
    1. npm run build
  4. Copy the video player and all node modules to the Amazon S3 bucket created by the CDK deployment. The MediaBucketName property can be found in the CloudFormation outputs for the nested storage stack.
    1. aws s3 cp dist/ s3://<MediaBucketName> --recursive
    2. aws s3 cp node_modules/ s3://<MediaBucketName>/node_modules/ --recursive

Test the solution

The stack does not start your channel automatically. Navigate to MediaLive in the AWS Console and click the Channels link in the left-hand navigation bar. Select protected_stream_channel and click the Start button.

NOTE: Remember to stop your channel when you are done testing to avoid unwanted charges.

Set up the private stream input

For this tutorial, we walk through how to stream from your webcam to the MediaLive channel, and view it from your browser using API Gateway. The traffic will flow through the private connectivity we deployed through the CDK. We use OBS Studio software for this demo, but you can use any software or stream that can be configured for RTMP Push.

First, we need to connect to our ClientVPN:

  1. Using the AWS ClientVPN software, follow the instructions for your client device OS to add a new profile using the downloaded-client-config.ovpn downloaded and edited in the previous steps.
  2. Connect to the VPN.
  3. Update your local DNS settings, instructions here for macOS or Windows to use the Amazon DNS server in your VPC at

Next, we want to configure OBS to stream our webcam:

  1. In OBS, navigate to Settings, and select Stream. Choose Custom from the drop down list.
  2. For the server address, add in the RTMP address details we captured earlier from the MediaLive input under Destination A. Add everything up until first path, such as rtmp://xx.xx.xx.xx:1935/protected_stream_app/
  3. Add the application instance name protected_stream_appinst1 for the primary MediaLive pipeline as the stream key in the field below.
  4. Your OBS settings should look something like this:

  1. Select Apply and OK and return to the main OBS landing console.
  2. Next, we create our video source. Under Sources select the + to add a new source, and choose Video Capture Device

  1. Choose a name, select OK and choose a device to capture a video input.
  2. Once done, you should see your video device on the OBS landing page. The final step here is to select Start Streaming. This will connect to the MediaLive endpoint via the VPN and start to push your video content from your device, for us to receive on the other side through API Gateway.

Connect to private API to view the stream output

Now that we have a live video stream, we want to connect to our private network through the ClientVPN so we can stream it.

  1. Using the Protected Stream API ID you captured earlier, invoke the API using this format:


  1. You should now be streaming media content privately. To confirm, disconnect from the ClientVPN and refresh your browser.

Additional security measures to move to least privilege

The Amazon S3 bucket that stores the video content is a primary component of this solution. The current implementation of the design applies some flexible policies to allow for testing and implementation in your accounts. If you do plan to deploy this architecture into a production environment, we recommend some additional tuning and scoping down of the S3 bucket policy to control the origin of the data as well as where the data can be distributed.

  1. Restrict the MediaBucketName to only allow actions on that bucket originating from the VPC endpoint. This would be done on the MediaLiveAccessPolicy. You can use this userguide to achieve this and tailor for your environment.
  2. Further restrict permissions and scope down so that the only principal that can write to the S3 bucket is the role used by MediaLive. Equally, scope down which principals can get the objects from the S3 bucket so that only the role used by API Gateway can do so. You can access guidance related to scoping down the bucket policy here.


Once you are done testing, you should consider destroying the resources created as part of this walkthrough to save on costs.

  1. Navigate to the MediaLive console and stop the channel.
  2. In your terminal, run cdk destroy. This will start the process to remove the CloudFormation stacks that have been created.

NOTE: Also make sure to update your local DNS settings to no longer use the Amazon DNS in your VPC.


In this blog post, we demonstrated how to deploy a solution that creates a secure streaming network using AWS Elemental MediaLive, combined with private networking architectures. This allows customers to have more control and flexibility in protecting their streams from traversing the public internet, all while adding extra layers of authentication. This addresses customer requests for a method to deliver highly sensitive streaming content with reduced exposure to security risks.

As a next step in this solution, customers may want to explore networking options like AWS Direct Connect or AWS Site-to-Site VPN. This way, they can avoid the need for employees or third parties to install ClientVPN software on their devices to access a private stream.

For more information about AWS Media Services and how they can assist you in creating and delivering video content, visit Media Services on AWS.

Peter Henebäck

Peter Henebäck

Peter is a Solutions Architect working with Global customers across Media & Entertainment and Games. He has worked with customers on multiple continents designing and implemented innovative solutions across entertainment, sports, news, and games.

Danny Cortegaca

Danny Cortegaca

Danny is a Senior Security Specialist at AWS. With over 10 years of experience across Financial Services, FinTech, Telecommunications, and Media customers, Danny has recently been focusing on supporting customers with risk based conversations using threat modeling, and driving AppSec capabilities and practices.