Skip to content

Commit

Permalink
fix(scheduler-targets-alpha): imported target resources as schedule t…
Browse files Browse the repository at this point in the history
…arget throws synth error (#32105)

### Issue # (if applicable)

Tracking #31785 

### Reason for this change

Similar to what was done in this PR for the Lambda Invoke target: #31837. 
Reasoning is explained in this [comment](#29615 (comment)):
> At synth time, there are cases where CDK does not know about the actual environment (e.g. when the environment is using Tokens). In other words, the environment check works in some scenarios and not others. This creates more confusion than benefit.
IF cross env target support is added in the future, this check will become a blocker for CDK customers to set up cross env target.


### Description of changes

Remove synth-time error that checks for same account and region for all targets to allow use of imported resources as target.

### Description of how you validated changes

All tests are passing.

### Checklist
- [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
gracelu0 authored Nov 14, 2024
1 parent dcb5cf1 commit 1a8306f
Show file tree
Hide file tree
Showing 24 changed files with 57 additions and 615 deletions.
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-scheduler-targets-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ const eventEntry: targets.EventBridgePutEventsEntry = {

new Schedule(this, 'Schedule', {
schedule: ScheduleExpression.rate(Duration.hours(1)),
target: new targets.EventBridgePutEvents(eventEntry, {}),
target: new targets.EventBridgePutEvents(eventEntry),
});
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IProject } from 'aws-cdk-lib/aws-codebuild';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Use an AWS CodeBuild as a target for AWS EventBridge Scheduler.
*/
export class CodeBuildStartBuild extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly project: IProject,
private readonly props: ScheduleTargetBaseProps = {},
props: ScheduleTargetBaseProps = {},
) {
super(props, project.projectArn);
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
if (!sameEnvDimension(this.project.env.region, schedule.env.region)) {
throw new Error(`Cannot assign project in region ${this.project.env.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the project must be in the same region.`);
}

if (!sameEnvDimension(this.project.env.account, schedule.env.account)) {
throw new Error(`Cannot assign project in account ${this.project.env.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the project must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, schedule.env.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.account}. Both the target and the execution role must be in the same account.`);
}

protected addTargetActionToRole(role: IRole): void {
role.addToPrincipalPolicy(new PolicyStatement({
actions: ['codebuild:StartBuild'],
resources: [this.project.projectArn],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,20 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IPipeline } from 'aws-cdk-lib/aws-codepipeline';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Use an AWS CodePipeline pipeline as a target for AWS EventBridge Scheduler.
*/
export class CodePipelineStartPipelineExecution extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly pipeline: IPipeline,
private readonly props: ScheduleTargetBaseProps = {},
props: ScheduleTargetBaseProps = {},
) {
super(props, pipeline.pipelineArn);
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
const region = this.pipeline.env.region ?? '';
const account = this.pipeline.env.account ?? '';

if (!sameEnvDimension(region, schedule.env.region)) {
throw new Error(`Cannot assign pipeline in region ${region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the pipeline must be in the same region.`);
}

if (!sameEnvDimension(account, schedule.env.account)) {
throw new Error(`Cannot assign pipeline in account ${account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the pipeline must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(this.pipeline.node)} in account ${account}. Both the target and the execution role must be in the same account.`);
}

protected addTargetActionToRole(role: IRole): void {
role.addToPrincipalPolicy(new PolicyStatement({
actions: ['codepipeline:StartPipelineExecution'],
resources: [this.pipeline.pipelineArn],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { IScheduleTarget, ISchedule, ScheduleTargetInput, ScheduleTargetConfig } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import * as events from 'aws-cdk-lib/aws-events';
import { IRole } from 'aws-cdk-lib/aws-iam';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* An entry to be sent to EventBridge
*
Expand Down Expand Up @@ -52,28 +49,16 @@ export interface EventBridgePutEventsEntry {
export class EventBridgePutEvents extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly entry: EventBridgePutEventsEntry,
private readonly props: ScheduleTargetBaseProps,
private readonly props: ScheduleTargetBaseProps = {},
) {
super(props, entry.eventBus.eventBusArn);
if (this.props.input) {
throw new Error('ScheduleTargetBaseProps.input is not supported for EventBridgePutEvents. Please use entry.detail instead.');
}
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
protected addTargetActionToRole(role: IRole): void {
const eventBus = this.entry.eventBus;
const eventBusEnv = eventBus.env;
if (!sameEnvDimension(eventBusEnv.region, schedule.env.region)) {
throw new Error(`Cannot assign eventBus in region ${eventBusEnv.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the eventBus must be in the same region.`);
}

if (!sameEnvDimension(eventBusEnv.account, schedule.env.account)) {
throw new Error(`Cannot assign eventBus in account ${eventBusEnv.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the eventBus must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, eventBusEnv.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(eventBus.node)} in account ${eventBusEnv.account}. Both the target and the execution role must be in the same account.`);
}

eventBus.grantPutEventsTo(role);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,23 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { CfnAssessmentTemplate } from 'aws-cdk-lib/aws-inspector';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Use an Amazon Inspector as a target for AWS EventBridge Scheduler.
*/
export class InspectorStartAssessmentRun extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly template: CfnAssessmentTemplate,
private readonly props: ScheduleTargetBaseProps = {},
template: CfnAssessmentTemplate,
props: ScheduleTargetBaseProps = {},
) {
super(props, template.attrArn);
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
if (!sameEnvDimension(this.template.stack.region, schedule.env.region)) {
throw new Error(`Cannot assign assessment template in region ${this.template.stack.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the assessment template must be in the same region.`);
}

if (!sameEnvDimension(this.template.stack.account, schedule.env.account)) {
throw new Error(`Cannot assign assessment template in account ${this.template.stack.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the assessment template must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, this.template.stack.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(this.template.node)} in account ${this.template.stack.account}. Both the target and the execution role must be in the same account.`);
}

protected addTargetActionToRole(role: IRole): void {
role.addToPrincipalPolicy(new PolicyStatement({
actions: ['inspector:StartAssessmentRun'],
resources: ['*'],
}));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,24 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { CfnDeliveryStream } from 'aws-cdk-lib/aws-kinesisfirehose';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Use an Amazon Kinesis Data Firehose as a target for AWS EventBridge Scheduler.
*/
export class KinesisDataFirehosePutRecord extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly deliveryStream: CfnDeliveryStream,
private readonly props: ScheduleTargetBaseProps = {},
props: ScheduleTargetBaseProps = {},
) {
super(props, deliveryStream.attrArn);
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
if (!sameEnvDimension(this.deliveryStream.stack.region, schedule.env.region)) {
throw new Error(`Cannot assign the Firehose delivery stream in region ${this.deliveryStream.stack.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the Firehose delivery stream must be in the same region.`);
}

if (!sameEnvDimension(this.deliveryStream.stack.account, schedule.env.account)) {
throw new Error(`Cannot assign the Firehose delivery stream in account ${this.deliveryStream.stack.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the Firehose delivery stream must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, this.deliveryStream.stack.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(this.deliveryStream.node)} in account ${this.deliveryStream.stack.account}. Both the target and the execution role must be in the same account.`);
}
protected addTargetActionToRole(role: IRole): void {

role.addToPrincipalPolicy(new PolicyStatement({
actions: ['firehose:PutRecord'],
resources: [this.deliveryStream.attrArn],
}));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { ISchedule, IScheduleTarget, ScheduleTargetConfig } from '@aws-cdk/aws-scheduler-alpha';
import { Names, Token } from 'aws-cdk-lib';
import { Token } from 'aws-cdk-lib';
import { IRole } from 'aws-cdk-lib/aws-iam';
import * as kinesis from 'aws-cdk-lib/aws-kinesis';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Properties for a Kinesis Data Streams Target
Expand Down Expand Up @@ -34,19 +33,7 @@ export class KinesisStreamPutRecord extends ScheduleTargetBase implements ISched
}
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
if (!sameEnvDimension(this.stream.env.region, schedule.env.region)) {
throw new Error(`Cannot assign stream in region ${this.stream.env.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the stream must be in the same region.`);
}

if (!sameEnvDimension(this.stream.env.account, schedule.env.account)) {
throw new Error(`Cannot assign stream in account ${this.stream.env.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the stream must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, this.stream.env.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(this.stream.node)} in account ${this.stream.env.account}. Both the target and the execution role must be in the same account.`);
}

protected addTargetActionToRole(role: IRole): void {
this.stream.grantWrite(role);
}

Expand All @@ -58,4 +45,4 @@ export class KinesisStreamPutRecord extends ScheduleTargetBase implements ISched
},
};
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IRole } from 'aws-cdk-lib/aws-iam';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
Expand All @@ -17,7 +17,7 @@ export class LambdaInvoke extends ScheduleTargetBase implements IScheduleTarget
this.func = func;
}

protected addTargetActionToRole(_schedule: ISchedule, role: IRole): void {
protected addTargetActionToRole(role: IRole): void {
this.func.grantInvoke(role);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { ISchedule, IScheduleTarget, ScheduleTargetConfig } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IRole } from 'aws-cdk-lib/aws-iam';
import { IPipeline } from 'aws-cdk-lib/aws-sagemaker';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Properties for a pipeline parameter
Expand Down Expand Up @@ -51,19 +49,7 @@ export class SageMakerStartPipelineExecution extends ScheduleTargetBase implemen
}
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
if (!sameEnvDimension(this.pipeline.stack.region, schedule.env.region)) {
throw new Error(`Cannot assign pipeline in region ${this.pipeline.stack.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the pipeline must be in the same region.`);
}

if (!sameEnvDimension(this.pipeline.stack.account, schedule.env.account)) {
throw new Error(`Cannot assign pipeline in account ${this.pipeline.stack.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the pipeline must be in the same account.`);
}

if (this.props.role && !sameEnvDimension(this.props.role.env.account, this.pipeline.stack.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(this.pipeline.node)} in account ${this.pipeline.stack.account}. Both the target and the execution role must be in the same account.`);
}

protected addTargetActionToRole(role: IRole): void {
this.pipeline.grantStartPipelineExecution(role);
}

Expand All @@ -81,4 +67,4 @@ export class SageMakerStartPipelineExecution extends ScheduleTargetBase implemen
sageMakerPipelineParameters,
};
}
}
}
23 changes: 3 additions & 20 deletions packages/@aws-cdk/aws-scheduler-targets-alpha/lib/sns-publish.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,20 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { IRole } from 'aws-cdk-lib/aws-iam';
import * as sns from 'aws-cdk-lib/aws-sns';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Use an Amazon SNS topic as a target for AWS EventBridge Scheduler.
*/
export class SnsPublish extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly topic: sns.ITopic,
private readonly props: ScheduleTargetBaseProps = {},
props: ScheduleTargetBaseProps = {},
) {
super(props, topic.topicArn);
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
// Check if target and schedule are in the region
if (!sameEnvDimension(this.topic.env.region, schedule.env.region)) {
throw new Error(`Cannot assign topic in region ${this.topic.env.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the topic must be in the same region.`);
}

// Check if target and schedule are in the same account
if (!sameEnvDimension(this.topic.env.account, schedule.env.account)) {
throw new Error(`Cannot assign topic in account ${this.topic.env.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${role.env.account}. Both the schedule and the topic must be in the same account.`);
}

// Check if target and role are in the same account
if (this.props.role && !sameEnvDimension(this.props.role.env.account, this.topic.env.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to publish to target ${Names.nodeUniqueId(this.topic.node)} in account ${this.topic.env.account}. Both the target and the execution role must be in the same account.`);
}

protected addTargetActionToRole(role: IRole): void {
this.topic.grantPublish(role);
}
}
Loading

0 comments on commit 1a8306f

Please sign in to comment.