Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
14 changes: 14 additions & 0 deletions .github/wiki/Security.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ This document provides an overview of the security modules available in the infr

## Available Security Modules

### CloudTrail

The CloudTrail module provides comprehensive API activity logging and monitoring for your AWS infrastructure to enhance security auditing and compliance.

#### Overview

AWS CloudTrail records API calls and events across your AWS account. This module:

- **Comprehensive event logging**: Captures management events, data events, and insight events based on configuration
- **Multi-region support**: Can be configured to log events across all AWS regions for complete visibility
- **CloudWatch integration**: Sends logs to CloudWatch for real-time monitoring and alerting
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Preferably put CloudWatch integration together with SNS notifications

→ Group them, as they both relate to alerting/monitoring.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated in 54e1427

- **SNS notifications**: Integrates with SNS topics for immediate alerting on critical events
- **S3 storage**: Stores all CloudTrail logs securely in Amazon S3 with configurable key prefix organization

### VPC Flow Log

The VPC Flow Log module captures network traffic information in your VPC to help with security monitoring and network analysis.
Expand Down
2 changes: 1 addition & 1 deletion src/commands/install/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe('Install add-on command', () => {
it('throws an error', async () => {
expect(stdoutSpy).toHaveBeenCalledWith(
expect.stringContaining(
'Expected invalid to be one of: vpc, securityGroup, alb, bastion, ecr, ecs, cloudwatch, rds, s3, ssm'
'Expected invalid to be one of: vpc, securityGroup, alb, bastion, cloudtrail, ecr, ecs, cloudwatch, rds, s3, ssm, vpcFlowLog'
)
);
});
Expand Down
62 changes: 60 additions & 2 deletions src/generators/addons/aws/advanced.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { remove } from '@/helpers/file';

import { AwsOptions } from '.';
import { AwsAddonModules, AwsOptions } from '.';
import { applyAdvancedTemplate } from './advanced';
import {
applyAwsAlb,
applyAwsBastion,
applyAwsCloudtrail,
applyAwsEcr,
applyAwsEcs,
applyAwsCloudwatch,
Expand Down Expand Up @@ -73,6 +74,10 @@ describe('AWS advanced template', () => {
it('does NOT apply VPC Flow Log add-on', () => {
expect(applyAwsVpcFlowLog).not.toHaveBeenCalled();
});

it('does NOT apply CloudTrail add-on', () => {
expect(applyAwsCloudtrail).not.toHaveBeenCalled();
});
});

describe('given enabledSecurityFeatures is true', () => {
Expand All @@ -83,7 +88,7 @@ describe('AWS advanced template', () => {
infrastructureType: 'advanced',
awsRegion: 'ap-southeast-1',
enabledSecurityFeatures: true,
addonModules: ['vpcFlowLog'],
addonModules: [AwsAddonModules.VPC_FLOW_LOG],
};

beforeAll(async () => {
Expand All @@ -102,6 +107,7 @@ describe('AWS advanced template', () => {
);
});
});

describe('given addonModules does NOT include vpcFlowLog', () => {
const optionsEnabledSecurityFeaturesWithoutVpcFlowLog: AwsOptions = {
projectName: projectDir,
Expand All @@ -124,6 +130,58 @@ describe('AWS advanced template', () => {
expect(applyAwsVpcFlowLog).not.toHaveBeenCalled();
});
});

describe('given addonModules includes cloudtrail', () => {
const optionsEnabledSecurityFeaturesWithCloudTrail: AwsOptions = {
projectName: projectDir,
provider: 'aws',
infrastructureType: 'advanced',
awsRegion: 'ap-southeast-1',
enabledSecurityFeatures: true,
addonModules: [AwsAddonModules.CLOUDTRAIL],
};

beforeAll(async () => {
jest.clearAllMocks();
await applyAdvancedTemplate(
optionsEnabledSecurityFeaturesWithCloudTrail
);
});

afterAll(() => {
jest.clearAllMocks();
remove('/', projectDir);
});

it('applies CloudTrail add-on when flag is set', () => {
expect(applyAwsCloudtrail).toHaveBeenCalledWith(
optionsEnabledSecurityFeaturesWithCloudTrail
);
});
});

describe('given addonModules does NOT include cloudtrail', () => {
const optionsEnabledSecurityFeaturesWithoutCloudTrail: AwsOptions = {
projectName: projectDir,
provider: 'aws',
infrastructureType: 'advanced',
awsRegion: 'ap-southeast-1',
enabledSecurityFeatures: true,
addonModules: [], // No cloudtrail
};

afterAll(() => {
jest.clearAllMocks();
remove('/', projectDir);
});

it('does NOT apply CloudTrail add-on when flag is set but module is not included', async () => {
await applyAdvancedTemplate(
optionsEnabledSecurityFeaturesWithoutCloudTrail
);
expect(applyAwsCloudtrail).not.toHaveBeenCalled();
});
});
});
});
});
7 changes: 5 additions & 2 deletions src/generators/addons/aws/advanced.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { AwsOptions } from '.';
import { AwsAddonModules, AwsOptions } from '.';
import {
applyAwsAlb,
applyAwsBastion,
applyAwsCloudtrail,
applyAwsEcr,
applyAwsEcs,
applyAwsCloudwatch,
Expand All @@ -25,8 +26,10 @@ const applyAdvancedTemplate = async (options: AwsOptions) => {
await Promise.all(
options.addonModules.map((module) => {
switch (module) {
case 'vpcFlowLog':
case AwsAddonModules.VPC_FLOW_LOG:
return applyAwsVpcFlowLog(options);
case AwsAddonModules.CLOUDTRAIL:
return applyAwsCloudtrail(options);
default:
throw new Error(`Module ${module} has not been implemented!`);
}
Expand Down
7 changes: 7 additions & 0 deletions src/generators/addons/aws/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AwsOptions } from '@/generators/addons/aws';
import {
applyAwsAlb,
applyAwsBastion,
applyAwsCloudtrail,
applyAwsEcr,
applyAwsEcs,
applyAwsCloudwatch,
Expand Down Expand Up @@ -50,6 +51,12 @@ const AWS_MODULES: Record<AwsModuleName | string, AwsModule> = {
mainContent: 'module "bastion"',
applyModuleFunction: (options: AwsOptions) => applyAwsBastion(options),
},
cloudtrail: {
name: 'cloudtrail',
path: 'modules/cloudtrail',
mainContent: 'module "cloudtrail"',
applyModuleFunction: (options: AwsOptions) => applyAwsCloudtrail(options),
},
ecr: {
name: 'ecr',
path: 'modules/ecr',
Expand Down
17 changes: 11 additions & 6 deletions src/generators/addons/aws/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ import {
applyAwsVpc,
} from './modules';

enum AwsAddonModules {
VPC_FLOW_LOG = 'vpcFlowLog',
CLOUDTRAIL = 'cloudtrail',
}

type AwsOptions = GeneralOptions & {
infrastructureType?: 'blank' | 'advanced';
awsRegion?: string;
enabledSecurityFeatures?: boolean;
addonModules?: string[];
addonModules?: AwsAddonModules[];
};

const awsChoices = [
Expand Down Expand Up @@ -50,13 +55,13 @@ const awsChoices = [
message: 'Which security features do you want to add?',
choices: [
{
key: 'vpcFlowLog',
value: 'vpcFlowLog',
key: AwsAddonModules.VPC_FLOW_LOG,
value: AwsAddonModules.VPC_FLOW_LOG,
name: 'VPC Flow Logs',
},
{
key: 'cloudTrail',
value: 'cloudTrail',
key: AwsAddonModules.CLOUDTRAIL,
value: AwsAddonModules.CLOUDTRAIL,
name: 'CloudTrail',
},
],
Expand Down Expand Up @@ -107,4 +112,4 @@ const generateAwsTemplate = async (
};

export type { AwsOptions };
export { generateAwsTemplate };
export { generateAwsTemplate, AwsAddonModules };
74 changes: 74 additions & 0 deletions src/generators/addons/aws/modules/cloudtrail.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { AwsOptions } from '@/generators/addons/aws';
import { applyTerraformCore } from '@/generators/terraform';
import { remove } from '@/helpers/file';

import applyAwsCloudtrail, {
cloudtrailModuleContent,
cloudtrailOutputsContent,
cloudtrailVariablesContent,
} from './cloudtrail';
import applyTerraformAwsProvider from './core/provider';

jest.mock('inquirer', () => {
return {
prompt: jest.fn().mockResolvedValue({ apply: true }),
};
});

describe('CloudTrail add-on', () => {
describe('given valid AWS options', () => {
const projectDir = 'cloudtrail-addon-test';

beforeAll(async () => {
const awsOptions: AwsOptions = {
projectName: projectDir,
provider: 'aws',
infrastructureType: 'advanced',
};

await applyTerraformCore(awsOptions);
await applyTerraformAwsProvider(awsOptions);
await applyAwsCloudtrail(awsOptions);
});

afterAll(() => {
jest.clearAllMocks();
remove('/', projectDir);
});

it('creates expected files', () => {
const expectedFiles = [
'core/main.tf',
'core/providers.tf',
'core/outputs.tf',
'core/variables.tf',
'modules/cloudtrail/main.tf',
'modules/cloudtrail/variables.tf',
'modules/cloudtrail/outputs.tf',
];

expect(projectDir).toHaveFiles(expectedFiles);
});

it('adds cloudtrail module to main.tf', () => {
expect(projectDir).toHaveContentInFile(
'core/main.tf',
cloudtrailModuleContent
);
});

it('adds cloudtrail variables to variables.tf', () => {
expect(projectDir).toHaveContentInFile(
'core/variables.tf',
cloudtrailVariablesContent
);
});

it('adds cloudtrail outputs to outputs.tf', () => {
expect(projectDir).toHaveContentInFile(
'core/outputs.tf',
cloudtrailOutputsContent
);
});
});
});
Loading