跳转至

istio 安全 授权

  Istio 的授权功能为网格中的工作负载提供网格范围、命名空间范围和工作负载范围的访问控制。

1、授权架构

  授权策略对服务器端Envoy代理中的入站流量实施访问控制。每个Envoy代理都运行一个授权引擎,在运行时对请求进行授权。当请求到达代理时,授权引擎根据当前授权策略评估请求上下文,并返回授权结果ALLOW或DENY。

2、隐式启用

您无需明确启用 Istio 的授权功能;安装后即可使用。

对于未应用授权策略的工作负载,Istio 允许所有请求。

Istio按层检查匹配策略,顺序是:CUSTOM, DENY,然后ALLOW。对于每种类型的操作,Istio首先检查是否存在应用了该操作的策略,然后检查请求是否与策略规范匹配。如果请求与其中一层中的策略不匹配,则继续检查下一层。

3、授权策略

授权策略包括选择器、操作和规则列表:

  • selector字段指定策略的目标

  • action字段指定是否允许或拒绝请求

  • rules指定何时触发操作

  • from中的字段指定rules请求的来源

  • to中的字段指定rules请求的操作

  • when字段指定应用规则所需的条件

拒绝策略优先于允许策略 。如果请求与拒绝策略匹配,则匹配允许策略的请求会被拒绝。Istio 首先评估拒绝策略,以确保允许策略无法绕过拒绝策略。

3.1、策略目标

您可以使用metadata/namespace字段和可选的selector字段指定策略的范围或目标。策略应用于metadata/namespace字段中的命名空间。如果将其值设置为 根命名空间,则该策略应用于网格中的 所有命名空间 。根命名空间的值是可配置的,默认值为 istio-system 。如果设置为任何其他命名空间,则该策略仅适用于指定的命名空间。

您可以使用selector字段来进一步限制策略应用于特定工作负载。选择器使用标签来选择目标工作负载。选择器包含{key:Value}对的列表,其中键是标签的名称。 如果未设置,授权策略将应用于与授权策略相同命名空间中的所有工作负载。

3.2、值匹配

授权策略中的大多数字段都支持以下所有匹配模式:

  • 精确匹配:字符串精确匹配。

  • 前缀匹配:以"*"结尾的字符串。例如,"test.abc.*" 匹配"test.abc.com"、"test.abc.com.cn"、"test.abc.org"等。

  • 后缀匹配:以"*"开头的字符串。例如,"*.abc.com" 匹配"eng.abc.com"、"test.eng.abc.com"等。

  • 存在匹配:*用于指定任何内容但不能为空。要指定字段必须存在,请使用fieldname: ["*"]格式。这与不指定字段不同,后者表示匹配任何内容,包括空。

有些字段仅支持精确匹配。

3.3、排除匹配

为了匹配负条件,例如when字段中的notValues、source字段中的notIpBlocks、to字段中的notPorts,Istio支持排除匹配。如果请求路径不是/healthz,以下示例需要有效的请求主体,该主体从JWT身份验证派生。因此,该策略将对/healthz路径的请求排除在JWT身份验证之外:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

以下示例拒绝/api/没有请求主体的请求路径的请求:

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: enable-jwt-for-admin
  namespace: default
spec:
  selector:
    matchLabels:
      app: service-a
  action: DENY
  rules:
  - to:
    - operation:
        paths: ["/api/*"]
    from:
    - source:
        notRequestPrincipals: ["*"]
EOF

标签匹配是根据pod的标签进行匹配的。

curl "service-a.localserver.com/api/v1/testA/get_headers/" -s -o /dev/null -w "%{http_code}\n"
403

3.4、默认策略

下面的示例显示了一个不匹配任何内容的ALLOW策略。如果没有其他ALLOW策略,则由于“默认拒绝”行为,请求将始终被拒绝。

注意,“默认拒绝”行为仅在工作负载至少有一个带有ALLOW操作的授权策略时才适用。

警告

从“不允许”策略开始,然后逐渐添加更多的“允许”策略,以打开对工作负载的更多访问,这是一个很好的安全实践。
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW
  # the rules field is not specified, and the policy will never match.

实测也是非常有生产环境价值的功能,默认拒绝所有请求,在配置了上述策略之后,进行以下测试

服务间访问
curl http://service-c:9000/api/v1/testC/
RBAC: access denied

外部请求
curl "service-a.localserver.com/api/v1/testA/get_headers/" -s -o /dev/null -w "%{http_code}\n"\n
403

当我执行以下策略时,服务a可以正常访问,别的不可以。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: enable-jwt-for-admin-a
  namespace: default
spec:
  selector:
    matchLabels:
      app: service-a
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/api/*"]
EOF

下面的示例显示了显式拒绝所有访问的DENY策略。它将始终拒绝请求,即使存在另一个允许请求的ALLOW策略,因为deny策略优先于ALLOW策略。 如果您想暂时禁用对工作负载的所有访问 ,这很有用。

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  # the rules field has an empty rule, and the policy will always match.
  rules:
  - {}

下面的示例展示了允许对工作负载进行完全访问的ALLOW策略。它将使其他ALLOW策略无效,因为它总是允许请求。 如果您想暂时公开对工作负载的完全访问权限 ,这可能会很有用。注意,由于CUSTOM和DENY策略,请求仍然可能被拒绝。

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  # This matches everything.
  rules:
  - {}

4、http流量授权

4.1、默认策略

运行以下命令在命名空间default中创建策略allow-nothing。该策略没有selector字段,该字段将策略应用于 default命名空间中的每个工作负载。spec:策略的字段具有空值{}。该值表示不允许任何流量,从而有效地拒绝所有请求。

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
  namespace: default
spec:
  {}
EOF
浏览器访问任意服务应该都是"RBAC: access denied"。错误表明配置的deny-all策略按预期工作,并且 Istio 没有任何允许访问网格中工作负载的规则。

4.2、访问productpage

运行以下命令创建productpage-viewer策略以允许使用GET方法访问productpage工作负载。该策略未设置from 字段,这rules意味着允许所有来源,从而有效地允许所有用户和工作负载。

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: "productpage-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: productpage
  action: ALLOW
  rules:
  - to:
    - operation:
        methods: ["GET"]
EOF
访问bookinfo 这些错误是预料之中的,因为我们尚未授予productpage 工作负载对details和reviews工作负载的访问权限。接下来,您需要配置策略以授予对这些工作负载的访问权限。

4.3、productpage访问details

使用 cluster.local/ns/default/sa/bookinfo-productpage 服务账户通过get方法访问details工作负载。在productpage的deployment中引用了bookinfo-productpage的服务账户。

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: "details-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: details
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
    to:
    - operation:
        methods: ["GET"]
EOF
开放details

4.4、productpage访问reviews

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: "reviews-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: reviews
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
    to:
    - operation:
        methods: ["GET"]
EOF

4.5、reviews访问ratings

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: "ratings-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: ratings
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/bookinfo-reviews"]
    to:
    - operation:
        methods: ["GET"]
EOF

最终页面就跟没有任何授权控制一样。

5、tcp流量授权

5.1、allow

5.1.1、允许端口请求

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: tcp-policy
  namespace: foo
spec:
  selector:
    matchLabels:
      app: tcp-echo
  action: ALLOW
  rules:
  - to:
    - operation:
        ports: ["9000", "9001"]
EOF

5.1.2、增加仅http生效的字段

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: tcp-policy
  namespace: foo
spec:
  selector:
    matchLabels:
      app: tcp-echo
  action: ALLOW
  rules:
  - to:
    - operation:
        methods: ["GET"]
        ports: ["9000"]
EOF

验证对端口9000的请求被拒绝。 这是因为当规则对TCP通信使用仅限http的字段(方法)时 ,该规则将失效。Istio忽略无效的ALLOW规则。最终的结果是请求被拒绝,因为它不匹配任何ALLOW规则。

5.2、deny

5.2.1、配置包含http字段的策略

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: tcp-policy
  namespace: foo
spec:
  selector:
    matchLabels:
      app: tcp-echo
  action: DENY
  rules:
  - to:
    - operation:
        methods: ["GET"]
EOF

验证对端口 9000 的请求是否被拒绝。发生这种情况的原因是 Istio 在为 tcp 端口创建 DENY 规则时不理解 HTTP-only 字段,并且由于其限制性,它拒绝了到 tcp 端口的所有流量。

5.2.2、添加包含 TCP 和 HTTP 字段的 DENY 策略

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: tcp-policy
  namespace: foo
spec:
  selector:
    matchLabels:
      app: tcp-echo
  action: DENY
  rules:
  - to:
    - operation:
        methods: ["GET"]
        ports: ["9000"]
EOF

tcp和http的规则最好不要同时配置。

6、jwt令牌

6.1、最终用户身份验证

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
  name: "jwt-example"
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  jwtRules:
  - issuer: "testing@secure.istio.io"
    jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.24/security/tools/jwt/samples/jwks.json"
EOF
  • 验证带有无效 JWT 的请求返回401。

  • 没有带有token的请求被正常放行。

单独如上的配置加上token和没有token都可以正常访问。

6.2、加上授权策略

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - from:
    - source:
       requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
EOF

此时包含jwt的请求才能正常被通过。

7、明确拒绝

DENY操作具有更高的优先级,并且不会被任何ALLOW操作绕过。

7.1、拒绝get请求

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-method-get
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: DENY
  rules:
  - to:
    - operation:
        methods: ["GET"]
EOF

访问 app=httpbin的标签时,get请求被拒绝,post请求会被通过。

7.2、header中某个值不匹配

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-method-get
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: DENY
  rules:
  - to:
    - operation:
        methods: ["GET"]
    when:
    - key: request.headers[x-token]
      notValues: ["admin"]
EOF

7.3、path匹配

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-path-ip
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/ip"]
EOF

8、入口网关授权

8.1、基于ip的允许列表和拒绝列表

基于ip的访问策略

svc中如果配置了externalTrafficPolicy: Local


本文阅读量  次

评论