Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: for landing zone v3.0 #70

Merged
merged 20 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 75 additions & 2 deletions doc/DeployToControlTower.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ Here we set up ControlTower, SecurityHub, GuardDuty and IAM Access for the entir
Set up ControlTower.
See: [https://docs.aws.amazon.com/controltower/latest/userguide/setting-up.html]

> NOTE:
>
> From AWS Control Tower landing zone ver.3.0, when the CloudTrail configuration is enabled, the CloudTrail logs are aggregated into AWS CloudWatch Logs for your ManagementAccount.

> Ref:https://docs.aws.amazon.com/controltower/latest/userguide/2022-all.html#version-3.0
>
> As a result of, a CloudWatch Logs logGroup to gather CloudTrail logs is no longer newly created on the guest account. So, we can no longer deploy notifications to monitor AWS CloudTrail logs.
>
> BLEA defines preconditions as follows and provides code.
> For how to deal with environments other than the prerequisite environment, see [6-2. (Optional) Modify the code to match Control Tower landing zone settings](#6-2-governance-based-deployment-to-guest-accounts)
>
> Preconditions:
ohmurayu marked this conversation as resolved.
Show resolved Hide resolved
>
> - Start using Control Tower from landing zone ver.3.0
> - CloudTrail will be enabled when the Control Tower Landing Zone is updated to ver.3.0.

#### 1-2. Set up SecurityHub

- [https://docs.aws.amazon.com/securityhub/latest/userguide/designate-orgs-admin-account.html]
Expand Down Expand Up @@ -359,7 +375,64 @@ The contents of this setting are as follows.
| SlackNotifier.WorkspaceID | ID of Slack workspace set on AWS Chatbot |
| SlackNotifier.channelIDSec | The ID of the Slack channel that you configured on AWS Chatbot. You will be notified about security |

#### 6-2. Governance-based deployment to guest accounts
#### 6-2. (Optional) Modify the code to match Control Tower landing zone settings

Skip this section if the environment matches [prerequisites in 1-1. ControlTower setup](#1-1-ControlTower-setup).

First, use the following flow chart to check the appropriate way for your environment.
Abbreviations in the figure are as follows:

- CT: Control Tower
- LZ: Landing Zone
- CTrail: CloudTrail

```mermaid
flowchart TD
A[START] --> B{Whether CT LZ <br />is using or not?}
B -->|Using| C{Will CT LZ <br/>be updated to v3.0?}
C -->|YES, will update to v3.0| D{Turn on <br />the configuration <br />of CTrail in LZ}
C -->|NO, continue to use current ver.| F
D -->|YES, turn on CloudTrail| F[a: Use existing resource <br />on the guest account]
D -->|NO, turn off the CloudTrail| G[b: Create a new resource <br />on the guest account]
B -->|Not using| G
```

Also, just in case, before modifying the source code,
please check if there is a log group named `aws-controltower/CloudTrailLogs` in the guest account's CloudWatch Logs.

##### a. Use existing resource on the guest account

This is the case where exisitng of a log group named `aws-controltower/CloudTrailLogs` in the guest account's CloudWatch Logs.

Please delete the following code defined in BLEA and insert the code to use the existing resource.

**_ The code to delete _**

Please delete the following two places.

```
import { BLEATrailStack } from '../lib/blea-trail-stack';
```

```
const trail = new BLEATrailStack(app, `${pjPrefix}-Trail`, { env: getProcEnv() });
const logGroupName = trail.cloudTrailLogGroup.logGroupName;
```

**_ The code to insert _**

Please add settings to use an existing LogGroup.

```
const logGroupName = 'aws-controltower/CloudTrailLogs';
```

##### b. Create a new resource on the guest account

Similar to the prerequisite environment, this environment requires the addition of a LogGroup.
Please deploy without modifying the source code.

#### 6-3. Governance-based deployment to guest accounts

Log in to your guest account using AWS SSO.

Expand Down Expand Up @@ -401,7 +474,7 @@ The following settings that were set up in the Standalone version are configured
- Detect abnormal behavior with GuardDuty
- Detecting Deviations from Best Practices with SecurityHub (AWS Foundational Security Best Practice, CIS benchmark)

#### 6-3. (Optional) Set up other baseline setups manually
#### 6-4. (Optional) Set up other baseline setups manually

Besides setting up on a governance basis
AWS provides several operational baseline services. Set up these services as needed.
Expand Down
77 changes: 75 additions & 2 deletions doc/DeployToControlTower_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ ControlTower を利用することで、ガバナンスベースの一部の機
ControlTower をセットアップします。
See: [https://docs.aws.amazon.com/controltower/latest/userguide/setting-up.html]

> NOTE:
>
> AWS Control Tower landing zone ver.3.0 より、CloudTrail の設定を有効化した場合の CloudTrail のログは、ManagementAccount の AWS CloudWatch Logs に集約されるようになりました。
>
> ご参考:https://docs.aws.amazon.com/controltower/latest/userguide/2022-all.html#version-3.0
>
> その結果、これまでゲストアカウント上に存在していた CloudTrail のログが出力されていた CloudWatch Logs の LogGroup が新たに作成されなくなり、base-ct-guest でデプロイされていた AWS CloudTrail のログを監視する通知がデプロイできなくなりました。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> その結果、これまでゲストアカウント上に存在していた CloudTrail のログが出力されていた CloudWatch Logs の LogGroup が新たに作成されなくなり、base-ct-guest でデプロイされていた AWS CloudTrail のログを監視する通知がデプロイできなくなりました
> その結果、従来ゲストアカウント上に存在していた CloudTrail のログが出力されていた CloudWatch Logs の LogGroup が無くなりました。これによってゲストアカウントのガバナンスベースで提供していた CloudTrail のログ監視が行えなくなっています

>
> BLEA では、前提条件を以下のように定義し、コードを提供しています。
> 前提条件の環境以外への対応方法は、[6-2. (必要に応じて)Control Tower landing zone の設定に合わせコードを修正する](<#6-2-(必要に応じて)Control-Tower-landing-zone-の設定に合わせコードを修正する>)をご参照ください
Copy link
Contributor

@ohmurayu ohmurayu Sep 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> BLEA では、前提条件を以下のように定義し、コードを提供しています
> 前提条件の環境以外への対応方法は、[6-2. (必要に応じて)Control Tower landing zone の設定に合わせコードを修正する](<#6-2-(必要に応じて)Control-Tower-landing-zone-の設定に合わせコードを修正する>)をご参照ください
> BLEA マルチアカウント版はデフォルトで以下の前提条件への適用を想定しています
> LandingZoneをバージョンアップした場合などは前提条件と異なる場合があります。その際は [6-2. (必要に応じて)Control Tower landing zone の設定に合わせコードを修正する](<#6-2-(必要に応じて)Control-Tower-landing-zone-の設定に合わせコードを修正する>)をご覧ください。

>
> 前提条件:
>
> - Control Tower landing zone ver.3.0 から新規に Control Tower を利用する
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> - Control Tower landing zone ver.3.0 から新規に Control Tower を利用する
> - Control Tower のLanding Zone ver.3.0 を利用しており、組織レベルの CloudTrail を有効化している

> - Control Tower landing zone ver.3.0 の設定時に CloudTrail を有効化している

#### 1-2. SecurityHub のセットアップ

- [https://docs.aws.amazon.com/securityhub/latest/userguide/designate-orgs-admin-account.html]
Expand Down Expand Up @@ -358,7 +374,64 @@ usecases/base-ct-guest/cdk.json
| slackNotifier.workspaceId | AWS Chatbot に設定した Slack workspace の ID |
| slackNotifier.channelIdSec | AWS Chatbot に設定した Slack channel の ID。セキュリティに関する通知が行われます |

#### 6-2. ゲストアカウントにガバナンスベースデプロイする
#### 6-2. (必要に応じて)Control Tower landing zone の設定に合わせコードを修正する

本項は[1-1. ControlTower のセットアップ内に記載の前提条件](#1-1-ControlTower-のセットアップ)に合致した環境の場合、スキップしてください。

まず、次のフローチャートを利用し、ご自身の環境に適した対応方法をご確認ください。
図中の略語は以下の通りです。

- CT: Control Tower
- LZ: Landing Zone
- CTrail: CloudTrail

```mermaid
flowchart TD
A[START] --> B{現在CTを利用している}
B -->|利用している| C{現在のCT LZを<br>v3.0に更新する予定}
C -->|v3.0に上げる| D{LZのCTrailの設定を<br>有効化する}
C -->|v2.9以下のまま| F
D -->|有効にする| F[a: ゲストアカウント上の<br>既存のリソースを利用する]
D -->|有効にしない| G[b: ゲストアカウント上に<br>新規でリソースを作成する]
B -->|利用していない| G
```

また、念のため、ソースコードを修正する前に、
ゲストアカウント内の CloudWatch Logs に`aws-controltower/CloudTrailLogs`という名前のロググループの有無を確認してください。

##### a. ゲストアカウント上の既存のリソースを利用する

CloudWatch Logs に`aws-controltower/CloudTrailLogs`という名前のロググループが残っているケースになります。

BLEA で定義されている以下の箇所のコードを削除し、既存のリソースを利用するためのコードを挿入してください。

**_ 削除する箇所(2箇所) _**

以下の2箇所を削除してください。

```
import { BLEATrailStack } from '../lib/blea-trail-stack';
```

```
const trail = new BLEATrailStack(app, `${pjPrefix}-Trail`, { env: getProcEnv() });
const logGroupName = trail.cloudTrailLogGroup.logGroupName;
```

**_ 挿入するコード _**

既存の LogGroup を利用するための設定を追加します。

```
const logGroupName = 'aws-controltower/CloudTrailLogs';
```

##### b. ゲストアカウント上に新規でリソースを作成する

前提条件の環境と同様に、LogGroup の追加が必要な環境となります。
ソースコードを修正せずに、デプロイを実施してください。

#### 6-3. ゲストアカウントにガバナンスベースデプロイする

AWS SSO を使ってゲストアカウントにログインします。

Expand Down Expand Up @@ -399,7 +472,7 @@ Standalone 版でセットアップされていた以下の内容は ControlTowe
- GuardDuty による異常なふるまいの検知
- SecurityHub によるベストプラクティスからの逸脱検知 (AWS Foundational Security Best Practice, CIS benchmark)

#### 6-3. (オプション) 他のベースラインセットアップを手動でセットアップする
#### 6-4. (オプション) 他のベースラインセットアップを手動でセットアップする

ガバナンスベースでセットアップする他に
AWS はいくつかの運用上のベースラインサービスを提供しています。必要に応じてこれらのサービスのセットアップを行なってください。
Expand Down
14 changes: 9 additions & 5 deletions usecases/base-ct-guest/bin/blea-base-ct-guest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BLEAIamStack } from '../lib/blea-iam-stack';
import { BLEAConfigRulesStack } from '../lib/blea-config-rules-stack';
import { BLEASecurityAlarmStack } from '../lib/blea-security-alarm-stack';
import { BLEAChatbotStack } from '../lib/blea-chatbot-stack';
import { BLEATrailStack } from '../lib/blea-trail-stack';

const pjPrefix = 'BLEA-BASE';

Expand Down Expand Up @@ -39,16 +40,19 @@ function getProcEnv() {
new BLEAConfigRulesStack(app, `${pjPrefix}-ConfigRule`, { env: getProcEnv() });
new BLEAIamStack(app, `${pjPrefix}-Iam`, { env: getProcEnv() });

// AWS CloudTrail configuration in Control Tower Landing Zone v3.0 will not create CloudWatch Logs LogGroup in each Guest Accounts.
// And it will delete these LogGroups when AWS CloudTrial Configuration is disabled in case of updating Landing Zone version from older one.
// BLEA should notify their alarms continuously. So, if there is no CloudTrail and CloudWatch Logs in Guest Account, BLEA creates them to notify the Alarms.

const trail = new BLEATrailStack(app, `${pjPrefix}-Trail`, { env: getProcEnv() });
const logGroupName = trail.cloudTrailLogGroup.logGroupName;

// Security Alarms
// !!! Need to setup SecurityHub, GuardDuty manually on Organizations Management account
// AWS Config and CloudTrail are set up by ControlTower

// CloudWatch LogGroup Name for CloudTrail - Created by ControlTower for each account
const cloudTrailLogGroupName = 'aws-controltower/CloudTrailLogs';

const secAlarm = new BLEASecurityAlarmStack(app, `${pjPrefix}-SecurityAlarm`, {
notifyEmail: envVals['securityNotifyEmail'],
cloudTrailLogGroupName: cloudTrailLogGroupName,
cloudTrailLogGroupName: logGroupName,
env: getProcEnv(),
});

Expand Down
146 changes: 146 additions & 0 deletions usecases/base-ct-guest/lib/blea-trail-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_s3 as s3 } from 'aws-cdk-lib';
import { aws_cloudtrail as trail } from 'aws-cdk-lib';
import { aws_logs as cwl } from 'aws-cdk-lib';
import { aws_iam as iam } from 'aws-cdk-lib';
import { aws_kms as kms } from 'aws-cdk-lib';

export class BLEATrailStack extends cdk.Stack {
public readonly cloudTrailLogGroup: cwl.LogGroup;

constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);

// Archive Bucket for CloudTrail
const archiveLogsBucket = new s3.Bucket(this, 'ArchiveLogsBucket', {
accessControl: s3.BucketAccessControl.LOG_DELIVERY_WRITE,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: cdk.RemovalPolicy.RETAIN,
lifecycleRules: [
{
enabled: true,
expiration: cdk.Duration.days(2555),
transitions: [
{
transitionAfter: cdk.Duration.days(90),
storageClass: s3.StorageClass.GLACIER,
},
],
},
],
});
this.addBaseBucketPolicy(archiveLogsBucket);

// Bucket for CloudTrail
const cloudTrailBucket = new s3.Bucket(this, 'CloudTrailBucket', {
accessControl: s3.BucketAccessControl.PRIVATE,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
versioned: true,
serverAccessLogsBucket: archiveLogsBucket,
serverAccessLogsPrefix: 'cloudtraillogs',
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
this.addBaseBucketPolicy(cloudTrailBucket);

// CMK for CloudTrail
const cloudTrailKey = new kms.Key(this, 'CloudTrailKey', {
enableKeyRotation: true,
description: 'for CloudTrail',
alias: 'for-cloudtrail',
});
cloudTrailKey.addToResourcePolicy(
new iam.PolicyStatement({
actions: ['kms:GenerateDataKey*'],
principals: [new iam.ServicePrincipal('cloudtrail.amazonaws.com')],
resources: ['*'],
conditions: {
StringLike: {
'kms:EncryptionContext:aws:cloudtrail:arn': [`arn:aws:cloudtrail:*:${cdk.Stack.of(this).account}:trail/*`],
},
},
}),
);
cloudTrailKey.addToResourcePolicy(
new iam.PolicyStatement({
actions: ['kms:DescribeKey'],
principals: [new iam.ServicePrincipal('cloudtrail.amazonaws.com')],
resources: ['*'],
}),
);
cloudTrailKey.addToResourcePolicy(
new iam.PolicyStatement({
actions: ['kms:Decrypt', 'kms:ReEncryptFrom'],
principals: [new iam.AnyPrincipal()],
resources: ['*'],
conditions: {
StringEquals: { 'kms:CallerAccount': `${cdk.Stack.of(this).account}` },
StringLike: {
'kms:EncryptionContext:aws:cloudtrail:arn': [`arn:aws:cloudtrail:*:${cdk.Stack.of(this).account}:trail/*`],
},
},
}),
);
cloudTrailKey.addToResourcePolicy(
new iam.PolicyStatement({
actions: ['kms:Encrypt*', 'kms:Decrypt*', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', 'kms:Describe*'],
principals: [new iam.ServicePrincipal('logs.amazonaws.com')],
resources: ['*'],
conditions: {
ArnEquals: {
'kms:EncryptionContext:aws:logs:arn': `arn:aws:logs:${props?.env?.region}:${
cdk.Stack.of(this).account
}:log-group:*`,
},
},
}),
);

// CloudWatch Logs Group for CloudTrail
const cloudTrailLogGroup = new cwl.LogGroup(this, 'CloudTrailLogGroup', {
retention: cwl.RetentionDays.THREE_MONTHS,
encryptionKey: cloudTrailKey,
});
this.cloudTrailLogGroup = cloudTrailLogGroup;

// CloudTrail
new trail.Trail(this, 'CloudTrail', {
bucket: cloudTrailBucket,
enableFileValidation: true,
includeGlobalServiceEvents: true,
cloudWatchLogGroup: cloudTrailLogGroup,
encryptionKey: cloudTrailKey,
sendToCloudWatchLogs: true,
});
}

// Add base BucketPolicy for CloudTrail
addBaseBucketPolicy(bucket: s3.Bucket): void {
bucket.addToResourcePolicy(
new iam.PolicyStatement({
sid: 'Enforce HTTPS Connections',
effect: iam.Effect.DENY,
actions: ['s3:*'],
principals: [new iam.AnyPrincipal()],
resources: [bucket.arnForObjects('*')],
conditions: {
Bool: {
'aws:SecureTransport': false,
},
},
}),
);

bucket.addToResourcePolicy(
new iam.PolicyStatement({
sid: 'Restrict Delete* Actions',
effect: iam.Effect.DENY,
actions: ['s3:Delete*'],
principals: [new iam.AnyPrincipal()],
resources: [bucket.arnForObjects('*')],
}),
);
}
}