aws / aws/aws-cdk

aws-scheduler: ScheduleGroup.grantReadSchedules scopes ListSchedules to group ARN, but Scheduler authorizes schedule/*/*

Open
#38,201 2 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-scheduler bug effort/small p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

## Describe the bug

`ScheduleGroup.grantReadSchedules()` grants `scheduler:ListSchedules` on a group-scoped schedule ARN:

```json
{
"Action": [
"scheduler:CreateSchedule",
"scheduler:GetSchedule",
"scheduler:ListSchedules",
"scheduler:UpdateSchedule"
],
"Resource": "arn:aws:scheduler:::schedule//*",
"Effect": "Allow"
}
```

However, a call to `ListSchedules` with `ScheduleGroup=` fails with an IAM denial on `schedule/*/*`:

```text
User: arn:aws:sts:::assumed-role//
is not authorized to perform: scheduler:ListSchedules on resource:
arn:aws:scheduler:::schedule/*/*
because no identity-based policy allows the scheduler:ListSchedules action
```

This is different from https://github.com/aws/aws-cdk/issues/36165. That issue was about CDK generating `schedule-group//*` instead of `schedule//*`. In this case, CDK generates the expected group-scoped schedule ARN, but EventBridge Scheduler still evaluates `ListSchedules` against `schedule/*/*`.

## Regression Issue

- [ ] Select this option if this issue appears to be a regression.

## Last Known Working CDK Library Version

Not known.

## Expected Behavior

Either:

- `ScheduleGroup.grantReadSchedules()` should grant `scheduler:ListSchedules` on a resource shape accepted by EventBridge Scheduler, or
- `ListSchedules` should not be included in the group-scoped grant if it cannot be scoped to a schedule group.

## Current Behavior

CDK grants `ListSchedules` on:

```text
arn:aws:scheduler:::schedule//*
```

but EventBridge Scheduler authorizes the call against:

```text
arn:aws:scheduler:::schedule/*/*
```

Observed stack trace:

```text
Amazon.Scheduler.AmazonSchedulerException: User: arn:aws:sts:::assumed-role// is not authorized to perform: scheduler:ListSchedules on resource: arn:aws:scheduler:::schedule/*/* because no identity-based policy allows the scheduler:ListSchedules action
---> Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.
at Amazon.Runtime.HttpWebRequestMessage.ProcessHttpResponseMessage(HttpResponseMessage responseMessage)
at Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken)
at Amazon.Runtime.Internal.HttpHandler`1.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.Unmarshaller.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext)
--- End of inner exception stack trace ---
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionStream(IRequestContext requestContext, IWebResponseData httpErrorResponse, HttpErrorResponseException exception, Stream responseStream)
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionAsync(IExecutionContext executionContext, HttpErrorResponseException exception)
at Amazon.Runtime.Internal.ExceptionHandler`1.HandleAsync(IExecutionContext executionContext, Exception exception)
at Amazon.Runtime.Internal.ErrorHandler.ProcessExceptionAsync(IExecutionContext executionContext, Exception exception)
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.Signer.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.BaseAuthResolverHandler.InvokeAsync[T](IExecutionContext executionContext)
at Amazon.Runtime.Internal.Marshaller.InvokeAsync[T](IExecutionContext executionContext)
```

## Reproduction Steps

Create a schedule group and grant read schedules to a Lambda role:

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

const group = new scheduler.ScheduleGroup(this, 'Group', {
scheduleGroupName: 'my-group',
});

group.grantReadSchedules(myFunction);
```

This grants `scheduler:ListSchedules` on:

```text
arn:aws:scheduler:::schedule/my-group/*
```

Then call `ListSchedules` with the group filter.

Equivalent .NET SDK call:

```csharp
await schedulerClient.ListSchedulesAsync(new ListSchedulesRequest
{
GroupName = "my-group"
});
```

The .NET SDK marshaller sends:

```text
GET /schedules?ScheduleGroup=my-group
```

but the service denies access unless the role also has `scheduler:ListSchedules` on `schedule/*/*` or `*`.

## Possible Solution

Grant `scheduler:ListSchedules` separately on `*` / `schedule/*/*`, or remove it from `ScheduleGroup.grantReadSchedules()` and document that listing schedules is not group-resource-scoped.

The EventBridge Scheduler API reference documents `ScheduleGroup` as a query filter for `ListSchedules`:

https://docs.aws.amazon.com/scheduler/latest/APIReference/API_ListSchedules.html

The IAM service authorization reference does not list a resource type for `ListSchedules`, which may mean this action should require `Resource: "*"`:

https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoneventbridgescheduler.html

## Additional Information/Context

Actual generated permission:

```json
{
"Action": [
"scheduler:CreateSchedule",
"scheduler:GetSchedule",
"scheduler:ListSchedules",
"scheduler:UpdateSchedule"
],
"Resource": "arn:aws:scheduler:eu-central-1::schedule//*",
"Effect": "Allow"
}
```

The Lambda environment variable used for the SDK request is set to the same group name:

```text
SchedulerGroupOrderCreationSchedule=
```

The AWS SDK .NET marshaller was checked locally and produced:

```text
ResourcePath=/schedules
HttpMethod=GET
UseQueryString=True
Parameters:
ScheduleGroup=
```

## AWS CDK Library version (aws-cdk-lib)

`Amazon.CDK.Lib 2.235.1` (.NET package; this project does not use `npm ls aws-cdk-lib`).

## AWS CDK CLI version

```text
2.1126.0 (build a90d578)
```

## Node.js Version

```text
v24.15.0
```

## OS

```text
Windows
```

## Language

```text
.NET
```

## Language Version

```text
.NET SDK 10.0.301
```

## Other information

Related issue with a different root cause: https://github.com/aws/aws-cdk/issues/36165

Contributor guide

Open the contributing guide

Research direction

Start by inspecting ScheduleGroup.grantReadSchedules() in the AWS CDK scheduler implementation and its associated tests, then compare the generated policy with the EventBridge Scheduler IAM service authorization reference. Reproduce the ListSchedules call using the group filter and verify that the completed change either grants a service-accepted resource or excludes the action from the group-scoped grant.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.