@@ -5,6 +5,8 @@ import { stringType } from 'aws-sdk/clients/iam';
55import { PolicySummary } from 'aws-sdk/clients/organizations' ;
66import { OrganizationalUnit } from '@aws-accelerator/common-outputs/src/organizations' ;
77import { additionalReplacements , replaceDefaults } from './../util/common' ;
8+ import { AccountConfig } from '@aws-accelerator/common-config/src' ;
9+ import { Account } from '@aws-accelerator/common-outputs/src/accounts' ;
810
911export const FULL_AWS_ACCESS_POLICY_NAME = 'FullAWSAccess' ;
1012
@@ -266,6 +268,76 @@ export class ServiceControlPolicy {
266268 }
267269 }
268270
271+ /**
272+ * Attach new or detach removed policies based on the account configuration.
273+ */
274+ async attachOrDetachPoliciesToAccounts ( props : {
275+ existingPolicies : PolicySummary [ ] ;
276+ configurationAccounts : Account [ ] ;
277+ accountConfigs : [ string , AccountConfig ] [ ] ;
278+ acceleratorPrefix : string ;
279+ } ) {
280+ const { existingPolicies, configurationAccounts, accountConfigs, acceleratorPrefix } = props ;
281+
282+ for ( const [ accountKey , accountConfig ] of accountConfigs ) {
283+ const Account = configurationAccounts . find ( Account => Account . key === accountKey ) ;
284+ /**
285+ * Check if scps key is set on account. If not, ignore as SCPs are being managed in the outside the installer.
286+ */
287+ if ( accountConfig . scps == null ) {
288+ continue ;
289+ }
290+
291+ // Attach Accelerator SCPs to Accounts
292+ if ( ! Account ) {
293+ console . warn ( `Cannot find Account configuration with key "${ accountKey } "` ) ;
294+ continue ;
295+ }
296+
297+ const accountPolicyNames = accountConfig . scps . map ( policyName =>
298+ ServiceControlPolicy . policyNameToAcceleratorPolicyName ( { acceleratorPrefix, policyName } ) ,
299+ ) ;
300+
301+ if ( accountPolicyNames . length > 4 ) {
302+ console . warn ( `Maximum allowed SCP per Account is 5. Limit exceeded for Account ${ accountKey } ` ) ;
303+ continue ;
304+ }
305+
306+ // Find targets for this policy
307+ const policyTargets = await this . org . listPoliciesForTarget ( {
308+ Filter : 'SERVICE_CONTROL_POLICY' ,
309+ TargetId : Account . id ,
310+ } ) ;
311+
312+ // Detach removed policies
313+ for ( const policyTarget of policyTargets ) {
314+ const policyTargetName = policyTarget . Name ! ;
315+ if ( ! accountPolicyNames . includes ( policyTargetName ) && policyTargetName !== FULL_AWS_ACCESS_POLICY_NAME ) {
316+ console . log ( `Detaching ${ policyTargetName } from Account ${ accountKey } ` ) ;
317+ await this . org . detachPolicy ( policyTarget . Id ! , Account . id ) ;
318+ }
319+ }
320+
321+ // Attach new policies
322+ for ( const accountPolicyName of accountPolicyNames ) {
323+ const policy = existingPolicies . find ( p => p . Name === accountPolicyName ) ;
324+ if ( ! policy ) {
325+ console . warn ( `Cannot find policy with name "${ accountPolicyName } "` ) ;
326+ continue ;
327+ }
328+
329+ const policyTarget = policyTargets . find ( x => x . Name === accountPolicyName ) ;
330+ if ( policyTarget ) {
331+ console . log ( `Skipping attachment of ${ accountPolicyName } to already attached Account ${ accountKey } ` ) ;
332+ continue ;
333+ }
334+
335+ console . log ( `Attaching ${ accountPolicyName } to Account ${ accountKey } ` ) ;
336+ await this . org . attachPolicy ( policy . Id ! , Account . id ) ;
337+ }
338+ }
339+ }
340+
269341 static createQuarantineScpContent ( props : { acceleratorPrefix : string ; organizationAdminRole : string } ) {
270342 return JSON . stringify ( {
271343 Version : '2012-10-17' ,
0 commit comments