概述
Istio采用基于角色的访问控制方式,本文内容涵盖了为 HTTP 设置访问控制的各个环节。
前提
- 了解访问控制基本概念
- Istio启用认证功能
- 部署Bookinfo实例应用
- 创建Service Account来运行 Bookinfo 中的微服务,为了给不同的微服务赋予不同的访问权限。
- 创建 Service Account bookinfo-productpage,并用这一身份重新部署 productpage 微服务。
- 创建 Service Account bookinfo-reviews,并用它来重新部署 reviews。
kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo-add-serviceaccount.yaml)
YAML具体内容如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-productpage
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: productpage-v1
spec:
replicas: 1
template:
metadata:
labels:
app: productpage
version: v1
spec:
serviceAccountName: bookinfo-productpage
containers:
- name: productpage
image: istio/examples-bookinfo-productpage-v1:1.13.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-reviews
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v2
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v2
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v2:1.13.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v3
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v3
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v3:1.13.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
用浏览器打开 Bookinfo 的 productpage(http://$GATEWAY_URL/productpage)应该会看到:
- 页面左下方的 “Book Details” 中包含了类型、页数、出版商等信息。
- “Book Reviews” 应该显示在页面右下方。
- 多次刷新该页面,可能会看到页面中显示了 “Book Reviews” 的不同版本,红星、黑星和无星三个版本会轮换展示。
启用 Istio 访问控制
在 default 命名空间中启用 Istio 访问控制:
kubectl apply -f samples/bookinfo/platform/kube/rbac/rbac-config-ON.yaml
YAML具体内容如下:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ClusterRbacConfig
metadata:
name: default
spec:
mode: 'ON_WITH_INCLUSION'
inclusion:
namespaces: ["default"]
用浏览器打开 Bookinfo 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 其中的一个,就可以被同一命名空间(default)内的服务访问。运行下面的命令,来创建命名空间级的访问控制策略:
kubectl apply -f samples/bookinfo/platform/kube/rbac/namespace-policy.yaml
这条策略包括:一个名为 service-viewer 的 ServiceRole,该角色允许对于 default 命名空间内,并且 app 标签值在 productpage、reviews、details 和 ratings 范围内的服务发起读取访问。
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,给所有 istio-system 和 default 命名空间内的服务分配一个 service-viewer 角色。
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"
如果用浏览器访问 Bookinfo productpage(http://$GATEWAY_URL/productpage),应该会看到 “Bookinfo Sample” 页面,左下角是 “Book Details”,右下角是 “Book Reviews”。
清理命名空间级别的访问控制
通过下面命令删除相关配置
kubectl delete -f samples/bookinfo/platform/kube/rbac/namespace-policy.yaml
服务级访问控制
- 前提
- 启用 Istio 访问控制。
- 清理命名空间级别的访问控制。
用浏览器访问 Bookinfo productpage(http://$GATEWAY_URL/productpage),会看到 "RBAC: access denied"。我们将会逐步在 Bookinfo 中加入访问权限。
第一步:设置外部可以访问productpage 服务
创建一条策略,允许外部请求通过 Ingress 访问 productpage 服务。
kubectl apply -f samples/bookinfo/platform/kube/rbac/productpage-policy.yaml
该策略包括:创建一个名为 productpage-viewer 的 ServiceRole,允许对 productpage 服务进行读取访问。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: productpage-viewer
namespace: default
spec:
rules:
- services: ["productpage.default.svc.cluster.local"]
methods: ["GET"]
创建一个 ServiceRoleBinding,命名为 bind-productpager-viewer,将 productpage-viewer 角色授予所有用户和服务。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: bind-productpage-viewer
namespace: default
spec:
subjects:
- user: "*"
roleRef:
kind: ServiceRole
name: "productpage-viewer"
用浏览器访问 Bookinfo productpage(http://$GATEWAY_URL/productpage),现在应该就能看到 “Bookinfo Sample” 页面了,但是页面上会显示 Error fetching product details and Error fetching product reviews 的错误信息。这些错误信息是正常的,原因是 productpage 还无权访问 details 和 reviews 服务。
第二步:设置外部可以访问details 和 reviews 服务
利用已经创建的productpage 服务的身份标识Service Account bookinfo-productpage,创建一条策略,允许 productpage 访问 details 和 reviews 服务。
kubectl apply -f samples/bookinfo/platform/kube/rbac/details-reviews-policy.yaml
这个策略主要包括:新建名为 details-reviews-viewer 的 ServiceRole,该角色允许对 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-reviews,将 details-reviews-viewer 角色授予 cluster.local/ns/default/sa/bookinfo-productpage(也就是 productpage 服务)。
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 服务。要解决这一问题,就需要授权给 reviews 服务,允许它访问 ratings 服务。
第三步:设置外部可以访问ratings 服务
利用reviews 服务的身份标识Service Account bookinfo-reviews,创建一条策略,允许 reviews 服务访问 ratings 服务。运行下面的命令,创建允许 reviews 服务访问 ratings 服务的策略:
kubectl apply -f samples/bookinfo/platform/kube/rbac/ratings-policy.yaml
这条策略主要包括:创建一个名为 ratings-viewer 的 ServiceRole,并允许其访问 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(也就是 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
- 禁用 Istio 访问控制
kubectl delete -f samples/bookinfo/platform/kube/rbac/rbac-config-ON.yaml