Istio提供了非常易用的安全解决方案,包括服务间身份验证mTLS,服务间访问控制RBAC,以及终端用户身份验证JWT等,本文主要介绍如何使用服务间访问控制,同时涉及双向TLS

要实现RBAC主要理解以下几个类型的yaml配置,以及之间的关系:

  • 双向TLS
    • PolicyMeshPolicy,上游server开启TLS
    • DestinationRule,下游client开启TLS
  • RBAC
    • ClusterRbacConfig/RbacConfig,启用授权及范围
    • ServiceRole,角色权限规则
    • ServiceRoleBinding,角色绑定规则
  • Optional
    • ServiceAccountServiceRoleBinding.subjectsuser条件

假设场景

  • 网格内service-1service-2开启RBAC访问控制
  • service-1授权给ingressgateway访问,service-2则不能被ingressgateway访问

auth-adapter

双向TLS

1.上游server开启TLS

策略范围说明

  • 网格范围策略:在网格范围存储中定义的策略,没有目标选择器部分。网格中最多只能有一个网格范围的策略。
  • 命名空间范围的策略:在命名空间范围存储中定义的策略,名称为 default 且没有目标选择器部分。每个命名空间最多只能有一个命名空间范围的策略。
  • 特定于服务的策略:在命名空间范围存储中定义的策略,具有非空目标选择器部分。命名空间可以具有零个,一个或多个特定于服务的策略。

策略范围可以分别由PolicyMeshPolicy设置,Policy可以选择对命名空间所有服务生效,也可以指定targets特定服务生效,MeshPolicy则是整个网格内生效,对于命名空间范围网格范围名称都只能为default
同时配置多个策略时使用最窄匹配策略,特定服务>命名空间范围>网格范围,如果多个特定于服务的策略与服务匹配,则随机选择一个。下面是不同策略范围的具体配置参考:

Policy特定于服务的策略

  • targets支持name以及ports列表
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "policy-name"
spec:
  targets:
  - name: service-name-1
  - name: service-name-2
    ports:
    - number: 8080
  peers:
  - mtls: {}
---

Policy命名空间范围的策略

apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "default"
  namespace: "namespace-1"
spec:
  peers:
  - mtls: {}
---

MeshPolicy网格范围策略

apiVersion: "authentication.istio.io/v1alpha1"
kind: "MeshPolicy"
metadata:
  name: "default"
spec:
  peers:
  - mtls: {}
---

2.下游client开启TLS

client端TLS由目标规则DestinationRule配置,在流量策略trafficPolicy中开启tls

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: service-name-1
spec:
  host: service-host-1
  # NOTE: 开启TLS
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
---

TLSmode说明

mode值 描述
DISABLE 不要为上游端点使用 TLS。
SIMPLE 向上游端点发起 TLS 连接。
MUTUAL 发送客户端证书进行验证,用双向 TLS 连接上游端点。
ISTIO_MUTUAL 发送客户端证书进行验证,用双向 TLS 连接上游端点。和 MUTUAL 相比,这种方式使用的双向 TLS 证书系统是由 Istio 生成的。如果使用这种模式,TLSSettings 中的其他字段应该留空。

RBAC

有关RbacConfigServiceRoleServiceRoleBinding的属性结构Istio文档有详细的配置可以参考:Istio参考配置-授权-RBAC

1.开启授权ClusterRbacConfig

apiVersion: "rbac.istio.io/v1alpha1"
kind: ClusterRbacConfig
metadata:
  name: default
  namespace: istio-system
spec:
  mode: 'ON_WITH_INCLUSION'
  inclusion:
    #namespaces: ["namespace-1"]
    services: ["service-name-1.namespace-1.svc.cluster.local", "service-name-2.namespace-1.svc.cluster.local"]
  # NOTE: ENFORCED/PERMISSIVE,严格或宽容模式
  enforcement_mode: ENFORCED
---

enforcement_mode可以选择ENFORCED严格模式,或PERMISSIVE宽容模式,宽容模式便于授权策略需要变更时进行验证测试Istio任务-授权许可模式任务中有更具体的场景介绍。

模式mode说明

mode值 描述
OFF 关闭 Istio RBAC,RbacConfig 的所有配置将会失效,且 Istio RBAC Policies 不会执行。
ON 为所有 services 和 namespaces 启用 Istio RBAC。
ON_WITH_INCLUSION 仅针对 inclusion 字段中指定的 services 和 namespaces 启用 Istio RBAC。其它不在 inclusion 字段中的 services 和 namespaces 将不会被 Istio RBAC Policies 强制执行。
ON_WITH_EXCLUSION 针对除了 exclusion 字段中指定的 services 和 namespaces,启用 Istio RBAC。其它不在 exclusion 字段中的 services 和 namespaces 将按照 Istio RBAC Policies 执行。

2.角色权限规则ServiceRole

namespace + services + paths + methods 一起定义了如何访问服务,其中services必选,另外有constraints可以指定其它约束,支持的约束参考Istio参考配置-授权-约束和属性#支持的约束

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: service-role-1
  namespace: default
spec:
  rules:
  - services: ["service-name-1.namespace-1.svc.cluster.local"]
    methods: ["*"]
    # NOTE: 根据约束需要修改
    constraints:
    - key: request.headers[version]
      values: ["v1", "v2"]
---

3.角色绑定规则ServiceRoleBinding

user + properties 一起定义授权给谁,支持的属性参考Istio参考配置-授权-约束和属性#支持的属性

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: service-rb-1
  namespace: default
spec:
  subjects:
  # NOTE: 需要添加 ServiceAccount
  - user: "cluster.local/ns/namespace-1/sa/service-account-2"
    # NOTE: 根据属性需要修改
    properties:
      source.namespace: "default"
  # NOTE: ingressgateway授权
  - user: "cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"
  roleRef:
    kind: ServiceRole
    name: "service-role-1"
---

Optional

部署实例添加ServiceAccount

对于需要要在ServiceRoleBindingsubjects条件中授权的user,需要在部署实例时指定serviceAccountName,如前面ServiceRoleBinding配置要允许service-2访问service-1,则部署service-2时需要配置serviceAccountName: service-account-2

# NOTE: 创建ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: service-account-2
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: service-name-2-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: service-name-2
        version: v1
    spec:
      # NOTE: 为部署实例指定serviceAccountName
      serviceAccountName: service-account-2
      containers:
      - name: service-name-2-v1
        command: [
          "/main"
        ]
        image: hbchen/service-2:v0.0.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---

总结

Istio服务网格可以很方便的实现服务间访问控制,通过服务级的授权开关,再结合ServiceRoleServiceRoleBinding的约束和属性条件,可以实现细粒度的访问控制。本文未涉及Istio的终端用户身份验证,后面会结合IngressEgressTLSJWT一起分析边缘流量相关的安全问题。