Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apprunner): make Service implement IGrantable #26130

Merged
merged 9 commits into from
Jul 24, 2023
24 changes: 23 additions & 1 deletion packages/@aws-cdk/aws-apprunner-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ The `Service` construct allows you to create AWS App Runner services with `ECR P
- `Source.fromAsset()` - To define the source from local asset directory.


The `Service` construct implements `IGrantable`.

## ECR Public

To create a `Service` with ECR Public:
Expand Down Expand Up @@ -124,7 +126,27 @@ new apprunner.Service(this, 'Service', {
You are allowed to define `instanceRole` and `accessRole` for the `Service`.

`instanceRole` - The IAM role that provides permissions to your App Runner service. These are permissions that
your code needs when it calls any AWS APIs.
your code needs when it calls any AWS APIs. If not defined, a new instance role will be generated
when required.

To add IAM policy statements to this role, use `addToRolePolicy()`:

```ts
import * as iam from 'aws-cdk-lib/aws-iam';

const service = new apprunner.Service(this, 'Service', {
source: apprunner.Source.fromEcrPublic({
imageConfiguration: { port: 8000 },
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
});

service.addToRolePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:GetObject'],
resources: ['*'],
}))
```

`accessRole` - The IAM role that grants the App Runner service access to a source repository. It's required for
ECR image repositories (but not for ECR Public repositories). If not defined, a new access role will be generated
Expand Down
20 changes: 13 additions & 7 deletions packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ export interface ServiceProps {
*
* @see https://docs.aws.amazon.com/apprunner/latest/dg/security_iam_service-with-iam.html#security_iam_service-with-iam-roles-service.instance
*
* @default - no instance role attached.
* @default - generate a new instance role.
*/
readonly instanceRole?: iam.IRole;

Expand Down Expand Up @@ -959,7 +959,7 @@ export abstract class Secret {
/**
* The App Runner Service.
*/
export class Service extends cdk.Resource {
export class Service extends cdk.Resource implements iam.IGrantable {
/**
* Import from service name.
*/
Expand Down Expand Up @@ -993,9 +993,10 @@ export class Service extends cdk.Resource {

return new Import(scope, id);
}
public readonly grantPrincipal: iam.IPrincipal;
private readonly props: ServiceProps;
private accessRole?: iam.IRole;
private instanceRole?: iam.IRole;
private instanceRole: iam.IRole;
private source: SourceConfig;

/**
Expand Down Expand Up @@ -1051,7 +1052,8 @@ export class Service extends cdk.Resource {
this.source = source;
this.props = props;

this.instanceRole = this.props.instanceRole;
this.instanceRole = this.props.instanceRole ?? this.createInstanceRole();
this.grantPrincipal = this.instanceRole;

const environmentVariables = this.getEnvironmentVariables();
const environmentSecrets = this.getEnvironmentSecrets();
Expand Down Expand Up @@ -1117,6 +1119,13 @@ export class Service extends cdk.Resource {
this.serviceName = cdk.Fn.select(1, cdk.Fn.split('/', resourceFullName));
}

/**
* Adds a statement to the instance role.
*/
public addToRolePolicy(statement: iam.PolicyStatement) {
this.instanceRole.addToPrincipalPolicy(statement);
}

/**
* This method adds an environment variable to the App Runner service.
*/
Expand All @@ -1134,9 +1143,6 @@ export class Service extends cdk.Resource {
if (name.startsWith('AWSAPPRUNNER')) {
throw new Error(`Environment secret key ${name} with a prefix of AWSAPPRUNNER is not allowed`);
}
if (!this.instanceRole) {
this.instanceRole = this.createInstanceRole();
}
secret.grantRead(this.instanceRole);
this.secrets.push({ name: name, value: secret.arn });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,39 @@
"ImageRepositoryType": "ECR_PUBLIC"
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service1InstanceRole8CBC81F1",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "DEFAULT"
}
},
"ServiceName": "service1"
}
}
},
"Service1InstanceRole8CBC81F1": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
}
},
"Outputs": {
"URL1": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,14 @@
"ImageRepositoryType": "ECR"
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service3InstanceRoleD40BEE82",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "DEFAULT"
Expand Down Expand Up @@ -211,14 +218,55 @@
"ImageRepositoryType": "ECR"
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service2InstanceRole3F57F2AA",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "DEFAULT"
}
}
}
}
},
"Service3InstanceRoleD40BEE82": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"Service2InstanceRole3F57F2AA": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
}
},
"Outputs": {
"URL3": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
}
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service4InstanceRole26B443A0",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "DEFAULT"
Expand Down Expand Up @@ -50,13 +57,54 @@
}
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service5InstanceRole94C07D84",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "DEFAULT"
}
}
}
},
"Service4InstanceRole26B443A0": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"Service5InstanceRole94C07D84": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
}
},
"Outputs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,14 @@
"ImageRepositoryType": "ECR_PUBLIC"
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service6InstanceRole7220D460",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "VPC",
Expand All @@ -469,7 +476,14 @@
"ImageRepositoryType": "ECR_PUBLIC"
}
},
"InstanceConfiguration": {},
"InstanceConfiguration": {
"InstanceRoleArn": {
"Fn::GetAtt": [
"Service7InstanceRoleFD40F312",
"Arn"
]
}
},
"NetworkConfiguration": {
"EgressConfiguration": {
"EgressType": "VPC",
Expand All @@ -482,7 +496,41 @@
}
}
}
}
},
"Service6InstanceRole7220D460": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"Service7InstanceRoleFD40F312": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "tasks.apprunner.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
}
},
"Outputs": {
"URL6": {
Expand Down
Loading