# AWS Secrets Manger in Kubernetes

## Prerequisite

* **eksctl.** [details](https://github.com/weaveworks/eksctl)
    
* **AWS CLI.** [**details**](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
    
* **Helm**. [details](https://helm.sh/docs/intro/install/)
    

## Create EKS Cluster

This will create an EKS cluster in `us-east-1` region with 2 nodes in the node-group.

```bash
export CLUSTER_NAME=demo-cluster
export AWS_REGION=us-east-1
eksctl create cluster --name ${CLUSTER_NAME} --version 1.26 --node-type t3.medium --nodes 2 --managed --region ${AWS_REGION}
.....
.....
2023-05-28 18:47:47 [✔]  EKS cluster "demo-cluster" in "us-east-1" region is ready.
```

### verify

When running the following command `kubectl get nodes` you should see the nodes in a ready state.

```bash
➜ kubectl get nodes   
NAME                             STATUS   ROLES    AGE    VERSION
ip-192-168-17-231.ec2.internal   Ready    <none>   114m   v1.26.4-eks-0a21954
ip-192-168-61-195.ec2.internal   Ready    <none>   114m   v1.26.4-eks-0a21954
```

## Deploy External Secrets Operator

Use below helm commands to:

* add/update the repo
    
* install the operator
    

```bash
helm repo add external-secrets https://charts.external-secrets.io
helm repo update

helm install external-secrets \
  external-secrets/external-secrets \
    --namespace external-secrets \
    --create-namespace \
    --set installCRDs=true \
    --wait
.....
external-secrets has been deployed successfully!
....
```

### verify

When you run `k get all -n external-secrets` you should be able to see all the pods `pod/external-secrets-*` , `pod/external-secrets-cert-controller-*`, `pod/external-secrets-webhook-`\* running successfully.

```bash
➜ k get all -n external-secrets
NAME                                                    READY   STATUS    RESTARTS   AGE
pod/external-secrets-5997dc48b4-drncs                   1/1     Running   0          2m33s
pod/external-secrets-cert-controller-587977f796-mdk9p   1/1     Running   0          2m33s
pod/external-secrets-webhook-674f79cb47-jz7ds           1/1     Running   0          2m33s

NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/external-secrets-webhook   ClusterIP   10.100.84.243   <none>        443/TCP   2m33s

NAME                                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/external-secrets                   1/1     1            1           2m34s
deployment.apps/external-secrets-cert-controller   1/1     1            1           2m34s
deployment.apps/external-secrets-webhook           1/1     1            1           2m34s

NAME                                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/external-secrets-5997dc48b4                   1         1         1       2m34s
replicaset.apps/external-secrets-cert-controller-587977f796   1         1         1       2m34s
replicaset.apps/external-secrets-webhook-674f79cb47
```

## Configuring IAM roles for service accounts (IRSA) and Secrets Manager

### **Add OIDC Provider**

```bash
➜ eksctl utils associate-iam-oidc-provider --cluster=${CLUSTER_NAME} --approve

2023-05-28 13:25:07 [✔]  created IAM Open ID Connect provider for cluster "demo-cluster" in "us-east-1"
```

### **Create Secret in Secrets Manager**

```bash
SECRET_ARN=$(aws secretsmanager create-secret --name user-creds \
    --secret-string "{\"user\":\"admin\",\"password\":\"topsecret\"}" \
    --region ${AWS_REGION} | jq -r .ARN)
```

### **Create IAM Policy**

IAM Policy to Read/Describe the `user-creds` secret in the secrets manager

```bash
➜ IAM_POLICY_ARN=$(aws iam create-policy --policy-name eso-sm-reader-policy --policy-document '{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:DescribeSecret",
        "secretsmanager:GetSecretValue"
      ],
      "Resource": ["'${SECRET_ARN}'"]
    }
  ]
}' | jq -r .Policy.Arn)
```

### **Create a Service Account and Association**

```bash
➜ eksctl create iamserviceaccount \
    --name eso-secret-irsa \
    --namespace default \
    --cluster ${CLUSTER_NAME} \
    --role-name "eso-sm-reader-role" \
    --attach-policy-arn $IAM_POLICY_ARN \
    --approve
```

### **verify**

```bash
k describe sa eso-secret-irsa                      
Name:                eso-secret-irsa
Namespace:           default
Labels:              app.kubernetes.io/managed-by=eksctl
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::808053714438:role/eso-sm-reader-role
Image pull secrets:  <none>
Mountable secrets:   <none>
Tokens:              <none>
Events:              <none>
```

## Deploy External Secret Store/Secret

### **Create SecretStore**

```bash
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: secret-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        jwt:
          serviceAccountRef:
            name: eso-secret-irsa
EOF
```

### **Verify**

```bash
kubectl get SecretStore                
NAME           AGE   STATUS   CAPABILITIES   READY
secret-store   58s   Valid    ReadWrite      True
```

### **Create ExternalSecret**

```bash
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: user-creds
spec:
  refreshInterval: 5m
  secretStoreRef:
    name: secret-store
    kind: SecretStore
  target:
    name: user-creds
  data:
  - secretKey: user
    remoteRef:
      key: user-creds
      property: user
  - secretKey: password
    remoteRef:
      key: user-creds
      property: password
EOF
```

### **Verify**

```bash
➜ kubectl get ExternalSecret           
NAME         STORE          REFRESH INTERVAL   STATUS         READY
user-creds   secret-store   5m                 SecretSynced   True
➜ kubectl get secret
NAME         TYPE     DATA   AGE
user-creds   Opaque   2      30s
```

## Deploy Application

```bash
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: creds-app
spec:
  containers:
    - name: app
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - secretRef:
          name: user-creds
EOF
```

### **Verify**

```bash
➜ kubectl logs pod/creds-app     
....   
user=admin
password=topsecret
....
```
