wooden-morning-79874
08/18/2025, 5:09 PMprovider
argument I setup to pass through into the CDK related harness to just work , but it didn't. My provider is one which assumes a role in another account, and I need this to be able to deploy this CDK lib into different AWS accounts from a 'central' account. The default provider that the pulumi-cdk harness seems to use is therefore one with credentials from my 'central' account and everything gets deployed into that account, which is not my desired state.
Am I missing anything here, or is this a limitation that I'm not going to be able to get around? This issue seems to be the one I am facing: https://github.com/pulumi/pulumi-cdk/issues/61numerous-book-75463
08/18/2025, 5:12 PMwooden-morning-79874
08/18/2025, 5:21 PMwooden-morning-79874
08/18/2025, 5:28 PM<http://pulumicdk.App|pulumicdk.App>
constructor. However, the stack I'm creating in the <http://pulumicdk.App|pulumicdk.App>
callback seems to be going into the 'central' AWS account now. So I'm halfway there 😅wooden-morning-79874
08/18/2025, 5:34 PMimport * as aws from '@pulumi/aws';
import * as pulumi from '@pulumi/pulumi';
import * as pulumicdk from '@pulumi/cdk';
import { ConsumerInfraConstruct } from "@redacted/service-hub-consumer-infra";
import { ServiceHubEnvironment, ServiceHubManagementAccountId } from '../../types/service-hub';
interface ServiceHubTargetInfraStackOptions extends pulumicdk.StackOptions {
managementAccountId: ServiceHubManagementAccountId;
serviceHubS3BucketArn: string;
secretArn: string;
environment: ServiceHubEnvironment;
}
class ServiceHubInfraStack extends pulumicdk.Stack {
serviceRoleArn: pulumi.Output<string>;
constructor(scope: pulumicdk.App, id: string, options: ServiceHubTargetInfraStackOptions) {
super(scope, id, options);
const service = new ConsumerInfraConstruct(this, 'service', {
managementAccountId: options.managementAccountId,
serviceHubS3BucketArn: options.serviceHubS3BucketArn,
secretArn: options.secretArn,
environment: options.environment,
});
this.serviceRoleArn = this.asOutput(service.serviceRole.roleArn);
}
}
export class ServiceHubTargetInfraComponent extends pulumi.ComponentResource {
constructor(id: string, args: {
provider: aws.Provider,
serviceHubEnvironment: ServiceHubEnvironment,
}, opts?: pulumi.ComponentResourceOptions) {
// By calling super(), we ensure any instantiation of this class
// inherits from the ComponentResource class so we don't have to
// declare all the same things all over again.
super("pkg:index:ServiceHubTargetInfraComponent", id, args, opts);
const { provider, serviceHubEnvironment } = args;
// Work out service hub settings based on only one service hub setting (the serviceHubEnvironment), so that we reduce setting fatigue for users/cloud operations.
const managementAccountId = 'redacted';
const serviceHubS3BucketArn = 'redacted';
const secretArn = 'redacted';
// Pulumi's CDK adapter requires you to define an App and a Stack
const app = new pulumicdk.App('app', (scope: pulumicdk.App): pulumicdk.AppOutputs => {
const stack = new ServiceHubInfraStack(scope, 'service-hub-target-account-infra', {
managementAccountId: managementAccountId,
serviceHubS3BucketArn: serviceHubS3BucketArn,
secretArn: secretArn,
environment: serviceHubEnvironment,
provider: provider,
});
return {
serviceRoleArn: stack.serviceRoleArn,
};
}, {
// This is fine, since we are using a cross-account provider, and the stack is deployed in the desired target account.
provider: provider
});
// Register any Pulumi outputs from the stack if needed
this.registerOutputs({}); // This is required for a ComponentResource
}
}
numerous-book-75463
08/18/2025, 5:56 PMaws
provider and the aws-native
providerwooden-morning-79874
08/18/2025, 10:03 PMaws-native
?) and the other provider is what my 'central' account uses (and hosts the pulumi CDK policies bucket (e.g. pulumi-cdk-rol-policies-prod-staging...
) ?
I passed through both providers to the app and stack, and also set the props
on the stack to provide an explicit account
and region
to the cdk stack (as it looks like it becomes environment-agnostic after passing in more than one provider). This got me to a state where my target account received the expected CDK-defined resources, but my SNS topic resource failed to fully deploy with this error:
error: 1 error occurred:
* setting SNS Topic (arn:aws:sns:eu-west-1:123456789012:service-hub-build-status-changes) attribute (Policy): operation error SNS: SetTopicAttributes, https response error StatusCode: 403, RequestID: 123456-a513-5144-acdc-1762061ac1ff, AuthorizationError: User: arn:aws:sts::666666666666:assumed-role/AWSReservedSSO_redacted/redacted@redacted.com is not authorized to perform: SNS:SetTopicAttributes on resource: arn:aws:sns:eu-west-1:TARGET_ACCOUNT_ID_HERE:service-hub-build-status-changes because no resource-based policy allows the SNS:SetTopicAttributes action
This error suggests that the resource referred to (the SNS topic) is trying to be modified by my calling user account, which exists in my 'central' account - so somehow most CDK resources are being deployed by the aws-native
provider, but one part of those CDK resources are falling back to the aws
'central' account provider.
This is what that part of my CDK library code looks like:
const snsTopic = new Topic(this, 'CodeBuildProjectTopic', {
topicName: 'service-hub-build-status-changes',
});
snsTopic.addSubscription(new LambdaSubscription(lambda));
// add the <http://codestar-notifications.amazonaws.com|codestar-notifications.amazonaws.com> service principal to the sns topic
snsTopic.grantPublish(new ServicePrincipal('<http://codestar-notifications.amazonaws.com|codestar-notifications.amazonaws.com>'));
Any idea why this might be happening?numerous-book-75463
08/19/2025, 11:45 AMaws-native
provider, but some of the resources do not exist in aws-native
and are deployed with the aws
provider.
I know that the sns.Topic
resource is deployed with aws-native
and sns.TopicPolicy
is deployed with aws
.
Are you using the providers
option and passing both the aws-native
and aws
providers?wooden-morning-79874
08/19/2025, 12:37 PMproviders
option and passing both now, with them both being configured with my dynamic target account role that needs to be assumed. This got me there.
The last point I'm on now is trying to customise the staging bucket. I need my target accounts to be able to Get/List the assets in this (lambda pkgs etc), and noticed it is created in my 'central' account. I found that I could create a custom stack synthesizer, and specify the bucket name, and then pulumi-cdk seems to create that bucket + a random ID suffix.
For now, I've manually edited the bucket's policy to add a policy that allows any Account principal in my organization to have Get access which is working now, but it required that one manual intervention. Is there a way to customise this staging bucket's policy myself with pulumi?wooden-morning-79874
08/19/2025, 12:39 PM{
"Version": "2012-10-17",
"Id": "require-ssl",
"Statement": [
{
"Sid": "ssl",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::pulumi-cdk-staging-assets-access-123456789012-9f15c80",
"arn:aws:s3:::pulumi-cdk-staging-assets-access-123456789012-9f15c80/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Sid": "AllowOrgGetListAccess",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::pulumi-cdk-staging-assets-access-123456789012-9f15c80",
"arn:aws:s3:::pulumi-cdk-staging-assets-access-123456789012-9f15c80/*"
],
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-MYORGIDHERE"
}
}
}
]
}
numerous-book-75463
08/19/2025, 1:56 PMprivate
methods to protected
so that you can override them.wooden-morning-79874
08/19/2025, 2:33 PMconst stackSynthesizer = new pulumicdk.synthesizer.PulumiSynthesizer({
appId: `pulcdk-${pulumi.getStack()}`,
autoDeleteStagingAssets: true,
stagingBucketName: 'pulumi-cdk-staging-assets-for-access-123456789012',
// Note: this bucket is automatically created by Pulumi, and gets some random suffix added. I needed to manually edit the bucket resource policy
// to allow org-wide Get/List access to assets in the bucket so our target accounts can access the assets when pulumi-cdk the deploy-hub-infra stack to them.
// TODO: it would be nice to be able to set this bucket policy here on the stackSynthesizer.
});
I needed to dig into the .d.ts files to figure out that my import needed /synthesizer
added too.
Yes - that would be amazing if the private methods could be changed so that they are able to be overridden, specifically allowing customisation on the getCreateBucket
method options such as policy would be perfect - https://github.com/pulumi/pulumi-cdk/blob/ff43bfcbbd4ace37eaf8efd32f494193f4f9693a/src/synthesizer.ts#L318