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

Implement module for VPC flow logs #1

Merged
merged 17 commits into from
Nov 21, 2017
16 changes: 16 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
addons:
apt:
packages:
- git
- make
- curl

install:
- make init

script:
- make terraform:install
- make terraform:get-plugins
- make terraform:get-modules
- make terraform:lint
- make terraform:validate
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}
Copyright 2017 Cloud Posse, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SHELL := /bin/bash

-include $(shell curl -sSL -o .build-harness "https://git.io/build-harness"; echo .build-harness)

lint:
$(SELF) terraform:install terraform:get-modules terraform:get-plugins terraform:lint terraform:validate
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# terraform-aws-cloudwatch-flow-logs [![Build Status](https://travis-ci.org/cloudposse/terraform-aws-cloudwatch-flow-logs.svg)](https://travis-ci.org/cloudposse/terraform-aws-cloudwatch-flow-logs)

Terraform module for enabling [`flow logs`](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/flow-logs.html) for `vpc` and `subnets`.

## Usage

```terraform
module "flow_logs" {
source = "git::https://github.com/cloudposse/terraform-aws-cloudwatch-flow-logs.git?ref=master"
vpc_id = "${var.vpc_id}"
namespace = "${var.namespace}"
stage = "${var.stage}"
}
```
## Inputs

| Name | Default | Description | Required |
|:----------------------|:--------------------------------------:|:--------------------------------------------------------------------------------------------------------|:--------:|
| `namespace` | `` | Namespace (e.g. `cp` or `cloudposse`) | Yes |
| `stage` | `` | Stage (e.g. `prod`, `dev`, `staging`) | Yes |
| `name` | `` | Name (e.g. `bastion` or `db`) | No |
| `delimiter` | `-` | Delimiter to be used between `name`, `namespace`, `stage`, etc. | No |
| `attributes` | `[]` | Additional attributes (e.g. `policy` or `role`) | No |
| `tags` | `{}` | Additional tags (e.g. `map("BusinessUnit","XYZ")` | No |
| `vpc_id` | `` | ID of VPC | Yes |
| `subnet_ids` | `[]` | IDs of subnets | No |
| `eni_ids` | `[]` | IDs of ENIs | No |
| `region` | `` | AWS region e.g. `us-central-1` | No |
| `retention_in_days` | `30` | Number of days you want to retain log events in the log group | No |
| `traffic_type` | `ALL` | Type of traffic to capture. Valid values: ACCEPT,REJECT, ALL | No |
| `shard_count` | `1` | Number of shards that the stream will use | No |
| `retention_period` | `48` | Length of time data records are accessible after they are added to the stream | No |
| `shard_level_metrics` | `[ "IncomingBytes", "OutgoingBytes",]` | List of shard-level CloudWatch metrics which can be enabled for the stream | No |
| `encryption_type` | `NONE` | GUID for the customer-managed KMS key to use for encryption. The only acceptable values are NONE or KMS | No |
| `kms_key_id` | `` | ID of KMS key | No |
| `filter_pattern` | `"[]"` | Valid CloudWatch Logs filter pattern for subscribing to a filtered stream of log events | No |
| `enabled` | `true` | Set to false to prevent the module from creating anything | No |

## Outputs

| Name | Description |
|:----------------------|:---------------------------|
| `log_group_arn` | ARN of the log group |
| `eni_flow_ids` | Flow Log IDs of ENIs |
| `subnet_flow_ids` | Flow Log IDs of subnets |
| `vpc_flow_id` | Flow Log IDs of VPC |
| `kinesis_arn` | ARN of Stream |
| `kinesis_id` | Stream ID |
| `kinesis_name` | Stream name |
| `kinesis_shard_count` | Count of Shards for Stream |

## License

Apache 2 License. See [`LICENSE`](LICENSE) for full details.
79 changes: 79 additions & 0 deletions iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
data "aws_iam_policy_document" "log_assume" {
count = "${var.enabled == "true" ? 1 : 0}"

statement {
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["vpc-flow-logs.amazonaws.com"]
}
}
}

data "aws_iam_policy_document" "log" {
statement {
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
]

resources = [
"*",
]
}
}

resource "aws_iam_role_policy" "log" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.vpc_label.id}"
role = "${aws_iam_role.log.id}"
policy = "${data.aws_iam_policy_document.log.json}"
}

resource "aws_iam_role" "log" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.vpc_label.id}"
assume_role_policy = "${data.aws_iam_policy_document.log_assume.json}"
}

data "aws_iam_policy_document" "kinesis_assume" {
statement {
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["logs.${length(var.region) > 0 ? var.region: data.aws_region.default.name}.amazonaws.com"]
}
}
}

data "aws_iam_policy_document" "kinesis" {
statement {
actions = [
"kinesis:PutRecord*",
"kinesis:DescribeStream",
"kinesis:ListStreams",
]

resources = [
"${aws_kinesis_stream.default.arn}",
]
}
}

resource "aws_iam_role" "kinesis" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.kinesis_label.id}"
assume_role_policy = "${data.aws_iam_policy_document.kinesis_assume.json}"
}

resource "aws_iam_role_policy" "kinesis" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.vpc_label.id}"
role = "${aws_iam_role.kinesis.id}"
policy = "${data.aws_iam_policy_document.kinesis.json}"
}
41 changes: 41 additions & 0 deletions kinesis.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module "kinesis_label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.1"
namespace = "${var.namespace}"
name = "${var.name}"
stage = "${var.stage}"
delimiter = "${var.delimiter}"
attributes = "${compact(concat(var.attributes, list("kinesis")))}"
tags = "${var.tags}"
enabled = "${var.enabled}"
}

module "subscription_filter_label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.1"
namespace = "${var.namespace}"
name = "${var.name}"
stage = "${var.stage}"
delimiter = "${var.delimiter}"
attributes = "${compact(concat(var.attributes, list("filter")))}"
tags = "${var.tags}"
enabled = "${var.enabled}"
}

resource "aws_kinesis_stream" "default" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.kinesis_label.id}"
shard_count = "${var.shard_count}"
retention_period = "${var.retention_period}"
shard_level_metrics = "${var.shard_level_metrics}"
encryption_type = "${var.encryption_type}"
kms_key_id = "${var.kms_key_id}"
tags = "${module.kinesis_label.tags}"
}

resource "aws_cloudwatch_log_subscription_filter" "default" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.subscription_filter_label.id}"
log_group_name = "${aws_cloudwatch_log_group.default.name}"
filter_pattern = "${var.filter_pattern}"
destination_arn = "${aws_kinesis_stream.default.arn}"
role_arn = "${aws_iam_role.kinesis.arn}"
}
67 changes: 67 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
data "aws_region" "default" {
current = "true"
}

module "log_group_label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.1"
namespace = "${var.namespace}"
name = "${var.name}"
stage = "${var.stage}"
delimiter = "${var.delimiter}"
attributes = "${compact(concat(var.attributes, list("log")))}"
tags = "${var.tags}"
enabled = "${var.enabled}"
}

module "vpc_label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.1"
namespace = "${var.namespace}"
name = "${var.name}"
stage = "${var.stage}"
delimiter = "${var.delimiter}"
attributes = "${compact(concat(var.attributes, list("vpc")))}"
tags = "${var.tags}"
enabled = "${var.enabled}"
}

module "subnet_label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.1"
namespace = "${var.namespace}"
name = "${var.name}"
stage = "${var.stage}"
delimiter = "${var.delimiter}"
attributes = "${compact(concat(var.attributes, list("subnets")))}"
tags = "${var.tags}"
enabled = "${var.enabled}"
}

resource "aws_cloudwatch_log_group" "default" {
count = "${var.enabled == "true" ? 1 : 0}"
name = "${module.log_group_label.id}"
retention_in_days = "${var.retention_in_days}"
tags = "${module.log_group_label.tags}"
}

resource "aws_flow_log" "vpc" {
count = "${var.enabled == "true" ? 1 : 0}"
log_group_name = "${aws_cloudwatch_log_group.default.name}"
iam_role_arn = "${aws_iam_role.log.arn}"
vpc_id = "${var.vpc_id}"
traffic_type = "${var.traffic_type}"
}

resource "aws_flow_log" "subnets" {
count = "${var.enabled == "true" ? length(compact(var.subnet_ids)) : 0}"
log_group_name = "${aws_cloudwatch_log_group.default.name}"
iam_role_arn = "${aws_iam_role.log.arn}"
subnet_id = "${element(compact(var.subnet_ids), count.index)}"
traffic_type = "${var.traffic_type}"
}

resource "aws_flow_log" "eni" {
count = "${var.enabled == "true" ? length(compact(var.eni_ids)) : 0}"
log_group_name = "${aws_cloudwatch_log_group.default.name}"
iam_role_arn = "${aws_iam_role.log.arn}"
subnet_id = "${element(compact(var.eni_ids), count.index)}"
traffic_type = "${var.traffic_type}"
}
39 changes: 39 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
output "log_group_arn" {
value = "${aws_cloudwatch_log_group.default.arn}"
description = "ARN of the log group"
}

output "vpc_flow_id" {
value = "${aws_flow_log.vpc.id}"
description = "Flow Log IDs of VPCs"
}

output "subnet_flow_ids" {
value = "${aws_flow_log.subnets.*.id}"
description = "Flow Log IDs of subnets"
}

output "eni_flow_ids" {
value = "${aws_flow_log.eni.*.id}"
description = "Flow Log IDs of ENIs"
}

output "kinesis_id" {
value = "${aws_kinesis_stream.default.id}"
description = "Stream ID"
}

output "kinesis_name" {
value = "${aws_kinesis_stream.default.name}"
description = "Stream name"
}

output "kinesis_shard_count" {
value = "${aws_kinesis_stream.default.shard_count}"
description = "Count of Shards for Stream"
}

output "kinesis_arn" {
value = "${aws_kinesis_stream.default.arn}"
description = "ARN of Stream"
}
Loading