Basic Authentication Policy(0.8)

通过这个task,你将学会如何:

  • 使用认证策略建立相互TLS
  • 使用认证策略进行最终用户的认证

Before you begin

  • 理解istio authentication policy 和相关的 mutual TLS authentication 概念。
  • 有一个安装Istio的k8s集群,没开启全局相互TLS(如使用 install/kubernetes/istio-demo.yaml ,或者使用 Helm 设置global.mtls.enabled 为false)。
  • 对于演示,创建两个命名空间foobar ,并部署带有sidecar的 httpbinsleep 。同时,运行一个没有sidecar的sleep 应用(为了保持分离,在命名空间legacy 上运行)
kubectl create ns foo
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n foo
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
kubectl create ns bar
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n bar
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n bar
kubectl create ns legacy
kubectl apply -f samples/sleep/sleep.yaml -n legacy
  • 通过发送http请求(使用curl命令)从任何sleep pod(命名空间foo, bar or legacy 的那些)到httpbin.foohttpbin.bar来验证设置。所有请求都应该成功返回HTTP code 200.

例如,这个命令检查 sleep.barhttpbin.foo 是否可达:

kubectl exec $(kubectl get pod -l app=sleep -n bar -o jsonpath={.items..metadata.name}) -c sleep -n bar -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"

200

方便的是,这行命令遍历所有组合:

for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done

sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.legacy to httpbin.foo: 200
sleep.legacy to httpbin.bar: 200

  • 同时确认系统中没有认证策略
kubectl get policies.authentication.istio.io --all-namespaces

No resources found.

Enable mutual TLS for all services in a namespace

运行这个命令来为命名空间foo 设置命名空间级策略:

cat <<EOF | istioctl create -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "example-1"
  namespace: "foo"
spec:
  peers:
  - mtls:
EOF

验证策略已添加:

kubectl get policies.authentication.istio.io -n foo
NAME        AGE
example-1   1m

添加这个目标规则来配置客户端使用相互TLS:

cat <<EOF | istioctl create -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "example-1"
  namespace: "foo"
spec:
  host: "*.foo.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
EOF

注意: 这个规则假定系统中没有任何其他目标规则。如果不是这种情况,你需要相应修改存在规则的流量策略。 *.foo.svc.cluster.local 匹配所有在命名空间foo 的服务。 在Istio相互TLS模式下,Istio将根据其内部实现为密钥和证书(如clientCertificate, privateKey and caCertificates)来设置路径。

运行上面相同的测试命令。你应该看到从 sleep.legacyhttpbin.foo 的请求开始失败,这是 httpbin.foo 启动相互TLS但是sleep.legacy 没有sidecar支持的结果。另一方面,对于使用sidecar(sleep.foo and sleep.bar)的客户端,Istio自动将它们配置为在与 http.foo交流时使用互相TLS,以便它们继续工作。此外,对 httpbin.bar 的请求没有影响,因为策略仅在命名空间 foo 上有效。

for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.legacy to httpbin.foo: 000
command terminated with exit code 56
sleep.legacy to httpbin.bar: 200

如果上面的目标规则没有创建,所有到 httpbin.foo 的请求都将失败,因为客户端没有正确配置切换到使用互相TLS。

Enable mutual TLS for single service httpbin.bar

运行这个命令仅为httpbin.bar 服务设置另一个策略。注意这个例子中,我们没有指定命名空间,但是在命令行中使用了 (-n bar)。效果相同

cat <<EOF | istioctl create -n bar -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "example-2"
spec:
  targets:
  - name: httpbin
  peers:
  - mtls:
EOF

目标规则:

cat <<EOF | istioctl create -n bar -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "example-2"
spec:
  host: "httpbin.bar.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
EOF

再次运行探测命令。正如所料,从 sleep.legacyhttpbin.bar 的请求由于相同原因开始失败。

...
sleep.legacy to httpbin.bar: 000
command terminated with exit code 56

如果我们在命名空间 bar中有更多服务,我们应该观察出到它们的流量未受影响。我们没有增加更多服务来演示这种行为,而是稍微修改了这个策略。

cat <<EOF | istioctl replace -n bar -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "example-2"
spec:
  targets:
  - name: httpbin
    ports:
    - number: 1234
  peers:
  - mtls:
EOF

对应目标规则的改动

cat <<EOF | istioctl replace -n bar -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "example-2"
spec:
  host: httpbin.bar.svc.cluster.local
  trafficPolicy:
    tls:
      mode: DISABLE
    portLevelSettings:
    - port:
        number: 1234
      tls:
        mode: ISTIO_MUTUAL
EOF

新策略仅对于 httpbin 服务的1234 端口生效。结果, 8000 端口的互相TLS(再次)失效,从 sleep.legacy 来的请求将再次工作。

kubectl exec $(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name}) -c sleep -n legacy -- curl http://httpbin.bar:8000/ip -s -o /dev/null -w "%{http_code}\n"

200

Having both namespace-level and service-level policies

假设我们已经添加了命名空间级的策略,它为命名空间中foo 的所有服务开启互相TLS,并观察从 sleep.legacyhttpbin.foo的请求失败(见上文)。现在添加另一个策略,专门为httpbin 服务禁用相互TLS(peers部分为空)

cat <<EOF | istioctl create -n foo -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "example-3"
spec:
  targets:
  - name: httpbin
EOF

目标规则

cat <<EOF | istioctl create -n foo -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "example-3"
spec:
  host: httpbin.foo.svc.cluster.local
  trafficPolicy:
    tls:
      mode: DISABLE
EOF

再次运行从sleep.legacy 触发的请求,我们将会再次看到返回成功码(200),确认服务级策略覆盖了命名空间级策略。

kubectl exec $(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name}) -c sleep -n legacy -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"

200

Setup end-user authentication

你将需要一个有效的JWT(对应于你想要用于演示的JWKS端点)。请遵循指示 here 创建一个。你同样可以在demo中使用你自己的JWT/JWKS 端点。一旦你拥有了,导出了一些环境变量。

export SVC_ACCOUNT="[email protected]"
export JWKS=https://www.googleapis.com/service_accounts/v1/jwk/${SVC_ACCOUNT}
export TOKEN=<YOUR-TOKEN>

同样,为了便利,通过ingress暴露 httpbin.foo (更多细节,查看 ingress task

cat <<EOF | kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: httpbin-ingress
  namespace: foo
  annotations:
    kubernetes.io/ingress.class: istio
spec:
  rules:
  - http:
      paths:
      - path: /headers
        backend:
          serviceName: httpbin
          servicePort: 8000
EOF

获得ingress IP

export INGRESS_HOST=$(kubectl get ing -n foo -o=jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')

运行一个测试查询

curl $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"

200

现在,让我们为 httpbin.foo 添加一个需要最终用户JWT的策略。下一个命令假定名称为“httpbin”的策略已经存在(如果你按照前面的部分照做了就应该是这样)。你可以运行 kubectl get policies.authentication.istio.io -n foo 来确认,如果找不到资源,则使用istio create (而不是istio replace)。同样注意在这个策略中,peer认证(相互TLS)也被设置,尽管可以在不影响原始验证设置的情况下将其删除。

cat <<EOF | istioctl replace -n foo -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "example-3"
spec:
  targets:
  - name: httpbin
  peers:
  - mtls:
  origins:
  - jwt:
      issuer: $SVC_ACCOUNT
      jwksUri: $JWKS
  principalBinding: USE_ORIGIN
EOF

之前同样的curl命令将返回401错误码,原因是服务器期待JWT,但没有提供:

curl $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"

401

附加上面生成的有效标记返回成功:

curl --header "Authorization: Bearer $TOKEN" $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"

200

你或许想要尝试修改token或策略(如修改发行人,听众,到期日等)来观察JWT验证其他方面。

Cleanup

移除所有资源

kubectl delete ns foo bar legacy

猜你喜欢

转载自blog.csdn.net/ybt_c_index/article/details/80742647