Skip to content

Commit

Permalink
add convenience grant methods to Distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
Tietew committed Oct 31, 2022
1 parent 228c865 commit d1b3c49
Show file tree
Hide file tree
Showing 15 changed files with 777 additions and 21 deletions.
12 changes: 12 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/README.md
Expand Up @@ -554,6 +554,18 @@ const distribution = cloudfront.Distribution.fromDistributionAttributes(this, 'I
});
```

### Permissions

Use the `grant()` method to allow actions on the distribution.
`grantCreateInvalidation()` is a shorthand to allow `CreateInvalidation`.

```ts
declare const distribution: cloudfront.Distribution;
declare const lambdaFn: lambda.Function;
distribution.grant(lambdaFn, 'cloudfront:ListInvalidations', 'cloudfront:GetInvalidation');
distribution.grantCreateInvalidation(lambdaFn);
```

## Migrating from the original CloudFrontWebDistribution to the newer Distribution construct

It's possible to migrate a distribution from the original to the modern API.
Expand Down
45 changes: 45 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/distribution.ts
@@ -1,4 +1,5 @@
import * as acm from '@aws-cdk/aws-certificatemanager';
import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda';
import * as s3 from '@aws-cdk/aws-s3';
import { ArnFormat, IResource, Lazy, Resource, Stack, Token, Duration, Names, FeatureFlags } from '@aws-cdk/core';
Expand All @@ -12,6 +13,7 @@ import { IKeyGroup } from './key-group';
import { IOrigin, OriginBindConfig, OriginBindOptions } from './origin';
import { IOriginRequestPolicy } from './origin-request-policy';
import { CacheBehavior } from './private/cache-behavior';
import { formatDistributionArn } from './private/utils';
import { IResponseHeadersPolicy } from './response-headers-policy';

/**
Expand Down Expand Up @@ -39,6 +41,22 @@ export interface IDistribution extends IResource {
* @attribute
*/
readonly distributionId: string;

/**
* Adds an IAM policy statement associated with this distribution to an IAM
* principal's policy.
*
* @param identity The principal
* @param actions The set of actions to allow (i.e. "cloudfront:ListInvalidations")
*/
grant(identity: iam.IGrantable, ...actions: string[]): iam.Grant;

/**
* Grant to create invalidations for this bucket to an IAM principal (Role/Group/User).
*
* @param identity The principal
*/
grantCreateInvalidation(identity: iam.IGrantable): iam.Grant;
}

/**
Expand Down Expand Up @@ -257,6 +275,13 @@ export class Distribution extends Resource implements IDistribution {
this.distributionDomainName = attrs.domainName;
this.distributionId = attrs.distributionId;
}

public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
return iam.Grant.addToPrincipal({ grantee, actions, resourceArns: [formatDistributionArn(this)] });
}
public grantCreateInvalidation(grantee: iam.IGrantable): iam.Grant {
return this.grant(grantee, 'cloudfront:CreateInvalidation');
}
}();
}

Expand Down Expand Up @@ -345,6 +370,26 @@ export class Distribution extends Resource implements IDistribution {
this.additionalBehaviors.push(new CacheBehavior(originId, { pathPattern, ...behaviorOptions }));
}

/**
* Adds an IAM policy statement associated with this distribution to an IAM
* principal's policy.
*
* @param identity The principal
* @param actions The set of actions to allow (i.e. "cloudfront:ListInvalidations")
*/
public grant(identity: iam.IGrantable, ...actions: string[]): iam.Grant {
return iam.Grant.addToPrincipal({ grantee: identity, actions, resourceArns: [formatDistributionArn(this)] });
}

/**
* Grant to create invalidations for this bucket to an IAM principal (Role/Group/User).
*
* @param identity The principal
*/
public grantCreateInvalidation(identity: iam.IGrantable): iam.Grant {
return this.grant(identity, 'cloudfront:CreateInvalidation');
}

private addOrigin(origin: IOrigin, isFailoverOrigin: boolean = false): string {
const ORIGIN_ID_MAX_LENGTH = 128;

Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/private/utils.ts
@@ -0,0 +1,14 @@
import { Stack } from '@aws-cdk/core';
import { IDistribution } from '..';

/**
* Format distribution ARN from stack and distribution ID.
*/
export function formatDistributionArn(dist: IDistribution) {
return Stack.of(dist).formatArn({
service: 'cloudfront',
region: '',
resource: 'distribution',
resourceName: dist.distributionId,
});
}
28 changes: 28 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/web-distribution.ts
Expand Up @@ -10,6 +10,7 @@ import { FunctionAssociation } from './function';
import { GeoRestriction } from './geo-restriction';
import { IKeyGroup } from './key-group';
import { IOriginAccessIdentity } from './origin-access-identity';
import { formatDistributionArn } from './private/utils';

/**
* HTTP status code to failover to second origin
Expand Down Expand Up @@ -758,6 +759,13 @@ export class CloudFrontWebDistribution extends cdk.Resource implements IDistribu
this.distributionDomainName = attrs.domainName;
this.distributionId = attrs.distributionId;
}

public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
return iam.Grant.addToPrincipal({ grantee, actions, resourceArns: [formatDistributionArn(this)] });
}
public grantCreateInvalidation(identity: iam.IGrantable): iam.Grant {
return this.grant(identity, 'cloudfront:CreateInvalidation');
}
}();
}

Expand Down Expand Up @@ -983,6 +991,26 @@ export class CloudFrontWebDistribution extends cdk.Resource implements IDistribu
this.distributionId = distribution.ref;
}

/**
* Adds an IAM policy statement associated with this distribution to an IAM
* principal's policy.
*
* @param identity The principal
* @param actions The set of actions to allow (i.e. "cloudfront:ListInvalidations")
*/
public grant(identity: iam.IGrantable, ...actions: string[]): iam.Grant {
return iam.Grant.addToPrincipal({ grantee: identity, actions, resourceArns: [formatDistributionArn(this)] });
}

/**
* Grant to create invalidations for this bucket to an IAM principal (Role/Group/User).
*
* @param identity The principal
*/
grantCreateInvalidation(identity: iam.IGrantable): iam.Grant {
return this.grant(identity, 'cloudfront:CreateInvalidation');
}

private toBehavior(input: BehaviorWithOrigin, protoPolicy?: ViewerProtocolPolicy) {
let toReturn = {
allowedMethods: this.METHOD_LOOKUP_MAP[input.allowedMethods || CloudFrontAllowedMethods.GET_HEAD],
Expand Down
@@ -1 +1 @@
{"version":"20.0.0"}
{"version":"21.0.0"}
@@ -1,15 +1,15 @@
{
"version": "20.0.0",
"version": "21.0.0",
"files": {
"e56a9eb81eb88d748b8062f87488a5f2d9ec1137d330b9d5e0eb33f3ea9de5c7": {
"36c6ded30c4c42464c2753c997c004bf740b9311a744c363fda5f951929a9504": {
"source": {
"path": "integ-distribution-basic.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "e56a9eb81eb88d748b8062f87488a5f2d9ec1137d330b9d5e0eb33f3ea9de5c7.json",
"objectKey": "36c6ded30c4c42464c2753c997c004bf740b9311a744c363fda5f951929a9504.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down
Expand Up @@ -24,6 +24,148 @@
]
}
}
},
"Role13A5C70C1": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::",
{
"Ref": "AWS::AccountId"
},
":root"
]
]
}
}
}
],
"Version": "2012-10-17"
}
}
},
"Role1DefaultPolicyD3EF4D0A": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "cloudfront:CreateInvalidation",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":cloudfront::",
{
"Ref": "AWS::AccountId"
},
":distribution/",
{
"Ref": "DistB3B78991"
}
]
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "Role1DefaultPolicyD3EF4D0A",
"Roles": [
{
"Ref": "Role13A5C70C1"
}
]
}
},
"Role291939BC6": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::",
{
"Ref": "AWS::AccountId"
},
":root"
]
]
}
}
}
],
"Version": "2012-10-17"
}
}
},
"Role2DefaultPolicy3A7A0A1B": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "cloudfront:ListInvalidations",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":cloudfront::",
{
"Ref": "AWS::AccountId"
},
":distribution/",
{
"Ref": "DistB3B78991"
}
]
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "Role2DefaultPolicy3A7A0A1B",
"Roles": [
{
"Ref": "Role291939BC6"
}
]
}
}
},
"Parameters": {
Expand Down
@@ -1,14 +1,12 @@
{
"version": "20.0.0",
"version": "21.0.0",
"testCases": {
"integ.distribution-basic": {
"integ-distribution-basic/distribution-basic-test/DefaultTest": {
"stacks": [
"integ-distribution-basic"
],
"diffAssets": false,
"stackUpdateWorkflow": true
"assertionStack": "integ-distribution-basic/distribution-basic-test/DefaultTest/DeployAssert",
"assertionStackName": "integdistributionbasicdistributionbasictestDefaultTestDeployAssert2D53EBF0"
}
},
"synthContext": {},
"enableLookups": false
}
}
@@ -0,0 +1,19 @@
{
"version": "21.0.0",
"files": {
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
"source": {
"path": "integdistributionbasicdistributionbasictestDefaultTestDeployAssert2D53EBF0.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
}
},
"dockerImages": {}
}

0 comments on commit d1b3c49

Please sign in to comment.