RFC - CloudFront + MediaPackage V2 Origin Integration
May 6, 2026 · View on GitHub
Native CloudFront Origin Support for MediaPackage V2
- Original Author(s): @jamiepmullan
- Tracking Issue: #907
- API Bar Raiser: @alvazjor
Today, connecting a CloudFront distribution to a MediaPackage V2 origin endpoint requires manually configuring origin access control, resource policies, and custom origin settings. This RFC adds first-class support across two modules so that developers can wire up a CloudFront + MediaPackage V2 pipeline in a few lines of code.
The implementation spans a stable module and an alpha module: a generic
MediaPackageV2OriginAccessControl OAC class is added to
aws-cdk-lib/aws-cloudfront (stable), while the opinionated
MediaPackageV2Origin origin class lives in
@aws-cdk/aws-mediapackagev2-alpha. This keeps the dependency direction
correct — the alpha module depends on the stable cloudfront module, not
the other way around — and allows the stable module to ship a reusable
OAC primitive without taking a dependency on alpha types. The origin
class in the alpha module then builds on that primitive to deliver the
full integration experience (OAC auto-creation, resource policy grants,
egress domain wiring). If MediaPackage V2 were already stable, the
origin class would naturally live in aws-cloudfront-origins alongside
S3BucketOrigin — but since it depends on alpha types, it must remain
in the alpha module until graduation.
Before (L1 escape hatches):
const oac = new cloudfront.CfnOriginAccessControl(this, 'OAC', {
originAccessControlConfig: {
name: 'my-mediapackage-oac',
originAccessControlOriginType: 'mediapackagev2',
signingBehavior: 'always',
signingProtocol: 'sigv4',
},
});
const distribution = new cloudfront.Distribution(this, 'Dist', {
defaultBehavior: {
origin: new HttpOrigin(channelGroup.egressDomain, {
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
}),
},
});
const cfnDistribution = distribution.node.defaultChild as cloudfront.CfnDistribution;
cfnDistribution.addOverride(
'Properties.DistributionConfig.Origins.0.OriginAccessControlId',
oac.ref,
);
endpoint.addToResourcePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
principals: [new iam.ServicePrincipal('cloudfront.amazonaws.com')],
actions: ['mediapackagev2:GetObject', 'mediapackagev2:GetHeadObject'],
resources: [endpoint.originEndpointArn],
conditions: {
StringEquals: {
'aws:SourceArn': `arn:aws:cloudfront::${Aws.ACCOUNT_ID}:distribution/${distribution.distributionId}`,
},
},
}));
After (L2):
new cloudfront.Distribution(this, 'Dist', {
defaultBehavior: {
origin: new MediaPackageV2Origin(endpoint, {
channelGroup: group,
}),
},
});
Working Backwards
README
MediaPackageV2OriginAccessControl (aws-cdk-lib/aws-cloudfront)
A new OAC class for MediaPackage V2 origins, following the same pattern as S3OriginAccessControl and FunctionUrlOriginAccessControl.
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
// Create a new OAC for MediaPackage V2
const oac = new cloudfront.MediaPackageV2OriginAccessControl(stack, 'MyOAC');
// Import an existing OAC
const importedOac = cloudfront.MediaPackageV2OriginAccessControl.fromOriginAccessControlId(
stack, 'ImportedOAC', 'E1234567890ABC',
);
Property Interface:
export interface MediaPackageV2OriginAccessControlProps {
/**
* A description of the origin access control.
* @default - no description
*/
readonly description?: string;
/**
* A name to identify the origin access control.
* @default - a generated name
*/
readonly originAccessControlName?: string;
}
MediaPackageV2Origin (@aws-cdk/aws-mediapackagev2-alpha)
A CloudFront origin class that handles the full integration between
CloudFront and MediaPackage V2. It extends cloudfront.OriginBase and
wires together OAC creation, resource policies, and origin configuration.
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as mediapackagev2 from '@aws-cdk/aws-mediapackagev2-alpha';
declare const endpoint: mediapackagev2.IOriginEndpoint;
declare const channelGroup: mediapackagev2.IChannelGroup;
// Simple usage — OAC is auto-created
const distribution = new cloudfront.Distribution(stack, 'Distribution', {
defaultBehavior: {
origin: new mediapackagev2.MediaPackageV2Origin(endpoint, {
channelGroup: channelGroup,
}),
},
});
With explicit OAC and CDN auth:
declare const endpoint: mediapackagev2.IOriginEndpoint;
declare const channelGroup: mediapackagev2.IChannelGroup;
const oac = new cloudfront.MediaPackageV2OriginAccessControl(stack, 'OAC');
const distribution = new cloudfront.Distribution(stack, 'Distribution', {
defaultBehavior: {
origin: new mediapackagev2.MediaPackageV2Origin(endpoint, {
channelGroup: channelGroup,
originAccessControl: oac,
cdnAuthConfiguration: {
headerName: 'X-MediaPackage-CDNIdentifier',
secretHeaderValue: secretsmanager.Secret.fromSecretNameV2(
stack, 'CdnSecret', 'my-cdn-auth-secret',
),
},
}),
},
});
Property Interface:
export interface MediaPackageV2OriginProps extends cloudfront.OriginProps {
/**
* The channel group that contains the origin endpoint.
* Used to derive the egress domain for the custom origin.
*/
readonly channelGroup: mediapackagev2.IChannelGroup;
/**
* The origin access control to use.
* @default - a new MediaPackageV2OriginAccessControl is created
*/
readonly originAccessControl?: cloudfront.IOriginAccessControlRef;
/**
* CDN authorization configuration.
* When provided, the specified header and secret are included
* in origin requests for MediaPackage V2 CDN auth validation.
* @default - no CDN authorization
*/
readonly cdnAuthConfiguration?: CdnAuthConfiguration;
}
export interface CdnAuthConfiguration {
/**
* The header name used for CDN authorization.
*/
readonly headerName: string;
/**
* The Secrets Manager secret containing the header value.
*/
readonly secretHeaderValue: secretsmanager.ISecret;
}
The origin automatically:
- Configures HTTPS-only custom origin pointing at the channel group's egress domain
- Creates a
MediaPackageV2OriginAccessControlif one isn't provided - Calls
endpoint.addToResourcePolicy()to grant the CloudFront distribution access (includingGetHeadObjectfor MQAR support)
Ticking the box below indicates that the public API of this RFC has been
signed-off by the API bar raiser (the status/api-approved label was applied to the
RFC pull request):
[ ] Signed-off by API Bar Raiser @xxxxx
Public FAQ
What are we launching today?
Two additions across two modules:
MediaPackageV2OriginAccessControlin the stableaws-cdk-lib/aws-cloudfrontmodule — a new OAC class for MediaPackage V2 origins.MediaPackageV2Originin@aws-cdk/aws-mediapackagev2-alpha— a CloudFront origin class that handles the full CloudFront + MediaPackage V2 integration.
Why should I use this feature?
If you're building a live streaming pipeline with CloudFront and MediaPackage V2, this removes the need to manually configure OAC, resource policies, and custom origin settings. Instead of ~30 lines of boilerplate, you get a single origin class that handles it all.
Internal FAQ
Why are we doing this?
Connecting CloudFront to MediaPackage V2 currently requires users to understand OAC configuration, resource policy grants, egress domain construction, and HTTPS-only origin settings. This is error-prone and repetitive. The S3 origin integration already sets the precedent for auto-wiring OAC and bucket policies — we're applying the same pattern to MediaPackage V2.
Why should we not do this?
Users can achieve this today with escape hatches and manual configuration. However, the integration is complex enough that most users get it wrong on the first attempt, particularly around resource policies and MQAR support.
What is the technical solution (design) of this feature?
The design splits across two modules to maintain correct dependency direction:
-
The stable
aws-cloudfrontmodule getsMediaPackageV2OriginAccessControl, which is a standalone OAC class following the existingS3OriginAccessControlpattern. It creates aCfnOriginAccessControlwithoriginAccessControlOriginType: MEDIAPACKAGEV2. TheMEDIAPACKAGEV2enum value already exists inOriginAccessControlOriginType. -
The alpha
aws-mediapackagev2-alphamodule getsMediaPackageV2Origin, which extendscloudfront.OriginBase. It takes anIOriginEndpointandIChannelGroup, auto-creates OAC if needed, grants resource policy access, and renders HTTPS-only custom origin config. The alpha module depends on the stable cloudfront module (not the other way around).
This mirrors how aws-cloudfront-origins provides S3BucketOrigin
that auto-creates S3OriginAccessControl, except the origin lives in
the mediapackagev2 alpha package since it depends on alpha types.
Is this a breaking change?
No. Both additions are net-new classes with no changes to existing APIs.
What alternative solutions did you consider?
- Placing
MediaPackageV2Origininaws-cloudfront-origins— rejected because it would require the stable module to depend on alpha MediaPackage V2 types. - A standalone integration module — unnecessary complexity for two classes that fit naturally in their respective modules.
What are the drawbacks of this solution?
The origin class lives in the alpha module, so users must install
@aws-cdk/aws-mediapackagev2-alpha to get the integration. Once
MediaPackage V2 graduates to stable, the origin class would move to
aws-cloudfront-origins or remain in the stable mediapackagev2 module.
What is the high-level project plan?
Implementation is already drafted. The OAC class is a small addition to the stable cloudfront module. The origin class builds on the existing mediapackagev2 alpha constructs.
Are there any open issues that need to be addressed later?
Graduation Plan: Non-Standard Module Split
At graduation, the alpha module cannot promote as a single unit.
MediaPackageV2Origin must move to aws-cloudfront-origins to follow
the established convention — every CloudFront origin class
(S3BucketOrigin, FunctionUrlOrigin, LoadBalancerV2Origin,
RestApiOrigin) lives there.
The split at graduation:
| What | Graduates to |
|---|---|
ChannelGroup, Channel, OriginEndpoint, and all other MediaPackage V2 types | aws-cdk-lib/aws-mediapackagev2 |
MediaPackageV2Origin, MediaPackageV2OriginProps | aws-cdk-lib/aws-cloudfront-origins |
MediaPackageV2OriginAccessControl | aws-cdk-lib/aws-cloudfront (already stable, no change) |
The dependency direction is one-way and clean —
aws-cloudfront-origins imports public interfaces from
aws-mediapackagev2 and aws-cloudfront. No circular dependencies,
no private type leakage.
Import path changes for users:
// Alpha (current)
import {
MediaPackageV2Origin, ChannelGroup, Channel, OriginEndpoint,
} from '@aws-cdk/aws-mediapackagev2-alpha';
// Stable (after graduation)
import {
ChannelGroup, Channel, OriginEndpoint,
} from 'aws-cdk-lib/aws-mediapackagev2';
import {
MediaPackageV2Origin,
} from 'aws-cdk-lib/aws-cloudfront-origins';
Two import path updates instead of one. The MediaPackageV2Origin API
itself (constructor, props, behavior) does not change — only the import
path. The alpha module's README should document this planned split so
users are aware ahead of graduation.