Skip to content
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

new: Secrets Manager integration with EKS #686

Merged
merged 34 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
62f19eb
Refactoring folder structure for Secrets Management
rodrigobersa Oct 6, 2023
014627f
Adding Secrets manager index
rodrigobersa Oct 6, 2023
d555406
Changing module order
rodrigobersa Oct 6, 2023
2c56cc8
Adding Deployment directory
rodrigobersa Oct 6, 2023
41737c6
Fixing directory structure
rodrigobersa Oct 7, 2023
79a89de
EKS Validation
rodrigobersa Oct 7, 2023
6f52599
Fixing Addon, and validation steps
rodrigobersa Oct 9, 2023
d93e4fa
Secrets module directory structure
rodrigobersa Oct 9, 2023
88a8e84
Adding secret store
rodrigobersa Oct 10, 2023
e7059cc
Fix typo
rodrigobersa Oct 10, 2023
ba426f0
Changing module strucutre
rodrigobersa Oct 11, 2023
2616806
Fixing descriptoon and adding describe command
rodrigobersa Oct 11, 2023
e5cff65
Running tests v1
rodrigobersa Oct 12, 2023
cb8a2ca
Running tests v1
rodrigobersa Oct 12, 2023
bcdaaa6
Adjusting validation step
rodrigobersa Oct 12, 2023
f72aae0
Updating mounting secrets section
rodrigobersa Oct 12, 2023
2a98e28
Fixing kustomization path
rodrigobersa Oct 12, 2023
92e09ef
Fixing linting
rodrigobersa Oct 12, 2023
8b1734b
Adjusting code blocks
rodrigobersa Oct 12, 2023
8548fa2
Fix typu
rodrigobersa Oct 12, 2023
03c43c0
Adding external secrets
rodrigobersa Oct 12, 2023
05675f4
Fix typo
rodrigobersa Oct 12, 2023
6e68eda
Review
rodrigobersa Oct 13, 2023
ce9d40c
Fixing path
rodrigobersa Oct 13, 2023
7d2e8a9
Merge branch 'main' into security/secrets-manager
rodrigobersa Oct 13, 2023
b718c92
Code review
rodrigobersa Oct 19, 2023
005e873
Fix variable and rephrasing
rodrigobersa Oct 19, 2023
b3fe970
Fixing typo
rodrigobersa Oct 19, 2023
33d1910
Fixing typo
rodrigobersa Oct 19, 2023
ab6bd65
Fixing typo
rodrigobersa Oct 19, 2023
eab136c
Adding tag for Sealed Secrets
rodrigobersa Oct 19, 2023
1700c9b
Adding tag for Sealed Secrets
rodrigobersa Oct 19, 2023
c047333
Adding tag for Sealed Secrets
rodrigobersa Oct 19, 2023
70b0c5e
Removing optinal tag from Sealed Secrets
rodrigobersa Oct 19, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: "cluster-secret-store"
spec:
provider:
aws:
service: SecretsManager
region: $AWS_REGION
auth:
jwt:
serviceAccountRef:
name: "external-secrets-sa"
namespace: "external-secrets"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AWS_REGION
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- secret-provider-class.yaml
- cluster-secret-store.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: catalog-spc
namespace: catalog
spec:
provider: aws
parameters:
objects: |
- objectName: "eks-workshop/catalog-secret"
objectType: "secretsmanager"
jmesPath:
- path: username
objectAlias: username
- path: password
objectAlias: password
secretObjects:
- secretName: catalog-secret
type: Opaque
data:
- objectName: username
key: username
- objectName: password
key: password
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
module "secrets-store-csi-driver" {
source = "github.com/aws-ia/terraform-aws-eks-blueprints?ref=v4.32.1//modules/kubernetes-addons/secrets-store-csi-driver"

helm_config = {
version = "1.3.4"
set = [{
name = "syncSecret.enabled"
value = true
},
{
name = "enableSecretRotation"
value = true
}]
}

addon_context = local.addon_context
}

module "secrets_store_csi_driver_provider_aws" {
source = "github.com/aws-ia/terraform-aws-eks-blueprints?ref=v4.32.1//modules/kubernetes-addons/csi-secrets-store-provider-aws"

helm_config = {
version = "0.3.4"
}

addon_context = local.addon_context
}

module "external_secrets" {
source = "github.com/aws-ia/terraform-aws-eks-blueprints?ref=v4.32.1//modules/kubernetes-addons/external-secrets"

helm_config = {
version = "0.9.5"
}

addon_context = local.addon_context
}

module "secrets_manager_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
version = "~> 5.30"

role_name_prefix = "${data.aws_eks_cluster.eks_cluster.id}-secrets-manager-"

role_policy_arns = {
policy = aws_iam_policy.secrets_manager.arn
}

oidc_providers = {
main = {
provider_arn = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.eks_oidc_issuer_url}"
namespace_service_accounts = ["catalog:catalog"]
}
}

tags = local.tags
}

resource "aws_iam_policy" "secrets_manager" {
name_prefix = "${data.aws_eks_cluster.eks_cluster.id}-secrets-manager-"
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:${data.aws_partition.current.partition}:secretsmanager:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:secret:*"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": "arn:${data.aws_partition.current.partition}:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:key/*"
}
]
}
POLICY
}

resource "kubernetes_annotations" "catalog-sa" {
api_version = "v1"
kind = "ServiceAccount"
metadata {
name = "catalog"
namespace = "catalog"
}
annotations = {
"eks.amazonaws.com/role-arn" = "${module.secrets_manager_role.iam_role_arn}"
}
force = true
}

resource "kubectl_manifest" "cluster_secretstore" {
yaml_body = <<YAML
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: "cluster-secret-store"
spec:
provider:
aws:
service: SecretsManager
region: "${data.aws_region.current.name}"
auth:
jwt:
serviceAccountRef:
name: "external-secrets-sa"
namespace: "external-secrets"
YAML
depends_on = [module.external_secrets]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog
namespace: catalog
spec:
template:
spec:
containers:
- name: catalog
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: catalog-external-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: catalog-external-secret
key: password
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: "catalog-external-secret"
namespace: "catalog"
spec:
refreshInterval: 1h
secretStoreRef:
name: "cluster-secret-store"
kind: ClusterSecretStore
dataFrom:
- extract:
key: "eks-workshop/catalog-secret"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../../../base-application/catalog
patches:
- deployment.yaml
resources:
- external-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog
namespace: catalog
spec:
template:
spec:
containers:
- name: catalog
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: catalog-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: catalog-secret
key: password
volumeMounts:
- name: catalog-secret
mountPath: "/etc/catalog-secret"
readOnly: true
volumes:
- name: catalog-secret
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: catalog-spc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../../../base-application/catalog
patches:
- deployment.yaml
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion website/docs/security/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ Security at AWS is the highest priority, and is a shared responsibility between

In this chapter, we'll explore various aspects of Amazon EKS related to security. To learn more about security with EKS refer to the [EKS Best Practices Guide](https://aws.github.io/aws-eks-best-practices/security/docs/).

![Shared Responsibility](assets/shared-responsibility.jpg)
![Shared Responsibility](assets/managed-nodegroups.png)

---

![Shared Responsibility](assets/selfmanaged-nodegroups.png)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Exploring Secrets"
sidebar_position: 40
sidebar_position: 51
---

Kubernetes secrets can be exposed to the Pods in different ways such as via environment variables and volumes.
Expand Down Expand Up @@ -66,53 +66,3 @@ With the above Pod specification, the following will occur:

* value for the username key in the database-credentials Secret is stored in the file `/etc/data/DATABASE_USER` within the Pod
* value for the password key is stored in the file `/etc/data/DATABASE_PASSWORD`

### Exploring the catalog Pod

The `catalog` deployment in the `catalog` Namespace accesses the following database values from the catalog-db secret via environment variables:

* `DB_USER`
* `DB_PASSWORD`

```bash
$ kubectl -n catalog get deployment catalog -o yaml | yq '.spec.template.spec.containers[] | .env'

- name: DB_USER
valueFrom:
secretKeyRef:
key: username
name: catalog-db
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: catalog-db
- name: DB_NAME
valueFrom:
configMapKeyRef:
key: name
name: catalog
- name: DB_READ_ENDPOINT
valueFrom:
secretKeyRef:
key: endpoint
name: catalog-db
- name: DB_ENDPOINT
valueFrom:
secretKeyRef:
key: endpoint
name: catalog-db
```

Upon exploring the `catalog-db` Secret we can see that it is only encoded with base64 which can be easily decoded as follows hence making it difficult for the secrets manifests to be part of the GitOps workflow.

```file
manifests/base-application/catalog/secrets.yaml
```

```bash
$ kubectl -n catalog get secrets catalog-db --template {{.data.username}} | base64 -d
catalog_user%
$ kubectl -n catalog get secrets catalog-db --template {{.data.password}} | base64 -d
default_password%
```
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
---
title: "Securing Secrets Using Sealed Secrets"
title: "Secrets Management"
sidebar_position: 50
sidebar_custom_props: {"module": true}
---

:::tip Before you start
Prepare your environment for this section:

```bash timeout=300 wait=30
$ prepare-environment security/sealed-secrets
```

:::

[Kubernetes Secret](https://kubernetes.io/docs/concepts/configuration/secret/) is a resource that helps cluster operators manage the deployment of sensitive information such as passwords, OAuth tokens, and ssh keys etc. These secrets can be mounted as data volumes or exposed as environment variables to the containers in a Pod, thus decoupling Pod deployment from managing sensitive data needed by the containerized applications within a Pod.

It has become a common practice for a DevOps Team to manage the YAML manifests for various Kubernetes resources and version control them using a Git repository. This enables them to integrate a Git repository with a GitOps workflow to do Continuous Delivery of such resources to an EKS cluster.
It has become a common practice for a DevOps Team to manage the YAML manifests for various Kubernetes resources and version control them using a Git repository. This enables them to integrate a Git repository with a GitOps workflow to do Continuous Delivery of such resources to an EKS cluster.
Kubernetes obfuscate sensitive data in a Secret by using a merely base64 encoding, also storing such files in a Git repository is extremely insecure as it is trivial to decode the base64 encoded data. This makes it difficult to manage the YAML manifests for Kubernetes Secrets outside a cluster.

[Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) provides a mechanism to encrypt a Secret object so that it is safe to store - even to a public repository. A SealedSecret can be decrypted only by the controller running in the Kubernetes cluster and nobody else is able to obtain the original Secret from a SealedSecret.

In this chapter, you will use SealedSecrets to encrypt YAML manifests pertaining to Kubernetes Secrets as well as be able to deploy these encrypted Secrets to your EKS clusters using normal workflows with tools such as [kubectl](https://kubernetes.io/docs/reference/kubectl/).
There are a few different approaches you can use for secrets management, in this chapter for Secrets Management, we will cover a couple of them, [Sealed Secrets for Kubernetes](https://github.com/bitnami-labs/sealed-secrets) and [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html).
17 changes: 17 additions & 0 deletions website/docs/security/secrets-management/sealed-secrets/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "Securing Secrets Using Sealed Secrets (optional)"
sidebar_position: 70
sidebar_custom_props: {"module": true}
---

:::tip Before you start
Prepare your environment for this section:

```bash timeout=300 wait=30
$ prepare-environment security/sealed-secrets
```
:::

[Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) provides a mechanism to encrypt a Secret object so that it is safe to store - even to a public repository. A SealedSecret can be decrypted only by the controller running in the Kubernetes cluster and nobody else is able to obtain the original Secret from a SealedSecret.

In this chapter, you will use SealedSecrets to encrypt YAML manifests pertaining to Kubernetes Secrets as well as be able to deploy these encrypted Secrets to your EKS clusters using normal workflows with tools such as [kubectl](https://kubernetes.io/docs/reference/kubectl/).
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Installing Sealed Secrets"
sidebar_position: 60
sidebar_position: 72
---

The `kubeseal` CLI is used to interact with the sealed secrets controller, and has already been installed in Cloud9.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Managing the Sealing Key"
sidebar_position: 80
sidebar_position: 74
---

The only way to decrypt the encrypted data within a SealedSecret is with the sealing key that is managed by the controller. There could be situations where you are trying to restore the original state of a cluster after a disaster or you want to leverage GitOps workflow to deploy the Kubernetes resources, including SealedSecrets, from a Git repository and create a new EKS cluster. The controller deployed in the new EKS cluster must use the same sealing key to be able to unseal the SealedSecrets.
Expand Down
Loading
Loading