Skip to content
Merged
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
21 changes: 8 additions & 13 deletions argocd/iac/terraform/examples/eks/external-secrets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@

This example shows how to deploy Amazon EKS with addons configured via ArgoCD

The example demonstrate how to use private git repository for workload apps.

The example stores your ssh key in AWS Secret Manager, and External Secret Operator to create the secret
for ArgoCD to access the git repositories.

## Prerequisites
- Create a Github ssh key file, example assumes the file path `~/.ssh/id_rsa`, update `main.tf` if using a different location
The example demonstrate how to use [External Secret Operator(ESO)](https://external-secrets.io) with
AWS Secret Manager and AWS Systems Manager Parameter Store

Deploy EKS Cluster
```shell
Expand All @@ -21,16 +16,16 @@ Access Terraform output to configure `kubectl` and `argocd`
terraform output
```

There is a file `github.yaml` located in the addons git repository `clusters/ex-external-secrets/secret/` this file creates the resources `ClusterSecretStore` and `ExternalSecret`. Update git url in this file when you change the git repository for the workloads specified in `bootstrap/workloads.yaml`. Also update the region in this file if you are using a different region for AWS Secret Manager.

To verify that the ArgoCD secret with ssh key is created run the following command
Verify that the secrets `external-secrets-ps` and `external-secrets-sm` are present
```shell
kubectl get secret private-repo-creds -n argocd
kubectl get secrets -n external-secrets
```

Expected output, should have 3 data items in secret
```
NAME TYPE DATA AGE
private-repo-creds Opaque 3 6m45s
NAME TYPE DATA AGE
external-secrets-ps Opaque 2 1m
external-secrets-sm Opaque 2 1m
```

Destroy EKS Cluster
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
---
apiVersion: argoproj.io/v1alpha1
kind: Application
kind: ApplicationSet
metadata:
name: bootstrap-addons
namespace: 'argocd'
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
namespace: 'argocd'
project: default
source:
path: ${path}
repoURL: ${repoURL}
targetRevision: ${targetRevision}
directory:
recurse: true
exclude: exclude/*
syncPolicy:
automated: {}
preserveResourcesOnDeletion: true
generators:
- clusters:
selector:
matchExpressions:
- key: akuity.io/argo-cd-cluster-name
operator: NotIn
values: [in-cluster]
template:
metadata:
name: 'bootstrap-addons'
spec:
project: default
source:
repoURL: '{{metadata.annotations.gitops_bridge_repo_url}}'
path: '{{metadata.annotations.gitops_bridge_repo_path}}'
targetRevision: '{{metadata.annotations.gitops_bridge_repo_revision}}'
directory:
recurse: true
exclude: exclude/*
destination:
namespace: 'argocd'
name: '{{name}}'
syncPolicy:
automated: {}
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
---
apiVersion: argoproj.io/v1alpha1
kind: Application
kind: ApplicationSet
metadata:
name: bootstrap-workloads
namespace: 'argocd'
finalizers:
- resources-finalizer.argocd.argoproj.io
name: external-secrets-example
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
namespace: 'guestbook'
project: default
source:
path: helm-guestbook
repoURL: git@github.com:argoproj/argocd-example-apps.git
targetRevision: HEAD
syncPolicy:
automated: {}
syncOptions:
- CreateNamespace=true
preserveResourcesOnDeletion: true
generators:
- clusters:
selector:
matchExpressions:
- key: akuity.io/argo-cd-cluster-name
operator: NotIn
values: [in-cluster]
template:
metadata:
name: 'external-secrets-example'
spec:
project: default
source:
repoURL: '{{metadata.annotations.workload_repo_url}}'
path: '{{metadata.annotations.workload_repo_path}}'
targetRevision: '{{metadata.annotations.workload_repo_revision}}'
helm:
releaseName: 'external-secrets-example'
values: |
region: '{{metadata.annotations.aws_region}}'
externalSecret:
clusterSecretStore:
secret: '{{metadata.annotations.workload_sm_secret}}'
secretStore:
secret: '{{metadata.annotations.workload_ps_secret}}'
destination:
namespace: '{{metadata.annotations.external_secrets_namespace}}'
name: '{{name}}'
syncPolicy:
automated: {}
retry:
backoff:
duration: 1m
limit: 10
syncOptions:
- CreateNamespace=true
24 changes: 24 additions & 0 deletions argocd/iac/terraform/examples/eks/external-secrets/k8s/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: v2
name: resources
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.0.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: cluster-secretstore-sm
spec:
provider:
aws:
service: SecretsManager
region: {{ .Values.region }}
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: external-secrets-sm
spec:
refreshInterval: 1h
secretStoreRef:
name: cluster-secretstore-sm
kind: ClusterSecretStore
dataFrom:
- extract:
key: {{ .Values.externalSecret.clusterSecretStore.secret }}
---
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secretstore-ps
spec:
provider:
aws:
service: ParameterStore
region: {{ .Values.region }}
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: external-secrets-ps
spec:
refreshInterval: 1h
secretStoreRef:
name: secretstore-ps
kind: SecretStore
dataFrom:
- extract:
key: {{ .Values.externalSecret.secretStore.secret }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
region: us-west-2
externalSecret:
clusterSecretStore:
secret: secret
secretStore:
secret: /external-secrets/secret
97 changes: 64 additions & 33 deletions argocd/iac/terraform/examples/eks/external-secrets/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,36 @@ provider "kubernetes" {
}

locals {
name = "ex-${replace(basename(path.cwd), "_", "-")}"
environment = "dev"
region = "us-west-2"
cluster_version = "1.27"
gitops_url = var.gitops_url
gitops_revision = var.gitops_revision
gitops_path = var.gitops_path
name = "ex-${replace(basename(path.cwd), "_", "-")}"
environment = "dev"
region = "us-west-2"
cluster_version = "1.27"
gitops_addons_org = var.gitops_addons_org
gitops_addons_repo = var.gitops_addons_repo
gitops_addons_path = var.gitops_addons_path
gitops_addons_revision = var.gitops_addons_revision
gitops_addons_url = "${local.gitops_addons_org}/${local.gitops_addons_repo}"

gitops_workload_org = var.gitops_workload_org
gitops_workload_repo = var.gitops_workload_repo
gitops_workload_path = var.gitops_workload_path
gitops_workload_revision = var.gitops_workload_revision
gitops_workload_url = "${local.gitops_workload_org}/${local.gitops_workload_repo}"

# Secret names in AWS
workload_sm_secret = local.name
workload_pm_secret = "/${local.name}/secret"

aws_secret_manager_secret_name = "argocd-ssh-key"
git_private_ssh_key = "~/.ssh/id_rsa" # Update with the git ssh key to be used by ArgoCD

aws_addons = {
enable_cert_manager = true
#enable_cert_manager = true
#enable_aws_efs_csi_driver = true
#enable_aws_fsx_csi_driver = true
#enable_aws_cloudwatch_metrics = true
#enable_aws_privateca_issuer = true
#enable_cluster_autoscaler = true
#enable_external_dns = true
enable_external_secrets = true
enable_external_secrets = true
#enable_aws_load_balancer_controller = true
#enable_fargate_fluentbit = true
#enable_aws_for_fluentbit = true
Expand All @@ -82,7 +92,7 @@ locals {
#enable_ingress_nginx = true
#enable_kyverno = true
#enable_kube_prometheus_stack = true
enable_metrics_server = true
#enable_metrics_server = true
#enable_prometheus_adapter = true
#enable_secrets_store_csi_driver = true
#enable_vpa = true
Expand All @@ -99,17 +109,23 @@ locals {
aws_vpc_id = module.vpc.vpc_id
},
{
gitops_bridge_repo_url = local.gitops_url
gitops_bridge_repo_revision = local.gitops_revision
gitops_bridge_repo_url = local.gitops_addons_url
gitops_bridge_repo_path = local.gitops_addons_path
gitops_bridge_repo_revision = local.gitops_addons_revision
},
{
workload_repo_url = local.gitops_workload_url
workload_repo_path = local.gitops_workload_path
workload_repo_revision = local.gitops_workload_revision
},
{
workload_sm_secret = aws_secretsmanager_secret.secret.name
workload_ps_secret = aws_ssm_parameter.secret_parameter.name
}
)

argocd_bootstrap_app_of_apps = {
addons = templatefile("${path.module}/bootstrap/addons.yaml", {
repoURL = local.gitops_url
targetRevision = local.gitops_revision
path = local.gitops_path
})
addons = file("${path.module}/bootstrap/addons.yaml")
workloads = file("${path.module}/bootstrap/workloads.yaml")
}

Expand All @@ -122,6 +138,35 @@ locals {
}
}

################################################################################
# Secret Manager & Parameter Store
################################################################################
resource "aws_kms_key" "secrets" {
enable_key_rotation = true
}
resource "aws_secretsmanager_secret" "secret" {
name = local.workload_sm_secret
recovery_window_in_days = 0
kms_key_id = aws_kms_key.secrets.arn
}
resource "aws_secretsmanager_secret_version" "secret" {
secret_id = aws_secretsmanager_secret.secret.id
secret_string = jsonencode({
username = "secretuser",
password = "secretpassword"
})
}
resource "aws_ssm_parameter" "secret_parameter" {
name = local.workload_pm_secret
type = "SecureString"
value = jsonencode({
username = "secretuser",
password = "secretpassword"
})
key_id = aws_kms_key.secrets.arn
}


################################################################################
# GitOps Bridge: Metadata
################################################################################
Expand All @@ -144,20 +189,6 @@ module "gitops_bridge_bootstrap" {
argocd_bootstrap_app_of_apps = local.argocd_bootstrap_app_of_apps
}

################################################################################
# AWS Secret Manager
################################################################################
#tfsec:ignore:aws-ssm-secret-use-customer-key
resource "aws_secretsmanager_secret" "git_ssh_key" {
name = local.aws_secret_manager_secret_name
recovery_window_in_days = 0 # Set to zero for this example to force delete during Terraform destroy
}
resource "aws_secretsmanager_secret_version" "git_ssh_key" {
secret_id = aws_secretsmanager_secret.git_ssh_key.id
secret_string = file(pathexpand(local.git_private_ssh_key))
}


################################################################################
# EKS Blueprints Addons
################################################################################
Expand Down
Loading