Skip to content

Commit

Permalink
feat: add aws cn support (#1722)
Browse files Browse the repository at this point in the history
Fixes #1547 snapshots
  • Loading branch information
mergify[bot] authored Dec 18, 2024
2 parents a4de737 + c3c5770 commit 8640eed
Show file tree
Hide file tree
Showing 28 changed files with 94 additions and 54 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ AWS Organizations has some limitations:

> AWS Organizations is a global service with service endpoints in `us-east-1`, `us-gov-west-1` and `cn-northwest-1`. Read also
> [Endpoint to call When using the AWS CLI or the AWS SDK](https://docs.aws.amazon.com/organizations/latest/APIReference/Welcome.html).
> Currently all custom resources of this library are hard set to use `us-east-1`.
> Currently all custom resources of this library defaults to use `us-east-1`, but it can be configured to use `cn-northwest-1`
> with the environment variable `CDK_AWS_PARTITION` set to `aws-cn`.
## Example

Expand Down
8 changes: 8 additions & 0 deletions src/account-provider/account-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ export class AccountProvider extends NestedStack {
constructor(scope: Construct, id: string, props: AccountProviderProps) {
super(scope, id, props);

const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

this.onEventHandler = new OnEventHandlerFunction(this, "OnEventHandlerFunction", {
environment: {
ORGANIZATIONS_ENDPOINT_REGION: organizationsRegion,
},
timeout: Duration.minutes(10),
initialPolicy: [
new PolicyStatement({
Expand All @@ -57,6 +62,9 @@ export class AccountProvider extends NestedStack {
});

this.isCompleteHandler = new IsCompleteHandlerFunction(this, "IsCompleteHandlerFunction", {
environment: {
ORGANIZATIONS_ENDPOINT_REGION: organizationsRegion,
},
timeout: Duration.minutes(1),
initialPolicy: [
new PolicyStatement({
Expand Down
3 changes: 2 additions & 1 deletion src/account-provider/is-complete-handler.lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as AWS from "aws-sdk";
import { Organizations } from "aws-sdk";

let organizationsClient: AWS.Organizations;
const organizationsRegion = process.env.ORGANIZATIONS_ENDPOINT_REGION ?? "us-east-1";

/**
* The isComplete handler is repeatedly invoked checking CreateAccountStatus until SUCCEEDED or FAILED.
Expand All @@ -15,7 +16,7 @@ export async function handler(event: IsCompleteRequest): Promise<IsCompleteRespo
console.log(`Request of type ${event.RequestType} received`);

if (!organizationsClient) {
organizationsClient = new AWS.Organizations({ region: "us-east-1" });
organizationsClient = new AWS.Organizations({ region: organizationsRegion });
}

console.log("Payload: %j", event);
Expand Down
3 changes: 2 additions & 1 deletion src/account-provider/on-event-handler.lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CdkCustomResourceEvent as OnEventRequest, CdkCustomResourceResponse as
import { Organizations } from "aws-sdk";

let organizationsClient: Organizations;
const organizationsRegion = process.env.ORGANIZATIONS_ENDPOINT_REGION ?? "us-east-1";

/**
* The onEvent handler is invoked whenever a resource lifecycle event for an Account occurs
Expand All @@ -12,7 +13,7 @@ export async function handler(event: OnEventRequest): Promise<OnEventResponse> {
console.log(`Request of type ${event.RequestType} received`);

if (!organizationsClient) {
organizationsClient = new Organizations({ region: "us-east-1" });
organizationsClient = new Organizations({ region: organizationsRegion });
}

console.log("Payload: %j", event);
Expand Down
3 changes: 2 additions & 1 deletion src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ export class Account extends Construct implements IAccount, ITaggableResource {
* @param {DelegatedAdministratorProps} props additional DelegatedAdministrator props
*/
public delegateAdministrator(servicePrincipal: string, region?: string, props: Record<string, any> = {}) {
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";
const delegatedAdministrator = new DelegatedAdministrator(
this.scope,
`Delegate${pascalCase(servicePrincipal)}${
region && region !== "us-east-1" ? `-${region}` : ""
region && region !== organizationsRegion ? `-${region}` : ""
}-${Names.nodeUniqueId(this.node)}`,
{
...props,
Expand Down
5 changes: 3 additions & 2 deletions src/delegated-administrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ export class DelegatedAdministrator extends Construct {
super(scope, id);

const { account, servicePrincipal, region } = props;
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

new AwsCustomResource(this, "DelegatedAdministratorCustomResource", {
resourceType: "Custom::Organizations_DelegatedAdministrator",
onCreate: {
service: "Organizations",
action: "registerDelegatedAdministrator", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#registerDelegatedAdministrator-property
region: region ?? "us-east-1",
region: region ?? organizationsRegion,
physicalResourceId: PhysicalResourceId.of(`${account.accountId}:${servicePrincipal}`),
parameters: {
AccountId: account.accountId,
Expand All @@ -56,7 +57,7 @@ export class DelegatedAdministrator extends Construct {
onDelete: {
service: "Organizations",
action: "deregisterDelegatedAdministrator", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#deregisterDelegatedAdministrator-property
region: region ?? "us-east-1",
region: region ?? organizationsRegion,
parameters: {
AccountId: account.accountId,
ServicePrincipal: servicePrincipal,
Expand Down
5 changes: 3 additions & 2 deletions src/enable-aws-service-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ export class EnableAwsServiceAccess extends Construct {
super(scope, id);

const { servicePrincipal } = props;
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

new AwsCustomResource(this, "EnableAwsServiceAccessCustomResource", {
resourceType: "Custom::Organizations_EnableAwsServiceAccess",
onCreate: {
service: "Organizations",
action: "enableAWSServiceAccess", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#enableAWSServiceAccess-property
region: "us-east-1",
region: organizationsRegion,
physicalResourceId: PhysicalResourceId.of(`${servicePrincipal}`),
parameters: {
ServicePrincipal: servicePrincipal,
Expand All @@ -35,7 +36,7 @@ export class EnableAwsServiceAccess extends Construct {
onDelete: {
service: "Organizations",
action: "disableAWSServiceAccess", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#disableAWSServiceAccess-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
ServicePrincipal: servicePrincipal,
},
Expand Down
5 changes: 3 additions & 2 deletions src/enable-policy-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ export class EnablePolicyType extends Construct {
super(scope, id);

const { root, policyType } = props;
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

new AwsCustomResource(this, "EnablePolicyTypeCustomResource", {
resourceType: "Custom::Organizations_EnablePolicyType",
onCreate: {
service: "Organizations",
action: "enablePolicyType", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#enablePolicyType-property
region: "us-east-1",
region: organizationsRegion,
physicalResourceId: PhysicalResourceId.of(`${root.rootId}:${policyType}`),
parameters: {
RootId: root.rootId,
Expand All @@ -35,7 +36,7 @@ export class EnablePolicyType extends Construct {
onDelete: {
service: "Organizations",
action: "disablePolicyType", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#disablePolicyType-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
RootId: root.rootId,
PolicyType: policyType,
Expand Down
3 changes: 2 additions & 1 deletion src/organization-provider/on-event-handler.lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CdkCustomResourceEvent as OnEventRequest, CdkCustomResourceResponse as
import { AWSError, Organizations } from "aws-sdk";

let organizationsClient: Organizations;
const organizationsRegion = process.env.ORGANIZATIONS_ENDPOINT_REGION ?? "us-east-1";

/**
* The onEvent handler is invoked whenever a resource lifecycle event for an organization occurs
Expand All @@ -12,7 +13,7 @@ export async function handler(event: OnEventRequest): Promise<OnEventResponse> {
console.log(`Request of type ${event.RequestType} received`);

if (!organizationsClient) {
organizationsClient = new Organizations({ region: "us-east-1" });
organizationsClient = new Organizations({ region: organizationsRegion });
}

console.log("Payload: %j", event);
Expand Down
9 changes: 7 additions & 2 deletions src/organization-provider/organization-provider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Duration, NestedStack, NestedStackProps, Stack } from "aws-cdk-lib";
import { Aws, Duration, NestedStack, NestedStackProps, Stack } from "aws-cdk-lib";
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
import { Function } from "aws-cdk-lib/aws-lambda";
import { Provider } from "aws-cdk-lib/custom-resources";
Expand Down Expand Up @@ -44,7 +44,12 @@ export class OrganizationProvider extends NestedStack {
constructor(scope: Construct, id: string, props: OrganizationProviderProps) {
super(scope, id, props);

const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

this.onEventHandler = new OnEventHandlerFunction(this, "OnEventHandlerFunction", {
environment: {
ORGANIZATIONS_ENDPOINT_REGION: organizationsRegion,
},
timeout: Duration.minutes(10),
initialPolicy: [
new PolicyStatement({
Expand All @@ -54,7 +59,7 @@ export class OrganizationProvider extends NestedStack {
// permit the creation of service-linked role https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_create.html#create-org
new PolicyStatement({
actions: ["iam:CreateServiceLinkedRole"],
resources: ["arn:aws:iam::*:role/*"],
resources: [`arn:${Aws.PARTITION}:iam::*:role/*`],
}),
],
});
Expand Down
14 changes: 9 additions & 5 deletions src/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,21 @@ export class Organization extends Construct implements IOrganization {
public constructor() {
super(scope, id);

const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

const resource = new custom_resources.AwsCustomResource(scope, "CustomResource", {
resourceType: "Custom::Organizations_ImportOrganization",
onCreate: {
service: "Organizations",
action: "describeOrganization", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#describeOrganization-property
region: "us-east-1",
region: organizationsRegion,
parameters: {},
physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("Organization.Id"),
},
onUpdate: {
service: "Organizations",
action: "describeOrganization", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#describeOrganization-property
region: "us-east-1",
region: organizationsRegion,
parameters: {},
physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("Organization.Id"),
},
Expand Down Expand Up @@ -227,24 +229,26 @@ export class Root extends Construct implements IParent, IPolicyAttachmentTarget,
super(scope, id);
this.scope = scope;

const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

this.resource = new custom_resources.AwsCustomResource(this, "RootCustomResource", {
resourceType: "Custom::Organizations_Root",
onCreate: {
service: "Organizations",
action: "listRoots", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listRoots-property
region: "us-east-1",
region: organizationsRegion,
physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("Roots.0.Id"),
},
onUpdate: {
service: "Organizations",
action: "listRoots", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listRoots-property
region: "us-east-1",
region: organizationsRegion,
physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("Roots.0.Id"),
},
onDelete: {
service: "Organizations",
action: "listRoots", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listRoots-property
region: "us-east-1",
region: organizationsRegion,
},
installLatestAwsSdk: false,
policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({
Expand Down
3 changes: 2 additions & 1 deletion src/organizational-unit-provider/on-event-handler.lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CdkCustomResourceEvent as OnEventRequest, CdkCustomResourceResponse as
import { AWSError, Organizations } from "aws-sdk";

let organizationsClient: Organizations;
const organizationsRegion = process.env.ORGANIZATIONS_ENDPOINT_REGION ?? "us-east-1";

/**
* The onEvent handler is invoked whenever a resource lifecycle event for an organizational unit occurs
Expand All @@ -12,7 +13,7 @@ export const handler = async (event: OnEventRequest): Promise<OnEventResponse> =
console.log(`Request of type ${event.RequestType} received`);

if (!organizationsClient) {
organizationsClient = new Organizations({ region: "us-east-1" });
organizationsClient = new Organizations({ region: organizationsRegion });
}

console.log("Payload: %j", event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ export class OrganizationalUnitProvider extends NestedStack {
constructor(scope: Construct, id: string, props: OrganizationalUnitProviderProps) {
super(scope, id, props);

const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

this.onEventHandler = new OnEventHandlerFunction(this, "OnEventHandlerFunction", {
environment: {
ORGANIZATIONS_ENDPOINT_REGION: organizationsRegion,
},
timeout: Duration.minutes(10),
initialPolicy: [
new PolicyStatement({
Expand Down
7 changes: 4 additions & 3 deletions src/parent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ export abstract class ParentBase extends Construct implements IParent {
super(scope, id);

const { childId } = props;
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

const parent = new AwsCustomResource(this, "ListParentsCustomResource", {
onCreate: {
service: "Organizations",
action: "listParents", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listParents-property
region: "us-east-1",
region: organizationsRegion,
physicalResourceId: PhysicalResourceId.fromResponse("Parents.0.Id"),
parameters: {
ChildId: childId,
Expand All @@ -35,7 +36,7 @@ export abstract class ParentBase extends Construct implements IParent {
onUpdate: {
service: "Organizations",
action: "listParents", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listParents-property
region: "us-east-1",
region: organizationsRegion,
physicalResourceId: PhysicalResourceId.fromResponse("Parents.0.Id"),
parameters: {
ChildId: childId,
Expand All @@ -44,7 +45,7 @@ export abstract class ParentBase extends Construct implements IParent {
onDelete: {
service: "Organizations",
action: "listParents", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#listParents-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
ChildId: childId,
},
Expand Down
5 changes: 3 additions & 2 deletions src/policy-attachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ export class PolicyAttachment extends Construct {
super(scope, id);

const { target, policy } = props;
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

new AwsCustomResource(this, "CustomResource", {
resourceType: "Custom::Organizations_PolicyAttachment",
onCreate: {
service: "Organizations",
action: "attachPolicy", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#attachPolicy-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
PolicyId: policy.policyId,
TargetId: target.identifier(),
Expand All @@ -40,7 +41,7 @@ export class PolicyAttachment extends Construct {
onDelete: {
service: "Organizations",
action: "detachPolicy", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#detachPolicy-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
PolicyId: policy.policyId,
TargetId: target.identifier(),
Expand Down
7 changes: 4 additions & 3 deletions src/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class Policy extends Construct implements IPolicy, ITaggableResource {
super(scope, id);

const { content, description, policyName, policyType } = props;
const organizationsRegion = process.env.CDK_AWS_PARTITION === "aws-cn" ? "cn-northwest-1" : "us-east-1";

if (!Validators.of().policyContent(content)) {
Annotations.of(this).addError(
Expand All @@ -92,7 +93,7 @@ export class Policy extends Construct implements IPolicy, ITaggableResource {
onCreate: {
service: "Organizations",
action: "createPolicy", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#createPolicy-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
Content: content,
Description: description,
Expand All @@ -105,7 +106,7 @@ export class Policy extends Construct implements IPolicy, ITaggableResource {
onUpdate: {
service: "Organizations",
action: "updatePolicy", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#updatePolicy-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
Content: content,
Description: description,
Expand All @@ -118,7 +119,7 @@ export class Policy extends Construct implements IPolicy, ITaggableResource {
onDelete: {
service: "Organizations",
action: "deletePolicy", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#deletePolicy-property
region: "us-east-1",
region: organizationsRegion,
parameters: {
PolicyId: new PhysicalResourceIdReference(),
},
Expand Down
3 changes: 2 additions & 1 deletion src/tag-resource-provider/on-event-handler.lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CdkCustomResourceEvent as OnEventRequest, CdkCustomResourceResponse as
import { Organizations } from "aws-sdk";

let organizationsClient: Organizations;
const organizationsRegion = process.env.ORGANIZATIONS_ENDPOINT_REGION ?? "us-east-1";

/**
* The onEvent handler is invoked whenever a resource lifecycle event for a TagResource occurs
Expand All @@ -12,7 +13,7 @@ export async function handler(event: OnEventRequest): Promise<OnEventResponse> {
console.log(`Request of type ${event.RequestType} received`);

if (!organizationsClient) {
organizationsClient = new Organizations({ region: "us-east-1" });
organizationsClient = new Organizations({ region: organizationsRegion });
}

console.log("Payload: %j", event);
Expand Down
Loading

0 comments on commit 8640eed

Please sign in to comment.