Skip to content

API Key rotation for Grafana Workspace #259

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

Closed
wants to merge 15 commits into from
Closed
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
10 changes: 10 additions & 0 deletions examples/existing-cluster-with-base-and-infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ View the full documentation for this example [here](https://aws-observability.gi
| Name | Source | Version |
|------|--------|---------|
| <a name="module_eks_monitoring"></a> [eks\_monitoring](#module\_eks\_monitoring) | ../../modules/eks-monitoring | n/a |
| <a name="module_grafana_key_rotation"></a> [grafana\_key\_rotation](#module\_grafana\_key\_rotation) | ../../modules/grafana-key-rotation | n/a |

## Resources

Expand All @@ -52,7 +53,12 @@ View the full documentation for this example [here](https://aws-observability.gi
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS Region | `string` | n/a | yes |
| <a name="input_eks_cluster_id"></a> [eks\_cluster\_id](#input\_eks\_cluster\_id) | Name of the EKS cluster | `string` | `"eks-cluster-with-vpc"` | no |
| <a name="input_enable_dashboards"></a> [enable\_dashboards](#input\_enable\_dashboards) | Enables or disables curated dashboards. Dashboards are managed by the Grafana Operator | `bool` | `true` | no |
| <a name="input_enable_grafana_key_rotation"></a> [enable\_grafana\_key\_rotation](#input\_enable\_grafana\_key\_rotation) | Enables or disables Grafana API key rotation | `bool` | `true` | no |
| <a name="input_eventbridge_scheduler_schedule_expression"></a> [eventbridge\_scheduler\_schedule\_expression](#input\_eventbridge\_scheduler\_schedule\_expression) | Schedule Expression for EventBridge Scheduler in Grafana API Key Rotation | `string` | `"rate(60 minutes)"` | no |
| <a name="input_grafana_api_key"></a> [grafana\_api\_key](#input\_grafana\_api\_key) | API key for authorizing the Grafana provider to make changes to Amazon Managed Grafana | `string` | n/a | yes |
| <a name="input_grafana_api_key_interval"></a> [grafana\_api\_key\_interval](#input\_grafana\_api\_key\_interval) | Number of seconds for secondsToLive value while creating API Key | `number` | `5400` | no |
| <a name="input_grafana_api_key_refresh_interval"></a> [grafana\_api\_key\_refresh\_interval](#input\_grafana\_api\_key\_refresh\_interval) | Refresh Internal to be used by External Secrets for Grafana API Key rotation | `string` | `"5m"` | no |
| <a name="input_lambda_runtime_grafana_key_rotation"></a> [lambda\_runtime\_grafana\_key\_rotation](#input\_lambda\_runtime\_grafana\_key\_rotation) | Python Runtime Identifier for the Lambda Function | `string` | `"python3.12"` | no |
| <a name="input_managed_grafana_workspace_id"></a> [managed\_grafana\_workspace\_id](#input\_managed\_grafana\_workspace\_id) | Amazon Managed Grafana Workspace ID | `string` | n/a | yes |
| <a name="input_managed_prometheus_workspace_id"></a> [managed\_prometheus\_workspace\_id](#input\_managed\_prometheus\_workspace\_id) | Amazon Managed Service for Prometheus Workspace ID | `string` | `""` | no |

Expand All @@ -62,6 +68,10 @@ View the full documentation for this example [here](https://aws-observability.gi
|------|-------------|
| <a name="output_eks_cluster_id"></a> [eks\_cluster\_id](#output\_eks\_cluster\_id) | EKS Cluster Id |
| <a name="output_eks_cluster_version"></a> [eks\_cluster\_version](#output\_eks\_cluster\_version) | EKS Cluster version |
| <a name="output_grafana_key_rotation_eventbridge_scheduler_arn"></a> [grafana\_key\_rotation\_eventbridge\_scheduler\_arn](#output\_grafana\_key\_rotation\_eventbridge\_scheduler\_arn) | ARN of the EventBridge Scheduler invoking Lambda Function for Key rotation |
| <a name="output_grafana_key_rotation_eventbridge_scheduler_role_arn"></a> [grafana\_key\_rotation\_eventbridge\_scheduler\_role\_arn](#output\_grafana\_key\_rotation\_eventbridge\_scheduler\_role\_arn) | ARN of the IAM Role of EventBridge Scheduler invoking Lambda Function for Key rotation |
| <a name="output_grafana_key_rotation_lambda_function_arn"></a> [grafana\_key\_rotation\_lambda\_function\_arn](#output\_grafana\_key\_rotation\_lambda\_function\_arn) | ARN of the Lambda function performing Key rotation |
| <a name="output_grafana_key_rotation_lambda_function_role_arn"></a> [grafana\_key\_rotation\_lambda\_function\_role\_arn](#output\_grafana\_key\_rotation\_lambda\_function\_role\_arn) | ARN of the Lambda function execution role |
| <a name="output_managed_prometheus_workspace_endpoint"></a> [managed\_prometheus\_workspace\_endpoint](#output\_managed\_prometheus\_workspace\_endpoint) | Amazon Managed Prometheus workspace endpoint |
| <a name="output_managed_prometheus_workspace_id"></a> [managed\_prometheus\_workspace\_id](#output\_managed\_prometheus\_workspace\_id) | Amazon Managed Prometheus workspace ID |
| <a name="output_managed_prometheus_workspace_region"></a> [managed\_prometheus\_workspace\_region](#output\_managed\_prometheus\_workspace\_region) | AWS Region |
Expand Down
26 changes: 21 additions & 5 deletions examples/existing-cluster-with-base-and-infra/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ module "eks_monitoring" {
enable_apiserver_monitoring = true

# deploys external-secrets in to the cluster
enable_external_secrets = true
grafana_api_key = var.grafana_api_key
target_secret_name = "grafana-admin-credentials"
target_secret_namespace = "grafana-operator"
grafana_url = "https://${data.aws_grafana_workspace.this.endpoint}"
enable_external_secrets = true
grafana_api_key = var.grafana_api_key
target_secret_name = "grafana-admin-credentials"
target_secret_namespace = "grafana-operator"
grafana_url = "https://${data.aws_grafana_workspace.this.endpoint}"
grafana_api_key_refresh_interval = var.grafana_api_key_refresh_interval

# control the publishing of dashboards by specifying the boolean value for the variable 'enable_dashboards', default is 'true'
enable_dashboards = var.enable_dashboards
Expand All @@ -79,3 +80,18 @@ module "eks_monitoring" {

tags = local.tags
}

# Enabling Grafana API Key Rotation
module "grafana_key_rotation" {
source = "../../modules/grafana-key-rotation"
count = var.enable_grafana_key_rotation ? 1 : 0

managed_grafana_workspace_id = var.managed_grafana_workspace_id
grafana_api_key_interval = var.grafana_api_key_interval
eventbridge_scheduler_schedule_expression = var.eventbridge_scheduler_schedule_expression
lambda_runtime_grafana_key_rotation = var.lambda_runtime_grafana_key_rotation

ssmparameter_name = module.eks_monitoring.ssmparameter_name
ssmparameter_arn = module.eks_monitoring.ssmparameter_arn
kms_key_arn_ssm = module.eks_monitoring.kms_key_arn
}
27 changes: 27 additions & 0 deletions examples/existing-cluster-with-base-and-infra/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,30 @@ output "eks_cluster_id" {
description = "EKS Cluster Id"
value = module.eks_monitoring.eks_cluster_id
}

output "grafana_key_rotation_lambda_function_arn" {
description = "ARN of the Lambda function performing Key rotation"
# value = module.grafana_key_rotation.lambda_function_arn
value = var.enable_grafana_key_rotation ? module.grafana_key_rotation[0].lambda_function_arn : null
}


output "grafana_key_rotation_lambda_function_role_arn" {
description = "ARN of the Lambda function execution role"
# value = module.grafana_key_rotation.lambda_function_role_arn
value = var.enable_grafana_key_rotation ? module.grafana_key_rotation[0].lambda_function_role_arn : null
}


output "grafana_key_rotation_eventbridge_scheduler_arn" {
description = "ARN of the EventBridge Scheduler invoking Lambda Function for Key rotation"
# value = module.grafana_key_rotation.eventbridge_scheduler_arn
value = var.enable_grafana_key_rotation ? module.grafana_key_rotation[0].eventbridge_scheduler_arn : null
}


output "grafana_key_rotation_eventbridge_scheduler_role_arn" {
description = "ARN of the IAM Role of EventBridge Scheduler invoking Lambda Function for Key rotation"
# value = module.grafana_key_rotation.eventbridge_scheduler_role_arn
value = var.enable_grafana_key_rotation ? module.grafana_key_rotation[0].eventbridge_scheduler_role_arn : null
}
30 changes: 30 additions & 0 deletions examples/existing-cluster-with-base-and-infra/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,33 @@ variable "enable_dashboards" {
type = bool
default = true
}

variable "enable_grafana_key_rotation" {
description = "Enables or disables Grafana API key rotation"
type = bool
default = true
}

variable "grafana_api_key_interval" {
description = "Number of seconds for secondsToLive value while creating API Key"
type = number
default = 5400
}

variable "eventbridge_scheduler_schedule_expression" {
description = "Schedule Expression for EventBridge Scheduler in Grafana API Key Rotation"
type = string
default = "rate(60 minutes)"
}

variable "grafana_api_key_refresh_interval" {
description = "Refresh Internal to be used by External Secrets for Grafana API Key rotation"
type = string
default = "5m"
}

variable "lambda_runtime_grafana_key_rotation" {
description = "Python Runtime Identifier for the Lambda Function"
type = string
default = "python3.12"
}
4 changes: 4 additions & 0 deletions modules/eks-monitoring/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ See examples using this Terraform modules in the **Amazon EKS** section of [this
| <a name="input_flux_kustomization_path"></a> [flux\_kustomization\_path](#input\_flux\_kustomization\_path) | Flux Kustomization Path | `string` | `"./artifacts/grafana-operator-manifests/eks/infrastructure"` | no |
| <a name="input_go_config"></a> [go\_config](#input\_go\_config) | Grafana Operator configuration | <pre>object({<br> create_namespace = optional(bool, true)<br> helm_chart = optional(string, "oci://ghcr.io/grafana-operator/helm-charts/grafana-operator")<br> helm_name = optional(string, "grafana-operator")<br> k8s_namespace = optional(string, "grafana-operator")<br> helm_release_name = optional(string, "grafana-operator")<br> helm_chart_version = optional(string, "v5.5.2")<br> })</pre> | `{}` | no |
| <a name="input_grafana_api_key"></a> [grafana\_api\_key](#input\_grafana\_api\_key) | Grafana API key for the Amazon Managed Grafana workspace. Required if `enable_external_secrets = true` | `string` | `""` | no |
| <a name="input_grafana_api_key_refresh_interval"></a> [grafana\_api\_key\_refresh\_interval](#input\_grafana\_api\_key\_refresh\_interval) | Refresh Internal to be used by External Secrets for Grafana API Key rotation | `string` | `"5m"` | no |
| <a name="input_grafana_cluster_dashboard_url"></a> [grafana\_cluster\_dashboard\_url](#input\_grafana\_cluster\_dashboard\_url) | Dashboard URL for Cluster Grafana Dashboard JSON | `string` | `"https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/v0.2.0/artifacts/grafana-dashboards/eks/infrastructure/cluster.json"` | no |
| <a name="input_grafana_kubelet_dashboard_url"></a> [grafana\_kubelet\_dashboard\_url](#input\_grafana\_kubelet\_dashboard\_url) | Dashboard URL for Kubelet Grafana Dashboard JSON | `string` | `"https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/v0.2.0/artifacts/grafana-dashboards/eks/infrastructure/kubelet.json"` | no |
| <a name="input_grafana_kubeproxy_dashboard_url"></a> [grafana\_kubeproxy\_dashboard\_url](#input\_grafana\_kubeproxy\_dashboard\_url) | Dashboard URL for kube-proxy Grafana Dashboard JSON | `string` | `"https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/v0.2.0/artifacts/grafana-dashboards/eks/kube-proxy/kube-proxy.json"` | no |
Expand Down Expand Up @@ -144,7 +145,10 @@ See examples using this Terraform modules in the **Amazon EKS** section of [this
| <a name="output_adot_irsa_arn"></a> [adot\_irsa\_arn](#output\_adot\_irsa\_arn) | IRSA Arn for ADOT |
| <a name="output_eks_cluster_id"></a> [eks\_cluster\_id](#output\_eks\_cluster\_id) | EKS Cluster Id |
| <a name="output_eks_cluster_version"></a> [eks\_cluster\_version](#output\_eks\_cluster\_version) | EKS Cluster version |
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | Name of the SSM Parameter |
| <a name="output_managed_prometheus_workspace_endpoint"></a> [managed\_prometheus\_workspace\_endpoint](#output\_managed\_prometheus\_workspace\_endpoint) | Amazon Managed Prometheus workspace endpoint |
| <a name="output_managed_prometheus_workspace_id"></a> [managed\_prometheus\_workspace\_id](#output\_managed\_prometheus\_workspace\_id) | Amazon Managed Prometheus workspace ID |
| <a name="output_managed_prometheus_workspace_region"></a> [managed\_prometheus\_workspace\_region](#output\_managed\_prometheus\_workspace\_region) | Amazon Managed Prometheus workspace region |
| <a name="output_ssmparameter_arn"></a> [ssmparameter\_arn](#output\_ssmparameter\_arn) | Name of the SSM Parameter |
| <a name="output_ssmparameter_name"></a> [ssmparameter\_name](#output\_ssmparameter\_name) | Name of the SSM Parameter |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
7 changes: 6 additions & 1 deletion modules/eks-monitoring/add-ons/external-secrets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,16 @@ This deploys an EKS Cluster with the External Secrets Operator. The cluster is p
| <a name="input_addon_context"></a> [addon\_context](#input\_addon\_context) | Input configuration for the addon | <pre>object({<br> aws_caller_identity_account_id = string<br> aws_caller_identity_arn = string<br> aws_eks_cluster_endpoint = string<br> aws_partition_id = string<br> aws_region_name = string<br> eks_cluster_id = string<br> eks_oidc_issuer_url = string<br> eks_oidc_provider_arn = string<br> irsa_iam_role_path = string<br> irsa_iam_permissions_boundary = string<br> tags = map(string)<br> })</pre> | n/a | yes |
| <a name="input_enable_external_secrets"></a> [enable\_external\_secrets](#input\_enable\_external\_secrets) | Enable external-secrets | `bool` | `true` | no |
| <a name="input_grafana_api_key"></a> [grafana\_api\_key](#input\_grafana\_api\_key) | Grafana API key for the Amazon Managed Grafana workspace | `string` | n/a | yes |
| <a name="input_grafana_api_key_refresh_interval"></a> [grafana\_api\_key\_refresh\_interval](#input\_grafana\_api\_key\_refresh\_interval) | Refresh Internal to be used by External Secrets for Grafana API Key rotation | `string` | n/a | yes |
| <a name="input_helm_config"></a> [helm\_config](#input\_helm\_config) | Helm provider config for external secrets | `any` | `{}` | no |
| <a name="input_target_secret_name"></a> [target\_secret\_name](#input\_target\_secret\_name) | Name to store the secret for Grafana API Key | `string` | n/a | yes |
| <a name="input_target_secret_namespace"></a> [target\_secret\_namespace](#input\_target\_secret\_namespace) | Namespace to store the secret for Grafana API Key | `string` | n/a | yes |

## Outputs

No outputs.
| Name | Description |
|------|-------------|
| <a name="output_kms_key_arn_ssm"></a> [kms\_key\_arn\_ssm](#output\_kms\_key\_arn\_ssm) | Name of the SSM Parameter |
| <a name="output_ssmparameter_arn"></a> [ssmparameter\_arn](#output\_ssmparameter\_arn) | Name of the SSM Parameter |
| <a name="output_ssmparameter_name"></a> [ssmparameter\_name](#output\_ssmparameter\_name) | Name of the SSM Parameter |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
2 changes: 1 addition & 1 deletion modules/eks-monitoring/add-ons/external-secrets/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ metadata:
name: ${local.name}-sm
namespace: ${var.target_secret_namespace}
spec:
refreshInterval: 1h
refreshInterval: ${var.grafana_api_key_refresh_interval}
secretStoreRef:
name: ${local.cluster_secretstore_name}
kind: ClusterSecretStore
Expand Down
14 changes: 14 additions & 0 deletions modules/eks-monitoring/add-ons/external-secrets/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
output "ssmparameter_name" {
description = "Name of the SSM Parameter"
value = aws_ssm_parameter.secret.name
}

output "ssmparameter_arn" {
description = "Name of the SSM Parameter"
value = aws_ssm_parameter.secret.arn
}

output "kms_key_arn_ssm" {
description = "Name of the SSM Parameter"
value = aws_kms_key.secrets.arn
}
5 changes: 5 additions & 0 deletions modules/eks-monitoring/add-ons/external-secrets/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ variable "target_secret_name" {
description = "Name to store the secret for Grafana API Key"
type = string
}

variable "grafana_api_key_refresh_interval" {
description = "Refresh Internal to be used by External Secrets for Grafana API Key rotation"
type = string
}
11 changes: 6 additions & 5 deletions modules/eks-monitoring/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,12 @@ module "external_secrets" {
source = "./add-ons/external-secrets"
count = var.enable_external_secrets ? 1 : 0

enable_external_secrets = var.enable_external_secrets
grafana_api_key = var.grafana_api_key
addon_context = local.context
target_secret_namespace = var.target_secret_namespace
target_secret_name = var.target_secret_name
enable_external_secrets = var.enable_external_secrets
grafana_api_key = var.grafana_api_key
addon_context = local.context
target_secret_namespace = var.target_secret_namespace
target_secret_name = var.target_secret_name
grafana_api_key_refresh_interval = var.grafana_api_key_refresh_interval

depends_on = [resource.helm_release.grafana_operator]
}
15 changes: 15 additions & 0 deletions modules/eks-monitoring/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ output "adot_irsa_arn" {
value = module.helm_addon.irsa_arn
}

output "ssmparameter_name" {
description = "Name of the SSM Parameter"
value = module.external_secrets[0].ssmparameter_name
}

output "ssmparameter_arn" {
description = "Name of the SSM Parameter"
value = module.external_secrets[0].ssmparameter_arn
}

output "kms_key_arn" {
description = "Name of the SSM Parameter"
value = module.external_secrets[0].kms_key_arn_ssm
}

output "managed_prometheus_workspace_endpoint" {
description = "Amazon Managed Prometheus workspace endpoint"
value = local.managed_prometheus_workspace_endpoint
Expand Down
6 changes: 6 additions & 0 deletions modules/eks-monitoring/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -565,3 +565,9 @@ variable "kubeproxy_monitoring_config" {
# defaults are pre-computed in locals.tf, provide a full definition to override
default = null
}

variable "grafana_api_key_refresh_interval" {
description = "Refresh Internal to be used by External Secrets for Grafana API Key rotation"
type = string
default = "5m"
}
Loading
Loading