TLS ACM

在本实验中,我们将使用 AWS Certificate Manager Private Certificate Authority (ACM PCA) 颁发的私有证书,在 App Mesh 的两个应用之间启用 TLS 加密。

实验准备

  • 要为 appmesh-controller创建IRSA(IAM Roles for Service Account),请按照 此处 来创建;或者按照https://github.com/aws/aws-app-mesh-examples/blob/main/walkthroughs/eks 的流程。如果将所有 IAM 权限已经添加到 IAM role,则节点应具有以下 IAM 权限:AWSAppMeshFullAccessAWSCloudMapFullAccess

  • 将 ACM PCA 用于 TLS 时需要一些额外的 IAM 权限。请验证worker节点的 IAM 角色是否具有以下 IAM 权限:

    • appmesh:StreamAggregatedResources
    • acm:ExportCertificate
    • acm-pca:GetCertificateAuthorityCertificate
  • aws-app-mesh-controller-for-k8s 版本大于等于v1.0.0 。运行以下命令以检查您正在运行的appmesh-controller版本:

$ kubectl get deployment -n appmesh-system appmesh-controller -o json | jq -r ".spec.template.spec.containers[].image" | cut -f2 -d ':'|tail -n1

image-20210718222403912

  • 安装docker。后面将制作应用的镜像。

Step 1: 环境设置

  1. 克隆仓库并进入到 walkthrough/howto-k8s-tls-acm 文件夹,所有命令都将从这个位置执行:

    git clone https://github.com/aws/aws-app-mesh-examples
    cd walkthroughs/howto-k8s-tls-acm
    
  2. 设置环境变量

    export AWS_ACCOUNT_ID=<your_account_id>  
    export AWS_DEFAULT_REGION=us-west-2  
    export SERVICES_DOMAIN="howto-k8s-tls-acm.svc.cluster.local"  # 创建 AWS Certificate Manager PCA时要使用的SERVICES_DOMAIN
    

    image-20210718222710872

Step 2: 创建证书

在我们加密Mesh中服务之间的流量之前,我们需要生成一个证书。 App Mesh 当前支持由 ACM 私有证书颁发机构 颁发的证书,我们将在此步骤中创建它。

首先在 ACM 中创建根证书颁发机构 (CA):

注意:您需要为每个 ACM PCA按月支付费用。 有关更多信息,请参阅 AWS Certificate Manager 定价 .

export ROOT_CA_ARN=`aws acm-pca create-certificate-authority \
    --certificate-authority-type ROOT \
    --certificate-authority-configuration \
    "KeyAlgorithm=RSA_2048,
    SigningAlgorithm=SHA256WITHRSA,
    Subject={
        Country=US,
        State=WA,
        Locality=Seattle,
        Organization=App Mesh Examples,
        OrganizationalUnit=TLS Example,
        CommonName=${SERVICES_DOMAIN}}" \
        --query CertificateAuthorityArn --output text`

接下来,您需要对根 CA 进行自签名(self-sign)。 首先检查 CSR 内容:

ROOT_CA_CSR=`aws acm-pca get-certificate-authority-csr \
    --certificate-authority-arn ${ROOT_CA_ARN} \
    --query Csr --output text`

使用自身作为发行人签署 CSR。

请注意,如果您使用的是 AWS CLI 2的版本,则需要在调用issue-certificate命令之前通过base64编码传递 CSR 数据。

注意,这一步使用aws cli2版本测试时,发现报错,此时可以重新安装v1版本来进行后面的操作:

sudo pip3 install awscli
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)
[[ ${AWS_CLI_VERSION} -gt 1 ]] && ROOT_CA_CSR="$(echo ${ROOT_CA_CSR} | base64)"
ROOT_CA_CERT_ARN=`aws acm-pca issue-certificate \
    --certificate-authority-arn ${ROOT_CA_ARN} \
    --template-arn arn:aws:acm-pca:::template/RootCACertificate/V1 \
    --signing-algorithm SHA256WITHRSA \
    --validity Value=10,Type=YEARS \
    --csr "${ROOT_CA_CSR}" \
    --query CertificateArn --output text`

然后将签名证书导入,作为根 CA:

ROOT_CA_CERT=`aws acm-pca get-certificate \
    --certificate-arn ${ROOT_CA_CERT_ARN} \
    --certificate-authority-arn ${ROOT_CA_ARN} \
    --query Certificate --output text`

再次注意 AWS CLI 版本 2,您需要通过编码传递证书数据:

[[ ${AWS_CLI_VERSION} -gt 1 ]] && ROOT_CA_CERT="$(echo ${ROOT_CA_CERT} | base64)"

导入证书:

aws acm-pca import-certificate-authority-certificate \    --certificate-authority-arn $ROOT_CA_ARN \    --certificate "${ROOT_CA_CERT}"

我们还希望授予 CA 自动续期托管证书的权限:

aws acm-pca create-permission \    --certificate-authority-arn $ROOT_CA_ARN \    --actions IssueCertificate GetCertificate ListPermissions \    --principal acm.amazonaws.com

使用此 CA 从 ACM 请求托管证书:

export CERTIFICATE_ARN=`aws acm request-certificate \    --domain-name "*.${SERVICES_DOMAIN}" \    --certificate-authority-arn ${ROOT_CA_ARN} \    --query CertificateArn --output text`

image-20210718234118703

对于托管证书,ACM 将自动续订即将到期的证书,而 App Mesh 将自动分发续订的证书。

创建启用 TLS 的Mesh

我们将设置一个具有四个virtual nodes的mesh:Frontend、Blue、Green和Red,一个virtual service:color, 一个virtual router:color。

先创建mesh:

./mesh.sh up

Frontend有对应的virtual service(color)后端,virtual service(color)使用virtual router(color)。 Virtual router(color)配置了三个路由:

  • color-route-blue:匹配 HTTP 标头“blue”以将流量路由到虚拟节点 blue
  • color-route-green:匹配 HTTP 标头“green”以将流量路由到虚拟节点 green
  • color-route-red:匹配 HTTP 标头“red”以将流量路由到虚拟节点 red

virtual node blue配置了为其侦听器启用了 TLS。 这是blue virtual node的定义:

apiVersion: appmesh.k8s.aws/v1beta2kind: VirtualNodemetadata:  name: blue  namespace: howto-k8s-tls-acmspec:  podSelector:    matchLabels:      app: color      version: blue  listeners:    - portMapping:        port: 8080        protocol: http      healthCheck:        protocol: http        path: '/ping'        healthyThreshold: 2        unhealthyThreshold: 2        timeoutMillis: 2000        intervalMillis: 5000      tls:        mode: STRICT        certificate:          acm:            certificateARN: arn:aws:acm:us-west-2:<ACCOUNT_ID>:certificate/<certificate>  serviceDiscovery:    dns:      hostname: color-blue.howto-k8s-tls-acm.svc.cluster.local

tls 模块指定了要使用的 ACM 证书。

验证已启动TLS

kubectl run -i --tty curler --image=public.ecr.aws/k8m1l3p1/alpine/curler:latest --rmcurl -H "color_header: blue" front.howto-k8s-tls-acm.svc.cluster.local:8080/; echo;

当使用 HTTP 标头color_header: blue时,会看到响应成功:

image-20210727184109368

让我们检查 SSL 握手的统计信息:

BLUE_POD=$(kubectl get pod -l "version=blue" -n howto-k8s-tls-acm --output=jsonpath={.items..metadata.name})kubectl exec -it $BLUE_POD -n howto-k8s-tls-acm -c envoy -- curl -s http://localhost:9901/stats | grep ssl.handshake

image-20210727184130709

您应该会看到类似于以下内容的输出:listener.0.0.0.0_15000.ssl.handshake:1,表明在前端和blue color app之间成功进行 SSL 握手。

资源清理

如果您想保持应用程序运行,可以忽略这一节的操作。

运行以下命令以清理我们创建的资源。:

kubectl delete -f _output/manifest.yaml

删除 ECR 仓库, force 标志将删除 ECR 存储库中的 docker 镜像:

aws ecr delete-repository  --repository-name howto-k8s-tls-acm/colorapp --forceaws ecr delete-repository  --repository-name howto-k8s-tls-acm/feapp --force

删除证书:

aws acm delete-certificate --certificate-arn $CERTIFICATE_ARNaws acm-pca update-certificate-authority --certificate-authority-arn $ROOT_CA_ARN --status DISABLEDaws acm-pca delete-certificate-authority --certificate-authority-arn $ROOT_CA_ARN

删除 appmesh-controller deployment:

helm delete appmesh-controller -n appmesh-system

删除 appmesh-system 命名空间:

kubectl delete ns appmesh-system