From 316271d425c995b20de5cdbd6b6d06541c95457f Mon Sep 17 00:00:00 2001 From: Ryan Jaeger Date: Thu, 15 Sep 2022 19:01:52 -0700 Subject: [PATCH 01/10] add frequency for GuardDuty --- .../src/deployments/guardduty/guardduty.ts | 21 +++++++++++++++++++ src/lib/config-i18n/src/en.ts | 5 +++++ src/lib/config-i18n/src/fr.ts | 4 ++++ src/lib/config/src/config.v2.ts | 1 + .../cdk-guardduty-admin-setup/cdk/index.ts | 3 +++ .../runtime/src/index.ts | 20 ++++++++++++++---- 6 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts index bba98a581..eae03a937 100644 --- a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts +++ b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts @@ -23,6 +23,12 @@ import { GuardDutyAdminSetup } from '@aws-accelerator/custom-resource-guardduty- import { IamRoleOutputFinder } from '@aws-accelerator/common-outputs/src/iam-role'; import { StackOutput } from '@aws-accelerator/common-outputs/src/stack-output'; +export enum GuardDutyFrequency { + FIFTEEN_MINUTES = 'FIFTEEN_MINUTES', + ONE_HOUR = 'ONE_HOUR', + SIX_HOURS = 'SIX_HOURS', +} + export interface GuardDutyStepProps { accountStacks: AccountStacks; config: AcceleratorConfig; @@ -110,12 +116,14 @@ export async function step2(props: GuardDutyStepProps) { })); const centralServiceConfig = props.config['global-options']['central-security-services']; const s3ProtectionExclRegions = centralServiceConfig['guardduty-s3-excl-regions'] || []; + const frequency = await getFrequency(props.config); regions?.map(region => { const masterAccountStack = props.accountStacks.getOrCreateAccountStack(masterAccountKey, region); new GuardDutyAdminSetup(masterAccountStack, 'GuardDutyAdminSetup', { memberAccounts: accountDetails, roleArn: adminSetupRoleOutput.roleArn, s3Protection: centralServiceConfig['guardduty-s3'] && !s3ProtectionExclRegions.includes(region), + frequency, }); }); } @@ -197,3 +205,16 @@ export async function getValidRegions(config: AcceleratorConfig) { const validRegions = regions.filter(x => !excl?.includes(x)); return validRegions; } + +export async function getFrequency(config: AcceleratorConfig) { + const frequency = config['global-options']['central-security-services']['guardduty-frequency']; + if (frequency === GuardDutyFrequency.SIX_HOURS) { + return GuardDutyFrequency.SIX_HOURS; + } else if (frequency === GuardDutyFrequency.ONE_HOUR) { + return GuardDutyFrequency.ONE_HOUR; + } else if (frequency === GuardDutyFrequency.FIFTEEN_MINUTES) { + return GuardDutyFrequency.FIFTEEN_MINUTES; + } else { + return GuardDutyFrequency.SIX_HOURS; + } +} diff --git a/src/lib/config-i18n/src/en.ts b/src/lib/config-i18n/src/en.ts index 3b2fc030d..908a3c9fd 100644 --- a/src/lib/config-i18n/src/en.ts +++ b/src/lib/config-i18n/src/en.ts @@ -2807,6 +2807,11 @@ translate(c.CentralServicesConfigType, { title: 'GuardDuty S3 Protection Exclusion Regions', description: 'List of excluded regions from Guardduty S3 protection. [SECURITY]', }, + 'guardduty-frequency': { + title: 'Update Frequency for Policy Findings', + description: + 'The schedule GuardDuty uses to publish updates to policy findings. Supported values are: FIFTEEN_MINUTES, ONE_HOUR, SIX_HOURS. [SECURITY]', + }, 'access-analyzer': { title: '', description: diff --git a/src/lib/config-i18n/src/fr.ts b/src/lib/config-i18n/src/fr.ts index f515c353f..0c122d386 100644 --- a/src/lib/config-i18n/src/fr.ts +++ b/src/lib/config-i18n/src/fr.ts @@ -2609,6 +2609,10 @@ translate(c.CentralServicesConfigType, { title: '', description: '', }, + 'guardduty-frequency': { + title: '', + description: '', + }, 'access-analyzer': { title: '', description: '', diff --git a/src/lib/config/src/config.v2.ts b/src/lib/config/src/config.v2.ts index 402aa2d31..b1a1f5e71 100644 --- a/src/lib/config/src/config.v2.ts +++ b/src/lib/config/src/config.v2.ts @@ -907,6 +907,7 @@ export const CentralServicesConfigType = t.interface({ 'guardduty-excl-regions': t.optional(t.array(t.nonEmptyString)), 'guardduty-s3': t.defaulted(t.boolean, false), 'guardduty-s3-excl-regions': t.optional(t.array(t.nonEmptyString)), + 'guardduty-frequency': t.optional(t.nonEmptyString), 'access-analyzer': t.defaulted(t.boolean, false), cwl: t.defaulted(t.boolean, false), 'cwl-access-level': t.optional(t.nonEmptyString), diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts index e7c8c0636..91118019f 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts @@ -15,6 +15,7 @@ import * as path from 'path'; import * as cdk from '@aws-cdk/core'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; +import { GuardDutyFrequency } from '@aws-accelerator/custom-resource-guardduty-admin-setup-runtime'; const resourceType = 'Custom::GuardDutyAdminSetup'; @@ -27,6 +28,7 @@ export interface GuardDutyAdminSetupProps { memberAccounts: AccountDetail[]; roleArn: string; s3Protection: boolean; + frequency: GuardDutyFrequency; } /** @@ -43,6 +45,7 @@ export class GuardDutyAdminSetup extends cdk.Construct { const handlerProperties = { memberAccounts: props.memberAccounts, s3Protection: props.s3Protection, + frequency: props.frequency, }; const adminSetup = this.lambdaFunction(props.roleArn); diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts index e255b5f55..4a83722c0 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts @@ -28,6 +28,12 @@ const guardduty = new AWS.GuardDuty(); // Guardduty CreateMembers, UpdateMembers and DeleteMembers apis only supports max 50 accounts per request const pageSize = 50; +export enum GuardDutyFrequency { + FIFTEEN_MINUTES = 'FIFTEEN_MINUTES', + ONE_HOUR = 'ONE_HOUR', + SIX_HOURS = 'SIX_HOURS', +} + export interface AccountDetail { AccountId: string; Email: string; @@ -37,6 +43,7 @@ export interface HandlerProperties { deligatedAdminAccountId: string; memberAccounts: AccountDetail[]; s3Protection: boolean; + frequency: GuardDutyFrequency; } export const handler = errorHandler(onEvent); @@ -69,8 +76,8 @@ async function onCreateOrUpdate( }; } - const { memberAccounts, s3Protection } = properties; - await updateS3Protection(detectorId, s3Protection); + const { memberAccounts, s3Protection, frequency } = properties; + await updateS3ProtectionAndFrequency(detectorId, s3Protection, frequency); const isAutoEnabled = await isConfigurationAutoEnabled(detectorId, s3Protection); if (!isAutoEnabled) { @@ -209,7 +216,11 @@ async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorI } } -async function updateS3Protection(detectorId: string, s3Protection: boolean) { +async function updateS3ProtectionAndFrequency( + detectorId: string, + s3Protection: boolean, + frequency?: GuardDutyFrequency, +) { try { await throttlingBackOff(() => guardduty @@ -220,6 +231,7 @@ async function updateS3Protection(detectorId: string, s3Protection: boolean) { Enable: s3Protection, }, }, + FindingPublishingFrequency: frequency, }) .promise(), ); @@ -288,7 +300,7 @@ async function onDelete(event: CloudFormationCustomResourceDeleteEvent) { const { memberAccounts } = properties; try { const detectorId = await getDetectorId(); - await updateS3Protection(detectorId!, false); + await updateS3ProtectionAndFrequency(detectorId!, false, undefined); await updateConfig(detectorId!, false, false); await updateMemberDataSource(memberAccounts, detectorId!, false); await deleteMembers(memberAccounts, detectorId!); From 5d8ab9b99d9e4febc47bb9b9d6093fc8ab6a3760 Mon Sep 17 00:00:00 2001 From: Ryan Jaeger Date: Thu, 15 Sep 2022 19:07:58 -0700 Subject: [PATCH 02/10] update sample config files with new config option --- reference-artifacts/SAMPLE_CONFIGS/config.example.json | 1 + .../SAMPLE_CONFIGS/config.lite-CTNFW-example.json | 1 + reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json | 1 + reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json | 1 + reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json | 1 + .../SAMPLE_CONFIGS/config.multi-region-example.json | 1 + reference-artifacts/SAMPLE_CONFIGS/config.test-example.json | 1 + .../SAMPLE_CONFIGS/config.ultralite-CT-example.json | 1 + reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json | 1 + 9 files changed, 9 insertions(+) diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.example.json b/reference-artifacts/SAMPLE_CONFIGS/config.example.json index 42bc2f0e7..e7b5d7264 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json index da29f7a0d..3833d6f8b 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json @@ -74,6 +74,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json index 095db3dae..34fa6275a 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json index 51f9cad1a..189cb2377 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json @@ -56,6 +56,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json index e681b6ab7..9ef0c4c38 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json index 1ab587275..59dd52d4f 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json index f444e5ba7..811a7d0c2 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json @@ -73,6 +73,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [ diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json index 9b1016889..8219ca0b7 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json @@ -37,6 +37,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json index b3e5b83e0..3e85d2499 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json @@ -35,6 +35,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", "access-analyzer": true, From 862b54a77ce59f8c46897b86d02151974c9cb60d Mon Sep 17 00:00:00 2001 From: Ryan Jaeger Date: Fri, 16 Sep 2022 13:45:04 -0700 Subject: [PATCH 03/10] add guardduty eks support --- pnpm-lock.yaml | 302 ++++++++++++++++-- .../SAMPLE_CONFIGS/config.example.json | 2 + .../config.lite-CTNFW-example.json | 2 + .../config.lite-GWLB-example.json | 2 + .../config.lite-NFW-example.json | 2 + .../config.lite-VPN-example.json | 2 + .../config.multi-region-example.json | 2 + .../SAMPLE_CONFIGS/config.test-example.json | 2 + .../config.ultralite-CT-example.json | 2 + .../config.ultralite-example.json | 2 + .../src/deployments/guardduty/guardduty.ts | 2 + src/lib/config-i18n/src/en.ts | 9 + src/lib/config-i18n/src/fr.ts | 8 + src/lib/config/src/config.v2.ts | 2 + .../cdk-guardduty-admin-setup/cdk/index.ts | 2 + .../runtime/package.json | 4 +- .../runtime/src/index.ts | 70 ++-- 17 files changed, 364 insertions(+), 53 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 062f25756..b1f35acfa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1630,14 +1630,14 @@ importers: '@types/aws-lambda': 8.10.76 '@types/node': 14.14.31 aws-lambda: 1.0.6 - aws-sdk: 2.944.0 + aws-sdk: 2.1217.0 esbuild: 0.11.18 typescript: 4.2.4 dependencies: '@aws-accelerator/custom-resource-cfn-utils': link:../../cdk-cfn-utils '@aws-accelerator/custom-resource-runtime-cfn-response': link:../../runtime-cfn-response aws-lambda: 1.0.6 - aws-sdk: 2.944.0 + aws-sdk: 2.1217.0 devDependencies: '@types/aws-lambda': 8.10.76 '@types/node': 14.14.31 @@ -5306,6 +5306,8 @@ packages: /@aws-cdk/cdk-assets-schema/1.44.0: resolution: {integrity: sha512-FeII0+Avnin3xemZR56gcsqbOosWdQ7i3L8C+JuZRPgCNMc8uvsH7rB6QditTbw6l43rGMLnlEbtHVobPVRnKg==} engines: {node: '>= 10.13.0 <13 || >=13.7.0'} + dependencies: + semver: 7.3.5 dev: false bundledDependencies: - semver @@ -5329,6 +5331,9 @@ packages: /@aws-cdk/cloud-assembly-schema/1.44.0: resolution: {integrity: sha512-n/jln7teKE7o5ZYJ6o6+Jix4nRluC3hNFt+KYzEuVYOAkL0Mwoj92FpJnHkqU5jh0vw6K3OAd5Bq8+fICzEgaQ==} engines: {node: '>= 10.13.0 <13 || >=13.7.0'} + dependencies: + jsonschema: 1.4.0 + semver: 7.3.5 dev: false bundledDependencies: - jsonschema @@ -5567,6 +5572,7 @@ packages: '@aws-cdk/cloud-assembly-schema': 1.44.0 '@aws-cdk/cx-api': 1.44.0 constructs: 3.3.71 + minimatch: 3.0.5 dev: false bundledDependencies: - minimatch @@ -5598,6 +5604,7 @@ packages: engines: {node: '>= 10.13.0 <13 || >=13.7.0'} dependencies: '@aws-cdk/cloud-assembly-schema': 1.44.0 + semver: 7.3.5 dev: false bundledDependencies: - semver @@ -12405,6 +12412,11 @@ packages: postcss-value-parser: 4.1.0 dev: true + /available-typed-arrays/1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: false + /aws-cdk/1.144.0: resolution: {integrity: sha512-4sVYurq8CYwl+glnRtMBBa2vQ3RI63K9gVPQtMaqCFR2SEj4+U2e2rX/zU29ko0Lzm+OQxS1UbaklMM4KaFo3A==} engines: {node: '>= 10.13.0 <13 || >=13.7.0'} @@ -12463,6 +12475,22 @@ packages: uuid: 3.3.2 xml2js: 0.4.19 + /aws-sdk/2.1217.0: + resolution: {integrity: sha512-Mem3YD+vevt0qNg1aKB+7jdM2UMRIW2b3L5YDHzCctukndh91Y0rpy+EypPo4GXhQv5lfP+H9h+Csh/dvOQJiw==} + engines: {node: '>= 10.0.0'} + dependencies: + buffer: 4.9.2 + events: 1.1.1 + ieee754: 1.1.13 + jmespath: 0.16.0 + querystring: 0.2.0 + sax: 1.2.1 + url: 0.10.3 + util: 0.12.4 + uuid: 8.0.0 + xml2js: 0.4.19 + dev: false + /aws-sdk/2.944.0: resolution: {integrity: sha512-QHKDbs/og1kUhOZsE6A8KN/Rw3LHkfEWBqziRaWDNoijDZzY9XlbLHnLmpkluCe4HNKY1KOOyBajhf2CkJahcQ==} engines: {node: '>= 0.8.0'} @@ -13232,7 +13260,6 @@ packages: dependencies: function-bind: 1.1.1 get-intrinsic: 1.1.1 - dev: true /call-me-maybe/1.0.1: resolution: {integrity: sha1-JtII6onje1y95gJQoV8DHBak1ms=} @@ -13720,6 +13747,7 @@ packages: /constructs/3.3.71: resolution: {integrity: sha512-3KFtTsA7OV27m/+pJhN4iJkKzHbPIPvyvEX5BQ/JCAWjfCHOQEVpIgxHLpT4i8L1OFta+pJrzcEVAHo6UitwqA==} engines: {node: '>= 10.17.0'} + bundledDependencies: [] /contains-path/0.1.0: resolution: {integrity: sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=} @@ -14359,7 +14387,14 @@ packages: engines: {node: '>= 0.4'} dependencies: object-keys: 1.1.1 - dev: true + + /define-properties/1.1.4: + resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: false /define-property/0.2.5: resolution: {integrity: sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=} @@ -14780,14 +14815,42 @@ packages: unbox-primitive: 1.0.1 dev: true + /es-abstract/1.20.2: + resolution: {integrity: sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + es-to-primitive: 1.2.1 + function-bind: 1.1.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.1.3 + get-symbol-description: 1.0.0 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-symbols: 1.0.3 + internal-slot: 1.0.3 + is-callable: 1.2.6 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-weakref: 1.0.2 + object-inspect: 1.12.2 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + string.prototype.trimend: 1.0.5 + string.prototype.trimstart: 1.0.5 + unbox-primitive: 1.0.2 + dev: false + /es-to-primitive/1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: - is-callable: 1.2.3 + is-callable: 1.2.6 is-date-object: 1.0.2 is-symbol: 1.0.3 - dev: true /es5-ext/0.10.53: resolution: {integrity: sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==} @@ -15376,7 +15439,7 @@ packages: dev: true /events/1.1.1: - resolution: {integrity: sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=} + resolution: {integrity: sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==} engines: {node: '>=0.4.x'} /events/3.3.0: @@ -15767,6 +15830,12 @@ packages: debug: 4.3.1_supports-color@6.1.0 dev: true + /for-each/0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.3 + dev: false + /for-in/1.0.2: resolution: {integrity: sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=} engines: {node: '>=0.10.0'} @@ -15913,12 +15982,25 @@ packages: /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true + + /function.prototype.name/1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.20.2 + functions-have-names: 1.2.3 + dev: false /functional-red-black-tree/1.0.1: resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} dev: true + /functions-have-names/1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: false + /gensync/1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -15934,7 +16016,13 @@ packages: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.2 - dev: true + + /get-intrinsic/1.1.3: + resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 /get-own-enumerable-property-symbols/3.0.2: resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} @@ -15964,6 +16052,14 @@ packages: pump: 3.0.0 dev: true + /get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + dev: false + /get-uri/3.0.2: resolution: {integrity: sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==} engines: {node: '>= 6'} @@ -16170,6 +16266,10 @@ packages: resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==} dev: true + /has-bigints/1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: false + /has-flag/3.0.0: resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} engines: {node: '>=4'} @@ -16179,10 +16279,25 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + /has-property-descriptors/1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.1.3 + dev: false + /has-symbols/1.0.2: resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==} engines: {node: '>= 0.4'} - dev: true + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.2 /has-value/0.3.1: resolution: {integrity: sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=} @@ -16220,7 +16335,6 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: true /hash-base/3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} @@ -16631,10 +16745,9 @@ packages: resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.1.1 + get-intrinsic: 1.1.3 has: 1.0.3 side-channel: 1.0.4 - dev: true /io-ts-types/0.5.16_io-ts@2.2.16: resolution: {integrity: sha512-h9noYVfY9rlbmKI902SJdnV/06jgiT2chxG6lYDxaYNp88HscPi+SBCtmcU+m0E7WT5QSwt7sIMj93+qu0FEwQ==} @@ -16730,7 +16843,6 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - dev: true /is-arrayish/0.2.1: resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} @@ -16742,7 +16854,6 @@ packages: /is-bigint/1.0.1: resolution: {integrity: sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==} - dev: true /is-binary-path/1.0.1: resolution: {integrity: sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=} @@ -16762,7 +16873,6 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - dev: true /is-buffer/1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} @@ -16777,7 +16887,10 @@ packages: /is-callable/1.2.3: resolution: {integrity: sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==} engines: {node: '>= 0.4'} - dev: true + + /is-callable/1.2.6: + resolution: {integrity: sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==} + engines: {node: '>= 0.4'} /is-ci/2.0.0: resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} @@ -16820,7 +16933,6 @@ packages: /is-date-object/1.0.2: resolution: {integrity: sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==} engines: {node: '>= 0.4'} - dev: true /is-descriptor/0.1.6: resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} @@ -16881,6 +16993,13 @@ packages: engines: {node: '>=6'} dev: true + /is-generator-function/1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + /is-glob/3.1.0: resolution: {integrity: sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=} engines: {node: '>=0.10.0'} @@ -16903,10 +17022,14 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-negative-zero/2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: false + /is-number-object/1.0.4: resolution: {integrity: sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==} engines: {node: '>= 0.4'} - dev: true /is-number/3.0.0: resolution: {integrity: sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=} @@ -16979,6 +17102,14 @@ packages: has-symbols: 1.0.2 dev: true + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + /is-regexp/1.0.0: resolution: {integrity: sha1-/S2INUXEa6xaYz57mgnof6LLUGk=} engines: {node: '>=0.10.0'} @@ -16993,6 +17124,12 @@ packages: engines: {node: '>=6'} dev: true + /is-shared-array-buffer/1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: false + /is-stream/1.1.0: resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} engines: {node: '>=0.10.0'} @@ -17007,17 +17144,39 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + /is-symbol/1.0.3: resolution: {integrity: sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==} engines: {node: '>= 0.4'} dependencies: - has-symbols: 1.0.2 - dev: true + has-symbols: 1.0.3 + + /is-typed-array/1.1.9: + resolution: {integrity: sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-abstract: 1.20.2 + for-each: 0.3.3 + has-tostringtag: 1.0.0 + dev: false /is-typedarray/1.0.0: resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=} dev: true + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: false + /is-windows/1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -17039,7 +17198,7 @@ packages: resolution: {integrity: sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=} /isarray/1.0.0: - resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} /isexe/2.0.0: resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} @@ -18028,6 +18187,11 @@ packages: resolution: {integrity: sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=} engines: {node: '>= 0.6.0'} + /jmespath/0.16.0: + resolution: {integrity: sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==} + engines: {node: '>= 0.6.0'} + dev: false + /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -19175,6 +19339,9 @@ packages: kind-of: 3.2.2 dev: true + /object-inspect/1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + /object-inspect/1.9.0: resolution: {integrity: sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==} dev: true @@ -19190,7 +19357,6 @@ packages: /object-keys/1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - dev: true /object-visit/1.0.1: resolution: {integrity: sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=} @@ -19209,6 +19375,16 @@ packages: object-keys: 1.1.1 dev: true + /object.assign/4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + /object.entries/1.1.3: resolution: {integrity: sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==} engines: {node: '>= 0.4'} @@ -20557,7 +20733,7 @@ packages: dev: true /punycode/1.3.2: - resolution: {integrity: sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=} + resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} @@ -20592,7 +20768,7 @@ packages: dev: true /querystring/0.2.0: - resolution: {integrity: sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=} + resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} engines: {node: '>=0.4.x'} deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. @@ -21092,6 +21268,15 @@ packages: define-properties: 1.1.3 dev: true + /regexp.prototype.flags/1.4.3: + resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + functions-have-names: 1.2.3 + dev: false + /regexpp/3.1.0: resolution: {integrity: sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==} engines: {node: '>=8'} @@ -21509,7 +21694,7 @@ packages: dev: true /sax/1.2.1: - resolution: {integrity: sha1-e45lYZCyKOgaZq6nSEgNgozS03o=} + resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} /sax/1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -21739,9 +21924,8 @@ packages: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.1 - object-inspect: 1.9.0 - dev: true + get-intrinsic: 1.1.3 + object-inspect: 1.12.2 /signal-exit/3.0.3: resolution: {integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==} @@ -22131,6 +22315,14 @@ packages: define-properties: 1.1.3 dev: true + /string.prototype.trimend/1.0.5: + resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + /string.prototype.trimstart/1.0.4: resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==} dependencies: @@ -22138,6 +22330,14 @@ packages: define-properties: 1.1.3 dev: true + /string.prototype.trimstart/1.0.5: + resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + /string_decoder/0.10.31: resolution: {integrity: sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=} @@ -22884,6 +23084,15 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /unbox-primitive/1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: false + /unicode-canonical-property-names-ecmascript/1.0.4: resolution: {integrity: sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==} engines: {node: '>=4'} @@ -23021,7 +23230,7 @@ packages: dev: true /url/0.10.3: - resolution: {integrity: sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=} + resolution: {integrity: sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==} dependencies: punycode: 1.3.2 querystring: 0.2.0 @@ -23094,6 +23303,17 @@ packages: inherits: 2.0.3 dev: true + /util/0.12.4: + resolution: {integrity: sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.0 + is-generator-function: 1.0.10 + is-typed-array: 1.1.9 + safe-buffer: 5.2.1 + which-typed-array: 1.1.8 + dev: false + /utila/0.4.0: resolution: {integrity: sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=} dev: true @@ -23113,6 +23333,11 @@ packages: hasBin: true dev: true + /uuid/8.0.0: + resolution: {integrity: sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==} + hasBin: true + dev: false + /uuid/8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -23452,14 +23677,25 @@ packages: is-bigint: 1.0.1 is-boolean-object: 1.1.0 is-number-object: 1.0.4 - is-string: 1.0.5 + is-string: 1.0.7 is-symbol: 1.0.3 - dev: true /which-module/2.0.0: resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} dev: true + /which-typed-array/1.1.8: + resolution: {integrity: sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-abstract: 1.20.2 + for-each: 0.3.3 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.9 + dev: false + /which/1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true @@ -23721,7 +23957,7 @@ packages: dev: false /xmlbuilder/9.0.7: - resolution: {integrity: sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=} + resolution: {integrity: sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==} engines: {node: '>=4.0'} /xmlchars/2.2.0: diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.example.json b/reference-artifacts/SAMPLE_CONFIGS/config.example.json index e7b5d7264..d6d405d4c 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json index 3833d6f8b..b1254199b 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json @@ -74,6 +74,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json index 34fa6275a..25b50dafe 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json index 189cb2377..d1846dccc 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json @@ -56,6 +56,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json index 9ef0c4c38..04cdb05da 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json index 59dd52d4f..a320e80ea 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json index 811a7d0c2..b373aeb1b 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json @@ -73,6 +73,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json index 8219ca0b7..b1909a046 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json @@ -37,6 +37,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json index 3e85d2499..631b5f31c 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json @@ -35,6 +35,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", diff --git a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts index eae03a937..c523c8a87 100644 --- a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts +++ b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts @@ -116,6 +116,7 @@ export async function step2(props: GuardDutyStepProps) { })); const centralServiceConfig = props.config['global-options']['central-security-services']; const s3ProtectionExclRegions = centralServiceConfig['guardduty-s3-excl-regions'] || []; + const eksProtectionExclRegions = centralServiceConfig['guardduty-eks-excl-regions'] || []; const frequency = await getFrequency(props.config); regions?.map(region => { const masterAccountStack = props.accountStacks.getOrCreateAccountStack(masterAccountKey, region); @@ -123,6 +124,7 @@ export async function step2(props: GuardDutyStepProps) { memberAccounts: accountDetails, roleArn: adminSetupRoleOutput.roleArn, s3Protection: centralServiceConfig['guardduty-s3'] && !s3ProtectionExclRegions.includes(region), + eksProtection: centralServiceConfig['guardduty-eks'] && !eksProtectionExclRegions.includes(region), frequency, }); }); diff --git a/src/lib/config-i18n/src/en.ts b/src/lib/config-i18n/src/en.ts index 908a3c9fd..39dfdcfe7 100644 --- a/src/lib/config-i18n/src/en.ts +++ b/src/lib/config-i18n/src/en.ts @@ -2807,6 +2807,15 @@ translate(c.CentralServicesConfigType, { title: 'GuardDuty S3 Protection Exclusion Regions', description: 'List of excluded regions from Guardduty S3 protection. [SECURITY]', }, + 'guardduty-eks': { + title: 'GuardDuty EKS Protection', + description: + 'EKS protection enables Amazon GuardDuty to monitor control plane activity by analyzing Kubernetes audit logs. [SECURITY]', + }, + 'guardduty-eks-excl-regions': { + title: 'GuardDuty EKS Protection Exclusion Regions', + description: 'List of excluded regions from Guardduty EKS protection. [SECURITY]', + }, 'guardduty-frequency': { title: 'Update Frequency for Policy Findings', description: diff --git a/src/lib/config-i18n/src/fr.ts b/src/lib/config-i18n/src/fr.ts index 0c122d386..a18028422 100644 --- a/src/lib/config-i18n/src/fr.ts +++ b/src/lib/config-i18n/src/fr.ts @@ -2609,6 +2609,14 @@ translate(c.CentralServicesConfigType, { title: '', description: '', }, + 'guardduty-eks': { + title: '', + description: '', + }, + 'guardduty-eks-excl-regions': { + title: '', + description: '', + }, 'guardduty-frequency': { title: '', description: '', diff --git a/src/lib/config/src/config.v2.ts b/src/lib/config/src/config.v2.ts index b1a1f5e71..b5c8c77c5 100644 --- a/src/lib/config/src/config.v2.ts +++ b/src/lib/config/src/config.v2.ts @@ -907,6 +907,8 @@ export const CentralServicesConfigType = t.interface({ 'guardduty-excl-regions': t.optional(t.array(t.nonEmptyString)), 'guardduty-s3': t.defaulted(t.boolean, false), 'guardduty-s3-excl-regions': t.optional(t.array(t.nonEmptyString)), + 'guardduty-eks': t.defaulted(t.boolean, false), + 'guardduty-eks-excl-regions': t.optional(t.array(t.nonEmptyString)), 'guardduty-frequency': t.optional(t.nonEmptyString), 'access-analyzer': t.defaulted(t.boolean, false), cwl: t.defaulted(t.boolean, false), diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts index 91118019f..373194183 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts @@ -28,6 +28,7 @@ export interface GuardDutyAdminSetupProps { memberAccounts: AccountDetail[]; roleArn: string; s3Protection: boolean; + eksProtection: boolean; frequency: GuardDutyFrequency; } @@ -45,6 +46,7 @@ export class GuardDutyAdminSetup extends cdk.Construct { const handlerProperties = { memberAccounts: props.memberAccounts, s3Protection: props.s3Protection, + eksProtection: props.eksProtection, frequency: props.frequency, }; diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json index 7cc9bd495..cc7336a4f 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "types": "src/index.ts", "scripts": { - "build": "pnpx esbuild --minify --bundle --platform=node --target=node14 --external:aws-sdk --outfile=./dist/index.js src/index.ts", + "build": "pnpx esbuild --minify --bundle --platform=node --target=node14 --outfile=./dist/index.js src/index.ts", "lint:typecheck": "pnpx tsc --noEmit", "lint:eslint": "pnpx eslint '{cdk,lib,src}/**/*.{js,ts}'" }, @@ -13,7 +13,7 @@ "@aws-accelerator/custom-resource-cfn-utils": "workspace:*", "@aws-accelerator/custom-resource-runtime-cfn-response": "workspace:*", "aws-lambda": "1.0.6", - "aws-sdk": "2.944.0" + "aws-sdk": "2.1217.0" }, "devDependencies": { "@types/aws-lambda": "8.10.76", diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts index 4a83722c0..953b6e0bc 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts @@ -12,7 +12,7 @@ */ import * as AWS from 'aws-sdk'; -AWS.config.logger = console; +//AWS.config.logger = console; import { CloudFormationCustomResourceEvent, CloudFormationCustomResourceCreateEvent, @@ -43,6 +43,7 @@ export interface HandlerProperties { deligatedAdminAccountId: string; memberAccounts: AccountDetail[]; s3Protection: boolean; + eksProtection: boolean; frequency: GuardDutyFrequency; } @@ -76,13 +77,13 @@ async function onCreateOrUpdate( }; } - const { memberAccounts, s3Protection, frequency } = properties; - await updateS3ProtectionAndFrequency(detectorId, s3Protection, frequency); + const { memberAccounts, s3Protection, eksProtection, frequency } = properties; + await updateS3ProtectionAndFrequency(detectorId, s3Protection, eksProtection, frequency); - const isAutoEnabled = await isConfigurationAutoEnabled(detectorId, s3Protection); + const isAutoEnabled = await isConfigurationAutoEnabled(detectorId, s3Protection, eksProtection); if (!isAutoEnabled) { // Update Config to handle new Account created under Organization - await updateConfig(detectorId, s3Protection); + await updateConfig(detectorId, s3Protection, eksProtection); } else { console.log(`GuardDuty is already enabled ORG Level`); } @@ -93,9 +94,10 @@ async function onCreateOrUpdate( ); if (requiredMemberAccounts.length > 0) { await createMembers(requiredMemberAccounts, detectorId); - await updateMemberDataSource(requiredMemberAccounts, detectorId, s3Protection); } + await updateMemberDataSource(existingMembers, detectorId, s3Protection, eksProtection); + return { physicalResourceId, data: {}, @@ -142,7 +144,7 @@ async function createMembers(memberAccounts: AccountDetail[], detectorId: string } // Step 3 of https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html -async function updateConfig(detectorId: string, s3Protection: boolean, autoEnable = true) { +async function updateConfig(detectorId: string, s3Protection: boolean, eksProtection: boolean, autoEnable = true) { try { console.log(`Calling api "guardduty.updateOrganizationConfiguration()", ${detectorId}`); await throttlingBackOff(() => @@ -154,6 +156,11 @@ async function updateConfig(detectorId: string, s3Protection: boolean, autoEnabl S3Logs: { AutoEnable: s3Protection, }, + Kubernetes: { + AuditLogs: { + AutoEnable: eksProtection, + }, + }, }, }) .promise(), @@ -165,7 +172,11 @@ async function updateConfig(detectorId: string, s3Protection: boolean, autoEnabl } // describe-organization-configuration to check if security hub is already enabled in org level or not -async function isConfigurationAutoEnabled(detectorId: string, s3Protection: boolean): Promise { +async function isConfigurationAutoEnabled( + detectorId: string, + s3Protection: boolean, + eksProtection: boolean, +): Promise { try { console.log(`Calling api "guardduty.describeOrganizationConfiguration()", ${detectorId}`); const response = await throttlingBackOff(() => @@ -175,7 +186,11 @@ async function isConfigurationAutoEnabled(detectorId: string, s3Protection: bool }) .promise(), ); - return response.AutoEnable && response.DataSources?.S3Logs.AutoEnable! === s3Protection; + return ( + response.AutoEnable && + response.DataSources?.S3Logs.AutoEnable! === s3Protection && + response.DataSources?.Kubernetes?.AuditLogs.AutoEnable! === eksProtection + ); } catch (error) { console.error( `Error Occurred while checking configuration auto enabled of GuardDuty ${error.code}: ${error.message}`, @@ -184,16 +199,21 @@ async function isConfigurationAutoEnabled(detectorId: string, s3Protection: bool } } -async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorId: string, s3Protection: boolean) { - if (s3Protection) { - return; - } +async function updateMemberDataSource( + memberAccounts: AccountDetail[], + detectorId: string, + s3Protection: boolean, + eksProtection: boolean, +) { + // if (s3Protection && eksProtection) { + // return; + // } try { let pageNumber = 1; let currentAccounts: AccountDetail[] = paginate(memberAccounts, pageNumber, pageSize); while (currentAccounts.length > 0) { console.log( - `Calling api "guardduty.updateMemberDetectors()", ${currentAccounts}, ${detectorId} to disable S3Protection`, + `Calling api "guardduty.updateMemberDetectors()", ${currentAccounts}, ${detectorId} to update S3Protection or EKSProtection`, ); await throttlingBackOff(() => guardduty @@ -202,7 +222,12 @@ async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorI DetectorId: detectorId, DataSources: { S3Logs: { - Enable: false, + Enable: s3Protection, + }, + Kubernetes: { + AuditLogs: { + Enable: eksProtection, + }, }, }, }) @@ -219,6 +244,7 @@ async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorI async function updateS3ProtectionAndFrequency( detectorId: string, s3Protection: boolean, + eksProtection: boolean, frequency?: GuardDutyFrequency, ) { try { @@ -230,6 +256,11 @@ async function updateS3ProtectionAndFrequency( S3Logs: { Enable: s3Protection, }, + Kubernetes: { + AuditLogs: { + Enable: eksProtection, + }, + }, }, FindingPublishingFrequency: frequency, }) @@ -288,6 +319,9 @@ function getPropertiesFromEvent(event: CloudFormationCustomResourceEvent) { if (typeof properties.s3Protection === 'string') { properties.s3Protection = properties.s3Protection === 'true'; } + if (typeof properties.eksProtection === 'string') { + properties.eksProtection = properties.eksProtection === 'true'; + } return properties; } @@ -300,9 +334,9 @@ async function onDelete(event: CloudFormationCustomResourceDeleteEvent) { const { memberAccounts } = properties; try { const detectorId = await getDetectorId(); - await updateS3ProtectionAndFrequency(detectorId!, false, undefined); - await updateConfig(detectorId!, false, false); - await updateMemberDataSource(memberAccounts, detectorId!, false); + await updateS3ProtectionAndFrequency(detectorId!, false, false, undefined); + await updateConfig(detectorId!, false, false, false); + await updateMemberDataSource(memberAccounts, detectorId!, false, false); await deleteMembers(memberAccounts, detectorId!); } catch (error) { console.warn('Exception while performing Delete Action'); From 1b6f0be98a9aeb8f1cddb72090e8098b9cc0b6f2 Mon Sep 17 00:00:00 2001 From: Ryan Jaeger <41204211+rjjaegeraws@users.noreply.github.com> Date: Thu, 29 Sep 2022 13:06:00 -0700 Subject: [PATCH 04/10] fix for issue with ALB forwarder when no HOSTS defined (#1019) --- .../src/alb-to-alb-target/alb-target-record-monitor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/deployments/runtime/src/alb-to-alb-target/alb-target-record-monitor.ts b/src/deployments/runtime/src/alb-to-alb-target/alb-target-record-monitor.ts index 7ce696c9d..8303a9b9a 100644 --- a/src/deployments/runtime/src/alb-to-alb-target/alb-target-record-monitor.ts +++ b/src/deployments/runtime/src/alb-to-alb-target/alb-target-record-monitor.ts @@ -100,7 +100,7 @@ const createListenerRule = async ( ruleParams.Conditions.push(pathConfig); } - if (hosts.length > 0) { + if (hosts?.length > 0) { const hostConfig = { Field: 'host-header', Values: hosts, @@ -131,7 +131,7 @@ const updateListenerRule = async (ruleArn: string, paths: string[], hosts: strin ruleParams?.Conditions?.push(pathConfig); } - if (hosts.length > 0) { + if (hosts?.length > 0) { const hostConfig = { Field: 'host-header', Values: hosts, From 5f02a9afcb5dbfd4fee27bf6fe82b517e9f23cba Mon Sep 17 00:00:00 2001 From: rycerrat <42330513+rycerrat@users.noreply.github.com> Date: Thu, 29 Sep 2022 15:08:53 -0500 Subject: [PATCH 05/10] Decreasing max concurrency limit to 10 (#1062) --- src/core/cdk/src/tasks/store-outputs-task.ts | 4 ++-- src/core/cdk/src/tasks/store-outputs-to-ssm-task.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/cdk/src/tasks/store-outputs-task.ts b/src/core/cdk/src/tasks/store-outputs-task.ts index c16962adf..33fd6acad 100644 --- a/src/core/cdk/src/tasks/store-outputs-task.ts +++ b/src/core/cdk/src/tasks/store-outputs-task.ts @@ -47,7 +47,7 @@ export class StoreOutputsTask extends sfn.StateMachineFragment { const storeAccountOutputs = new sfn.Map(this, `Store Account Outputs`, { itemsPath: `$.accounts`, resultPath: 'DISCARD', - maxConcurrency: 50, + maxConcurrency: 10, parameters: { 'accountId.$': '$$.Map.Item.Value', 'regions.$': '$.regions', @@ -120,7 +120,7 @@ export class StoreOutputsTask extends sfn.StateMachineFragment { const storeAccountRegionOutputs = new sfn.Map(this, `Store Account Region Outputs`, { itemsPath: `$.regions`, resultPath: 'DISCARD', - maxConcurrency: 20, + maxConcurrency: 10, parameters: { 'account.$': '$.account', 'region.$': '$$.Map.Item.Value', diff --git a/src/core/cdk/src/tasks/store-outputs-to-ssm-task.ts b/src/core/cdk/src/tasks/store-outputs-to-ssm-task.ts index 7fa8d9c2c..c63857f19 100644 --- a/src/core/cdk/src/tasks/store-outputs-to-ssm-task.ts +++ b/src/core/cdk/src/tasks/store-outputs-to-ssm-task.ts @@ -59,7 +59,7 @@ export class StoreOutputsToSSMTask extends sfn.StateMachineFragment { const storeAccountOutputs = new sfn.Map(this, `Store Account Outputs To SSM`, { itemsPath: `$.accounts`, resultPath: 'DISCARD', - maxConcurrency: 50, + maxConcurrency: 10, parameters: { 'accountId.$': '$$.Map.Item.Value', 'regions.$': '$.regions', @@ -148,7 +148,7 @@ export class StoreOutputsToSSMTask extends sfn.StateMachineFragment { const storeAccountRegionOutputs = new sfn.Map(this, `Store Account Region Outputs To SSM`, { itemsPath: `$.regions`, resultPath: 'DISCARD', - maxConcurrency: 20, + maxConcurrency: 10, parameters: { 'account.$': '$.account', 'region.$': '$$.Map.Item.Value', From 33ecd9b2bbadbdc9b07a6ac30881b5bcdcd535d9 Mon Sep 17 00:00:00 2001 From: hickeydh-aws <88673813+hickeydh-aws@users.noreply.github.com> Date: Fri, 30 Sep 2022 13:49:27 -0500 Subject: [PATCH 06/10] (Fix): SM jitter (#1050) * exponential backoff fix * exponential backoff fix * Fixed backoff for lambdas * added backoff in other location * fixed lambda timeouts and added timeout aspect * fixed typo * tweak default max jitter delay to 2s from 5s Co-authored-by: hickeydh-aws Co-authored-by: Brian969 <56414362+Brian969@users.noreply.github.com> --- .../opensiem/lambdas/common/src/backoff.ts | 19 ++++++++++++++++++- src/core/cdk/src/index.ts | 2 ++ src/core/cdk/src/initial-setup.ts | 2 ++ .../cdk/src/common/alb-ip-forwarding.ts | 4 ++-- src/installer/cdk/src/index.ts | 10 ++++++++++ .../src/core/accelerator-stack.ts | 4 +++- src/lib/cdk-accelerator/src/core/index.ts | 2 ++ .../src/core/lambda-default-timeout.ts | 12 ++++++++++++ .../src/core/lambda-env-variables.ts | 10 ++++++++++ src/lib/common/src/aws/backoff.ts | 19 ++++++++++++++++++- .../cdk-acm-import-certificate/cdk/index.ts | 2 +- .../cdk-cfn-utils/cdk/index.ts | 18 +++++++++++++++++- .../cdk-cur-report-definition/cdk/index.ts | 2 +- .../cdk/index.ts | 2 +- .../cdk-ec2-keypair/cdk/index.ts | 2 +- .../cdk-kms-grant/cdk/index.ts | 2 +- .../cdk/index.ts | 2 +- .../ec2-ebs-default-encryption/lib/index.ts | 2 +- 18 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 src/lib/cdk-accelerator/src/core/lambda-default-timeout.ts create mode 100644 src/lib/cdk-accelerator/src/core/lambda-env-variables.ts diff --git a/reference-artifacts/Add-ons/opensiem/lambdas/common/src/backoff.ts b/reference-artifacts/Add-ons/opensiem/lambdas/common/src/backoff.ts index bec056d47..23ee07437 100644 --- a/reference-artifacts/Add-ons/opensiem/lambdas/common/src/backoff.ts +++ b/reference-artifacts/Add-ons/opensiem/lambdas/common/src/backoff.ts @@ -20,8 +20,24 @@ export function throttlingBackOff( request: () => Promise, options?: Partial>, ): Promise { + const defaultDelay = 500; + let maxDelayValue = 2000; + + if (process.env.BACKOFF_START_DELAY) { + const backoffStartDelay = parseInt(process.env.BACKOFF_START_DELAY, 10); + if (Number.isInteger(backoffStartDelay)) { + maxDelayValue = backoffStartDelay; + } + } + + // Add jitter to the starting delay + const startingDelay = Math.random() * (maxDelayValue - defaultDelay + 1) + defaultDelay; + + console.log(`throttlingBackOff delay set to ${startingDelay}`); + return backOff(request, { - startingDelay: 500, + startingDelay, + delayFirstAttempt: true, jitter: 'full', retry: isThrottlingError, ...options, @@ -34,6 +50,7 @@ export const isThrottlingError = (e: any) => e.code === 'ConcurrentModificationException' || // Retry for AWS Organizations e.code === 'InsufficientDeliveryPolicyException' || // Retry for ConfigService e.code === 'NoAvailableDeliveryChannelException' || // Retry for ConfigService + e.code === 'ConcurrentModifications' || // Retry for AssociateHostedZone e.code === 'TooManyRequestsException' || e.code === 'Throttling' || e.code === 'ThrottlingException' || diff --git a/src/core/cdk/src/index.ts b/src/core/cdk/src/index.ts index a755d7670..cd57b9759 100644 --- a/src/core/cdk/src/index.ts +++ b/src/core/cdk/src/index.ts @@ -39,6 +39,7 @@ async function main() { env.CONFIG_S3_BUCKET || `${acceleratorPrefix.toLowerCase()}${cdk.Aws.ACCOUNT_ID}-${cdk.Aws.REGION}-config`; const codebuildComputeType = env.BUILD_COMPUTE_TYPE || 'BUILD_GENERAL1_LARGE'; const pageSize = env.DEPLOY_STACK_PAGE_SIZE || '900'; + const backoff = env.BACKOFF_START_DELAY; const enablePrebuiltProject = 'ENABLE_PREBUILT_PROJECT' in env; const notificationEmail = env.NOTIFICATION_EMAIL || 'notify@example.com'; const installerCmk = env.INSTALLER_CMK || `alias/${acceleratorPrefix}Installer-Key`; @@ -70,6 +71,7 @@ async function main() { installerCmk, codebuildComputeType, pageSize, + backoff, }); } diff --git a/src/core/cdk/src/initial-setup.ts b/src/core/cdk/src/initial-setup.ts index 2f8f66cc7..57f665d6c 100644 --- a/src/core/cdk/src/initial-setup.ts +++ b/src/core/cdk/src/initial-setup.ts @@ -57,6 +57,7 @@ export namespace InitialSetup { // eslint-disable-next-line @typescript-eslint/no-explicit-any codebuildComputeType: any; pageSize: string; + backoff: string | undefined; /** * Current Accelerator version */ @@ -264,6 +265,7 @@ export namespace InitialSetup { SUBNET_CIDR_ASSIGNED_POOL: subnetCidrPoolTable.tableName, CIDR_POOL: cidrPoolTable.tableName, DEPLOY_STACK_PAGE_SIZE: props.pageSize, + BACKOFF_START_DELAY: props.backoff || '', COMPUTE_TYPE: props.codebuildComputeType, }, }); diff --git a/src/deployments/cdk/src/common/alb-ip-forwarding.ts b/src/deployments/cdk/src/common/alb-ip-forwarding.ts index b79a36a2f..de0f68fab 100644 --- a/src/deployments/cdk/src/common/alb-ip-forwarding.ts +++ b/src/deployments/cdk/src/common/alb-ip-forwarding.ts @@ -59,7 +59,7 @@ export class AlbIpForwarding extends Construct { runtime: lambda.Runtime.NODEJS_14_X, code: lambdaCode, handler: 'index.albIpMonitor', - timeout: Duration.seconds(30), + timeout: Duration.seconds(60), environment: { LOOKUP_TABLE: ddbTable.tableName, }, @@ -82,7 +82,7 @@ export class AlbIpForwarding extends Construct { runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.albTargetRecordMonitor', code: lambdaCode, - timeout: Duration.seconds(30), + timeout: Duration.seconds(60), environment: { LOOKUP_TABLE: ddbTable.tableName, }, diff --git a/src/installer/cdk/src/index.ts b/src/installer/cdk/src/index.ts index d86385ce3..d82c9c9e8 100644 --- a/src/installer/cdk/src/index.ts +++ b/src/installer/cdk/src/index.ts @@ -115,6 +115,12 @@ class Installer extends cdk.Stack { default: 680, }); + const backoffStartDelay = new cdk.CfnParameter(this, 'Backoff Start Delay', { + description: + 'The start delay for exponential backoff of API calls in milliseconds. Leave at the default of 2000 unless needed.', + default: 2000, + }); + const stateMachineName = `${acceleratorPrefix}MainStateMachine_sm`; // The state machine name has to match the name of the state machine in initial setup @@ -322,6 +328,10 @@ class Installer extends cdk.Stack { type: codebuild.BuildEnvironmentVariableType.PLAINTEXT, value: stackDeployPageSize.valueAsString, }, + BACKOFF_START_DELAY: { + type: codebuild.BuildEnvironmentVariableType.PLAINTEXT, + value: backoffStartDelay.valueAsString, + }, }, }, cache: codebuild.Cache.local(codebuild.LocalCacheMode.SOURCE), diff --git a/src/lib/cdk-accelerator/src/core/accelerator-stack.ts b/src/lib/cdk-accelerator/src/core/accelerator-stack.ts index a813c0218..f46dc3e40 100644 --- a/src/lib/cdk-accelerator/src/core/accelerator-stack.ts +++ b/src/lib/cdk-accelerator/src/core/accelerator-stack.ts @@ -12,7 +12,7 @@ */ import * as cdk from '@aws-cdk/core'; -import { AcceleratorNameTagger, AcceleratorProtectedTagger } from '.'; +import { AcceleratorNameTagger, AcceleratorProtectedTagger, LambdaEnvironmentVariables, LambdaDefaultTimeout } from '.'; export interface AcceleratorStackProps extends cdk.StackProps { acceleratorName: string; @@ -34,6 +34,8 @@ export class AcceleratorStack extends cdk.Stack { cdk.Aspects.of(this).add(new cdk.Tag('Accelerator', this.acceleratorName)); cdk.Aspects.of(this).add(new AcceleratorNameTagger()); cdk.Aspects.of(this).add(new AcceleratorProtectedTagger(this.acceleratorName)); + cdk.Aspects.of(this).add(new LambdaEnvironmentVariables()); + cdk.Aspects.of(this).add(new LambdaDefaultTimeout()); } static of(construct: cdk.IConstruct): AcceleratorStack { diff --git a/src/lib/cdk-accelerator/src/core/index.ts b/src/lib/cdk-accelerator/src/core/index.ts index a38054f14..e58f07144 100644 --- a/src/lib/cdk-accelerator/src/core/index.ts +++ b/src/lib/cdk-accelerator/src/core/index.ts @@ -14,3 +14,5 @@ export * from './cfn-include'; export * from './name-tagger'; export * from './accelerator-protected-tagger'; +export * from './lambda-env-variables'; +export * from './lambda-default-timeout'; diff --git a/src/lib/cdk-accelerator/src/core/lambda-default-timeout.ts b/src/lib/cdk-accelerator/src/core/lambda-default-timeout.ts new file mode 100644 index 000000000..0f8acad69 --- /dev/null +++ b/src/lib/cdk-accelerator/src/core/lambda-default-timeout.ts @@ -0,0 +1,12 @@ +import * as cdk from '@aws-cdk/core'; +import * as lambda from '@aws-cdk/aws-lambda'; + +export class LambdaDefaultTimeout implements cdk.IAspect { + visit(node: cdk.IConstruct): void { + if (node instanceof lambda.CfnFunction) { + if (!node.timeout) { + node.timeout = 60; + } + } + } +} diff --git a/src/lib/cdk-accelerator/src/core/lambda-env-variables.ts b/src/lib/cdk-accelerator/src/core/lambda-env-variables.ts new file mode 100644 index 000000000..a50674a44 --- /dev/null +++ b/src/lib/cdk-accelerator/src/core/lambda-env-variables.ts @@ -0,0 +1,10 @@ +import * as cdk from '@aws-cdk/core'; +import * as lambda from '@aws-cdk/aws-lambda'; + +export class LambdaEnvironmentVariables implements cdk.IAspect { + visit(node: cdk.IConstruct): void { + if (node instanceof lambda.Function) { + node.addEnvironment('BACKOFF_START_DELAY', process.env['BACKOFF_START_DELAY'] || '2000'); + } + } +} diff --git a/src/lib/common/src/aws/backoff.ts b/src/lib/common/src/aws/backoff.ts index bec056d47..23ee07437 100644 --- a/src/lib/common/src/aws/backoff.ts +++ b/src/lib/common/src/aws/backoff.ts @@ -20,8 +20,24 @@ export function throttlingBackOff( request: () => Promise, options?: Partial>, ): Promise { + const defaultDelay = 500; + let maxDelayValue = 2000; + + if (process.env.BACKOFF_START_DELAY) { + const backoffStartDelay = parseInt(process.env.BACKOFF_START_DELAY, 10); + if (Number.isInteger(backoffStartDelay)) { + maxDelayValue = backoffStartDelay; + } + } + + // Add jitter to the starting delay + const startingDelay = Math.random() * (maxDelayValue - defaultDelay + 1) + defaultDelay; + + console.log(`throttlingBackOff delay set to ${startingDelay}`); + return backOff(request, { - startingDelay: 500, + startingDelay, + delayFirstAttempt: true, jitter: 'full', retry: isThrottlingError, ...options, @@ -34,6 +50,7 @@ export const isThrottlingError = (e: any) => e.code === 'ConcurrentModificationException' || // Retry for AWS Organizations e.code === 'InsufficientDeliveryPolicyException' || // Retry for ConfigService e.code === 'NoAvailableDeliveryChannelException' || // Retry for ConfigService + e.code === 'ConcurrentModifications' || // Retry for AssociateHostedZone e.code === 'TooManyRequestsException' || e.code === 'Throttling' || e.code === 'ThrottlingException' || diff --git a/src/lib/custom-resources/cdk-acm-import-certificate/cdk/index.ts b/src/lib/custom-resources/cdk-acm-import-certificate/cdk/index.ts index 76352f486..ee0f1cef6 100644 --- a/src/lib/custom-resources/cdk-acm-import-certificate/cdk/index.ts +++ b/src/lib/custom-resources/cdk-acm-import-certificate/cdk/index.ts @@ -122,7 +122,7 @@ export class AcmImportCertificate extends cdk.Construct implements cdk.ITaggable code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(10), + timeout: cdk.Duration.seconds(60), }); } } diff --git a/src/lib/custom-resources/cdk-cfn-utils/cdk/index.ts b/src/lib/custom-resources/cdk-cfn-utils/cdk/index.ts index a4b0d75cc..2a086040f 100644 --- a/src/lib/custom-resources/cdk-cfn-utils/cdk/index.ts +++ b/src/lib/custom-resources/cdk-cfn-utils/cdk/index.ts @@ -22,8 +22,24 @@ export function throttlingBackOff( request: () => Promise, options?: Partial>, ): Promise { + const defaultDelay = 500; + let maxDelayValue = 2000; + + if (process.env.BACKOFF_START_DELAY) { + const backoffStartDelay = parseInt(process.env.BACKOFF_START_DELAY, 10); + if (Number.isInteger(backoffStartDelay)) { + maxDelayValue = backoffStartDelay; + } + } + + // Add jitter to the starting delay + const startingDelay = Math.random() * (maxDelayValue - defaultDelay + 1) + defaultDelay; + + console.log(`throttlingBackOff delay set to ${startingDelay}`); + return backOff(request, { - startingDelay: 500, + startingDelay, + delayFirstAttempt: true, jitter: 'full', retry: isThrottlingError, ...options, diff --git a/src/lib/custom-resources/cdk-cur-report-definition/cdk/index.ts b/src/lib/custom-resources/cdk-cur-report-definition/cdk/index.ts index a809da332..6bf5c75e9 100644 --- a/src/lib/custom-resources/cdk-cur-report-definition/cdk/index.ts +++ b/src/lib/custom-resources/cdk-cur-report-definition/cdk/index.ts @@ -135,7 +135,7 @@ export class CurReportDefinition extends cdk.Construct { code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(10), + timeout: cdk.Duration.seconds(60), }); } } diff --git a/src/lib/custom-resources/cdk-ec2-ebs-default-encryption/cdk/index.ts b/src/lib/custom-resources/cdk-ec2-ebs-default-encryption/cdk/index.ts index b770dba30..ad1fcfb10 100644 --- a/src/lib/custom-resources/cdk-ec2-ebs-default-encryption/cdk/index.ts +++ b/src/lib/custom-resources/cdk-ec2-ebs-default-encryption/cdk/index.ts @@ -87,7 +87,7 @@ export class EbsDefaultEncryption extends cdk.Construct { code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(10), + timeout: cdk.Duration.seconds(60), }); } } diff --git a/src/lib/custom-resources/cdk-ec2-keypair/cdk/index.ts b/src/lib/custom-resources/cdk-ec2-keypair/cdk/index.ts index 5bbd9aeea..ff01e8138 100644 --- a/src/lib/custom-resources/cdk-ec2-keypair/cdk/index.ts +++ b/src/lib/custom-resources/cdk-ec2-keypair/cdk/index.ts @@ -100,7 +100,7 @@ export class Keypair extends cdk.Construct implements cdk.ITaggable { code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(10), + timeout: cdk.Duration.seconds(60), }); } } diff --git a/src/lib/custom-resources/cdk-kms-grant/cdk/index.ts b/src/lib/custom-resources/cdk-kms-grant/cdk/index.ts index dd75faeff..31122e398 100644 --- a/src/lib/custom-resources/cdk-kms-grant/cdk/index.ts +++ b/src/lib/custom-resources/cdk-kms-grant/cdk/index.ts @@ -118,7 +118,7 @@ export class Grant extends cdk.Construct { code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(10), + timeout: cdk.Duration.seconds(60), }); } } diff --git a/src/lib/custom-resources/cdk-s3-update-logarchive-bucket-policy/cdk/index.ts b/src/lib/custom-resources/cdk-s3-update-logarchive-bucket-policy/cdk/index.ts index 056e3219a..10b806f2f 100644 --- a/src/lib/custom-resources/cdk-s3-update-logarchive-bucket-policy/cdk/index.ts +++ b/src/lib/custom-resources/cdk-s3-update-logarchive-bucket-policy/cdk/index.ts @@ -106,7 +106,7 @@ export class S3UpdateLogArchivePolicy extends cdk.Construct { code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(30), + timeout: cdk.Duration.seconds(60), }); } } diff --git a/src/lib/custom-resources/ec2-ebs-default-encryption/lib/index.ts b/src/lib/custom-resources/ec2-ebs-default-encryption/lib/index.ts index b770dba30..ad1fcfb10 100644 --- a/src/lib/custom-resources/ec2-ebs-default-encryption/lib/index.ts +++ b/src/lib/custom-resources/ec2-ebs-default-encryption/lib/index.ts @@ -87,7 +87,7 @@ export class EbsDefaultEncryption extends cdk.Construct { code: lambda.Code.fromAsset(lambdaDir), handler: 'index.handler', role, - timeout: cdk.Duration.seconds(10), + timeout: cdk.Duration.seconds(60), }); } } From 07da113aa710e29d5a65ef583ccaad8b94002267 Mon Sep 17 00:00:00 2001 From: Elden Jahnke <94935251+ejahnke@users.noreply.github.com> Date: Fri, 30 Sep 2022 13:42:48 -0700 Subject: [PATCH 07/10] (docs): Eb faq doc update (#1055) * added Elastic Beanstalk entry to FAQ * Update index.md Co-authored-by: Jahnke --- src/mkdocs/docs/faq/index.md | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/mkdocs/docs/faq/index.md b/src/mkdocs/docs/faq/index.md index ae79cb5ad..4466de089 100644 --- a/src/mkdocs/docs/faq/index.md +++ b/src/mkdocs/docs/faq/index.md @@ -873,6 +873,48 @@ ![Logging](../installation/img/ASEA-Logging-Arch.png) +??? faq "1.6.17. How do I deploy AWS Elastic Beanstalk instances?" + + #### How do I deploy AWS Elastic Beanstalk instances? + + If your deployed environment contains an SCP enforcing volume encryption of EC2 instances, your Elastic Beanstalk deployment will fail. + + The SCP will contain an entry like this: + + ```json + { + "Sid": "EBS1", + "Effect": "Deny", + "Action": "ec2:RunInstances", + "Resource": "arn:aws:ec2:*:*:volume/*", + "Condition": { + "Bool": { + "ec2:Encrypted": "false" + } + } + }, + + ``` + A solution is to encrypt the root volume of the AMI that Elastic Beanstalk uses for your selected platform, and perform a custom AMI deployment of your Elastic Beanstalk application. + + You can gather the AMI that Elastic Beanstalk uses via CLI with the following command: + + ```bash + aws elasticbeanstalk describe-platform-version --region --platform-arn + ``` + + Once you have gathered the AMI ID successfully, go to the EC2 console and: + + - Click on the ‘AMIs’ option in the left navigation pane + - Search for your AMI after selecting ‘Public Images’ from the dropdown list. + - Select the AMI + - Go to Actions and Copy AMI + - Click on the checkbox to enable ‘Encryption’ and then select "Copy AMI". + + Once the AMI is successfully copied, you can use this AMI to specify a custom AMI in your Elastic Beanstalk environments with root volume encrypted. + + + ## 1.7. Network Architecture ??? faq "1.7.1. We want to securely connect our on-premises networks/datacenters to our AWS Cloud PBMM tenancy, what does AWS you recommend?" From b32f21796d2ba480c1104cbee836f4b94136e2ac Mon Sep 17 00:00:00 2001 From: Ryan Jaeger <41204211+rjjaegeraws@users.noreply.github.com> Date: Mon, 3 Oct 2022 10:50:36 -0700 Subject: [PATCH 08/10] (addon): OpenSearch SIEM added CW Alarms (#1056) * added CW Alarms * fix typo Co-authored-by: Brian969 <56414362+Brian969@users.noreply.github.com> --- .../Add-ons/opensiem/README.md | 14 + .../Add-ons/opensiem/SiemConfig.json | 2 + .../Add-ons/opensiem/lib/open-search.ts | 4 +- .../opensiem/lib/opensearch-siem-stack.ts | 24 +- .../Add-ons/opensiem/lib/siem-alerts.ts | 353 ++++++++++++++++++ .../Add-ons/opensiem/lib/siem-cognito.ts | 6 +- .../Add-ons/opensiem/lib/siem-config.ts | 2 + .../Add-ons/opensiem/package-lock.json | 52 ++- .../Add-ons/opensiem/package.json | 4 +- 9 files changed, 425 insertions(+), 36 deletions(-) create mode 100644 reference-artifacts/Add-ons/opensiem/lib/siem-alerts.ts diff --git a/reference-artifacts/Add-ons/opensiem/README.md b/reference-artifacts/Add-ons/opensiem/README.md index 54879a06e..47925f262 100644 --- a/reference-artifacts/Add-ons/opensiem/README.md +++ b/reference-artifacts/Add-ons/opensiem/README.md @@ -543,3 +543,17 @@ The following AWS resources are retained when deleting the solution: 2. In the operations account 1. navigate to S3, open the S3 bucket prefixed with **opensearchsiemstack-**, and delete all the objects inside 1. navigate to CloudFormation and delete the **OpenSearchSiemStack** stack + + +## 11. Updates + +### September 2022 +- Updated the CDK version to v2.40.0 +- Updated the OpenSearch cluster with the latest version 1.3 (will cause a Blue/Green Deployment) +- Updated the OpenSearch cluster to use GP3 for the EBS volume type (will cause a Blue/Green Deployment) +- Added 14 CloudWatch Alarms to monitor the OpenSearch cluster based on the recommendations [here](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/cloudwatch-alarms.html) +- Reduced the Lambda Processor memory to 512MB and changed timeout to 2 minutes +- Added a SNS queue to send alerts to registered emails. +- New configurations: + - "alertNotificationEmails": ["user@email.com"] CloudWatch Alarm will send notifications to emails listed here + - "enableLambdaInsights": true Will enable CloudWatch Lambda Insights. This brings visibility into memory usage to have data to fine tune the Processor Lambda. \ No newline at end of file diff --git a/reference-artifacts/Add-ons/opensiem/SiemConfig.json b/reference-artifacts/Add-ons/opensiem/SiemConfig.json index f65a80c23..208c61f45 100644 --- a/reference-artifacts/Add-ons/opensiem/SiemConfig.json +++ b/reference-artifacts/Add-ons/opensiem/SiemConfig.json @@ -54,5 +54,7 @@ "s3NotificationTopicNameOrExistingArn": "----- REPLACE -----", "enableLambdaSubscription": false, "organizationId": "----- REPLACE -----", + "enableLambdaInsights": false, + "alertNotificationEmails": [""], "siemVersion": "v2.6.1a" } \ No newline at end of file diff --git a/reference-artifacts/Add-ons/opensiem/lib/open-search.ts b/reference-artifacts/Add-ons/opensiem/lib/open-search.ts index 2d8e6c705..a80095ab3 100644 --- a/reference-artifacts/Add-ons/opensiem/lib/open-search.ts +++ b/reference-artifacts/Add-ons/opensiem/lib/open-search.ts @@ -98,7 +98,7 @@ export class OpenSearchDomain extends Construct { }); this.resource = new opensearch.CfnDomain(this, 'Domain', { - engineVersion: 'OpenSearch_1.1', + engineVersion: 'OpenSearch_1.3', domainName, clusterConfig: { dedicatedMasterEnabled: true, @@ -117,7 +117,7 @@ export class OpenSearchDomain extends Construct { ebsOptions: { ebsEnabled: true, volumeSize, - volumeType: 'gp2', + volumeType: 'gp3', }, advancedSecurityOptions: { internalUserDatabaseEnabled: false, diff --git a/reference-artifacts/Add-ons/opensiem/lib/opensearch-siem-stack.ts b/reference-artifacts/Add-ons/opensiem/lib/opensearch-siem-stack.ts index 12e6b2c82..8c0c1b7a0 100644 --- a/reference-artifacts/Add-ons/opensiem/lib/opensearch-siem-stack.ts +++ b/reference-artifacts/Add-ons/opensiem/lib/opensearch-siem-stack.ts @@ -23,12 +23,14 @@ import { SnsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources'; import * as events from 'aws-cdk-lib/aws-events'; import * as eventTargets from 'aws-cdk-lib/aws-events-targets'; import * as sns from 'aws-cdk-lib/aws-sns'; +import * as snsSubscriptions from 'aws-cdk-lib/aws-sns-subscriptions'; import * as sqs from 'aws-cdk-lib/aws-sqs'; import * as cognito from './siem-cognito'; import { SiemConfig } from './siem-config'; import * as opensearch from './open-search'; import { OpenSearchSiemConfigure } from './siem-configure'; import { OpenSearchSiemGeoIpInit } from './siem-geoip-download'; +import { Alerts } from './siem-alerts'; export interface OpenSearchSiemStackProps extends StackProps { provisionServiceLinkedRole?: boolean; @@ -251,14 +253,15 @@ export class OpenSearchSiemStack extends Stack { siemConfig.s3LogBuckets, siemConfig.siemVersion, siemConfig.enableLambdaSubscription, + siemConfig.enableLambdaInsights, siemConfig.s3NotificationTopicNameOrExistingArn, siemBucket, ); - this.configureSnsAlerts(this, kmsEncryptionKey); + this.configureSnsAlerts(this, kmsEncryptionKey, domain.name, siemConfig.alertNotificationEmails); } - configureSnsAlerts(scope: Construct, kmsKey: kms.Key) { + configureSnsAlerts(scope: Construct, kmsKey: kms.Key, clusterDomainName: string, alertEmails: string[]) { const snsAlertRole = new iam.Role(scope, 'SnsAlertRole', { roleName: 'opensearch-siem-sns-role', assumedBy: new iam.ServicePrincipal('es.amazonaws.com'), @@ -270,7 +273,18 @@ export class OpenSearchSiemStack extends Stack { masterKey: kmsKey, }); + if (alertEmails && alertEmails.length > 0) { + for (const email of alertEmails) { + snsAlertTopic.addSubscription(new snsSubscriptions.EmailSubscription(email)); + } + } + snsAlertTopic.grantPublish(snsAlertRole); + + new Alerts(scope, 'opensearch-siem-alerts', { + alertTopic: snsAlertTopic, + clusterDomainName, + }); } configureSiemProcessor( @@ -284,6 +298,7 @@ export class OpenSearchSiemStack extends Stack { s3LogBuckets: string[], siemVersion: string, enableTopicSubscription: boolean, + enableLambdaInsights: boolean, s3NotificationTopicNameOrExistingArn: string, geoIpUploadBucket?: s3.Bucket, ) { @@ -294,9 +309,9 @@ export class OpenSearchSiemStack extends Stack { code: lambda.Code.fromAsset('lambdas/siem-processor/os-loader.zip'), role: lambdaRole, handler: 'index.lambda_handler', - timeout: Duration.seconds(900), + timeout: Duration.minutes(2), vpc, - memorySize: 2048, + memorySize: 512, vpcSubnets: { subnetFilters: [ec2.SubnetFilter.byIds(domainSubnetIds)], }, @@ -310,6 +325,7 @@ export class OpenSearchSiemStack extends Stack { GEOIP_BUCKET: geoIpUploadBucket?.bucketName || '', SIEM_VERSION: siemVersion, }, + insightsVersion: enableLambdaInsights ? lambda.LambdaInsightsVersion.VERSION_1_0_135_0 : undefined, }); for (const logBucket of s3LogBuckets) { diff --git a/reference-artifacts/Add-ons/opensiem/lib/siem-alerts.ts b/reference-artifacts/Add-ons/opensiem/lib/siem-alerts.ts new file mode 100644 index 000000000..080b8207f --- /dev/null +++ b/reference-artifacts/Add-ons/opensiem/lib/siem-alerts.ts @@ -0,0 +1,353 @@ +/** + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance + * with the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +import * as cdk from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as sns from 'aws-cdk-lib/aws-sns'; +import * as cw from 'aws-cdk-lib/aws-cloudwatch'; +import * as cwActions from 'aws-cdk-lib/aws-cloudwatch-actions'; + +export interface AlertsProps { + alertTopic: sns.ITopic; + clusterDomainName: string; +} + +export class Alerts extends Construct { + constructor(scope: Construct, id: string, private readonly props: AlertsProps) { + super(scope, id); + + const { alertTopic, clusterDomainName } = props; + + // + // CloudWatch Alarm - ClusterStatus.red + // + const clusterStatusRedAlarm = new cw.Alarm(this, 'ClusterStatusRed', { + alarmName: 'OpenSearchSIEM-ClusterStatus.red >= 1', + alarmDescription: 'Email when ClusterStatus.red >=1, 1 time within 1 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 1, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'ClusterStatus.red', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusRedAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusRedAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - ClusterStatus.yellow + // + const clusterStatusYellowAlarm = new cw.Alarm(this, 'ClusterStatusYellow', { + alarmName: 'OpenSearchSIEM-ClusterStatus.yellow >= 1', + alarmDescription: 'Email when ClusterStatus.yellow >=1, 1 time within 1 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 1, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'ClusterStatus.yellow', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusYellowAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusYellowAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - FreeStorageSpace + // + const clusterStatusFreeStorageSpaceAlarm = new cw.Alarm(this, 'FreeStorageSpace', { + alarmName: 'OpenSearchSIEM-FreeStorageSpace <= 20480', + alarmDescription: 'Email when FreeStorageSpace <= 20480, 1 time within 1 minutes', + comparisonOperator: cw.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 20480, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'FreeStorageSpace', + statistic: cw.Statistic.MINIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusFreeStorageSpaceAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusFreeStorageSpaceAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - ClusterIndexWritesBlocked + // + const clusterStatusClusterIndexWritesBlockedAlarm = new cw.Alarm(this, 'ClusterIndexWritesBlocked', { + alarmName: 'OpenSearchSIEM-ClusterIndexWritesBlocked >= 1', + alarmDescription: 'Email when ClusterIndexWritesBlocked >= 1, 1 time within 1 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 1, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'ClusterIndexWritesBlocked', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(300), + }), + }); + clusterStatusClusterIndexWritesBlockedAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusClusterIndexWritesBlockedAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - AutomatedSnapshotFailure + // + const clusterStatusClusterAutomatedSnapshotFailureAlarm = new cw.Alarm(this, 'AutomatedSnapshotFailure', { + alarmName: 'OpenSearchSIEM-AutomatedSnapshotFailure >= 1', + alarmDescription: 'Email when AutomatedSnapshotFailure >= 1, 1 time within 1 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 1, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'AutomatedSnapshotFailure', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusClusterAutomatedSnapshotFailureAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusClusterAutomatedSnapshotFailureAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - CPUUtilization + // + const clusterStatusClusterCPUUtilizationAlarm = new cw.Alarm(this, 'CPUUtilization', { + alarmName: 'OpenSearchSIEM-CPUUtilization >= 80', + alarmDescription: 'Email when CPUUtilization >= 80, 3 times within 15 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 80, + evaluationPeriods: 3, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'CPUUtilization', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(900), + }), + }); + clusterStatusClusterCPUUtilizationAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusClusterCPUUtilizationAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - JVMMemoryPressure + // + const clusterStatusJVMMemoryPressureAlarm = new cw.Alarm(this, 'JVMMemoryPressure', { + alarmName: 'OpenSearchSIEM-JVMMemoryPressure >= 80', + alarmDescription: 'Email when JVMMemoryPressure >= 80, 3 times within 5 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 80, + evaluationPeriods: 3, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'JVMMemoryPressure', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(300), + }), + }); + clusterStatusJVMMemoryPressureAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusJVMMemoryPressureAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - MasterCPUUtilization + // + const clusterStatusMasterCPUUtilizationAlarm = new cw.Alarm(this, 'MasterCPUUtilization', { + alarmName: 'OpenSearchSIEM-MasterCPUUtilization >= 50', + alarmDescription: 'Email when MasterCPUUtilization >= 50, 3 times within 5 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 50, + evaluationPeriods: 3, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'MasterCPUUtilization', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(300), + }), + }); + clusterStatusMasterCPUUtilizationAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusMasterCPUUtilizationAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - MasterJVMMemoryPressure + // + const clusterStatusMasterJVMMemoryPressureAlarm = new cw.Alarm(this, 'MasterJVMMemoryPressure', { + alarmName: 'OpenSearchSIEM-MasterJVMMemoryPressure >= 80', + alarmDescription: 'Email when MasterJVMMemoryPressure >= 80, 1 times within 15 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 80, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'MasterJVMMemoryPressure', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(900), + }), + }); + clusterStatusMasterJVMMemoryPressureAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusMasterJVMMemoryPressureAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - Shards.active + // + const clusterStatusShardsActiveAlarm = new cw.Alarm(this, 'ShardsActive', { + alarmName: 'OpenSearchSIEM-ShardsActive >= 30000', + alarmDescription: 'Email when ShardsActive >= 30000, 1 times within 1 minutes', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 30000, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'Shards.active', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusShardsActiveAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusShardsActiveAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - MasterReachableFromNode + // + const clusterStatusMasterReachableFromNodeAlarm = new cw.Alarm(this, 'MasterReachableFromNode', { + alarmName: 'OpenSearchSIEM-MasterReachableFromNode < 1', + alarmDescription: 'Email when MasterReachableFromNode < 1, 1 times within 1 day', + comparisonOperator: cw.ComparisonOperator.LESS_THAN_THRESHOLD, + threshold: 1, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'MasterReachableFromNode', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.days(1), + }), + }); + clusterStatusMasterReachableFromNodeAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusMasterReachableFromNodeAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - ThreadpoolWriteQueue + // + const clusterStatusThreadpoolWriteQueueAlarm = new cw.Alarm(this, 'ThreadpoolWriteQueue', { + alarmName: 'OpenSearchSIEM-ThreadpoolWriteQueue average >= 100', + alarmDescription: 'Email when ThreadpoolWriteQueue >= 100, 1 times within 1 minute', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 100, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'ThreadpoolWriteQueue', + statistic: cw.Statistic.AVERAGE, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusThreadpoolWriteQueueAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusThreadpoolWriteQueueAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - ThreadpoolSearchQueue + // + const clusterStatusThreadpoolSearchQueueAlarm = new cw.Alarm(this, 'ThreadpoolSearchQueue', { + alarmName: 'OpenSearchSIEM-ThreadpoolSearchQueue average >= 500', + alarmDescription: 'Email when average ThreadpoolSearchQueue >= 500, 1 times within 1 minute', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 500, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'ThreadpoolSearchQueue', + statistic: cw.Statistic.AVERAGE, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusThreadpoolSearchQueueAlarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusThreadpoolSearchQueueAlarm.addOkAction(new cwActions.SnsAction(alertTopic)); + + // + // CloudWatch Alarm - ThreadpoolSearchQueue5000 + // + const clusterStatusThreadpoolSearchQueue5000Alarm = new cw.Alarm(this, 'ThreadpoolSearchQueue5000', { + alarmName: 'OpenSearchSIEM-ThreadpoolSearchQueue >= 5000', + alarmDescription: 'Email when ThreadpoolSearchQueue >= 5000, 1 times within 1 minute', + comparisonOperator: cw.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + threshold: 5000, + evaluationPeriods: 1, + metric: new cw.Metric({ + namespace: 'AWS/ES', + metricName: 'ThreadpoolSearchQueue', + statistic: cw.Statistic.MAXIMUM, + dimensionsMap: { + ClientId: cdk.Stack.of(this).account, + DomainName: clusterDomainName, + }, + period: cdk.Duration.seconds(60), + }), + }); + clusterStatusThreadpoolSearchQueue5000Alarm.addAlarmAction(new cwActions.SnsAction(alertTopic)); + clusterStatusThreadpoolSearchQueue5000Alarm.addOkAction(new cwActions.SnsAction(alertTopic)); + } +} diff --git a/reference-artifacts/Add-ons/opensiem/lib/siem-cognito.ts b/reference-artifacts/Add-ons/opensiem/lib/siem-cognito.ts index f4799a106..79f368d9a 100644 --- a/reference-artifacts/Add-ons/opensiem/lib/siem-cognito.ts +++ b/reference-artifacts/Add-ons/opensiem/lib/siem-cognito.ts @@ -103,7 +103,11 @@ export class CognitoUserPool extends Construct { const { userPoolName, usernameAttributes } = props; - const externalId: string = Math.random().toString(11).slice(2); + let externalId: string = this.node.tryGetContext('externalId'); + + if (!externalId) { + externalId = Math.random().toString(11).slice(2); + } const snsRole = new iam.Role(this, 'MfaSnsRole', { assumedBy: new iam.ServicePrincipal('cognito-idp.amazonaws.com'), diff --git a/reference-artifacts/Add-ons/opensiem/lib/siem-config.ts b/reference-artifacts/Add-ons/opensiem/lib/siem-config.ts index f47090d53..8ba896547 100644 --- a/reference-artifacts/Add-ons/opensiem/lib/siem-config.ts +++ b/reference-artifacts/Add-ons/opensiem/lib/siem-config.ts @@ -56,6 +56,8 @@ export interface SiemConfig { enableLambdaSubscription: boolean; s3NotificationTopicNameOrExistingArn: string; organizationId: string; + alertNotificationEmails: string[]; + enableLambdaInsights: boolean; } export async function loadSiemConfig(): Promise { diff --git a/reference-artifacts/Add-ons/opensiem/package-lock.json b/reference-artifacts/Add-ons/opensiem/package-lock.json index cd273f0d7..a3c731cea 100644 --- a/reference-artifacts/Add-ons/opensiem/package-lock.json +++ b/reference-artifacts/Add-ons/opensiem/package-lock.json @@ -8,7 +8,7 @@ "name": "aws-asea-opensearch-siem", "version": "0.1.0", "dependencies": { - "aws-cdk-lib": "2.17.0", + "aws-cdk-lib": "2.40.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" }, @@ -20,7 +20,7 @@ "@types/node": "10.17.27", "@typescript-eslint/eslint-plugin": "4.22.0", "@typescript-eslint/parser": "4.22.0", - "aws-cdk": "2.17.0", + "aws-cdk": "2.40.0", "eslint": "7.25.0", "eslint-config-prettier": "8.3.0", "eslint-plugin-deprecation": "1.2.0", @@ -1632,9 +1632,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.17.0.tgz", - "integrity": "sha512-gRPPpTONOjtQ40A8sc2SzXPGDzFlVbSPPts1pjOx4VBJ2S91A0ON3Fkby+XX/Xqdo1GITTWAk5Va4PnoYyUhmA==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.40.0.tgz", + "integrity": "sha512-oHacGkLFDELwhpJsZSAhFHWDxIeZW3DgKkwiXlNO81JxNfjcHgPR2rsbh/Gz+n4ErAEzOV6WfuWVMe68zv+iPg==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -1647,9 +1647,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.17.0.tgz", - "integrity": "sha512-bga2HptbGx3rMdSkIKxBS13miogj/DHB2VPfQZAoKoCOAanOot+M3mHhYqe5aNdxhrppaRjG2eid2p1/MvRnvg==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.40.0.tgz", + "integrity": "sha512-AHDPU4I+WP3x+8W2TcSNPDhiA1wmvYkhaz5VjsQ9bqrnu2tJhcQaYkJCUu49MOVfUDpWYp9DnZIL0Yirlp5X6w==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -1666,10 +1666,10 @@ "case": "1.6.3", "fs-extra": "^9.1.0", "ignore": "^5.2.0", - "jsonschema": "^1.4.0", + "jsonschema": "^1.4.1", "minimatch": "^3.1.2", "punycode": "^2.1.1", - "semver": "^7.3.5", + "semver": "^7.3.7", "yaml": "1.10.2" }, "engines": { @@ -1734,7 +1734,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/graceful-fs": { - "version": "4.2.9", + "version": "4.2.10", "inBundle": true, "license": "ISC" }, @@ -1758,7 +1758,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/jsonschema": { - "version": "1.4.0", + "version": "1.4.1", "inBundle": true, "license": "MIT", "engines": { @@ -1796,7 +1796,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.3.5", + "version": "7.3.7", "inBundle": true, "license": "ISC", "dependencies": { @@ -7306,7 +7306,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -9967,27 +9966,27 @@ "dev": true }, "aws-cdk": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.17.0.tgz", - "integrity": "sha512-gRPPpTONOjtQ40A8sc2SzXPGDzFlVbSPPts1pjOx4VBJ2S91A0ON3Fkby+XX/Xqdo1GITTWAk5Va4PnoYyUhmA==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.40.0.tgz", + "integrity": "sha512-oHacGkLFDELwhpJsZSAhFHWDxIeZW3DgKkwiXlNO81JxNfjcHgPR2rsbh/Gz+n4ErAEzOV6WfuWVMe68zv+iPg==", "dev": true, "requires": { "fsevents": "2.3.2" } }, "aws-cdk-lib": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.17.0.tgz", - "integrity": "sha512-bga2HptbGx3rMdSkIKxBS13miogj/DHB2VPfQZAoKoCOAanOot+M3mHhYqe5aNdxhrppaRjG2eid2p1/MvRnvg==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.40.0.tgz", + "integrity": "sha512-AHDPU4I+WP3x+8W2TcSNPDhiA1wmvYkhaz5VjsQ9bqrnu2tJhcQaYkJCUu49MOVfUDpWYp9DnZIL0Yirlp5X6w==", "requires": { "@balena/dockerignore": "^1.0.2", "case": "1.6.3", "fs-extra": "^9.1.0", "ignore": "^5.2.0", - "jsonschema": "^1.4.0", + "jsonschema": "^1.4.1", "minimatch": "^3.1.2", "punycode": "^2.1.1", - "semver": "^7.3.5", + "semver": "^7.3.7", "yaml": "1.10.2" }, "dependencies": { @@ -10030,7 +10029,7 @@ } }, "graceful-fs": { - "version": "4.2.9", + "version": "4.2.10", "bundled": true }, "ignore": { @@ -10046,7 +10045,7 @@ } }, "jsonschema": { - "version": "1.4.0", + "version": "1.4.1", "bundled": true }, "lru-cache": { @@ -10068,7 +10067,7 @@ "bundled": true }, "semver": { - "version": "7.3.5", + "version": "7.3.7", "bundled": true, "requires": { "lru-cache": "^6.0.0" @@ -14248,8 +14247,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "set-blocking": { "version": "2.0.0", diff --git a/reference-artifacts/Add-ons/opensiem/package.json b/reference-artifacts/Add-ons/opensiem/package.json index fcaa8594d..042aca2bf 100644 --- a/reference-artifacts/Add-ons/opensiem/package.json +++ b/reference-artifacts/Add-ons/opensiem/package.json @@ -19,7 +19,7 @@ "devDependencies": { "@types/jest": "^26.0.10", "@types/node": "10.17.27", - "aws-cdk": "2.17.0", + "aws-cdk": "2.40.0", "jest": "^26.4.2", "ts-jest": "^26.2.0", "ts-node": "^9.0.0", @@ -37,7 +37,7 @@ "eslint-plugin-unicorn": "31.0.0" }, "dependencies": { - "aws-cdk-lib": "2.17.0", + "aws-cdk-lib": "2.40.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } From b8de5774aafe93656c587290d1f3a29c6e796a20 Mon Sep 17 00:00:00 2001 From: Ryan Jaeger <41204211+rjjaegeraws@users.noreply.github.com> Date: Mon, 3 Oct 2022 16:59:01 -0700 Subject: [PATCH 09/10] (enhancement): Frequency for updated findings for GuardDuty (#1057) * add frequency for GuardDuty * update sample config files with new config option --- .../SAMPLE_CONFIGS/config.example.json | 1 + .../config.lite-CTNFW-example.json | 1 + .../config.lite-GWLB-example.json | 1 + .../config.lite-NFW-example.json | 1 + .../config.lite-VPN-example.json | 1 + .../config.multi-region-example.json | 1 + .../SAMPLE_CONFIGS/config.test-example.json | 1 + .../config.ultralite-CT-example.json | 1 + .../config.ultralite-example.json | 1 + .../src/deployments/guardduty/guardduty.ts | 21 +++++++++++++++++++ src/lib/config-i18n/src/en.ts | 5 +++++ src/lib/config-i18n/src/fr.ts | 4 ++++ src/lib/config/src/config.v2.ts | 1 + .../cdk-guardduty-admin-setup/cdk/index.ts | 3 +++ .../runtime/src/index.ts | 20 ++++++++++++++---- 15 files changed, 59 insertions(+), 4 deletions(-) diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.example.json b/reference-artifacts/SAMPLE_CONFIGS/config.example.json index 42bc2f0e7..e7b5d7264 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json index da29f7a0d..3833d6f8b 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json @@ -74,6 +74,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json index 095db3dae..34fa6275a 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json index 51f9cad1a..189cb2377 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json @@ -56,6 +56,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json index e681b6ab7..9ef0c4c38 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json index 1ab587275..59dd52d4f 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json @@ -61,6 +61,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [], diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json index f444e5ba7..811a7d0c2 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json @@ -73,6 +73,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, "config-excl-regions": [ diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json index 9b1016889..8219ca0b7 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json @@ -37,6 +37,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json index b3e5b83e0..3e85d2499 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json @@ -35,6 +35,7 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", "access-analyzer": true, diff --git a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts index bba98a581..eae03a937 100644 --- a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts +++ b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts @@ -23,6 +23,12 @@ import { GuardDutyAdminSetup } from '@aws-accelerator/custom-resource-guardduty- import { IamRoleOutputFinder } from '@aws-accelerator/common-outputs/src/iam-role'; import { StackOutput } from '@aws-accelerator/common-outputs/src/stack-output'; +export enum GuardDutyFrequency { + FIFTEEN_MINUTES = 'FIFTEEN_MINUTES', + ONE_HOUR = 'ONE_HOUR', + SIX_HOURS = 'SIX_HOURS', +} + export interface GuardDutyStepProps { accountStacks: AccountStacks; config: AcceleratorConfig; @@ -110,12 +116,14 @@ export async function step2(props: GuardDutyStepProps) { })); const centralServiceConfig = props.config['global-options']['central-security-services']; const s3ProtectionExclRegions = centralServiceConfig['guardduty-s3-excl-regions'] || []; + const frequency = await getFrequency(props.config); regions?.map(region => { const masterAccountStack = props.accountStacks.getOrCreateAccountStack(masterAccountKey, region); new GuardDutyAdminSetup(masterAccountStack, 'GuardDutyAdminSetup', { memberAccounts: accountDetails, roleArn: adminSetupRoleOutput.roleArn, s3Protection: centralServiceConfig['guardduty-s3'] && !s3ProtectionExclRegions.includes(region), + frequency, }); }); } @@ -197,3 +205,16 @@ export async function getValidRegions(config: AcceleratorConfig) { const validRegions = regions.filter(x => !excl?.includes(x)); return validRegions; } + +export async function getFrequency(config: AcceleratorConfig) { + const frequency = config['global-options']['central-security-services']['guardduty-frequency']; + if (frequency === GuardDutyFrequency.SIX_HOURS) { + return GuardDutyFrequency.SIX_HOURS; + } else if (frequency === GuardDutyFrequency.ONE_HOUR) { + return GuardDutyFrequency.ONE_HOUR; + } else if (frequency === GuardDutyFrequency.FIFTEEN_MINUTES) { + return GuardDutyFrequency.FIFTEEN_MINUTES; + } else { + return GuardDutyFrequency.SIX_HOURS; + } +} diff --git a/src/lib/config-i18n/src/en.ts b/src/lib/config-i18n/src/en.ts index 3b2fc030d..908a3c9fd 100644 --- a/src/lib/config-i18n/src/en.ts +++ b/src/lib/config-i18n/src/en.ts @@ -2807,6 +2807,11 @@ translate(c.CentralServicesConfigType, { title: 'GuardDuty S3 Protection Exclusion Regions', description: 'List of excluded regions from Guardduty S3 protection. [SECURITY]', }, + 'guardduty-frequency': { + title: 'Update Frequency for Policy Findings', + description: + 'The schedule GuardDuty uses to publish updates to policy findings. Supported values are: FIFTEEN_MINUTES, ONE_HOUR, SIX_HOURS. [SECURITY]', + }, 'access-analyzer': { title: '', description: diff --git a/src/lib/config-i18n/src/fr.ts b/src/lib/config-i18n/src/fr.ts index f515c353f..0c122d386 100644 --- a/src/lib/config-i18n/src/fr.ts +++ b/src/lib/config-i18n/src/fr.ts @@ -2609,6 +2609,10 @@ translate(c.CentralServicesConfigType, { title: '', description: '', }, + 'guardduty-frequency': { + title: '', + description: '', + }, 'access-analyzer': { title: '', description: '', diff --git a/src/lib/config/src/config.v2.ts b/src/lib/config/src/config.v2.ts index 402aa2d31..b1a1f5e71 100644 --- a/src/lib/config/src/config.v2.ts +++ b/src/lib/config/src/config.v2.ts @@ -907,6 +907,7 @@ export const CentralServicesConfigType = t.interface({ 'guardduty-excl-regions': t.optional(t.array(t.nonEmptyString)), 'guardduty-s3': t.defaulted(t.boolean, false), 'guardduty-s3-excl-regions': t.optional(t.array(t.nonEmptyString)), + 'guardduty-frequency': t.optional(t.nonEmptyString), 'access-analyzer': t.defaulted(t.boolean, false), cwl: t.defaulted(t.boolean, false), 'cwl-access-level': t.optional(t.nonEmptyString), diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts index e7c8c0636..91118019f 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts @@ -15,6 +15,7 @@ import * as path from 'path'; import * as cdk from '@aws-cdk/core'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; +import { GuardDutyFrequency } from '@aws-accelerator/custom-resource-guardduty-admin-setup-runtime'; const resourceType = 'Custom::GuardDutyAdminSetup'; @@ -27,6 +28,7 @@ export interface GuardDutyAdminSetupProps { memberAccounts: AccountDetail[]; roleArn: string; s3Protection: boolean; + frequency: GuardDutyFrequency; } /** @@ -43,6 +45,7 @@ export class GuardDutyAdminSetup extends cdk.Construct { const handlerProperties = { memberAccounts: props.memberAccounts, s3Protection: props.s3Protection, + frequency: props.frequency, }; const adminSetup = this.lambdaFunction(props.roleArn); diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts index e255b5f55..4a83722c0 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts @@ -28,6 +28,12 @@ const guardduty = new AWS.GuardDuty(); // Guardduty CreateMembers, UpdateMembers and DeleteMembers apis only supports max 50 accounts per request const pageSize = 50; +export enum GuardDutyFrequency { + FIFTEEN_MINUTES = 'FIFTEEN_MINUTES', + ONE_HOUR = 'ONE_HOUR', + SIX_HOURS = 'SIX_HOURS', +} + export interface AccountDetail { AccountId: string; Email: string; @@ -37,6 +43,7 @@ export interface HandlerProperties { deligatedAdminAccountId: string; memberAccounts: AccountDetail[]; s3Protection: boolean; + frequency: GuardDutyFrequency; } export const handler = errorHandler(onEvent); @@ -69,8 +76,8 @@ async function onCreateOrUpdate( }; } - const { memberAccounts, s3Protection } = properties; - await updateS3Protection(detectorId, s3Protection); + const { memberAccounts, s3Protection, frequency } = properties; + await updateS3ProtectionAndFrequency(detectorId, s3Protection, frequency); const isAutoEnabled = await isConfigurationAutoEnabled(detectorId, s3Protection); if (!isAutoEnabled) { @@ -209,7 +216,11 @@ async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorI } } -async function updateS3Protection(detectorId: string, s3Protection: boolean) { +async function updateS3ProtectionAndFrequency( + detectorId: string, + s3Protection: boolean, + frequency?: GuardDutyFrequency, +) { try { await throttlingBackOff(() => guardduty @@ -220,6 +231,7 @@ async function updateS3Protection(detectorId: string, s3Protection: boolean) { Enable: s3Protection, }, }, + FindingPublishingFrequency: frequency, }) .promise(), ); @@ -288,7 +300,7 @@ async function onDelete(event: CloudFormationCustomResourceDeleteEvent) { const { memberAccounts } = properties; try { const detectorId = await getDetectorId(); - await updateS3Protection(detectorId!, false); + await updateS3ProtectionAndFrequency(detectorId!, false, undefined); await updateConfig(detectorId!, false, false); await updateMemberDataSource(memberAccounts, detectorId!, false); await deleteMembers(memberAccounts, detectorId!); From 4a1ba63b347d94e6ecd4b3a60bbc6719f3a418dc Mon Sep 17 00:00:00 2001 From: Ryan Jaeger Date: Fri, 16 Sep 2022 13:45:04 -0700 Subject: [PATCH 10/10] add guardduty eks support --- pnpm-lock.yaml | 302 ++++++++++++++++-- .../SAMPLE_CONFIGS/config.example.json | 2 + .../config.lite-CTNFW-example.json | 2 + .../config.lite-GWLB-example.json | 2 + .../config.lite-NFW-example.json | 2 + .../config.lite-VPN-example.json | 2 + .../config.multi-region-example.json | 2 + .../SAMPLE_CONFIGS/config.test-example.json | 2 + .../config.ultralite-CT-example.json | 2 + .../config.ultralite-example.json | 2 + .../src/deployments/guardduty/guardduty.ts | 2 + src/lib/config-i18n/src/en.ts | 9 + src/lib/config-i18n/src/fr.ts | 8 + src/lib/config/src/config.v2.ts | 2 + .../cdk-guardduty-admin-setup/cdk/index.ts | 2 + .../runtime/package.json | 4 +- .../runtime/src/index.ts | 70 ++-- 17 files changed, 364 insertions(+), 53 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 062f25756..b1f35acfa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1630,14 +1630,14 @@ importers: '@types/aws-lambda': 8.10.76 '@types/node': 14.14.31 aws-lambda: 1.0.6 - aws-sdk: 2.944.0 + aws-sdk: 2.1217.0 esbuild: 0.11.18 typescript: 4.2.4 dependencies: '@aws-accelerator/custom-resource-cfn-utils': link:../../cdk-cfn-utils '@aws-accelerator/custom-resource-runtime-cfn-response': link:../../runtime-cfn-response aws-lambda: 1.0.6 - aws-sdk: 2.944.0 + aws-sdk: 2.1217.0 devDependencies: '@types/aws-lambda': 8.10.76 '@types/node': 14.14.31 @@ -5306,6 +5306,8 @@ packages: /@aws-cdk/cdk-assets-schema/1.44.0: resolution: {integrity: sha512-FeII0+Avnin3xemZR56gcsqbOosWdQ7i3L8C+JuZRPgCNMc8uvsH7rB6QditTbw6l43rGMLnlEbtHVobPVRnKg==} engines: {node: '>= 10.13.0 <13 || >=13.7.0'} + dependencies: + semver: 7.3.5 dev: false bundledDependencies: - semver @@ -5329,6 +5331,9 @@ packages: /@aws-cdk/cloud-assembly-schema/1.44.0: resolution: {integrity: sha512-n/jln7teKE7o5ZYJ6o6+Jix4nRluC3hNFt+KYzEuVYOAkL0Mwoj92FpJnHkqU5jh0vw6K3OAd5Bq8+fICzEgaQ==} engines: {node: '>= 10.13.0 <13 || >=13.7.0'} + dependencies: + jsonschema: 1.4.0 + semver: 7.3.5 dev: false bundledDependencies: - jsonschema @@ -5567,6 +5572,7 @@ packages: '@aws-cdk/cloud-assembly-schema': 1.44.0 '@aws-cdk/cx-api': 1.44.0 constructs: 3.3.71 + minimatch: 3.0.5 dev: false bundledDependencies: - minimatch @@ -5598,6 +5604,7 @@ packages: engines: {node: '>= 10.13.0 <13 || >=13.7.0'} dependencies: '@aws-cdk/cloud-assembly-schema': 1.44.0 + semver: 7.3.5 dev: false bundledDependencies: - semver @@ -12405,6 +12412,11 @@ packages: postcss-value-parser: 4.1.0 dev: true + /available-typed-arrays/1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: false + /aws-cdk/1.144.0: resolution: {integrity: sha512-4sVYurq8CYwl+glnRtMBBa2vQ3RI63K9gVPQtMaqCFR2SEj4+U2e2rX/zU29ko0Lzm+OQxS1UbaklMM4KaFo3A==} engines: {node: '>= 10.13.0 <13 || >=13.7.0'} @@ -12463,6 +12475,22 @@ packages: uuid: 3.3.2 xml2js: 0.4.19 + /aws-sdk/2.1217.0: + resolution: {integrity: sha512-Mem3YD+vevt0qNg1aKB+7jdM2UMRIW2b3L5YDHzCctukndh91Y0rpy+EypPo4GXhQv5lfP+H9h+Csh/dvOQJiw==} + engines: {node: '>= 10.0.0'} + dependencies: + buffer: 4.9.2 + events: 1.1.1 + ieee754: 1.1.13 + jmespath: 0.16.0 + querystring: 0.2.0 + sax: 1.2.1 + url: 0.10.3 + util: 0.12.4 + uuid: 8.0.0 + xml2js: 0.4.19 + dev: false + /aws-sdk/2.944.0: resolution: {integrity: sha512-QHKDbs/og1kUhOZsE6A8KN/Rw3LHkfEWBqziRaWDNoijDZzY9XlbLHnLmpkluCe4HNKY1KOOyBajhf2CkJahcQ==} engines: {node: '>= 0.8.0'} @@ -13232,7 +13260,6 @@ packages: dependencies: function-bind: 1.1.1 get-intrinsic: 1.1.1 - dev: true /call-me-maybe/1.0.1: resolution: {integrity: sha1-JtII6onje1y95gJQoV8DHBak1ms=} @@ -13720,6 +13747,7 @@ packages: /constructs/3.3.71: resolution: {integrity: sha512-3KFtTsA7OV27m/+pJhN4iJkKzHbPIPvyvEX5BQ/JCAWjfCHOQEVpIgxHLpT4i8L1OFta+pJrzcEVAHo6UitwqA==} engines: {node: '>= 10.17.0'} + bundledDependencies: [] /contains-path/0.1.0: resolution: {integrity: sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=} @@ -14359,7 +14387,14 @@ packages: engines: {node: '>= 0.4'} dependencies: object-keys: 1.1.1 - dev: true + + /define-properties/1.1.4: + resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: false /define-property/0.2.5: resolution: {integrity: sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=} @@ -14780,14 +14815,42 @@ packages: unbox-primitive: 1.0.1 dev: true + /es-abstract/1.20.2: + resolution: {integrity: sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + es-to-primitive: 1.2.1 + function-bind: 1.1.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.1.3 + get-symbol-description: 1.0.0 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-symbols: 1.0.3 + internal-slot: 1.0.3 + is-callable: 1.2.6 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-weakref: 1.0.2 + object-inspect: 1.12.2 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + string.prototype.trimend: 1.0.5 + string.prototype.trimstart: 1.0.5 + unbox-primitive: 1.0.2 + dev: false + /es-to-primitive/1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: - is-callable: 1.2.3 + is-callable: 1.2.6 is-date-object: 1.0.2 is-symbol: 1.0.3 - dev: true /es5-ext/0.10.53: resolution: {integrity: sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==} @@ -15376,7 +15439,7 @@ packages: dev: true /events/1.1.1: - resolution: {integrity: sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=} + resolution: {integrity: sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==} engines: {node: '>=0.4.x'} /events/3.3.0: @@ -15767,6 +15830,12 @@ packages: debug: 4.3.1_supports-color@6.1.0 dev: true + /for-each/0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.3 + dev: false + /for-in/1.0.2: resolution: {integrity: sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=} engines: {node: '>=0.10.0'} @@ -15913,12 +15982,25 @@ packages: /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true + + /function.prototype.name/1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.20.2 + functions-have-names: 1.2.3 + dev: false /functional-red-black-tree/1.0.1: resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} dev: true + /functions-have-names/1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: false + /gensync/1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -15934,7 +16016,13 @@ packages: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.2 - dev: true + + /get-intrinsic/1.1.3: + resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 /get-own-enumerable-property-symbols/3.0.2: resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} @@ -15964,6 +16052,14 @@ packages: pump: 3.0.0 dev: true + /get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + dev: false + /get-uri/3.0.2: resolution: {integrity: sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==} engines: {node: '>= 6'} @@ -16170,6 +16266,10 @@ packages: resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==} dev: true + /has-bigints/1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: false + /has-flag/3.0.0: resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} engines: {node: '>=4'} @@ -16179,10 +16279,25 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + /has-property-descriptors/1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.1.3 + dev: false + /has-symbols/1.0.2: resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==} engines: {node: '>= 0.4'} - dev: true + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.2 /has-value/0.3.1: resolution: {integrity: sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=} @@ -16220,7 +16335,6 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: true /hash-base/3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} @@ -16631,10 +16745,9 @@ packages: resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.1.1 + get-intrinsic: 1.1.3 has: 1.0.3 side-channel: 1.0.4 - dev: true /io-ts-types/0.5.16_io-ts@2.2.16: resolution: {integrity: sha512-h9noYVfY9rlbmKI902SJdnV/06jgiT2chxG6lYDxaYNp88HscPi+SBCtmcU+m0E7WT5QSwt7sIMj93+qu0FEwQ==} @@ -16730,7 +16843,6 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - dev: true /is-arrayish/0.2.1: resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} @@ -16742,7 +16854,6 @@ packages: /is-bigint/1.0.1: resolution: {integrity: sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==} - dev: true /is-binary-path/1.0.1: resolution: {integrity: sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=} @@ -16762,7 +16873,6 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - dev: true /is-buffer/1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} @@ -16777,7 +16887,10 @@ packages: /is-callable/1.2.3: resolution: {integrity: sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==} engines: {node: '>= 0.4'} - dev: true + + /is-callable/1.2.6: + resolution: {integrity: sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==} + engines: {node: '>= 0.4'} /is-ci/2.0.0: resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} @@ -16820,7 +16933,6 @@ packages: /is-date-object/1.0.2: resolution: {integrity: sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==} engines: {node: '>= 0.4'} - dev: true /is-descriptor/0.1.6: resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} @@ -16881,6 +16993,13 @@ packages: engines: {node: '>=6'} dev: true + /is-generator-function/1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + /is-glob/3.1.0: resolution: {integrity: sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=} engines: {node: '>=0.10.0'} @@ -16903,10 +17022,14 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-negative-zero/2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: false + /is-number-object/1.0.4: resolution: {integrity: sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==} engines: {node: '>= 0.4'} - dev: true /is-number/3.0.0: resolution: {integrity: sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=} @@ -16979,6 +17102,14 @@ packages: has-symbols: 1.0.2 dev: true + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + /is-regexp/1.0.0: resolution: {integrity: sha1-/S2INUXEa6xaYz57mgnof6LLUGk=} engines: {node: '>=0.10.0'} @@ -16993,6 +17124,12 @@ packages: engines: {node: '>=6'} dev: true + /is-shared-array-buffer/1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: false + /is-stream/1.1.0: resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} engines: {node: '>=0.10.0'} @@ -17007,17 +17144,39 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + /is-symbol/1.0.3: resolution: {integrity: sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==} engines: {node: '>= 0.4'} dependencies: - has-symbols: 1.0.2 - dev: true + has-symbols: 1.0.3 + + /is-typed-array/1.1.9: + resolution: {integrity: sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-abstract: 1.20.2 + for-each: 0.3.3 + has-tostringtag: 1.0.0 + dev: false /is-typedarray/1.0.0: resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=} dev: true + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: false + /is-windows/1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -17039,7 +17198,7 @@ packages: resolution: {integrity: sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=} /isarray/1.0.0: - resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} /isexe/2.0.0: resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} @@ -18028,6 +18187,11 @@ packages: resolution: {integrity: sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=} engines: {node: '>= 0.6.0'} + /jmespath/0.16.0: + resolution: {integrity: sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==} + engines: {node: '>= 0.6.0'} + dev: false + /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -19175,6 +19339,9 @@ packages: kind-of: 3.2.2 dev: true + /object-inspect/1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + /object-inspect/1.9.0: resolution: {integrity: sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==} dev: true @@ -19190,7 +19357,6 @@ packages: /object-keys/1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - dev: true /object-visit/1.0.1: resolution: {integrity: sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=} @@ -19209,6 +19375,16 @@ packages: object-keys: 1.1.1 dev: true + /object.assign/4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + /object.entries/1.1.3: resolution: {integrity: sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==} engines: {node: '>= 0.4'} @@ -20557,7 +20733,7 @@ packages: dev: true /punycode/1.3.2: - resolution: {integrity: sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=} + resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} @@ -20592,7 +20768,7 @@ packages: dev: true /querystring/0.2.0: - resolution: {integrity: sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=} + resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} engines: {node: '>=0.4.x'} deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. @@ -21092,6 +21268,15 @@ packages: define-properties: 1.1.3 dev: true + /regexp.prototype.flags/1.4.3: + resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + functions-have-names: 1.2.3 + dev: false + /regexpp/3.1.0: resolution: {integrity: sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==} engines: {node: '>=8'} @@ -21509,7 +21694,7 @@ packages: dev: true /sax/1.2.1: - resolution: {integrity: sha1-e45lYZCyKOgaZq6nSEgNgozS03o=} + resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} /sax/1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -21739,9 +21924,8 @@ packages: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.1 - object-inspect: 1.9.0 - dev: true + get-intrinsic: 1.1.3 + object-inspect: 1.12.2 /signal-exit/3.0.3: resolution: {integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==} @@ -22131,6 +22315,14 @@ packages: define-properties: 1.1.3 dev: true + /string.prototype.trimend/1.0.5: + resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + /string.prototype.trimstart/1.0.4: resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==} dependencies: @@ -22138,6 +22330,14 @@ packages: define-properties: 1.1.3 dev: true + /string.prototype.trimstart/1.0.5: + resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + /string_decoder/0.10.31: resolution: {integrity: sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=} @@ -22884,6 +23084,15 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /unbox-primitive/1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: false + /unicode-canonical-property-names-ecmascript/1.0.4: resolution: {integrity: sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==} engines: {node: '>=4'} @@ -23021,7 +23230,7 @@ packages: dev: true /url/0.10.3: - resolution: {integrity: sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=} + resolution: {integrity: sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==} dependencies: punycode: 1.3.2 querystring: 0.2.0 @@ -23094,6 +23303,17 @@ packages: inherits: 2.0.3 dev: true + /util/0.12.4: + resolution: {integrity: sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.0 + is-generator-function: 1.0.10 + is-typed-array: 1.1.9 + safe-buffer: 5.2.1 + which-typed-array: 1.1.8 + dev: false + /utila/0.4.0: resolution: {integrity: sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=} dev: true @@ -23113,6 +23333,11 @@ packages: hasBin: true dev: true + /uuid/8.0.0: + resolution: {integrity: sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==} + hasBin: true + dev: false + /uuid/8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -23452,14 +23677,25 @@ packages: is-bigint: 1.0.1 is-boolean-object: 1.1.0 is-number-object: 1.0.4 - is-string: 1.0.5 + is-string: 1.0.7 is-symbol: 1.0.3 - dev: true /which-module/2.0.0: resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} dev: true + /which-typed-array/1.1.8: + resolution: {integrity: sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-abstract: 1.20.2 + for-each: 0.3.3 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.9 + dev: false + /which/1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true @@ -23721,7 +23957,7 @@ packages: dev: false /xmlbuilder/9.0.7: - resolution: {integrity: sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=} + resolution: {integrity: sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==} engines: {node: '>=4.0'} /xmlchars/2.2.0: diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.example.json b/reference-artifacts/SAMPLE_CONFIGS/config.example.json index e7b5d7264..d6d405d4c 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json index 3833d6f8b..b1254199b 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-CTNFW-example.json @@ -74,6 +74,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json index 34fa6275a..25b50dafe 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-GWLB-example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json index 189cb2377..d1846dccc 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-NFW-example.json @@ -56,6 +56,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json index 9ef0c4c38..04cdb05da 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.lite-VPN-example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json index 59dd52d4f..a320e80ea 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.multi-region-example.json @@ -61,6 +61,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json index 811a7d0c2..b373aeb1b 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.test-example.json @@ -73,6 +73,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "access-analyzer": true, diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json index 8219ca0b7..b1909a046 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-CT-example.json @@ -37,6 +37,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", diff --git a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json index 3e85d2499..631b5f31c 100644 --- a/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json +++ b/reference-artifacts/SAMPLE_CONFIGS/config.ultralite-example.json @@ -35,6 +35,8 @@ "guardduty-excl-regions": [], "guardduty-s3": true, "guardduty-s3-excl-regions": [], + "guardduty-eks": true, + "guardduty-eks-excl-regions": [], "guardduty-frequency": "FIFTEEN_MINUTES", "cwl": true, "cwl-access-level": "full", diff --git a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts index eae03a937..c523c8a87 100644 --- a/src/deployments/cdk/src/deployments/guardduty/guardduty.ts +++ b/src/deployments/cdk/src/deployments/guardduty/guardduty.ts @@ -116,6 +116,7 @@ export async function step2(props: GuardDutyStepProps) { })); const centralServiceConfig = props.config['global-options']['central-security-services']; const s3ProtectionExclRegions = centralServiceConfig['guardduty-s3-excl-regions'] || []; + const eksProtectionExclRegions = centralServiceConfig['guardduty-eks-excl-regions'] || []; const frequency = await getFrequency(props.config); regions?.map(region => { const masterAccountStack = props.accountStacks.getOrCreateAccountStack(masterAccountKey, region); @@ -123,6 +124,7 @@ export async function step2(props: GuardDutyStepProps) { memberAccounts: accountDetails, roleArn: adminSetupRoleOutput.roleArn, s3Protection: centralServiceConfig['guardduty-s3'] && !s3ProtectionExclRegions.includes(region), + eksProtection: centralServiceConfig['guardduty-eks'] && !eksProtectionExclRegions.includes(region), frequency, }); }); diff --git a/src/lib/config-i18n/src/en.ts b/src/lib/config-i18n/src/en.ts index 908a3c9fd..39dfdcfe7 100644 --- a/src/lib/config-i18n/src/en.ts +++ b/src/lib/config-i18n/src/en.ts @@ -2807,6 +2807,15 @@ translate(c.CentralServicesConfigType, { title: 'GuardDuty S3 Protection Exclusion Regions', description: 'List of excluded regions from Guardduty S3 protection. [SECURITY]', }, + 'guardduty-eks': { + title: 'GuardDuty EKS Protection', + description: + 'EKS protection enables Amazon GuardDuty to monitor control plane activity by analyzing Kubernetes audit logs. [SECURITY]', + }, + 'guardduty-eks-excl-regions': { + title: 'GuardDuty EKS Protection Exclusion Regions', + description: 'List of excluded regions from Guardduty EKS protection. [SECURITY]', + }, 'guardduty-frequency': { title: 'Update Frequency for Policy Findings', description: diff --git a/src/lib/config-i18n/src/fr.ts b/src/lib/config-i18n/src/fr.ts index 0c122d386..a18028422 100644 --- a/src/lib/config-i18n/src/fr.ts +++ b/src/lib/config-i18n/src/fr.ts @@ -2609,6 +2609,14 @@ translate(c.CentralServicesConfigType, { title: '', description: '', }, + 'guardduty-eks': { + title: '', + description: '', + }, + 'guardduty-eks-excl-regions': { + title: '', + description: '', + }, 'guardduty-frequency': { title: '', description: '', diff --git a/src/lib/config/src/config.v2.ts b/src/lib/config/src/config.v2.ts index b1a1f5e71..b5c8c77c5 100644 --- a/src/lib/config/src/config.v2.ts +++ b/src/lib/config/src/config.v2.ts @@ -907,6 +907,8 @@ export const CentralServicesConfigType = t.interface({ 'guardduty-excl-regions': t.optional(t.array(t.nonEmptyString)), 'guardduty-s3': t.defaulted(t.boolean, false), 'guardduty-s3-excl-regions': t.optional(t.array(t.nonEmptyString)), + 'guardduty-eks': t.defaulted(t.boolean, false), + 'guardduty-eks-excl-regions': t.optional(t.array(t.nonEmptyString)), 'guardduty-frequency': t.optional(t.nonEmptyString), 'access-analyzer': t.defaulted(t.boolean, false), cwl: t.defaulted(t.boolean, false), diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts index 91118019f..373194183 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/cdk/index.ts @@ -28,6 +28,7 @@ export interface GuardDutyAdminSetupProps { memberAccounts: AccountDetail[]; roleArn: string; s3Protection: boolean; + eksProtection: boolean; frequency: GuardDutyFrequency; } @@ -45,6 +46,7 @@ export class GuardDutyAdminSetup extends cdk.Construct { const handlerProperties = { memberAccounts: props.memberAccounts, s3Protection: props.s3Protection, + eksProtection: props.eksProtection, frequency: props.frequency, }; diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json index 7cc9bd495..cc7336a4f 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "types": "src/index.ts", "scripts": { - "build": "pnpx esbuild --minify --bundle --platform=node --target=node14 --external:aws-sdk --outfile=./dist/index.js src/index.ts", + "build": "pnpx esbuild --minify --bundle --platform=node --target=node14 --outfile=./dist/index.js src/index.ts", "lint:typecheck": "pnpx tsc --noEmit", "lint:eslint": "pnpx eslint '{cdk,lib,src}/**/*.{js,ts}'" }, @@ -13,7 +13,7 @@ "@aws-accelerator/custom-resource-cfn-utils": "workspace:*", "@aws-accelerator/custom-resource-runtime-cfn-response": "workspace:*", "aws-lambda": "1.0.6", - "aws-sdk": "2.944.0" + "aws-sdk": "2.1217.0" }, "devDependencies": { "@types/aws-lambda": "8.10.76", diff --git a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts index 4a83722c0..953b6e0bc 100644 --- a/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts +++ b/src/lib/custom-resources/cdk-guardduty-admin-setup/runtime/src/index.ts @@ -12,7 +12,7 @@ */ import * as AWS from 'aws-sdk'; -AWS.config.logger = console; +//AWS.config.logger = console; import { CloudFormationCustomResourceEvent, CloudFormationCustomResourceCreateEvent, @@ -43,6 +43,7 @@ export interface HandlerProperties { deligatedAdminAccountId: string; memberAccounts: AccountDetail[]; s3Protection: boolean; + eksProtection: boolean; frequency: GuardDutyFrequency; } @@ -76,13 +77,13 @@ async function onCreateOrUpdate( }; } - const { memberAccounts, s3Protection, frequency } = properties; - await updateS3ProtectionAndFrequency(detectorId, s3Protection, frequency); + const { memberAccounts, s3Protection, eksProtection, frequency } = properties; + await updateS3ProtectionAndFrequency(detectorId, s3Protection, eksProtection, frequency); - const isAutoEnabled = await isConfigurationAutoEnabled(detectorId, s3Protection); + const isAutoEnabled = await isConfigurationAutoEnabled(detectorId, s3Protection, eksProtection); if (!isAutoEnabled) { // Update Config to handle new Account created under Organization - await updateConfig(detectorId, s3Protection); + await updateConfig(detectorId, s3Protection, eksProtection); } else { console.log(`GuardDuty is already enabled ORG Level`); } @@ -93,9 +94,10 @@ async function onCreateOrUpdate( ); if (requiredMemberAccounts.length > 0) { await createMembers(requiredMemberAccounts, detectorId); - await updateMemberDataSource(requiredMemberAccounts, detectorId, s3Protection); } + await updateMemberDataSource(existingMembers, detectorId, s3Protection, eksProtection); + return { physicalResourceId, data: {}, @@ -142,7 +144,7 @@ async function createMembers(memberAccounts: AccountDetail[], detectorId: string } // Step 3 of https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html -async function updateConfig(detectorId: string, s3Protection: boolean, autoEnable = true) { +async function updateConfig(detectorId: string, s3Protection: boolean, eksProtection: boolean, autoEnable = true) { try { console.log(`Calling api "guardduty.updateOrganizationConfiguration()", ${detectorId}`); await throttlingBackOff(() => @@ -154,6 +156,11 @@ async function updateConfig(detectorId: string, s3Protection: boolean, autoEnabl S3Logs: { AutoEnable: s3Protection, }, + Kubernetes: { + AuditLogs: { + AutoEnable: eksProtection, + }, + }, }, }) .promise(), @@ -165,7 +172,11 @@ async function updateConfig(detectorId: string, s3Protection: boolean, autoEnabl } // describe-organization-configuration to check if security hub is already enabled in org level or not -async function isConfigurationAutoEnabled(detectorId: string, s3Protection: boolean): Promise { +async function isConfigurationAutoEnabled( + detectorId: string, + s3Protection: boolean, + eksProtection: boolean, +): Promise { try { console.log(`Calling api "guardduty.describeOrganizationConfiguration()", ${detectorId}`); const response = await throttlingBackOff(() => @@ -175,7 +186,11 @@ async function isConfigurationAutoEnabled(detectorId: string, s3Protection: bool }) .promise(), ); - return response.AutoEnable && response.DataSources?.S3Logs.AutoEnable! === s3Protection; + return ( + response.AutoEnable && + response.DataSources?.S3Logs.AutoEnable! === s3Protection && + response.DataSources?.Kubernetes?.AuditLogs.AutoEnable! === eksProtection + ); } catch (error) { console.error( `Error Occurred while checking configuration auto enabled of GuardDuty ${error.code}: ${error.message}`, @@ -184,16 +199,21 @@ async function isConfigurationAutoEnabled(detectorId: string, s3Protection: bool } } -async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorId: string, s3Protection: boolean) { - if (s3Protection) { - return; - } +async function updateMemberDataSource( + memberAccounts: AccountDetail[], + detectorId: string, + s3Protection: boolean, + eksProtection: boolean, +) { + // if (s3Protection && eksProtection) { + // return; + // } try { let pageNumber = 1; let currentAccounts: AccountDetail[] = paginate(memberAccounts, pageNumber, pageSize); while (currentAccounts.length > 0) { console.log( - `Calling api "guardduty.updateMemberDetectors()", ${currentAccounts}, ${detectorId} to disable S3Protection`, + `Calling api "guardduty.updateMemberDetectors()", ${currentAccounts}, ${detectorId} to update S3Protection or EKSProtection`, ); await throttlingBackOff(() => guardduty @@ -202,7 +222,12 @@ async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorI DetectorId: detectorId, DataSources: { S3Logs: { - Enable: false, + Enable: s3Protection, + }, + Kubernetes: { + AuditLogs: { + Enable: eksProtection, + }, }, }, }) @@ -219,6 +244,7 @@ async function updateMemberDataSource(memberAccounts: AccountDetail[], detectorI async function updateS3ProtectionAndFrequency( detectorId: string, s3Protection: boolean, + eksProtection: boolean, frequency?: GuardDutyFrequency, ) { try { @@ -230,6 +256,11 @@ async function updateS3ProtectionAndFrequency( S3Logs: { Enable: s3Protection, }, + Kubernetes: { + AuditLogs: { + Enable: eksProtection, + }, + }, }, FindingPublishingFrequency: frequency, }) @@ -288,6 +319,9 @@ function getPropertiesFromEvent(event: CloudFormationCustomResourceEvent) { if (typeof properties.s3Protection === 'string') { properties.s3Protection = properties.s3Protection === 'true'; } + if (typeof properties.eksProtection === 'string') { + properties.eksProtection = properties.eksProtection === 'true'; + } return properties; } @@ -300,9 +334,9 @@ async function onDelete(event: CloudFormationCustomResourceDeleteEvent) { const { memberAccounts } = properties; try { const detectorId = await getDetectorId(); - await updateS3ProtectionAndFrequency(detectorId!, false, undefined); - await updateConfig(detectorId!, false, false); - await updateMemberDataSource(memberAccounts, detectorId!, false); + await updateS3ProtectionAndFrequency(detectorId!, false, false, undefined); + await updateConfig(detectorId!, false, false, false); + await updateMemberDataSource(memberAccounts, detectorId!, false, false); await deleteMembers(memberAccounts, detectorId!); } catch (error) { console.warn('Exception while performing Delete Action');