Istio安全

认证

Istio授权

  • 启用授权

使用RbacConfig对象启用Istio授权。

RbacConfig对象,可以指定mode值进行权限限制:

  • OFF:禁用Istio授权。
  • ON:为网格中的所有服务启用了Istio授权。
  • ON_WITH_INCLUSION:仅对inclusion字段中指定的服务和命名空间启用Istio授权。
  • ON_WITH_EXCLUSION:对网格中的所有服务启用Istio授权,但exclusion 字段中指定的服务和命名空间除外。

对default命名空间启用Istio授权

apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
  name: default
spec:
  mode: 'ON_WITH_INCLUSION'
  inclusion:
    namespaces: ["default"]

TLS认证

前提:集群安装了istio和k8s集群,没有启动全局TLS,即使用istio-1.0.0/install/kubernetes/istio-demo.yaml安装istio,而不是istio-demo-auth.yaml

mode: 连接模式

名称 描述
DISABLE 不要设置到上游端点的TLS连接。
SIMPLE 发起与上游端点的TLS连接。
MUTUAL 通过提供客户端证书进行身份验证,使用相互TLS保护与上游的连接。
ISTIO_MUTUAL 通过提供客户端证书进行身份验证,使用相互TLS保护与上游的连接。与Mutual模式相比,此模式使用Istio自动生成的证书进行mTLS身份验证。使用此模式时,所有其他字段TLSSettings应为空。。
  • 建立

创建使用sidecar注入Envoy代理的两个服务foo、bar,没有sidecar注入的服务legacy

kubectl create ns foo
kubectl apply -f <(istioctl kube-inject -f istio-1.0.0/samples/httpbin/httpbin.yaml) -n foo
kubectl apply -f <(istioctl kube-inject -f istio-1.0.0/samples/sleep/sleep.yaml) -n foo
kubectl create ns bar
kubectl apply -f <(istioctl kube-inject -f istio-1.0.0/samples/httpbin/httpbin.yaml) -n bar
kubectl apply -f <(istioctl kube-inject -f istio-1.0.0/samples/sleep/sleep.yaml) -n bar
kubectl create ns legacy
kubectl apply -f istio-1.0.0/samples/httpbin/httpbin.yaml -n legacy
kubectl apply -f istio-1.0.0/samples/sleep/sleep.yaml -n legacy
  • 检查

检查sleep.bar到httpbin.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"

Istio安全

检查所有可达性,从任意客户端(例如 sleep.foo、sleep.bar 和 sleep.legacy) 向任意服务端 (httpbin.foo、 httpbin.bar 或 httpbin.legacy) 发送 HTTP 请求

for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; 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

Istio安全

  • 开启双向TLS认证

全局

cat <<EOF | istioctl create -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "MeshPolicy"
metadata:
  name: "default"
spec:
  peers:
  - mtls: {}
EOF


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

Istio安全

认证策略和规则配置了服务中的sidecar,使服务在双向TLS下进行接收和发送,没有注入sidecar的服务会请求失败,因为没有sidecar来支持认证
Istio安全
如果 HTTP 请求是在双向 TLS 模式下发送并且服务端只接受 HTTP 请求,则返回的错误码为 503。相反,如果请求是以纯文本的格式发送到使用双向 TLS 的服务端,则返回的错误码是 000 (同时 curl 退出码为 56,错误信息是 “failure with receiving network data”)。

  • 注入sidecar到不注入sidecar
cat <<EOF | istioctl create -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "httpbin"
  namespace: "legacy"
spec:
  host: "httpbin.legacy.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: DISABLE
EOF

Istio安全

  • 创建某服务专属策略

从不带 sidecar 的客户端到带有 sidecar 的服务的连接,将双向TLS模式切换到 PERMISSIVE 模式,创建foo服务

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

从 sleep.legacy 到 httpbin.foo 的请求应当是成功的,但是到 httpbin.bar 的请求依然会失败。
Istio安全

为单独namespace中所有服务启用双向TLS

  • 创建认证策略
cat <<EOF | istioctl create -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "default"
  namespace: "foo"
spec:
  peers:
  - mtls: {}
EOF
  • 创建规则
cat <<EOF | istioctl create -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "default"
  namespace: "foo"
spec:
  host: "*.foo.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
EOF
  • 发送测试请求
for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; 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

foo开启双向TLS认证,没有注入sidecar的客户端请求失败,bar没有开启TLS认证,没有注入sidecar的客户端可以请求
Istio安全

  • 单个服务启动双向TLS认证
  • 创建认证策略

这里使bar启用了双向TLS,在命令行中表明了namespace而不是在metadata,效果一样

cat <<EOF | istioctl create -n bar -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "httpbin"
spec:
  targets:
  - name: httpbin
  peers:
  - mtls: {}
EOF
  • 创建规则
cat <<EOF | istioctl create -n bar -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "httpbin"
spec:
  host: "httpbin.bar.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
EOF

这里的foo也开启了双向TLS认证(与上图做比较),所以请求foo也失败,这里以bar为准
Istio安全

  • 如果命名空间存在多个服务

其他服务的流量不会受到影响,这里使用将策略限制到端口的方法验证

  • 更新认证策略
cat <<EOF | istioctl replace -n bar -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "httpbin"
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: "httpbin"
spec:
  host: httpbin.bar.svc.cluster.local
  trafficPolicy:
    tls:
      mode: DISABLE
    portLevelSettings:
    - port:
        number: 1234
      tls:
        mode: ISTIO_MUTUAL
EOF
  • 测试请求
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"

限制到8000,在进行8000请求的时候失败
Istio安全
限制到1234,在进行8000请求的时候成功,表明8000端口不受影响
Istio安全

  • 清除
kubectl delete ns foo bar legacy

基于角色的访问控制

前提:启用了双向TLS认证,部署了bookinfo应用

  • 创建 Service account:bookinfo-productpage,并用这一身份部署 productpage。
  • 创建 Service account:bookinfo-reviews,并用这一身份部署 reviews(注意其中包含 reviews-v2 和 reviews-v3 两个版本)。
kubectl apply -f <(istioctl kube-inject -f istio-1.0.0/samples/bookinfo/platform/kube/bookinfo-add-serviceaccount.yaml)

访问productpage,服务在v1-v3切换

  • 启用Istio授权

RbacConfig被定义为Kubernetes CustomResourceDefinition (CRD)对象。
在RbacConfig对象中,运算符可以指定mode值,它可以是:

  • OFF:禁用 Istio 授权。
  • ON:为网格中的所有服务启用了 Istio 授权。
  • ON_WITH_INCLUSION:仅对包含字段中指定的服务和命名空间启用 Istio 授权。
  • ON_WITH_EXCLUSION:除了排除字段中指定的服务和命名空间外,网格中的所有服务都启用了 Istio 授权。
istioctl create -f samples/bookinfo/platform/kube/rbac/rbac-config-ON.yaml

[root@k8-master-1 istio-1.0.0]# cat samples/bookinfo/platform/kube/rbac/rbac-config-ON.yaml 
apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
  name: default
spec:
  mode: 'ON_WITH_INCLUSION'
  inclusion:
    namespaces: ["default"]

访问productpage,提示被拒绝
Istio安全

  • 命名空间级的访问控制

productpage、reviews、details 以及 ratings 服务被部署在 default 命名空间中,而 istio-ingressgateway 等 Istio 组件是部署在 istio-system 命名空间中的。我们可以定义一个策略,default 命名空间中所有服务,如果其 app 标签取值在 productpage、reviews、details 以及 ratings 范围之内,就可以被本命名空间内以及 istio-system 命名空间内的服务进行访问。

istioctl create -f samples/bookinfo/platform/kube/rbac/namespace-policy.yaml
  • 清楚命名空间级的访问控制
istioctl delete -f samples/bookinfo/platform/kube/rbac/namespace-policy.yaml
  • 服务级的访问控制

istio适用与http1.0以上(不包括1.0),http方法包含8种。
============
Istio安全

  • 允许访问productpage
istioctl create -f istio-1.0.0/samples/bookinfo/platform/kube/rbac/productpage-policy.yaml

[root@k8-master-1 istio-1.0.0]# cat samples/bookinfo/platform/kube/rbac/productpage-policy.yaml 
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: productpage-viewer
  namespace: default
spec:
  rules:
  - services: ["productpage.default.svc.cluster.local"]
    methods: ["GET"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: bind-productpage-viewer
  namespace: default
spec:
  subjects:
  - user: "*"
  roleRef:
    kind: ServiceRole
    name: "productpage-viewer"

可以访问productpage,但是details和reviews服务拒绝访问,没有给productpage访问details和reviews服务的授权
Istio安全

  • 允许访问details和reviews服务
istioctl create -f istio-1.0.0/samples/bookinfo/platform/kube/rbac/details-reviews-policy.yaml

[root@k8-master-1 ~]# cat  istio-1.0.0/samples/bookinfo/platform/kube/rbac/details-reviews-policy.yaml 
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: details-reviews-viewer
  namespace: default
spec:
  rules:
  - services: ["details.default.svc.cluster.local", "reviews.default.svc.cluster.local"]
    methods: ["GET"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: bind-details-reviews
  namespace: default
spec:
  subjects:
  - user: "cluster.local/ns/default/sa/bookinfo-productpage"
  roleRef:
    kind: ServiceRole
    name: "details-reviews-viewer"

Istio安全

  • 允许访问ratings服务
istioctl create -f istio-1.0.0/samples/bookinfo/platform/kube/rbac/ratings-policy.yaml

[root@k8-master-1 ~]# cat istio-1.0.0/samples/bookinfo/platform/kube/rbac/ratings-policy.yaml 
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: ratings-viewer
  namespace: default
spec:
  rules:
  - services: ["ratings.default.svc.cluster.local"]
    methods: ["GET"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: bind-ratings
  namespace: default
spec:
  subjects:
  - user: "cluster.local/ns/default/sa/bookinfo-reviews"
  roleRef:
    kind: ServiceRole
    name: "ratings-viewer"

Istio安全

上一篇:流量管理演变史


下一篇:Istio 调用链追踪与指标收集