# 授权

## HTTP流量授权

### 对使用HTTP流量的工作负载配置访问控制

使用Istio,您可以轻松地设置访问控制 工作量 在您的网格中。此任务显示如何使用Istio授权设置访问控制。首先,您配置一个简单的策略,该策略拒绝对工作负载的所有请求,然后逐渐并增量地授予对工作负载的更多访问权限。deny-all

* 运行以下命令deny-all在default名称空间中创建策略。该策略没有selector字段,该字段将策略应用于default名称空间中的每个工作负载 。该spec:政策的领域具有空值{}。该值表示不允许流量,实际上拒绝了所有请求。

```
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  {}
EOF
```

将浏览器指向Bookinfo productpage(<http://$GATEWAY_URL/productpage)。您应该看到"RBAC>: access denied"。该错误表明配置的deny-all策略按预期工作,并且Istio没有任何规则允许对网格中的工作负载进行任何访问。

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

```
kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "productpage-viewer"
  namespace: default
spec:
  selector:
    matchLabels:
      app: productpage
  rules:
  - to:
    - operation:
        methods: ["GET"]
EOF
```

将浏览器指向Bookinfo productpage(<http://$GATEWAY_URL/productpage)。现在,您应该看到`Bookinfo示例`页面。但是,您可以在页面上看到以下错误>:

* Error fetching product details
* Error fetching product reviews。

这些错误是预料之中的,因为我们尚未授予productpage 工作负载访问details和reviews工作负载的权限。接下来,您需要配置策略以授予对这些工作负载的访问权限。

* 运行以下命令以创建details-viewer策略,以允许productpage 使用cluster.local/ns/default/sa/bookinfo-productpage 服务帐户发出请求的details工作负载通过GET方法访问工作负载:

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

* 运行以下命令以创建策略,reviews-viewer以允许productpage使用cluster.local/ns/default/sa/bookinfo-productpage服务帐户发出请求的reviews工作负载通过GET方法访问工作负载:

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

将浏览器指向Bookinfo productpage(<http://$GATEWAY_URL/productpage)。现在,您应该看到`Bookinfo> Sample`页面,其左下角为`Book Details`,右下角为`Book Reviews`。但是,在`Book Reviews\`部分中存在错误Ratings service currently unavailable。

这是因为reviews工作负载无权访问该ratings工作负载。要解决此问题,您需要授予reviews工作负载访问工作负载的权限ratings。接下来,我们配置一个策略以授予reviews访问权限。

* 运行以下命令以创建ratings-viewer策略,以允许reviews使用`cluster.local/ns/default/sa/bookinfo-reviews`服务帐户发出请求的ratings工作负载通过GET方法访问工作负载:

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

将浏览器指向Bookinfo productpage(<http://$GATEWAY_URL/productpage)。您应该在`Book> Reviews`部分看到`黑色`和`红色\`ratings。

恭喜你！您已成功应用授权策略,以使用HTTP流量对工作负载实施访问控制。

### 清理

从您的配置中删除所有授权策略:

```
$ kubectl delete authorizationpolicy.security.istio.io/deny-all
$ kubectl delete authorizationpolicy.security.istio.io/productpage-viewer
$ kubectl delete authorizationpolicy.security.istio.io/details-viewer
$ kubectl delete authorizationpolicy.security.istio.io/reviews-viewer
$ kubectl delete authorizationpolicy.security.istio.io/ratings-viewer
```

## TCP流量授权

### 先决条件

在foo命名空间中一起部署名为sleep和的两个工作负载。这两个工作负载都先于Envoy代理运行。在tcp-echo监听9000,9001和9002端口,回显任何带有hello前缀的流量。例如,如果您将`world`发送给tcp-echo,它将以答复`hello world`。tcp-echo Kubernetes服务对象只声明端口9000和9001,并且省略了9002端口,直通过滤器链将处理端口9002的流量。使用以下命令部署示例名称空间和工作负载:

```
kubectl create ns foo
kubectl apply -f <(istioctl kube-inject -f samples/tcp-echo/tcp-echo.yaml) -n foo
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
```

使用以下命令验证tcp-echod的9000和9001端口上是否和sleep成功通信:

```
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9000
connection succeeded
```

```
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9001
connection succeeded
```

验证端口9002上是否sleep成功通信tcp-echo。tcp-echo由于端口9002在Kubernetes服务对象中未定义,因此您需要将流量直接发送到Pod IP tcp-echo。获取pod IP地址并使用以下命令发送请求:

```
TCP_ECHO_IP=$(kubectl get pod "$(kubectl get pod -l app=tcp-echo -n foo -o jsonpath={.items..metadata.name})" -n foo -o jsonpath="{.status.podIP}")
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c "echo \"port 9002\" | nc $TCP_ECHO_IP 9002" | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9002
connection succeeded
```

> 如果看不到预期的输出,请在几秒钟后重试。缓存和传播可能会导致延迟。
>
> ### 为TCP工作负载配置访问控制

1. 在名称空间中tcp-policy为tcp-echo工作负载创建授权策略foo。运行以下命令以应用策略以允许请求到端口9000和9001:

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

1. 使用以下命令验证是否允许对端口9000的请求:

```
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9000
connection succeeded
```

1. 使用以下命令验证是否允许对端口9001的请求:

```
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9001
connection succeeded
```

1. 验证对端口9002的请求是否被拒绝。即使未在tcp-echoKubernetes服务对象中显式声明端口,授权策略也将执行此策略,该策略也适用于直通过滤器链。运行以下命令并验证输出:

```
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c "echo \"port 9002\" | nc $TCP_ECHO_IP 9002" | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
```

1. 更新策略,以methods使用以下命令添加以端口9000命名的仅HTTP字段:

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

1. 验证对端口9000的请求是否被拒绝。发生这种情况是因为该规则在methods对TCP通信使用仅HTTP字段(methods)时变得无效。Istio会忽略无效的ALLOW规则。最终结果是该请求被拒绝,因为它与任何ALLOW规则都不匹配。运行以下命令并验证输出:

```
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
```

1. 验证对端口9001的请求是否被拒绝。发生这种情况是因为请求与任何ALLOW规则都不匹配。运行以下命令并验证输出:

```
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
```

1. 使用以下命令将策略更新为DENY策略:

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

1. 验证对端口9000的请求是否被拒绝。发生这种情况是因为Istio忽略了无效DENY规则中的仅HTTP字段。这与无效的ALLOW规则不同,ALLOW规则导致Istio忽略整个规则。最终结果是ports Istio仅使用该字段,并且由于它们与匹配而被拒绝ports:

```
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
```

1. 验证是否允许对端口9001的请求。发生这种情况是因为请求ports与DENY策略中的不匹配:

```
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9001
connection succeeded
```

### 清理

删除名称空间foo:

$ kubectl delete namespace foo

## JWT授权

此任务向您展示如何设置Istio授权策略以基于JSON Web令牌(JWT)强制执行访问。Istio授权策略支持字符串类型的和JWT字符串列表的声明。

### 先决条件

部署两个工作负载:httpbin和sleep。例如,将它们部署在一个名称空间中foo。这两个工作负载都在每个Envoy代理的前面运行。使用以下命令部署示例名称空间和工作负载:

```
$ 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
```

使用以下命令验证是否可以sleep成功通信httpbin:

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

如果看不到预期的输出,请在几秒钟后重试。缓存和传播可能会导致延迟。

## 允许具有有效JWT和列表类型声明的请求

1. 以下命令jwt-example为名称空间中的httpbin工作负载创建请求身份验证策略foo。此httpbin工作负载政策接受以下机构发布的JWT <testing@secure.istio.io>:

```
$ kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
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.8/security/tools/jwt/samples/jwks.json"
EOF
```

1. 验证带有无效JWT的请求是否被拒绝:

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

1. 验证是否允许没有JWT的请求,因为没有授权策略:

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

1. 以下命令require-jwt为名称空间中的httpbin工作负载创建授权策略foo。该策略要求对httpbin工作负载的所有请求都必须具有有效的JWT, requestPrincipal并将其设置为<testing@secure.istio.io>/testing\@secure.istio.io。Istio构建requestPrincipal通过组合iss和sub与令牌的JWT的/分离器,如下所示:

```
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
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
```

1. 获取将iss和sub键设置为相同值的JWT <testing@secure.istio.io>。这将导致Istio生成requestPrincipal具有以下值的属性<testing@secure.istio.io>/testing\@secure.istio.io:

```
$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode -
{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}
```

1. 验证是否允许带有有效JWT的请求:

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

1. 验证没有JWT的请求是否被拒绝:

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

1. 以下命令更新require-jwt授权策略,以要求JWT拥有一个groups包含值的声明group1:

```
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
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"]
    when:
    - key: request.auth.claims[groups]
      values: ["group1"]
EOF
```

> request.auth.claims除非声明本身包含引号,否则请勿在该字段中包含引号。

1. 获取将groups索赔声明设置为字符串列表的JWT :group1和group2:

```
$ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode -
{"exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"testing@secure.istio.io","scope":["scope1","scope2"],"sub":"testing@secure.istio.io"}
```

1. 验证是否允许与JWT包含group1在groups索赔中的请求:

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

1. 验证没有请求的JWT请求是否groups被拒绝:

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

### 清理

删除名称空间foo:

$ kubectl delete namespace foo

## 拒绝策略的授权策略

此任务说明如何设置拒绝Istio网格中HTTP流量的Istio授权策略。在我们的授权概念页面上了解更多信息。

## 先决条件

部署工作负载:

此任务使用部署在一个名称空间foo上的两个工作负载(httpbin和sleep)。这两个工作负载都在每个Envoy代理的前面运行。使用以下命令部署示例名称空间和工作负载:

```
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
```

使用以下命令验证与之sleep对话httpbin:

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

如果在执行任务时未看到预期的输出,请在几秒钟后重试。缓存和传播开销可能会导致一些延迟。

### 明确拒绝请求

1. 以下命令deny-method-get为名称空间中的httpbin工作负载创建授权策略foo。该策略将设置为action,DENY以拒绝满足本rules节中设置的条件的请求。这类策略被称为拒绝策略。在这种情况下,策略会拒绝请求,如果其方法为GET。

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

1. 验证GET请求是否被拒绝:

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

1. 验证是否POST允许请求:

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

1. 更新deny-method-get授权策略以GET仅在HTTP标头x-token值不是时才拒绝请求admin。以下示例策略将notValues字段的值设置为,\["admin"]以拒绝标头值为的请求admin:

```
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
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
```

1. 验证是否允许GET带有HTTP标头的请求x-token: admin:

```
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/get" -X GET -H "x-token: admin" -s -o /dev/null -w "%{http_code}\n"
200
```

1. 验证带有HTTP标头的GET请求是否x-token: guest被拒绝:

```
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/get" -X GET -H "x-token: guest" -s -o /dev/null -w "%{http_code}\n"
403
```

1. 以下命令创建allow-path-ip授权策略,以允许在工作负载/ip路径上的请求httpbin。此授权策略将action字段设置为ALLOW。这种类型的策略被称为允许策略。

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

1. 验证该策略是否拒绝在路径中GET带有HTTP标头的请求。拒绝策略优先于允许策略:x-token: guest/ipdeny-method-get

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

9.确认策略允许路径中GET带有HTTP标头的请求:x-token: admin/ipallow-path-ip

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

1. 验证路径为GETHTTP标头的请求是否被拒绝,因为它们与策略不匹配:x-token: admin/getallow-path-ip

```
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/get" -X GET -H "x-token: admin" -s -o /dev/null -w "%{http_code}\n"
403
```

### 清理

从配置中删除名称空间foo:

```
kubectl delete namespace foo
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rocdu.gitbook.io/deep-understanding-of-istio/4/6/6-3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
