ASM网关支持对外提供mTLS服务。mTLS协议要求客户端提供自身证书,证书中包含了用户的身份信息。您可以在授权策略中配置只有特定的用户才可以成功访问该服务,进而为服务提供更加高级别的保护。本文将介绍如何在ASM入口网关上配置mTLS服务,并且通过授权策略实现对特定用户的访问限制。
前提条件
已开启sidecar自动注入。具体操作,请参见配置Sidecar注入策略。
已部署入口网关和httpbin应用,请确保入口网关开启了443端口。具体操作,请参见部署httpbin应用。
步骤一:生成mTLS通信证书
在创建证书时,如果需要填写证书信息,请使用默认值。这些默认值已在配置文件中预先设置。
使用以下内容创建ca.cnf文件,生成根证书。
执行以下命令,生成根证书。
openssl req -x509 -config ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
此命令会输出
cacert.pem
和cakey.pem
文件。使用以下内容创建server.cnf文件,用于生成服务器证书。
HOME = . RANDFILE = $ENV::HOME/.rnd #################################################################### [ req ] default_bits = 2048 default_keyfile = serverkey.pem distinguished_name = server_distinguished_name req_extensions = server_req_extensions string_mask = utf8only #################################################################### [ server_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = bj localityName = Locality Name (eg, city) localityName_default = bj organizationName = Organization Name (eg, company) organizationName_default = test commonName = Common Name (e.g. server FQDN or YOUR name) commonName_default = test.com emailAddress = Email Address emailAddress_default = test@example.com #################################################################### [ server_req_extensions ] subjectKeyIdentifier = hash basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment subjectAltName = @alternate_names nsComment = "OpenSSL Generated Certificate" #################################################################### [ alternate_names ] DNS.1 = test.com
依次执行以下命令,生成服务器证书。
openssl req -config server.cnf -newkey rsa:2048 -sha256 -nodes -out server.csr -outform PEM
touch index.txt echo '01' > serial.txt
openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles server.csr
此命令会输出
servercert.pem
和serverkey.pem
。使用以下内容创建client.cnf文件,用于创建客户端证书。
HOME = . RANDFILE = $ENV::HOME/.rnd #################################################################### [ req ] default_bits = 2048 default_keyfile = client.key.pem distinguished_name = server_distinguished_name req_extensions = server_req_extensions string_mask = utf8only #################################################################### [ server_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = bj localityName = Locality Name (eg, city) localityName_default = bj organizationName = Organization Name (eg, company) organizationName_default = test.client commonName = Common Name (e.g. server FQDN or YOUR name) commonName_default = test.client emailAddress = Email Address emailAddress_default = test.client@example.com #################################################################### [ server_req_extensions ] subjectKeyIdentifier = hash basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment subjectAltName = @alternate_names nsComment = "OpenSSL Generated Certificate" #################################################################### [ alternate_names ] URI.1 = spiffe://test.client
客户端证书的
CommonName
为test.client
,SAN信息中需要新增字段URI.1 = spiffe://test.client
,这里需要额外加上spiffe://
前缀,因为ASM的授权策略中principals字段会匹配spiffe://
之后的部分。依次执行以下命令,生成客户端证书。
openssl req -config client.cnf -newkey rsa:2048 -sha256 -nodes -out clientcert.csr -outform PEM
openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -out clientcert.pem -infiles clientcert.csr
此命令会输出
clientcert.pem
以及client.key.pem
。使用ASM证书管理导入mTLS证书,请确保此处导入的证书名称为
test.com
。具体操作,请参见使用ASM证书管理。您也可以使用kubectl直接创建secret来完成证书导入。使用数据面集群的kubeconfig,执行如下命令。
kubectl create -n istio-system secret generic test.com \ --from-file=tls.key=serverkey.pem \ --from-file=tls.crt=servercert.pem \ --from-file=ca.crt=cacert.pem
步骤二:在网关443端口上配置mTLS监听
本节将为ASM网关的443端口配置mTLS监听,让外部客户端可以通过mTLS访问httpbin服务。
使用以下内容,更新网关规则。
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: httpbin namespace: default spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: test number: 80 protocol: HTTP - hosts: - test.com port: number: 443 name: https protocol: HTTPS tls: mode: MUTUAL credentialName: test.com
执行以下命令,使用client证书访问httpbin服务。
curl --header "host:test.com" --resolve "test.com:443:${ASM网关IP}" --cacert cacert.pem --cert clientcert.pem --key client.key.pem https://test.com/status/200 -I
预期输出:
HTTP/2 200 server: istio-envoy date: Sun, 28 Jul 2024 7:30:30 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 6
步骤三:配置授权策略,限制test.client访问
使用以下内容,部署授权策略。限制test.client不能访问httpbin应用的
/status/418
路径。具体操作,请参见为HTTP流量设置授权策略。apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: test namespace: istio-system spec: action: DENY rules: - from: - source: principals: - test.client to: - operation: paths: - /status/418 selector: matchLabels: istio: ingressgateway
执行以下命令,使用client证书访问
/status/200
路径。curl --header "host:test.com" --resolve "test.com:443:${ASM网关IP}" --cacert cacert.pem --cert clientcert.pem --key client.key.pem https://test.com/status/200 -I
预期输出:
HTTP/2 200 server: istio-envoy date: Sun, 28 Jul 2024 7:33:30 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 6
执行以下命令,使用client证书访问
/status/418
路径。curl --header "host:test.com" --resolve "test.com:443:${ASM网关IP}" --cacert cacert.pem --cert clientcert.pem --key client.key.pem https://test.com/status/418
预期输出:
RBAC: access denied%
执行以下命令,使用server证书访问
/status/418
路径。curl --header "host:test.com" --resolve "test.com:443:${ASM网关IP}" --cacert cacert.pem --cert servercert.pem --key serverkey.pem https://test.com/status/418
预期输出:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`