Skip to content

Commit b363bf5

Browse files
authored
Policy changes rule must only revert SCPs; not backup or tag policies (#1169)
1 parent b869c22 commit b363bf5

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

src/deployments/runtime/src/ou-validation-events/policy-changes.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,25 @@ export const handler = async (input: ScheduledEvent) => {
8383
return 'INVALID_REQUEST';
8484
}
8585

86-
if (await isControlTowerSCP(policyId)) {
87-
console.log('Policy Changes Performed by Control Tower, No operation required');
86+
// describe policy
87+
const policyResponse = await organizations.describePolicy(policyId);
88+
const policy = policyResponse.Policy;
89+
if (!policy) {
90+
console.error(`Invalid PolicyId provided ${policyId}`);
91+
return false;
92+
}
93+
94+
if (!isServiceControlPolicy(policy)) {
95+
console.log('The policy is NOT of type SERVICE_CONTROL_POLICY; No operation required');
96+
return 'NO_OPERATION_REQUIRED';
97+
}
98+
99+
if (isControlTowerSCP(policy)) {
100+
console.log('Policy Changes Performed by Control Tower; No operation required');
88101
return 'NO_OPERATION_REQUIRED';
89102
}
90103
const eventName = requestDetail.eventName;
91-
if (!['DeletePolicy', 'AttachPolicy'].includes(eventName) && !(await isAcceleratorScp(policyId, scpNames))) {
104+
if (!['DeletePolicy', 'AttachPolicy'].includes(eventName) && !isAcceleratorScp(policy, scpNames)) {
92105
console.log(`SCP ${policyId} is not managed by Accelerator`);
93106
return 'SUCCESS';
94107
}
@@ -155,15 +168,15 @@ export const handler = async (input: ScheduledEvent) => {
155168
);
156169
console.log(`SCP Names for Target are :: ${acclScpNames}`);
157170
if (eventName === 'AttachPolicy') {
158-
if (await isAcceleratorScp(policyId, acclScpNames)) {
171+
if (isAcceleratorScp(policy, acclScpNames)) {
159172
console.log('Accelerator Managed policy is attached');
160173
return 'IGNORE';
161174
}
162175
// Detach target from policy
163176
console.log(`Detaching target "${targetId}" from policy "${policyId}"`);
164177
await organizations.detachPolicy(policyId, targetId);
165178
} else {
166-
if (!(await isAcceleratorScp(policyId, acclScpNames))) {
179+
if (!isAcceleratorScp(policy, acclScpNames)) {
167180
console.log('Non Accelerator Managed policy is detached');
168181
return 'IGNORE';
169182
}
@@ -236,35 +249,44 @@ export const handler = async (input: ScheduledEvent) => {
236249
return 'SUCCESS';
237250
};
238251

239-
async function isAcceleratorScp(policyId: string, scpNames: string[]): Promise<boolean> {
240-
const policyResponse = await organizations.describePolicy(policyId);
241-
const policy = policyResponse.Policy;
242-
if (!policy) {
243-
console.error(`Invalid PolicyId provided ${policyId}`);
244-
return false;
245-
}
252+
function isAcceleratorScp(policy: any, scpNames: string[]): boolean {
246253
const policyName = policy.PolicySummary?.Name;
247254
if (!policyName) {
255+
console.error(`isAcceleratorScp - Invalid policy name`);
248256
return false;
249257
}
250-
if (policyName !== FULL_AWS_ACCESS_POLICY_NAME && !scpNames.includes(policy.PolicySummary?.Name!)) {
258+
if (policyName !== FULL_AWS_ACCESS_POLICY_NAME && !scpNames.includes(policyName!)) {
251259
console.error(`Policy is not handled through Accelerator`);
252260
return false;
253261
}
254262
return true;
255263
}
256264

257-
async function isControlTowerSCP(policyId: string): Promise<boolean> {
258-
const policyResponse = await organizations.describePolicy(policyId);
259-
const policy = policyResponse.Policy;
260-
265+
function isControlTowerSCP(policy: any): boolean {
261266
const policyName = policy?.PolicySummary?.Name;
262267
if (policyName?.startsWith('aws-guardrails-')) {
263268
return true;
264269
}
265270
return false;
266271
}
267272

273+
/**
274+
* Checks if the policy type is SERVICE_CONTROL_POLICY.
275+
* @see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/organizations.html#Organizations.Client.describe_policy
276+
*/
277+
function isServiceControlPolicy(policy: any): boolean {
278+
const policyType: string = policy?.PolicySummary?.Type;
279+
if (!policyType) {
280+
console.error(`isServiceControlPolicy - Invalid policy type`);
281+
return false;
282+
}
283+
console.log(`isServiceControlPolicy - Policy type : ${policyType}`);
284+
if (policyType === 'SERVICE_CONTROL_POLICY') {
285+
return true;
286+
}
287+
return false;
288+
}
289+
268290
async function loadAccountsAndOrganizationsFromConfig(
269291
config: AcceleratorConfig,
270292
): Promise<{ organizationalUnits: OrganizationalUnit[]; accounts: ConfigurationAccount[] }> {

0 commit comments

Comments
 (0)