diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dd4bc49..51ac832f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## v0.18 [2024-02-28] + +_What's new?_ + +- New dashboards added: + - [OpenSearch Domain Detail](https://hub.steampipe.io/mods/turbot/aws_insights/dashboards/dashboard.opensearch_domain_detail) ([#75](https://github.com/turbot/steampipe-mod-aws-insights/pull/338)) (Thanks [@Errahulaws](https://github.com/Errahulaws) for the contribution!) + ## v0.17 [2023-11-30] _Bug fixes_ diff --git a/dashboards/opensearch/docs/opensearch_details.md b/dashboards/opensearch/docs/opensearch_details.md new file mode 100644 index 00000000..949f762d --- /dev/null +++ b/dashboards/opensearch/docs/opensearch_details.md @@ -0,0 +1,7 @@ +This dashboard answers the following questions for each domain: + +- How is the domain configured? +- What tags are applied? +- What relationships does the function have with other resources? +- What is the security group applied? +- What is the subnet applied? diff --git a/dashboards/opensearch/opensearch.sp b/dashboards/opensearch/opensearch.sp index 7ad483db..bd348768 100644 --- a/dashboards/opensearch/opensearch.sp +++ b/dashboards/opensearch/opensearch.sp @@ -1,3 +1,8 @@ +locals { + opensearch_common_tags = { + service = "AWS/OpenSearch" + } +} category "opensearch_domain" { title = "OpenSearch Domain" color = local.analytics_color diff --git a/dashboards/opensearch/opensearch_details.sp b/dashboards/opensearch/opensearch_details.sp new file mode 100644 index 00000000..03a6db39 --- /dev/null +++ b/dashboards/opensearch/opensearch_details.sp @@ -0,0 +1,292 @@ +dashboard "opensearch_domain_detail" { + + title = "AWS OpenSearch Domain Detail" + + tags = merge(local.opensearch_common_tags, { + type = "Detail" + }) + + input "opensearch_arn" { + title = "select a domain:" + query = query.opensearch_domain_input + width = 4 + } + + container { + + card { + width = 3 + query = query.opensearch_domain_instance_type + args = [self.input.opensearch_arn.value] + } + + card { + width = 2 + query = query.opensearch_domain_version + args = [self.input.opensearch_arn.value] + } + + card { + width = 3 + query = query.opensearch_domain_endpoint + args = [self.input.opensearch_arn.value] + } + } + + with "vpc_security_groups_for_opensearch" { + query = query.vpc_security_groups_for_opensearch + args = [self.input.opensearch_arn.value] + } + + with "vpc_subnet_for_opensearch" { + query = query.vpc_subnet_ids_for_opensearch + args = [self.input.opensearch_arn.value] + } + + with "vpc_vpcs_for_opensearch" { + query = query.vpc_vpcs_for_opensearch + args = [self.input.opensearch_arn.value] + } + + container { + + graph { + + title = "Relationships" + type = "graph" + direction = "TD" + + node { + base = node.opensearch_domain + args = { + opensearch_arns = [self.input.opensearch_arn.value] + } + } + + node { + base = node.vpc_security_group + args = { + vpc_security_group_ids = with.vpc_security_groups_for_opensearch.rows[*].security_group_id + } + } + + node { + base = node.vpc_subnet + args = { + vpc_subnet_ids = with.vpc_subnet_for_opensearch.rows[*].subnet_id + } + } + + node { + base = node.vpc_vpc + args = { + vpc_vpc_ids = with.vpc_vpcs_for_opensearch.rows[*].vpc_id + } + } + + edge { + base = edge.opensearch_domain_to_vpc_security_group + args = { + opensearch_arn = self.input.opensearch_arn.value + } + } + + edge { + base = edge.opensearch_domain_to_vpc_subnet + args = { + opensearch_arn = self.input.opensearch_arn.value + } + } + + edge { + base = edge.vpc_subnet_to_vpc_vpc + args = { + vpc_subnet_ids = with.vpc_subnet_for_opensearch.rows[*].subnet_id + } + } + + } + + } + + container { + width = 12 + + table { + title = "Overview" + type = "line" + width = 6 + query = query.opensearch_domain_overview + args = [self.input.opensearch_arn.value] + } + + table { + title = "Tags" + width = 6 + query = query.opensearch_domain_tags + args = [self.input.opensearch_arn.value] + } + + } + +container { + width = 6 + + table { + title = "Security Groups" + query = query.opensearch_domain_security_groups + args = [self.input.opensearch_arn.value] + + column "Group ID" { + // cyclic dependency prevents use of url_path, hardcode for now + href = "/aws_insights.dashboard.vpc_security_group_detail?input.security_group_id={{.'Group ID' | @uri}}" + } + } + + } + container { + width = 6 + + table { + title = "Subnet" + query = query.opensearch_domain_subnet + args = [self.input.opensearch_arn.value] + } + } + +} + +query "opensearch_domain_input" { + sql = <<-EOQ + select + domain_name as label, + arn as value, + json_build_object( + 'domain_name', domain_name, + 'arn', arn + ) as tags + from + aws_opensearch_domain + order by + domain_name; + EOQ +} + +query "opensearch_domain_tags" { + sql = <<-EOQ + select + tags->>'Key' AS "Key", + tags->>'Value' AS "Value" + from ( + select jsonb_array_elements(tags_src) AS tags + from aws_opensearch_domain + where arn = $1 + ) AS subquery; + EOQ +} + +query "opensearch_domain_version" { + sql = <<-EOQ + select + engine_version as "Engine Version" + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "opensearch_domain_instance_type" { + sql = <<-EOQ + select + cluster_config->>'InstanceType' AS "Instance Type" + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "opensearch_domain_overview" { + sql = <<-EOQ + select + domain_name AS "Domain Name", + arn AS "ARN", + created as "Created", + processing as "Processing", + region as "Region", + account_id as "Account ID" + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "opensearch_domain_endpoint" { + sql = <<-EOQ + select + endpoints ->> 'vpc' as "VPC Endpoint" + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "vpc_security_groups_for_opensearch" { + sql = <<-EOQ + select + jsonb_array_elements_text(vpc_options -> 'SecurityGroupIds') AS security_group_id + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "vpc_subnet_ids_for_opensearch" { + sql = <<-EOQ + select + jsonb_array_elements_text(vpc_options -> 'SubnetIds') AS subnet_id + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "vpc_vpcs_for_opensearch" { + sql = <<-EOQ + select + vpc_options ->> 'VPCId' AS vpc_id + from + aws_opensearch_domain + where + arn = $1; + EOQ +} + +query "opensearch_domain_security_groups" { + sql = <<-EOQ + select + GroupID AS "Group ID" + from ( + select jsonb_array_elements_text(vpc_options -> 'SecurityGroupIds') AS GroupID + from aws_opensearch_domain + where arn = $1 + ) AS subquery; + EOQ +} + +query "opensearch_domain_subnet" { + sql = <<-EOQ + select + SubnetID AS "Subnet ID" + from ( + select jsonb_array_elements_text(vpc_options -> 'SubnetIds') AS SubnetID + from aws_opensearch_domain + where arn = $1 + ) AS subquery; + EOQ +} diff --git a/dashboards/opensearch/opensearch_edges.sp b/dashboards/opensearch/opensearch_edges.sp index 570ff265..0d0890df 100644 --- a/dashboards/opensearch/opensearch_edges.sp +++ b/dashboards/opensearch/opensearch_edges.sp @@ -12,4 +12,38 @@ edge "opensearch_domain_to_acm_certificate" { EOQ param "acm_certificate_arns" {} -} \ No newline at end of file +} + +edge "opensearch_domain_to_vpc_security_group" { + title = "Security Groups" + + sql = <<-EOQ + select + arn as from_id, + jsonb_array_elements_text(vpc_options -> 'SecurityGroupIds') AS to_id + from + aws_opensearch_domain + JOIN jsonb_array_elements(vpc_options -> 'SecurityGroupIds') AS s ON true + where + arn = $1; + EOQ + + param "opensearch_arn" {} +} + +edge "opensearch_domain_to_vpc_subnet" { + title = "subnet" + + sql = <<-EOQ + select + jsonb_array_elements_text(vpc_options -> 'SecurityGroupIds') as from_id, + jsonb_array_elements_text(vpc_options -> 'SubnetIds') AS to_id + from + aws_opensearch_domain + JOIN jsonb_array_elements(vpc_options -> 'SecurityGroupIds') AS s ON true + where + arn = $1; + EOQ + + param "opensearch_arn" {} +} diff --git a/dashboards/opensearch/opensearch_nodes.sp b/dashboards/opensearch/opensearch_nodes.sp index 8d1168b1..896d07e6 100644 --- a/dashboards/opensearch/opensearch_nodes.sp +++ b/dashboards/opensearch/opensearch_nodes.sp @@ -16,7 +16,7 @@ node "opensearch_domain" { from aws_opensearch_domain where - domain_endpoint_options ->> 'CustomEndpointCertificateArn' = any($1); + arn = any($1); EOQ param "opensearch_arns" {}