基于角色的访问控制
在服务网格中为服务进行授权控制(基于角色的访问控制)时,会涉及到本例中包含的一系列操作。在授权一节中讲述了更多这方面的内容,并且还有一个基本的 Istio 安全方面的教程。
准备任务
本文活动开始之前,我们有如下假设:
具有对授权概念的了解。
在 Istio 中遵循快速入门的步骤 启用了认证功能,这个教程对双向 TLS 有依赖,因此要在安装步骤中启用双向 TLS 认证。
部署 Bookinfo 示例应用。
这个任务里,我们会在 Service account 的基础上启用访问控制,在网格中进行加密的认证。为了给不同的微服务以不同的访问授权,就需要建立一系列不同的 Service account,用这些账号来分别运行 Bookinfo 中的微服务。
运行命令,完成以下目的:
- 创建 Service account:
bookinfo-productpage
,并用这一身份部署productpage
。 - 创建 Service account:
bookinfo-reviews
,并用这一身份部署reviews
(注意其中包含reviews-v2
和reviews-v3
两个版本)。
Zip
$ kubectl apply -f <(istioctl kube-inject -f @samples/bookinfo/platform/kube/bookinfo-add-serviceaccount.yaml@)
-
Istio 1.0 中的 RBAC 有较大更新。请确认在继续之前,已经清理了所有现存 RBAC 规则。
- 运行下面的命令,禁用旧的 RBAC 功能,在 1.0 中就无需这一步骤了:
$ kubectl delete authorization requestcontext -n istio-system
$ kubectl delete rbac handler -n istio-system
$ kubectl delete rule rbaccheck -n istio-system
- 用这个命令移除所有现存 RBAC 策略:
保存现有策略是可以的,不过需要对策略的
constraints
以及 properties
字段进行修改,参考约束和属性中的内容,了解这两个字段所支持的值。
$ kubectl delete servicerole —all
$ kubectl delete servicerolebinding —all
-
用浏览器打开 Bookinfo 的
productpage
页面,会看到:- 页面左下角是 “Book Details”,其中包含了类型、页数、出版商等信息。
- 页面右下角是 “Book Reviews” 部分。
如果刷新几次,会发现
productpage
在切换使用不同的 reviews
版本(红星、黑星、无)。## 授权许可模式
本节介绍如何在以下两种情况下使用授权许可模式:
在未经授权的环境中,测试是否可以安全地启用授权。
在已启用授权的环境中,测试添加新授权策略是否安全。
### 测试启用全局授权是否安全
此任务说明如何使用授权许可模式来测试是否可以安全地启用全局授权。
在开始之前,请确保您已完成准备任务。
-
将全局授权配置设置为许可模式。
运行以下命令:
$ kubectl apply -f - <<EOF
apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
name: default
spec:
mode: 'ON_WITH_INCLUSION'
inclusion:
namespaces: ["default"]
enforcement_mode: PERMISSIVE
EOF
将浏览器指向 Bookinfo
productpage
(http://$GATEWAY_URL/productpage
),您应该看到一切正常,与准备任务相同。-
将 YAML 文件应用于许可模式度量标准集合。
运行以下命令:
Zip
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/rbac-permissive-telemetry.yaml@
logentry.config.istio.io/rbacsamplelog created
stdio.config.istio.io/rbacsamplehandler created
rule.config.istio.io/rabcsamplestdio created
-
将流量发送到示例应用程序。
对于 Bookinfo 示例,请在 Web 浏览器中访问
http://$GATEWAY_URL/productpage
或发出以下命令:将您的浏览器指向 Bookinfo
productpage
(http://$GATEWAY_URL/productpage
),您应该看到一切正常。-
验证已创建日志流并检查
permissiveResponseCode
。在 Kubernetes 环境中,搜索日志以查找
istio-telemetry
pods,如下所示:
$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep \"instance\":\"rbacsamplelog.logentry.istio-system\"
{"level":"warn","time":"2018-08-30T21:53:42.059444Z","instance":"rbacsamplelog.logentry.istio-system","destination":"ratings","latency":"9.158879ms","permissiveResponseCode":"403","permissiveResponsePolicyID":"","responseCode":200,"responseSize":48,"source":"reviews","user":"cluster.local/ns/default/sa/bookinfo-reviews"}
{"level":"warn","time":"2018-08-30T21:53:41.037824Z","instance":"rbacsamplelog.logentry.istio-system","destination":"reviews","latency":"1.091670916s","permissiveResponseCode":"403","permissiveResponsePolicyID":"","responseCode":200,"responseSize":379,"source":"productpage","user":"cluster.local/ns/default/sa/bookinfo-productpage"}
{"level":"warn","time":"2018-08-30T21:53:41.019851Z","instance":"rbacsamplelog.logentry.istio-system","destination":"productpage","latency":"1.112521495s","permissiveResponseCode":"403","permissiveResponsePolicyID":"","responseCode":200,"responseSize":5723,"source":"istio-ingressgateway","user":"cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"}
在上面的遥测日志中,用户现在看到的
responseCode
是 200。用户在将全局授权配置从 PERMISSIVE
模式切换到 ENFORCED
模式后将看到 permissiveResponseCode
是 403,这表示全局授权配置在滚动到生产后将按预期工作。-
在生产中推出新的授权策略之前,请以许可模式应用它。
注意
,当全局授权配置处于许可模式时,默认情况下所有策略都将处于许可模式。运行以下命令:
Zip
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/productpage-policy.yaml@
-
再次向示例应用程序发送流量。
对于 Bookinfo 示例,请在 Web 浏览器中访问
http://$GATEWAY_URL/productpage
或发出以下命令:将您的浏览器指向 Bookinfo
productpage
(http://$GATEWAY_URL/productpage
),您应该看到一切正常。-
验证已创建日志流并检查
permissiveResponseCode
。在 Kubernetes 环境中,搜索日志以查找
istio-telemetry
pods,如下所示:
$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep \"instance\":\"rbacsamplelog.logentry.istio-system\"
{"level":"warn","time":"2018-08-30T21:55:53.590430Z","instance":"rbacsamplelog.logentry.istio-system","destination":"ratings","latency":"4.415633ms","permissiveResponseCode":"403","permissiveResponsePolicyID":"","responseCode":200,"responseSize":48,"source":"reviews","user":"cluster.local/ns/default/sa/bookinfo-reviews"}
{"level":"warn","time":"2018-08-30T21:55:53.565914Z","instance":"rbacsamplelog.logentry.istio-system","destination":"reviews","latency":"32.97524ms","permissiveResponseCode":"403","permissiveResponsePolicyID":"","responseCode":200,"responseSize":379,"source":"productpage","user":"cluster.local/ns/default/sa/bookinfo-productpage"}
{"level":"warn","time":"2018-08-30T21:55:53.544441Z","instance":"rbacsamplelog.logentry.istio-system","destination":"productpage","latency":"57.800056ms","permissiveResponseCode":"200","permissiveResponsePolicyID":"productpage-viewer","responseCode":200,"responseSize":5723,"source":"istio-ingressgateway","user":"cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"}
在上面的遥测日志中,用户现在看到的
responseCode
是 200。对于 productpage
页面服务,permissiveResponseCode
为 200,对于 ratings
和 reviews
服务为 403,这是用户在将策略模式从 PERMISSIVE
模式切换到 ENFORCED
模式后将看到的内容;结果与步骤1一致。-
删除与许可模式相关的 yaml 文件:
ZipZipZip
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/productpage-policy.yaml@
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/rbac-config-on-permissive.yaml@
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/rbac-permissive-telemetry.yaml@
-
现在我们已经验证了授权在打开时按预期工作,在启用 Istio 授权下面打开授权是安全的。
### 在滚动到生产之前,测试新的授权策略按预期工作
此任务说明如何使用授权许可模式来测试新授权策略在已启用授权的环境中按预期工作。
在开始之前,请确保您已完成步骤1。
-
在应用新策略之前,通过将其模式设置为permissive来测试它:
运行以下命令:
Zip
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/details-reviews-policy-permissive.yaml@
该策略与允许访问详细信息和评论服务中定义的策略相同,除了在 ServiceRoleBinding 中设置了
PERMISSIVE
模式。
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"
mode: PERMISSIVE
将您的浏览器指向 Bookinfo
productpage
(http://$GATEWAY_URL/productpage
),您仍然会在页面上看到错误 Error fetching product details
和 Error fetching product reviews
。由于策略处于 PERMISSIVE
模式,因此预期会出现这些错误。-
将 YAML 文件应用于许可模式度量标准集合。
运行以下命令:
Zip
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/rbac-permissive-telemetry.yaml@
-
将流量发送到示例应用程序。
对于 Bookinfo 示例,请在 Web 浏览器中访问
http://$GATEWAY_URL/productpage
或发出以下命令:-
验证日志并再次检查
permissiveResponseCode
。在 Kubernetes 环境中,搜索日志以查找
istio-telemetry
pods,如下所示:
$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep \"instance\":\"rbacsamplelog.logentry.istio-system\"
{"level":"warn","time":"2018-08-30T22:59:42.707093Z","instance":"rbacsamplelog.logentry.istio-system","destination":"details","latency":"423.381µs","permissiveResponseCode":"200","permissiveResponsePolicyID":"details-reviews-viewer","responseCode":403,"responseSize":19,"source":"productpage","user":"cluster.local/ns/default/sa/bookinfo-productpage"}
{"level":"warn","time":"2018-08-30T22:59:42.763423Z","instance":"rbacsamplelog.logentry.istio-system","destination":"reviews","latency":"237.333µs","permissiveResponseCode":"200","permissiveResponsePolicyID":"details-reviews-viewer","responseCode":403,"responseSize":19,"source":"productpage","user":"cluster.local/ns/default/sa/bookinfo-productpage"}
在上面的遥测日志中,用户现在看到的
ratings
和 reviews
服务的 responseCode
为 403。对于 ratings
和 reviews
服务,permissiveResponseCode
为 200,这是用户在将策略模式从 PERMISSIVE
模式切换到 ENFORCED
模式后将看到的内容;它表示新的授权策略在滚动到生产后将按预期工作。-
删除与许可模式相关的 yaml 文件:
ZipZip
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/details-reviews-policy-permissive.yaml@
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/rbac-permissive-telemetry.yaml@
-
现在我们已经验证了新策略将按预期工作,在步骤 2 应用策略之后是安全的。
## 启用 Istio 授权
运行下面的命令,为
default
命名空间启用 Istio 授权:Zip
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/rbac-config-ON.yaml@
用浏览器再次打开
productpage
(http://$GATEWAY_URL/productpage
),这次会看到 RBAC: access denied
。Istio 的鉴权行为是“缺省拒绝”的,也就是说必须要显式的进行授权,才能对服务进行访问。命名空间级的访问控制
Istio 的授权能力可以轻松的设置命名空间级的访问控制,只要指定命名空间内的所有(或者部分)服务可以被另一命名空间的服务访问即可。
Bookinfo 示例中,productpage
、reviews
、details
以及 ratings
服务被部署在 default
命名空间中,而 istio-ingressgateway
等 Istio 组件是部署在 istio-system
命名空间中的。我们可以定义一个策略,default
命名空间中所有服务,如果其 app
标签取值在 productpage
、reviews
、details
以及 ratings
范围之内,就可以被本命名空间内以及 istio-system
命名空间内的服务进行访问。
运行这一命令,创建一个命名空间级别的访问控制策略:
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/namespace-policy.yaml@
这一策略完成如下任务:
- 创建名为
service-viewer
的ServiceRole
,允许访问default
命名空间中所有app
标签值在productpage
、reviews
、details
以及ratings
范围之内的服务。注意其中的constraint
字段,确定了服务的app
标签取值必须在指定范围以内:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: service-viewer
namespace: default
spec:
rules:
- services: ["*"]
methods: ["GET"]
constraints:
- key: "destination.labels[app]"
values: ["productpage", "details", "reviews", "ratings"]
- 创建
ServiceRoleBinding
对象,用来把service-viewer
角色指派给所有istio-system
和default
命名空间的服务:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: bind-service-viewer
namespace: default
spec:
subjects:
- properties:
source.namespace: "istio-system"
- properties:
source.namespace: "default"
roleRef:
kind: ServiceRole
name: "service-viewer"
命令执行结果大致如下:
servicerole "service-viewer" created
servicerolebinding "bind-service-viewer" created
如果这时用浏览器浏览 Bookinfo 的 productpage
页面 (http://$GATEWAY_URL/productpage
),会再次看到完整的页面,包含了左下角的 “Book Details” 以及右下角的 “Book Reviews”。
清除命名空间级的访问控制
在进行后续任务之前,首先移除下面的配置:
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/namespace-policy.yaml@
服务级的访问控制
这个任务展示了使用 Istio 授权功能配置服务级访问控制的方法。开始之前,请进行下面的确认:
- 已经启用 Istio 授权
- 已经清除命名空间级的访问控制。会看到:
RBAC: access denied
。我们会在 Bookinfo 中逐步为服务加入访问许可。
第一步,允许到 productpage 服务的访问
这里我们要创建一条策略,允许外部请求通过 Ingress 浏览 productpage
。
执行命令:
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/productpage-policy.yaml@
这条策略完成以下工作:
- 创建
ServiceRole
,命名为productpage-viewer
,允许到productpage
服务的读取访问:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: productpage-viewer
namespace: default
spec:
rules:
- services: ["productpage.default.svc.cluster.local"]
methods: ["GET"]
- 创建
ServiceRole
,并命名为productpage-viewer
,将productpage-viewer
角色赋予给所有用户和服务:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: bind-productpager-viewer
namespace: default
spec:
subjects:
- user: "*"
roleRef:
kind: ServiceRole
name: "productpage-viewer"
再次浏览 Bookinfo 的 productpage
(http://$GATEWAY_URL/productpage
)。应该能看到 “Bookinfo Sample” 页面了。但是还会显示 Error fetching product details
和 Error fetching product reviews
的错误信息。这是因为我们还没有给 productpage
访问 details
和 reviews
服务的授权。我们接下来就修复这个问题。
第二步,允许对 details 和 reviews 服务的访问
创建一条策略,让 productpage
服务能够读取 details
和 reviews
服务。注意在准备任务中,我们给 productpage
服务创建了一个命名为 bookinfo-productpage
的 Service account,它就是 productpage
服务的认证 ID。
运行下面的命令:
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/details-reviews-policy.yaml@
这一策略完成以下任务:
- 创建一个
ServiceRole
,命名为details-reviews-viewer
,允许对details
和reviews
服务进行只读访问。
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"]
- 创建一个
ServiceRoleBinding
并命名为bind-details-review
,用来把details-reviews-viewer
角色授予给cluster.local/ns/default/sa/bookinfo-productpage
(也就是productpage
服务的 Service account)。
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"
浏览 Bookinfo 页面 productpage
(http://$GATEWAY_URL/productpage
)。现在看到的 “Bookinfo Sample” 中包含了左下角的 “Book Details” 以及右下角的 “Book Reviews”。然而 “Book Reviews” 中有一条错误信息: Ratings service currently unavailable
,这是因为 reviews
服务无权访问 ratings
服务,要更正这一问题,就应该给 ratings
服务授权,使其能够访问 reviews
服务。下面的步骤就会完成这一需要。
第三步,允许对 ratings 服务的访问
接下来新建一条策略,允许 reviews
服务对 ratings
发起读取访问。注意,我们在准备任务步骤里为 reviews
服务创建了 Service account bookinfo-reviews
,这个账号就是 reviews
服务的认证凭据。
下面的命令会创建一条允许 reviews
服务读取 ratings
服务的策略。
$ kubectl apply -f @samples/bookinfo/platform/kube/rbac/ratings-policy.yaml@
这条策略完成以下工作:
- 创建
ServiceRole
命名为ratings-viewer
,这一角色允许对ratings
服务的访问。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: ratings-viewer
namespace: default
spec:
rules:
- services: ["ratings.default.svc.cluster.local"]
methods: ["GET"]
- 创建
ServiceRoleBinding
,命名为bind-ratings
,将ratings-viewer
角色指派给cluster.local/ns/default/sa/bookinfo-reviews
,给这个 Service account 授权,也就就代表了给reviews
服务授权。
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"
用浏览器浏览 Bookinfo 应用的 productpage
(http://$GATEWAY_URL/productpage
),应该就会看到 “Book Reviews” 区域中显示红色或者黑色的评级信息。
清理
- 清理 Istio 授权策略的相关配置:
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/ratings-policy.yaml@
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/details-reviews-policy.yaml@
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/productpage-policy.yaml@
或者也可以运行命令删除所有的 ServiceRole
以及 ServiceRoleBinding
资源:
$ kubectl delete servicerole --all
$ kubectl delete servicerolebinding --all
- 禁用 Istio 的授权功能:
$ kubectl delete -f @samples/bookinfo/platform/kube/rbac/rbac-config-ON.yaml@