Skip to content

Commit 5009562

Browse files
CCM-8197: Cross Account Observability
1 parent 3ccec8c commit 5009562

7 files changed

Lines changed: 229 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!-- BEGIN_TF_DOCS -->
2+
<!-- markdownlint-disable -->
3+
<!-- vale off -->
4+
5+
## Requirements
6+
7+
| Name | Version |
8+
|------|---------|
9+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.0 |
10+
## Inputs
11+
12+
| Name | Description | Type | Default | Required |
13+
|------|-------------|------|---------|:--------:|
14+
| <a name="input_aws_account_id"></a> [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes |
15+
| <a name="input_component"></a> [component](#input\_component) | The name of the terraformscaffold component calling this module | `string` | n/a | yes |
16+
| <a name="input_default_tags"></a> [default\_tags](#input\_default\_tags) | Default tag map for application to all taggable resources in the module | `map(string)` | `{}` | no |
17+
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the terraformscaffold environment the module is called for | `string` | n/a | yes |
18+
| <a name="input_name"></a> [name](#input\_name) | A unique name to distinguish this module invocation from others within the same CSI scope | `string` | n/a | yes |
19+
| <a name="input_oam_sink_id"></a> [oam\_sink\_id](#input\_oam\_sink\_id) | The ID of the Cloudwatch OAM sink in the appropriate observability account. | `string` | `""` | no |
20+
| <a name="input_observability_account_id"></a> [observability\_account\_id](#input\_observability\_account\_id) | The Observability Account ID that needs access | `string` | n/a | yes |
21+
| <a name="input_project"></a> [project](#input\_project) | The name of the terraformscaffold project calling the module | `string` | n/a | yes |
22+
| <a name="input_region"></a> [region](#input\_region) | The AWS Region | `string` | n/a | yes |
23+
## Modules
24+
25+
No modules.
26+
## Outputs
27+
28+
| Name | Description |
29+
|------|-------------|
30+
| <a name="output_log_subscription_role_arn"></a> [log\_subscription\_role\_arn](#output\_log\_subscription\_role\_arn) | The ARN of the log subscription IAM role. |
31+
<!-- vale on -->
32+
<!-- markdownlint-enable -->
33+
<!-- END_TF_DOCS -->
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
resource "aws_iam_role" "log_subscription_role" {
2+
name = "${local.csi}-log-subscription-role"
3+
4+
assume_role_policy = jsonencode({
5+
Version = "2012-10-17"
6+
Statement = [
7+
{
8+
Effect = "Allow"
9+
Principal = {
10+
Service = "logs.${var.region}.amazonaws.com"
11+
}
12+
Action = "sts:AssumeRole"
13+
}
14+
]
15+
})
16+
}
17+
18+
resource "aws_iam_policy" "log_subscription_policy" {
19+
name = "${local.csi}-log-subscription-policy"
20+
description = "Policy for log subscription to send logs to the destination"
21+
22+
policy = jsonencode({
23+
Version = "2012-10-17"
24+
Statement = [
25+
{
26+
Effect = "Allow"
27+
Action = [
28+
"logs:PutSubscriptionFilter",
29+
"logs:DescribeLogGroups",
30+
"logs:DescribeLogStreams",
31+
"logs:PutLogEvents"
32+
]
33+
Resource = "arn:aws:logs:${var.region}:${var.observability_account_id}:destination:nhs-notify-main-acct-firehose-logs"
34+
}
35+
]
36+
})
37+
}
38+
39+
resource "aws_iam_role_policy_attachment" "log_subscription_policy_attachment" {
40+
role = aws_iam_role.log_subscription_role.name
41+
policy_arn = aws_iam_policy.log_subscription_policy.arn
42+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
locals {
2+
module = "eventpub"
3+
4+
csi = replace(
5+
format(
6+
"%s-%s-%s-%s",
7+
var.project,
8+
var.environment,
9+
var.component,
10+
var.name,
11+
),
12+
"_",
13+
"",
14+
)
15+
default_tags = merge(
16+
var.default_tags,
17+
{
18+
Module = local.module
19+
Name = local.csi
20+
},
21+
)
22+
23+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
resource "aws_oam_link" "cross_account_obs" {
2+
count = var.oam_sink_id != "" ? 1 : 0
3+
label_template = "$AccountName"
4+
resource_types = [
5+
"AWS::CloudWatch::Metric",
6+
"AWS::Logs::LogGroup"
7+
]
8+
sink_identifier = "arn:aws:oam:${var.region}:${var.observability_account_id}:sink/${var.oam_sink_id}"
9+
tags = var.default_tags
10+
}
11+
12+
data "aws_iam_policy" "cloudwatch_read_only" {
13+
count = var.oam_sink_id != "" ? 1 : 0
14+
name = "CloudWatchReadOnlyAccess"
15+
}
16+
17+
data "aws_iam_policy" "cloudwatch_automatic_dashboards" {
18+
count = var.oam_sink_id != "" ? 1 : 0
19+
name = "CloudWatchAutomaticDashboardsAccess"
20+
}
21+
22+
data "aws_iam_policy" "aws_xray_read_only" {
23+
count = var.oam_sink_id != "" ? 1 : 0
24+
name = "AWSXrayReadOnlyAccess"
25+
}
26+
27+
data "aws_iam_policy_document" "cross_account_obs_assume_role_policy" {
28+
count = var.oam_sink_id != "" ? 1 : 0
29+
statement {
30+
effect = "Allow"
31+
principals {
32+
type = "AWS"
33+
identifiers = [var.observability_account_id]
34+
}
35+
actions = ["sts:AssumeRole"]
36+
}
37+
}
38+
39+
resource "aws_iam_role" "cross_account_obs_role" {
40+
count = var.oam_sink_id != "" ? 1 : 0
41+
name = "CloudWatch-CrossAccountSharingRole"
42+
assume_role_policy = data.aws_iam_policy_document.cross_account_obs_assume_role_policy[0].json
43+
}
44+
45+
resource "aws_iam_role_policy_attachment" "cloudwatch_read_only_attachment" {
46+
count = var.oam_sink_id != "" ? 1 : 0
47+
policy_arn = data.aws_iam_policy.cloudwatch_read_only[0].arn
48+
role = aws_iam_role.cross_account_obs_role[0].name
49+
}
50+
51+
resource "aws_iam_role_policy_attachment" "cloudwatch_automatic_dashboards_attachment" {
52+
count = var.oam_sink_id != "" ? 1 : 0
53+
policy_arn = data.aws_iam_policy.cloudwatch_automatic_dashboards[0].arn
54+
role = aws_iam_role.cross_account_obs_role[0].name
55+
}
56+
57+
resource "aws_iam_role_policy_attachment" "aws_xray_read_only_attachment" {
58+
count = var.oam_sink_id != "" ? 1 : 0
59+
policy_arn = data.aws_iam_policy.aws_xray_read_only[0].arn
60+
role = aws_iam_role.cross_account_obs_role[0].name
61+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "log_subscription_role_arn" {
2+
description = "The ARN of the log subscription IAM role."
3+
value = aws_iam_role.log_subscription_role.arn
4+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
##
2+
# Basic inherited variables for terraformscaffold modules
3+
##
4+
5+
variable "project" {
6+
type = string
7+
description = "The name of the terraformscaffold project calling the module"
8+
}
9+
10+
variable "environment" {
11+
type = string
12+
description = "The name of the terraformscaffold environment the module is called for"
13+
}
14+
15+
variable "component" {
16+
type = string
17+
description = "The name of the terraformscaffold component calling this module"
18+
}
19+
20+
variable "aws_account_id" {
21+
type = string
22+
description = "The AWS Account ID (numeric)"
23+
}
24+
25+
##
26+
# Variable specific to the module
27+
##
28+
29+
# We presume this will always be specified. The default of {} will cause an error if a valid map is not specified.
30+
# If we ever want to define this but allow it to not be specified, then we must provide a default tag keypair will be applied
31+
# as the true default. In any other case default_tags should be removed from the module.
32+
variable "default_tags" {
33+
type = map(string)
34+
description = "Default tag map for application to all taggable resources in the module"
35+
default = {}
36+
}
37+
38+
variable "region" {
39+
type = string
40+
description = "The AWS Region"
41+
}
42+
43+
variable "name" {
44+
type = string
45+
description = "A unique name to distinguish this module invocation from others within the same CSI scope"
46+
}
47+
48+
variable "oam_sink_id" {
49+
description = "The ID of the Cloudwatch OAM sink in the appropriate observability account."
50+
type = string
51+
default = ""
52+
}
53+
54+
variable "observability_account_id" {
55+
type = string
56+
description = "The Observability Account ID that needs access"
57+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
terraform {
3+
required_providers {
4+
aws = {
5+
source = "hashicorp/aws"
6+
}
7+
}
8+
required_version = ">= 1.9.0"
9+
}

0 commit comments

Comments
 (0)