Skip to content

Commit

Permalink
feat(auth,platform,installer): support rbac (tkestack#1254)
Browse files Browse the repository at this point in the history
feat(platform,auth,installer): support k8s' native authorization of rbac

Co-authored-by: mingyutang <[email protected]>
  • Loading branch information
metang326 and mingyutang committed Apr 29, 2021
1 parent e41e4a9 commit ab38745
Show file tree
Hide file tree
Showing 10 changed files with 452 additions and 59 deletions.
3 changes: 2 additions & 1 deletion charts/tke-auth-api/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ metadata:
{{- include "tke-auth-api.labels" . | nindent 4 }}
data:
abac-policy.json: |
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"system:*","namespace":"*", "resource":"*","apiGroup":"*", "group": "*", "nonResourcePath":"*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"system:kube-*|system:serviceaccount:kube-system:*","namespace":"*", "resource":"*","apiGroup":"*tkestack.io", "group": "*", "nonResourcePath":"*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"^system:serviceaccount:tke:default$","namespace":"*", "resource":"*","apiGroup":"*", "group": "*", "nonResourcePath":"*"}}
tke-auth-api.toml: |
[secure_serving]
tls_cert_file = "/app/certs/tke-auth-api/tls.crt"
Expand Down
11 changes: 10 additions & 1 deletion cmd/tke-auth-api/app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer"
genericapiserver "k8s.io/apiserver/pkg/server"
serverstorage "k8s.io/apiserver/pkg/server/storage"
k8sinformers "k8s.io/client-go/informers"

authapi "tkestack.io/tke/api/auth"
authinternalclient "tkestack.io/tke/api/client/clientset/internalversion/typed/auth/internalversion"
Expand All @@ -70,6 +71,7 @@ import (
"tkestack.io/tke/pkg/auth/authorization/aggregation"
dexutil "tkestack.io/tke/pkg/auth/util/dex"
casbinlogger "tkestack.io/tke/pkg/auth/util/logger"
"tkestack.io/tke/pkg/util/apiclient"
"tkestack.io/tke/pkg/util/log"
"tkestack.io/tke/pkg/util/log/dex"
)
Expand All @@ -85,6 +87,7 @@ type Config struct {
OIDCExternalAddress string
GenericAPIServerConfig *genericapiserver.Config
VersionedSharedInformerFactory versionedinformers.SharedInformerFactory
K8sSharedInformerFactory k8sinformers.SharedInformerFactory
StorageFactory *serverstorage.DefaultStorageFactory

DexConfig *dexserver.Config
Expand Down Expand Up @@ -145,6 +148,11 @@ func CreateConfigFromOptions(serverName string, opts *options.Options) (*Config,
}
versionedInformers := versionedinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)

k8sClient, err := apiclient.BuildKubeClient()
if err != nil {
return nil, fmt.Errorf("failed to create real external clientset: %v", err)
}
k8sInformers := k8sinformers.NewSharedInformerFactory(k8sClient, 1*time.Minute)
enforcer, err := setupCasbinEnforcer(opts.Authorization)
if err != nil {
return nil, err
Expand All @@ -161,7 +169,7 @@ func CreateConfigFromOptions(serverName string, opts *options.Options) (*Config,
return nil, err
}

aggregateAuthz, err := aggregation.NewAuthorizer(authClient, opts.Authorization, opts.Auth, enforcer, opts.Authentication.PrivilegedUsername)
aggregateAuthz, err := aggregation.NewAuthorizer(authClient, opts.Authorization, opts.Auth, enforcer, opts.Authentication.PrivilegedUsername, k8sInformers)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -200,6 +208,7 @@ func CreateConfigFromOptions(serverName string, opts *options.Options) (*Config,
GenericAPIServerConfig: genericAPIServerConfig,
StorageFactory: storageFactory,
VersionedSharedInformerFactory: versionedInformers,
K8sSharedInformerFactory: k8sInformers,
DexConfig: dexConfig,
DexStorage: dexConfig.Storage,
CasbinEnforcer: enforcer,
Expand Down
1 change: 1 addition & 0 deletions cmd/tke-auth-api/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func CreateServerChain(cfg *config.Config) (*genericapiserver.GenericAPIServer,

apiServer.GenericAPIServer.AddPostStartHookOrDie("start-auth-api-server-informers", func(context genericapiserver.PostStartHookContext) error {
cfg.VersionedSharedInformerFactory.Start(context.StopCh)
cfg.K8sSharedInformerFactory.Start(context.StopCh)
return nil
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: tke-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: default
namespace: tke
---
kind: Service
apiVersion: v1
metadata:
Expand Down Expand Up @@ -86,7 +103,8 @@ metadata:
namespace: tke
data:
abac-policy.json: |
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"system:*","namespace":"*", "resource":"*","apiGroup":"*", "group": "*", "nonResourcePath":"*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"system:kube-*|system:serviceaccount:kube-system:*","namespace":"*", "resource":"*","apiGroup":"*tkestack.io", "group": "*", "nonResourcePath":"*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"^system:serviceaccount:tke:default$","namespace":"*", "resource":"*","apiGroup":"*", "group": "*", "nonResourcePath":"*"}}
tke-auth-api.toml: |
[secure_serving]
tls_cert_file = "/app/certs/server.crt"
Expand Down
134 changes: 134 additions & 0 deletions docs/design-proposals/Auth RBAC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Auth RBAC


**Author**:
jason ([@wangao1236](https://github.com/wangao1236))
mingyu ([@metang326](https://github.com/metang326))


## Abstract

目前tke不支持k8s原生的rbac鉴权模式,无法通过创建ClusterRoleBinding、ClusterRole设置clusters、clustercredentials等资源的访问权限。


## Motivation

- 支持k8s原生的rbac鉴权

## Main proposal

增加一种鉴权方式,如果rbac鉴权通过则允许访问相应资源。

## Solution
1. 创建ClusterRoleBindings,将tke命名空间下的ServiceAccount(name:default)与ClusterRole(name:cluster-admin)进行绑定,使default能获得访问所有资源的权限。
2. 增加k8sinformers,对Roles、RoleBindings、ClusterRoles、ClusterRoleBindings进行watch。
3. 增加rbacAuthorizer,根据rbac进行鉴权,如有相应权限则Allowed为true
4. 由于ServiceAccount本身没有租户信息,会因为tenantID为空导致访问某些资源时会提示invalid tenantID,未进行鉴权就返回了。目前解决方法是对ServiceAccount命名时用后缀标记租户,例如-tenant-default,在代码中会对形如"system:serviceaccount:xx:xxx-tenant-xxx"的username进行解析。

## Test
### step 0
在tmy这个命名空间下创建一个名为rbac-tenant-default的sa用于测试,其基本信息如下:
```
# kubectl get sa -ntmy rbac -oyaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbac-tenant-default
namespace: tmy
secrets:
- name: rbac-token-5ljnn
```
获取其对应的secret后生成一个kubeconfig文件,用于后续的测试。
```
kubectl get secret -ntmy rbac-token-5ljnn -oyaml
echo -n "xxx" | base64 -d
cp ~/.kube/config test.config
vim test.config
```
test.config内容如下,其中token是上面执行echo -n "xxx" | base64 -d的结果。
```
apiVersion: v1
clusters:
- cluster:
insecure-skip-tls-verify: true
server: https://127.0.0.1:6443
name: default-cluster
contexts:
- context:
cluster: default-cluster
user: default-user
name: default-context
current-context: default-context
kind: Config
preferences: {}
users:
- name: default-user
user:
token: xxxx
```
创建clusterrole和clusterrolebinding,允许rbac对clusters进行get、list。
```
# kubectl get clusterrole cls-role -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cls-role
rules:
- apiGroups:
- '*'
resources:
- clusters
verbs:
- get
- list
# kubectl get clusterrolebinding cls-bind -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cls-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cls-role
subjects:
- kind: ServiceAccount
name: rbac-tenant-default
namespace: tmy
```

# step 1
使用rbac的kubeconfig文件执行kubectl命令,clusters资源被授权因此可以访问;clustercredentials资源未被授权,因此不能访问。
```
# kubectl get clusters --kubeconfig=test.config
NAME CREATED AT
cls-mmxx4mkr 2021-04-22T03:29:24Z
global 2021-02-23T06:49:58Z
# kubectl get clustercredentials --kubeconfig=test.config
Error from server (Forbidden): clustercredentials.platform.tkestack.io is forbidden: User "system:serviceaccount:tmy:rbac-tenant-default" cannot list resource "clustercredentials" in API group "platform.tkestack.io" at the cluster scope: permission for list on clustercredentials not verify
```

# step 2
通过kubectl edit clusterrole cls-role增加对clustercredentials的访问权限,修改后如下:
```
# kubectl get clusterrole cls-role -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cls-role
rules:
- apiGroups:
- '*'
resources:
- clusters
- clustercredentials
verbs:
- get
- list
```
增加权限后,可访问clustercredentials资源。
```
# kubectl get clustercredentials --kubeconfig=test.config
NAME CREATED AT
cc-global 2021-02-23T06:49:58Z
cc-xsvfnrng 2021-04-22T03:29:24Z
```
21 changes: 21 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,27 @@ replace (
github.com/deislabs/oras => github.com/deislabs/oras v0.8.0
google.golang.org/grpc => google.golang.org/grpc v1.26.0
helm.sh/helm/v3 => helm.sh/helm/v3 v3.2.0
k8s.io/api => k8s.io/api v0.18.2
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.18.2
k8s.io/apimachinery => k8s.io/apimachinery v0.18.2
k8s.io/apiserver => k8s.io/apiserver v0.18.2
k8s.io/cli-runtime => k8s.io/cli-runtime v0.18.2
k8s.io/client-go => k8s.io/client-go v0.18.2
k8s.io/cloud-provider => k8s.io/cloud-provider v0.18.2
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.18.2
k8s.io/code-generator => k8s.io/code-generator v0.18.2
k8s.io/component-base => k8s.io/component-base v0.18.2
k8s.io/cri-api => k8s.io/cri-api v0.18.2
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.18.2
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.18.2
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.18.2
k8s.io/kube-proxy => k8s.io/kube-proxy v0.18.2
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.18.2
k8s.io/kubectl => k8s.io/kubectl v0.18.2
k8s.io/kubelet => k8s.io/kubelet v0.18.2
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.18.2
k8s.io/metrics => k8s.io/metrics v0.18.2
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.18.2
)

require (
Expand Down Expand Up @@ -98,6 +118,7 @@ require (
k8s.io/kube-aggregator v0.18.2
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
k8s.io/kubectl v0.18.2
k8s.io/kubernetes v1.18.2
k8s.io/metrics v0.18.2
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89
rsc.io/letsencrypt v0.0.3 // indirect
Expand Down
Loading

0 comments on commit ab38745

Please sign in to comment.