-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #97 from vibe-io/task/aws-config-security
feat: Task/aws config security
- Loading branch information
Showing
22 changed files
with
7,203 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { ResourceProps } from 'aws-cdk-lib'; | ||
import { ManagedRule, MaximumExecutionFrequency } from 'aws-cdk-lib/aws-config'; | ||
import { Effect, ManagedPolicy, PolicyStatement, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; | ||
import { IConstruct } from 'constructs'; | ||
import { RemediationTarget } from '../config/lib'; | ||
import { RemediationConfiguration } from '../config/remediation-configuration'; | ||
import { AutomationDocument } from '../ssm'; | ||
|
||
|
||
export interface IamPasswordPolicyProps extends ResourceProps { | ||
readonly autoRemediation?: boolean; | ||
readonly configRuleName?: string; | ||
readonly description?: string; | ||
readonly maxPasswordAge?: number; | ||
readonly maximumExecutionFrequency?: MaximumExecutionFrequency; | ||
readonly minimumPasswordLength?: number; | ||
readonly passwordReusePrevention?: number; | ||
readonly requireLowercaseCharacters?: boolean; | ||
readonly requireNumbers?: boolean; | ||
readonly requireSymbols?: boolean; | ||
readonly requireUppercaseCharacters?: boolean; | ||
} | ||
|
||
export class IamPasswordPolicy extends ManagedRule { | ||
static readonly DEFAULT_DESCRIPTION: string = [ | ||
'Checks if the account password policy for AWS Identity and Access', | ||
'Management (IAM) users meets the specified requirements indicated in the', | ||
'parameters. The rule is NON_COMPLIANT if the account password policy', | ||
'does not meet the specified requirements.', | ||
].join(' '); | ||
static readonly DEFAULT_MAX_PASSWORD_AGE: number = 90; | ||
static readonly DEFAULT_MINIMUM_PASSWORD_LENGTH: number = 14; | ||
static readonly DEFAULT_PASSWORD_REUSE_PREVENTION: number = 24; | ||
static readonly DEFAULT_REQUIRE_LOWERCASE_CHARACTERS: boolean = true; | ||
static readonly DEFAULT_REQUIRE_NUMBERS: boolean = true; | ||
static readonly DEFAULT_REQUIRE_SYMBOLS: boolean = true; | ||
static readonly DEFAULT_REQUIRE_UPPERCASE_CHARACTERS: boolean = true; | ||
static readonly MANAGED_RULE_NAME: string = 'IAM_PASSWORD_POLICY'; | ||
static readonly REMEDIATION_DOCUMENT_NAME: string = 'AWSConfigRemediation-SetIAMPasswordPolicy'; | ||
|
||
|
||
readonly maxPasswordAge: number; | ||
readonly minimumPasswordLength: number; | ||
readonly passwordReusePrevention: number; | ||
readonly requireLowercaseCharacters: boolean; | ||
readonly requireNumbers: boolean; | ||
readonly requireSymbols: boolean; | ||
readonly requireUppercaseCharacters: boolean; | ||
readonly remediationConfiguration: RemediationConfiguration; | ||
readonly remediationPolicy: ManagedPolicy; | ||
readonly remediationRole: Role; | ||
|
||
|
||
public constructor(scope: IConstruct, id: string, props: IamPasswordPolicyProps) { | ||
const managedRuleName = IamPasswordPolicy.MANAGED_RULE_NAME; | ||
const maxPasswordAge = props.maxPasswordAge ?? IamPasswordPolicy.DEFAULT_MAX_PASSWORD_AGE; | ||
const minimumPasswordLength = props.minimumPasswordLength ?? IamPasswordPolicy.DEFAULT_MINIMUM_PASSWORD_LENGTH; | ||
const passwordReusePrevention = props.passwordReusePrevention ?? IamPasswordPolicy.DEFAULT_PASSWORD_REUSE_PREVENTION; | ||
const requireLowercaseCharacters = props.requireLowercaseCharacters ?? IamPasswordPolicy.DEFAULT_REQUIRE_UPPERCASE_CHARACTERS; | ||
const requireNumbers = props.requireNumbers ?? IamPasswordPolicy.DEFAULT_REQUIRE_NUMBERS; | ||
const requireSymbols = props.requireSymbols ?? IamPasswordPolicy.DEFAULT_REQUIRE_SYMBOLS; | ||
const requireUppercaseCharacters = props.requireUppercaseCharacters ?? IamPasswordPolicy.DEFAULT_REQUIRE_UPPERCASE_CHARACTERS; | ||
|
||
super(scope, id, { | ||
configRuleName: props.configRuleName, | ||
description: props.description ?? IamPasswordPolicy.DEFAULT_DESCRIPTION, | ||
identifier: managedRuleName, | ||
inputParameters: { | ||
MaxPasswordAge: maxPasswordAge, | ||
MinimumPasswordLength: minimumPasswordLength, | ||
PasswordReusePrevention: passwordReusePrevention, | ||
RequireLowercaseCharacters: requireLowercaseCharacters, | ||
RequireNumbers: requireNumbers, | ||
RequireSymbols: requireSymbols, | ||
RequireUppercaseCharacters: requireUppercaseCharacters, | ||
}, | ||
maximumExecutionFrequency: props.maximumExecutionFrequency, | ||
}); | ||
|
||
this.maxPasswordAge = maxPasswordAge; | ||
this.minimumPasswordLength = minimumPasswordLength; | ||
this.passwordReusePrevention = passwordReusePrevention; | ||
this.requireLowercaseCharacters = requireLowercaseCharacters; | ||
this.requireNumbers = requireNumbers; | ||
this.requireSymbols = requireSymbols; | ||
this.requireUppercaseCharacters = requireUppercaseCharacters; | ||
|
||
const description = [ | ||
`Allows remdiation of of a non-compliant '${managedRuleName}' AWS`, | ||
'Config rule finding.', | ||
].join(' '); | ||
|
||
this.remediationPolicy = new ManagedPolicy(this, 'remediation-policy', { | ||
description: description, | ||
path: '/config/', | ||
statements: [ | ||
new PolicyStatement({ | ||
actions: [ | ||
'iam:GetAccountPasswordPolicy', | ||
'iam:UpdateAccountPasswordPolicy', | ||
], | ||
effect: Effect.ALLOW, | ||
resources: [ | ||
'*', | ||
], | ||
}), | ||
], | ||
}); | ||
|
||
this.remediationRole = new Role(this, 'remediation-role', { | ||
assumedBy: new ServicePrincipal('ssm.amazonaws.com'), | ||
description: description, | ||
managedPolicies: [ | ||
this.remediationPolicy, | ||
], | ||
}); | ||
|
||
this.remediationConfiguration = new RemediationConfiguration(this, 'remediation-configuration', { | ||
configRule: this, | ||
staticParameters: { | ||
AutomationAssumeRole: [ | ||
this.remediationRole.roleArn, | ||
], | ||
MaxPasswordAge: [ | ||
maxPasswordAge, | ||
], | ||
MinimumPasswordLength: [ | ||
minimumPasswordLength, | ||
], | ||
PasswordReusePrevention: [ | ||
passwordReusePrevention, | ||
], | ||
RequireLowercaseCharacters: [ | ||
requireLowercaseCharacters, | ||
], | ||
RequireNumbers: [ | ||
requireNumbers, | ||
], | ||
RequireSymbols: [ | ||
requireSymbols, | ||
], | ||
RequireUppercaseCharacters: [ | ||
requireUppercaseCharacters, | ||
], | ||
}, | ||
target: RemediationTarget.automationDocument({ | ||
document: AutomationDocument.fromManaged(this, 'remediation-document', IamPasswordPolicy.REMEDIATION_DOCUMENT_NAME), | ||
}), | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './iam-password-policy'; | ||
export * from './vpc-default-security-group-closed'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { ArnFormat, ResourceProps } from 'aws-cdk-lib'; | ||
import { ManagedRule, MaximumExecutionFrequency, ResourceType, RuleScope } from 'aws-cdk-lib/aws-config'; | ||
import { Effect, ManagedPolicy, PolicyStatement, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; | ||
import { IConstruct } from 'constructs'; | ||
import { RemediationTarget } from '../config/lib'; | ||
import { RemediationConfiguration } from '../config/remediation-configuration'; | ||
import { AutomationDocument } from '../ssm'; | ||
|
||
|
||
export interface VpcDefaultSecurityGroupClosedProps extends ResourceProps { | ||
readonly autoRemediation?: boolean; | ||
readonly configRuleName?: string; | ||
readonly description?: string; | ||
readonly maximumExecutionFrequency?: MaximumExecutionFrequency; | ||
} | ||
|
||
export class VpcDefaultSecurityGroupClosed extends ManagedRule { | ||
public static readonly DEFAULT_DESCRIPTION: string = [ | ||
'Checks if the default security group of any Amazon Virtual Private Cloud', | ||
'(Amazon VPC) does not allow inbound or outbound traffic. The rule is', | ||
'NON_COMPLIANT if the default security group has one or more inbound or', | ||
'outbound traffic rules.', | ||
].join(' '); | ||
public static readonly MANAGED_RULE_NAME: string = 'VPC_DEFAULT_SECURITY_GROUP_CLOSED'; | ||
public static readonly REMEDIATION_DOCUMENT_NAME: string = 'AWSConfigRemediation-RemoveVPCDefaultSecurityGroupRules'; | ||
|
||
public readonly remediationConfiguration: RemediationConfiguration; | ||
public readonly remediationPolicy: ManagedPolicy; | ||
public readonly remediationRole: Role; | ||
|
||
|
||
public constructor(scope: IConstruct, id: string, props: VpcDefaultSecurityGroupClosedProps) { | ||
const managedRuleName = VpcDefaultSecurityGroupClosed.MANAGED_RULE_NAME; | ||
|
||
super(scope, id, { | ||
configRuleName: props.configRuleName, | ||
description: props.description ?? VpcDefaultSecurityGroupClosed.DEFAULT_DESCRIPTION, | ||
identifier: managedRuleName, | ||
maximumExecutionFrequency: props.maximumExecutionFrequency, | ||
ruleScope: RuleScope.fromResource(ResourceType.EC2_SECURITY_GROUP), | ||
}); | ||
|
||
const description = [ | ||
`Allows remdiation of of a non-compliant '${managedRuleName}' AWS`, | ||
'Config rule finding.', | ||
].join(' '); | ||
|
||
this.remediationPolicy = new ManagedPolicy(this, 'remediation-policy', { | ||
description: description, | ||
path: '/config/', | ||
statements: [ | ||
new PolicyStatement({ | ||
actions: [ | ||
'ec2:DescribeSecurityGroups', | ||
], | ||
effect: Effect.ALLOW, | ||
resources: [ | ||
'*', | ||
], | ||
}), | ||
new PolicyStatement({ | ||
actions: [ | ||
'ec2:RevokeSecurityGroupEgress', | ||
'ec2:RevokeSecurityGroupIngress', | ||
], | ||
effect: Effect.ALLOW, | ||
resources: [ | ||
this.stack.formatArn({ | ||
arnFormat: ArnFormat.SLASH_RESOURCE_NAME, | ||
resource: 'security-group', | ||
resourceName: '*', | ||
service: 'ec2', | ||
}), | ||
], | ||
}), | ||
], | ||
}); | ||
|
||
this.remediationRole = new Role(this, 'remediation-role', { | ||
assumedBy: new ServicePrincipal('ssm.amazonaws.com'), | ||
description: description, | ||
managedPolicies: [ | ||
this.remediationPolicy, | ||
], | ||
}); | ||
this.remediationConfiguration = new RemediationConfiguration(this, 'remediation-configuration', { | ||
configRule: this, | ||
resourceParameter: 'GroupId', | ||
staticParameters: { | ||
AutomationAssumeRole: [ | ||
this.remediationRole.roleArn, | ||
], | ||
}, | ||
target: RemediationTarget.automationDocument({ | ||
document: AutomationDocument.fromManaged(this, 'remediation-document', VpcDefaultSecurityGroupClosed.REMEDIATION_DOCUMENT_NAME), | ||
}), | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './lib'; | ||
export * from './remediation-configuration'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './remediation-target'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { CfnRemediationConfiguration } from 'aws-cdk-lib/aws-config'; | ||
import { IConstruct } from 'constructs'; | ||
import { IAutomationDocument } from '../../ssm'; | ||
import { definedFieldsOrUndefined } from '../../utils/formatting'; | ||
|
||
|
||
export class RemediationTargetType { | ||
static readonly SSM_DOCUMENT: RemediationTargetType = RemediationTargetType.of('SSM_DOCUMENT'); | ||
|
||
static of(value: string): RemediationTargetType { | ||
return new RemediationTargetType(value); | ||
} | ||
|
||
|
||
readonly value: string; | ||
|
||
private constructor(value: string) { | ||
this.value = value; | ||
} | ||
} | ||
|
||
export interface RemediationTargetConfiguration { | ||
readonly controls?: CfnRemediationConfiguration.ExecutionControlsProperty; | ||
readonly targetId: string; | ||
readonly targetType: RemediationTargetType; | ||
readonly targetVersion?: string; | ||
} | ||
|
||
export interface IRemediationTarget { | ||
bind(scope: IConstruct): RemediationTargetConfiguration; | ||
} | ||
|
||
export interface AutomationDocumentRemediationProps { | ||
readonly concurrencyPercentage?: number; | ||
readonly document: IAutomationDocument; | ||
readonly errorPercentage?: number; | ||
readonly version?: string; | ||
} | ||
|
||
export class RemediationTarget { | ||
static automationDocument(props: AutomationDocumentRemediationProps): IRemediationTarget { | ||
return { | ||
bind: (_scope) => { | ||
return { | ||
controls: definedFieldsOrUndefined({ | ||
ssmControls: definedFieldsOrUndefined({ | ||
concurrentExecutionRatePercentage: props.concurrencyPercentage, | ||
errorPercentage: props.errorPercentage, | ||
}), | ||
}), | ||
targetId: props.document.documentName, | ||
targetType: RemediationTargetType.SSM_DOCUMENT, | ||
targetVersion: props.version, | ||
}; | ||
}, | ||
}; | ||
} | ||
} |
Oops, something went wrong.