Skip to content
36 changes: 36 additions & 0 deletions infrastructure/modules/obs-datasource/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!-- BEGIN_TF_DOCS -->
<!-- markdownlint-disable -->
<!-- vale off -->

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.0 |
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_aws_account_id"></a> [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes |
| <a name="input_component"></a> [component](#input\_component) | The name of the terraformscaffold component calling this module | `string` | n/a | yes |
| <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 |
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the terraformscaffold environment the module is called for | `string` | n/a | yes |
| <a name="input_log_group_configuration"></a> [log\_group\_configuration](#input\_log\_group\_configuration) | Configuration for filtering log groups in the link configuration. | <pre>object({<br/> filter = string<br/> })</pre> | `null` | no |
| <a name="input_metric_configuration"></a> [metric\_configuration](#input\_metric\_configuration) | Configuration for filtering metrics in the link configuration. | <pre>object({<br/> filter = string<br/> })</pre> | `null` | no |
| <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 |
| <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 |
| <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 |
| <a name="input_project"></a> [project](#input\_project) | The name of the terraformscaffold project calling the module | `string` | n/a | yes |
| <a name="input_region"></a> [region](#input\_region) | The AWS Region | `string` | n/a | yes |
| <a name="input_resource_types"></a> [resource\_types](#input\_resource\_types) | The resource types to include in the OAM link. | `list(string)` | <pre>[<br/> "AWS::CloudWatch::Metric",<br/> "AWS::Logs::LogGroup"<br/>]</pre> | no |
## Modules

No modules.
## Outputs

| Name | Description |
|------|-------------|
| <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. |
<!-- vale on -->
<!-- markdownlint-enable -->
<!-- END_TF_DOCS -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
resource "aws_iam_role" "log_subscription_role" {
name = "${local.csi}-log-subscription-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "logs.${var.region}.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}

resource "aws_iam_policy" "log_subscription_policy" {
name = "${local.csi}-log-subscription-policy"
description = "Policy for log subscription to send logs to the destination"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:PutSubscriptionFilter",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
]
Resource = "arn:aws:logs:${var.region}:${var.observability_account_id}:destination:nhs-notify-main-acct-firehose-logs"
}
]
})
}

resource "aws_iam_role_policy_attachment" "log_subscription_policy_attachment" {
role = aws_iam_role.log_subscription_role.name
policy_arn = aws_iam_policy.log_subscription_policy.arn
}
23 changes: 23 additions & 0 deletions infrastructure/modules/obs-datasource/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
locals {
module = "obs-datasource"

csi = replace(
format(
"%s-%s-%s-%s",
var.project,
var.environment,
var.component,
var.name,
),
"_",
"",
)
default_tags = merge(
var.default_tags,
{
Module = local.module
Name = local.csi
},
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
resource "aws_oam_link" "cross_account_obs" {
label_template = "$AccountName"
resource_types = var.resource_types
sink_identifier = "arn:aws:oam:${var.region}:${var.observability_account_id}:sink/${var.oam_sink_id}"
tags = var.default_tags

link_configuration {
dynamic "log_group_configuration" {
for_each = var.log_group_configuration != null ? [var.log_group_configuration] : []
content {
filter = log_group_configuration.value.filter
}
}

dynamic "metric_configuration" {
for_each = var.metric_configuration != null ? [var.metric_configuration] : []
content {
filter = metric_configuration.value.filter
}
}
}
}

data "aws_iam_policy" "cloudwatch_read_only" {
name = "CloudWatchReadOnlyAccess"
}

data "aws_iam_policy" "cloudwatch_automatic_dashboards" {
name = "CloudWatchAutomaticDashboardsAccess"
}

data "aws_iam_policy" "aws_xray_read_only" {
name = "AWSXrayReadOnlyAccess"
}

data "aws_iam_policy_document" "cross_account_obs_assume_role_policy" {
statement {
effect = "Allow"
principals {
type = "AWS"
identifiers = [var.observability_account_id]
}
actions = ["sts:AssumeRole"]
}
}

resource "aws_iam_role" "cross_account_obs_role" {
name = "CloudWatch-CrossAccountSharingRole"
assume_role_policy = data.aws_iam_policy_document.cross_account_obs_assume_role_policy.json
}

resource "aws_iam_role_policy_attachment" "cloudwatch_read_only_attachment" {
policy_arn = data.aws_iam_policy.cloudwatch_read_only.arn
role = aws_iam_role.cross_account_obs_role.name
}

resource "aws_iam_role_policy_attachment" "cloudwatch_automatic_dashboards_attachment" {
policy_arn = data.aws_iam_policy.cloudwatch_automatic_dashboards.arn
role = aws_iam_role.cross_account_obs_role.name
}

resource "aws_iam_role_policy_attachment" "aws_xray_read_only_attachment" {
policy_arn = data.aws_iam_policy.aws_xray_read_only.arn
role = aws_iam_role.cross_account_obs_role.name
}
4 changes: 4 additions & 0 deletions infrastructure/modules/obs-datasource/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "log_subscription_role_arn" {
description = "The ARN of the log subscription IAM role."
value = aws_iam_role.log_subscription_role.arn
}
82 changes: 82 additions & 0 deletions infrastructure/modules/obs-datasource/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
##
# Basic inherited variables for terraformscaffold modules
##

variable "project" {
type = string
description = "The name of the terraformscaffold project calling the module"
}

variable "environment" {
type = string
description = "The name of the terraformscaffold environment the module is called for"
}

variable "component" {
type = string
description = "The name of the terraformscaffold component calling this module"
}

variable "aws_account_id" {
type = string
description = "The AWS Account ID (numeric)"
}

##
# Variable specific to the module
##

# We presume this will always be specified. The default of {} will cause an error if a valid map is not specified.
# 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
# as the true default. In any other case default_tags should be removed from the module.
variable "default_tags" {
type = map(string)
description = "Default tag map for application to all taggable resources in the module"
default = {}
}

variable "region" {
type = string
description = "The AWS Region"
}

variable "name" {
type = string
description = "A unique name to distinguish this module invocation from others within the same CSI scope"
}

variable "oam_sink_id" {
description = "The ID of the Cloudwatch OAM sink in the appropriate observability account."
type = string
default = ""
}

variable "observability_account_id" {
type = string
description = "The Observability Account ID that needs access"
}

variable "log_group_configuration" {
description = "Configuration for filtering log groups in the link configuration." # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/oam_link#link_configuration-block
type = object({
filter = string
})
default = null
}

variable "metric_configuration" {
description = "Configuration for filtering metrics in the link configuration." # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/oam_link#link_configuration-block
type = object({
filter = string
})
default = null
}

variable "resource_types" {
type = list(string)
description = "The resource types to include in the OAM link."
default = [
"AWS::CloudWatch::Metric",
"AWS::Logs::LogGroup"
]
}
9 changes: 9 additions & 0 deletions infrastructure/modules/obs-datasource/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
required_version = ">= 1.9.0"
}
Loading