diff --git a/blogs/cert-manager-tls/README.md b/blogs/cert-manager-tls/README.md new file mode 100644 index 00000000..770008f7 --- /dev/null +++ b/blogs/cert-manager-tls/README.md @@ -0,0 +1,66 @@ +# Securing Kubernetes applications with AWS App Mesh and cert-manager + +Full configuration files for blog post [Securing Kubernetes applications with AWS App Mesh and cert-manager]() + +## 0. Deploy base yelb with App Mesh + +`kubectl apply -f yelb-base.yaml` + +## 1. Install cert-manager + +``` +kubectl create ns cert-manager + +helm repo add jetstack https://charts.jetstack.io +helm repo update + +helm install \ + cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --version v0.16.1 \ + --set installCRDs=true +``` + +## 2. Create CA and issue certificates for microservices + +``` +#generate a private key +openssl genrsa -out ca.key 2048 + +#create a self signed x.509 CA certificate +openssl req -x509 -new -key ca.key -subj "/CN=App Mesh Examples CA" -days 3650 -out ca.crt + +#create TLS secret +kubectl create secret tls ca-key-pair \ + --cert=ca.crt \ + --key=ca.key \ + --namespace=yelb + +#create CA issuer +kubectl apply -f ca-issuer.yaml + +#create certificate +kubectl apply -f yelb-cert.yaml +``` + +## 3. Mount certificate to microservice deployment + +`kubectl apply -f yelb-deployment-secretMounts.yaml` + +## 4. Add TLS configuration to virtual node + +`kubectl apply -f yelb-virtualnode-tls.yaml` + +## 5. Configure encryption between external LB and App Mesh + +Please set `ENVOY_IMAGE` ENV variable to the correct value based on https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html + +Additionally set `LB_CERT_ARN` ENV variable with your own valid arn. + +``` +ENVOY_IMAGE="840364872350.dkr.ecr..amazonaws.com/aws-appmesh-envoy:" + +LB_CERT_ARN="arn:aws:acm:::certificate/" + +sed -e "s|{{ENVOY_IMAGE}}|${ENVOY_IMAGE}|g" -e "s|{{LB_CERT_ARN}}|${LB_CERT_ARN}|g" yelb-gw.yaml | kubectl apply -f - +``` diff --git a/blogs/cert-manager-tls/ca-issuer.yaml b/blogs/cert-manager-tls/ca-issuer.yaml new file mode 100644 index 00000000..859d500e --- /dev/null +++ b/blogs/cert-manager-tls/ca-issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1alpha2 +kind: Issuer +metadata: + name: ca-issuer + namespace: yelb +spec: + ca: + secretName: ca-key-pair diff --git a/blogs/cert-manager-tls/yelb-base.yaml b/blogs/cert-manager-tls/yelb-base.yaml new file mode 100644 index 00000000..cbc689e2 --- /dev/null +++ b/blogs/cert-manager-tls/yelb-base.yaml @@ -0,0 +1,336 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: yelb + labels: + appmesh.k8s.aws/sidecarInjectorWebhook: enabled + mesh: yelb +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: Mesh +metadata: + name: yelb +spec: + namespaceSelector: + matchLabels: + mesh: yelb +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-ui + namespace: yelb +spec: + awsName: yelb-ui-virtual-node + podSelector: + matchLabels: + app: yelb-ui + listeners: + - portMapping: + port: 80 + protocol: http + serviceDiscovery: + dns: + hostname: yelb-ui.yelb.svc.cluster.local + backends: + - virtualService: + virtualServiceRef: + name: yelb-appserver +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualService +metadata: + name: yelb-ui + namespace: yelb +spec: + awsName: yelb-ui + provider: + virtualNode: + virtualNodeRef: + name: yelb-ui +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-appserver + namespace: yelb +spec: + awsName: yelb-appserver-virtual-node + podSelector: + matchLabels: + app: yelb-appserver + listeners: + - portMapping: + port: 4567 + protocol: http + serviceDiscovery: + dns: + hostname: yelb-appserver.yelb.svc.cluster.local + backends: + - virtualService: + virtualServiceRef: + name: yelb-db + - virtualService: + virtualServiceRef: + name: redis-server +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualRouter +metadata: + namespace: yelb + name: yelb-appserver +spec: + awsName: yelb-appserver-virtual-router + listeners: + - portMapping: + port: 4567 + protocol: http + routes: + - name: route-to-yelb-appserver + httpRoute: + match: + prefix: / + action: + weightedTargets: + - virtualNodeRef: + name: yelb-appserver + weight: 1 + retryPolicy: + maxRetries: 2 + perRetryTimeout: + unit: ms + value: 2000 + httpRetryEvents: + - server-error + - client-error + - gateway-error +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualService +metadata: + name: yelb-appserver + namespace: yelb +spec: + awsName: yelb-appserver + provider: + virtualRouter: + virtualRouterRef: + name: yelb-appserver +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-db + namespace: yelb +spec: + awsName: yelb-db-virtual-node + podSelector: + matchLabels: + app: yelb-db + listeners: + - portMapping: + port: 5432 + protocol: tcp + serviceDiscovery: + dns: + hostname: yelb-db.yelb.svc.cluster.local +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualService +metadata: + name: yelb-db + namespace: yelb +spec: + awsName: yelb-db + provider: + virtualNode: + virtualNodeRef: + name: yelb-db +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: redis-server + namespace: yelb +spec: + awsName: redis-server-virtual-node + podSelector: + matchLabels: + app: redis-server + listeners: + - portMapping: + port: 6379 + protocol: tcp + serviceDiscovery: + dns: + hostname: redis-server.yelb.svc.cluster.local +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualService +metadata: + name: redis-server + namespace: yelb +spec: + awsName: redis-server + provider: + virtualNode: + virtualNodeRef: + name: redis-server +--- +apiVersion: v1 +kind: Service +metadata: + namespace: yelb + name: redis-server + labels: + app: redis-server + tier: cache +spec: + type: ClusterIP + ports: + - port: 6379 + selector: + app: redis-server + tier: cache +--- +apiVersion: v1 +kind: Service +metadata: + namespace: yelb + name: yelb-db + labels: + app: yelb-db + tier: backenddb +spec: + type: ClusterIP + ports: + - port: 5432 + selector: + app: yelb-db + tier: backenddb +--- +apiVersion: v1 +kind: Service +metadata: + namespace: yelb + name: yelb-appserver + labels: + app: yelb-appserver + tier: middletier +spec: + type: ClusterIP + ports: + - port: 4567 + selector: + app: yelb-appserver + tier: middletier +--- +apiVersion: v1 +kind: Service +metadata: + namespace: yelb + name: yelb-ui + labels: + app: yelb-ui + tier: frontend +spec: + type: LoadBalancer + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: yelb-ui + tier: frontend +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: yelb-ui +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-ui + tier: frontend + template: + metadata: + labels: + app: yelb-ui + tier: frontend + spec: + containers: + - name: yelb-ui + image: mreferre/yelb-ui:0.7 + ports: + - containerPort: 80 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: redis-server +spec: + selector: + matchLabels: + app: redis-server + tier: cache + replicas: 1 + template: + metadata: + labels: + app: redis-server + tier: cache + spec: + containers: + - name: redis-server + image: redis:4.0.2 + ports: + - containerPort: 6379 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: yelb-db +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-db + tier: backenddb + template: + metadata: + labels: + app: yelb-db + tier: backenddb + spec: + containers: + - name: yelb-db + image: mreferre/yelb-db:0.5 + ports: + - containerPort: 5432 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: yelb-appserver +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-appserver + tier: middletier + template: + metadata: + labels: + app: yelb-appserver + tier: middletier + spec: + containers: + - name: yelb-appserver + image: mreferre/yelb-appserver:0.5 + ports: + - containerPort: 4567 \ No newline at end of file diff --git a/blogs/cert-manager-tls/yelb-cert.yaml b/blogs/cert-manager-tls/yelb-cert.yaml new file mode 100644 index 00000000..2668f8d4 --- /dev/null +++ b/blogs/cert-manager-tls/yelb-cert.yaml @@ -0,0 +1,61 @@ +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: yelb-cert-ui + namespace: yelb +spec: + dnsNames: + - "yelb-ui.yelb.svc.cluster.local" + secretName: yelb-tls-ui + issuerRef: + name: ca-issuer +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: yelb-cert-app + namespace: yelb +spec: + dnsNames: + - "yelb-appserver.yelb.svc.cluster.local" + secretName: yelb-tls-app + issuerRef: + name: ca-issuer +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: yelb-cert-db + namespace: yelb +spec: + dnsNames: + - "yelb-db.yelb.svc.cluster.local" + secretName: yelb-tls-db + issuerRef: + name: ca-issuer +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: yelb-cert-redis + namespace: yelb +spec: + dnsNames: + - "redis-server.yelb.svc.cluster.local" + secretName: yelb-tls-redis + issuerRef: + name: ca-issuer +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: yelb-cert-gw + namespace: yelb +spec: + dnsNames: + - "yelb-gw.yelb.svc.cluster.local" + secretName: yelb-tls-gw + issuerRef: + name: ca-issuer +--- \ No newline at end of file diff --git a/blogs/cert-manager-tls/yelb-deployment-secretMounts.yaml b/blogs/cert-manager-tls/yelb-deployment-secretMounts.yaml new file mode 100644 index 00000000..11b03185 --- /dev/null +++ b/blogs/cert-manager-tls/yelb-deployment-secretMounts.yaml @@ -0,0 +1,100 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: yelb-ui +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-ui + tier: frontend + template: + metadata: + annotations: + appmesh.k8s.aws/secretMounts: yelb-tls-ui:/etc/keys/yelb + labels: + app: yelb-ui + tier: frontend + spec: + containers: + - name: yelb-ui + image: mreferre/yelb-ui:0.7 + ports: + - containerPort: 80 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: redis-server +spec: + selector: + matchLabels: + app: redis-server + tier: cache + replicas: 1 + template: + metadata: + annotations: + appmesh.k8s.aws/secretMounts: yelb-tls-redis:/etc/keys/yelb + labels: + app: redis-server + tier: cache + spec: + containers: + - name: redis-server + image: redis:4.0.2 + ports: + - containerPort: 6379 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: yelb-db +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-db + tier: backenddb + template: + metadata: + annotations: + appmesh.k8s.aws/secretMounts: yelb-tls-db:/etc/keys/yelb + labels: + app: yelb-db + tier: backenddb + spec: + containers: + - name: yelb-db + image: mreferre/yelb-db:0.5 + ports: + - containerPort: 5432 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: yelb + name: yelb-appserver +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-appserver + tier: middletier + template: + metadata: + annotations: + appmesh.k8s.aws/secretMounts: yelb-tls-app:/etc/keys/yelb + labels: + app: yelb-appserver + tier: middletier + spec: + containers: + - name: yelb-appserver + image: mreferre/yelb-appserver:0.5 + ports: + - containerPort: 4567 \ No newline at end of file diff --git a/blogs/cert-manager-tls/yelb-gw.yaml b/blogs/cert-manager-tls/yelb-gw.yaml new file mode 100644 index 00000000..bc0b04d0 --- /dev/null +++ b/blogs/cert-manager-tls/yelb-gw.yaml @@ -0,0 +1,148 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: yelb + labels: + appmesh.k8s.aws/sidecarInjectorWebhook: enabled + mesh: yelb + gateway: yelb-gw +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualGateway +metadata: + name: yelb-gw + namespace: yelb +spec: + backendDefaults: + clientPolicy: + tls: + validation: + trust: + file: + certificateChain: /etc/keys/yelb/ca.crt + namespaceSelector: + matchLabels: + gateway: yelb-gw + podSelector: + matchLabels: + app: yelb-gw + listeners: + - portMapping: + port: 8443 + protocol: http + tls: + certificate: + file: + certificateChain: /etc/keys/yelb/tls.crt + privateKey: /etc/keys/yelb/tls.key + mode: STRICT +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: GatewayRoute +metadata: + name: gateway-route + namespace: yelb +spec: + httpRoute: + match: + prefix: "/" + action: + target: + virtualService: + virtualServiceRef: + name: yelb-ui +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: yelb-cert-gw + namespace: yelb +spec: + dnsNames: + - "yelb-gw.yelb.svc.cluster.local" + secretName: yelb-tls-gw + issuerRef: + name: ca-issuer +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: yelb-gw + namespace: yelb +spec: + replicas: 1 + selector: + matchLabels: + app: yelb-gw + template: + metadata: + labels: + app: yelb-gw + spec: + containers: + - name: envoy + image: {{ENVOY_IMAGE}} + ports: + - containerPort: 8443 + volumeMounts: + - mountPath: "/etc/keys/yelb" + name: yelb-tls-gw + readOnly: true + volumes: + - name: yelb-tls-gw + secret: + secretName: yelb-tls-gw +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-ui + namespace: yelb +spec: + awsName: yelb-ui-virtual-node + podSelector: + matchLabels: + app: yelb-ui + listeners: + - portMapping: + port: 80 + protocol: http + tls: + certificate: + file: + certificateChain: /etc/keys/yelb/tls.crt + privateKey: /etc/keys/yelb/tls.key + mode: STRICT + serviceDiscovery: + dns: + hostname: yelb-ui.yelb.svc.cluster.local + backendDefaults: + clientPolicy: + tls: + validation: + trust: + file: + certificateChain: /etc/keys/yelb/ca.crt + backends: + - virtualService: + virtualServiceRef: + name: yelb-appserver +--- +apiVersion: v1 +kind: Service +metadata: + name: yelb-gw + namespace: yelb + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: {{LB_CERT_ARN}} + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "ssl" +spec: + type: LoadBalancer + ports: + - port: 443 + targetPort: 8443 + name: https + selector: + app: yelb-gw +--- diff --git a/blogs/cert-manager-tls/yelb-virtualnode-tls.yaml b/blogs/cert-manager-tls/yelb-virtualnode-tls.yaml new file mode 100644 index 00000000..6709dc92 --- /dev/null +++ b/blogs/cert-manager-tls/yelb-virtualnode-tls.yaml @@ -0,0 +1,130 @@ +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-ui + namespace: yelb +spec: + awsName: yelb-ui-virtual-node + podSelector: + matchLabels: + app: yelb-ui + listeners: + - portMapping: + port: 80 + protocol: http + serviceDiscovery: + dns: + hostname: yelb-ui.yelb.svc.cluster.local + backendDefaults: + clientPolicy: + tls: + validation: + trust: + file: + certificateChain: /etc/keys/yelb/ca.crt + backends: + - virtualService: + virtualServiceRef: + name: yelb-appserver +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-appserver + namespace: yelb +spec: + awsName: yelb-appserver-virtual-node + podSelector: + matchLabels: + app: yelb-appserver + listeners: + - portMapping: + port: 4567 + protocol: http + tls: + certificate: + file: + certificateChain: /etc/keys/yelb/tls.crt + privateKey: /etc/keys/yelb/tls.key + mode: STRICT + serviceDiscovery: + dns: + hostname: yelb-appserver.yelb.svc.cluster.local + backendDefaults: + clientPolicy: + tls: + validation: + trust: + file: + certificateChain: /etc/keys/yelb/ca.crt + backends: + - virtualService: + virtualServiceRef: + name: yelb-db + - virtualService: + virtualServiceRef: + name: redis-server +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: yelb-db + namespace: yelb +spec: + awsName: yelb-db-virtual-node + podSelector: + matchLabels: + app: yelb-db + listeners: + - portMapping: + port: 5432 + protocol: tcp + tls: + certificate: + file: + certificateChain: /etc/keys/yelb/tls.crt + privateKey: /etc/keys/yelb/tls.key + mode: STRICT + serviceDiscovery: + dns: + hostname: yelb-db.yelb.svc.cluster.local + backendDefaults: + clientPolicy: + tls: + validation: + trust: + file: + certificateChain: /etc/keys/yelb/ca.crt +--- +apiVersion: appmesh.k8s.aws/v1beta2 +kind: VirtualNode +metadata: + name: redis-server + namespace: yelb +spec: + awsName: redis-server-virtual-node + podSelector: + matchLabels: + app: redis-server + listeners: + - portMapping: + port: 6379 + protocol: tcp + tls: + certificate: + file: + certificateChain: /etc/keys/yelb/tls.crt + privateKey: /etc/keys/yelb/tls.key + mode: STRICT + serviceDiscovery: + dns: + hostname: redis-server.yelb.svc.cluster.local + backendDefaults: + clientPolicy: + tls: + validation: + trust: + file: + certificateChain: /etc/keys/yelb/ca.crt +---