はじめに
OpenShift Originを最近触っています。
各種チュートリアルでは新しいProject(≒K8sのNamespace)を作成しているのですが
「そもそも人によってProjectの作成を制限するにはどうすれば良いのか」と疑問が浮かんだので権限周りを調べました。
- デフォルトのユーザーはなにができるのか
- なぜそれができるのか
を軸に調べていきます。
※デフォルトユーザーは「クラスタ管理者が、明示的に権限を与えていないユーザー」とします
※ClusterRole/ClusterRoleBindingのあたりの説明は行いません。一番下にリンクがありますのでそちらからどうぞ。
環境
OpenShift Origin 3.9
(ユーザー周りはLDAP連携等いろいろありますが、今回はhtpasswdで簡単にすませました)
なにができるか
権限の確認
早速適当なユーザーを作成し、何ができるかを確認してみます。
自分がどのような操作が可能なのかは、oc auth can-i --list
で確認できます。
(Command "can-i" is deprecated, use 'oc auth can-i'
というメッセージが出てくるのですが、oc auth can-i
の方には--listがなさそうです。誰か一覧を出す方法を教えてください。)
VERBS NON-RESOURCE URLS RESOURCE NAMES API GROUPS RESOURCES
[get] [/] [] [] []
[get] [/] [] [] []
[get] [/] [] [] []
[get] [/.well-known] [] [] []
[get] [/.well-known] [] [] []
[get] [/.well-known] [] [] []
[get] [/.well-known/*] [] [] []
[get] [/.well-known/*] [] [] []
[get] [/.well-known/*] [] [] []
[get] [/api] [] [] []
[get] [/api] [] [] []
[get] [/api] [] [] []
[get] [/api/*] [] [] []
[get] [/api/*] [] [] []
[get] [/api/*] [] [] []
[get] [/apis] [] [] []
[get] [/apis] [] [] []
[get] [/apis] [] [] []
[get] [/apis/*] [] [] []
[get] [/apis/*] [] [] []
[get] [/apis/*] [] [] []
[get] [/healthz] [] [] []
[get] [/healthz/*] [] [] []
[get] [/oapi] [] [] []
[get] [/oapi] [] [] []
[get] [/oapi] [] [] []
[get] [/oapi/*] [] [] []
[get] [/oapi/*] [] [] []
[get] [/oapi/*] [] [] []
[get] [/osapi] [] [] []
[get] [/osapi] [] [] []
[get] [/osapi] [] [] []
[get] [/osapi/] [] [] []
[get] [/osapi/] [] [] []
[get] [/osapi/] [] [] []
[get] [/swagger-2.0.0.pb-v1] [] [] []
[get] [/swagger-2.0.0.pb-v1] [] [] []
[get] [/swagger-2.0.0.pb-v1] [] [] []
[get] [/swagger.json] [] [] []
[get] [/swagger.json] [] [] []
[get] [/swagger.json] [] [] []
[get] [/swaggerapi] [] [] []
[get] [/swaggerapi] [] [] []
[get] [/swaggerapi] [] [] []
[get] [/swaggerapi/*] [] [] []
[get] [/swaggerapi/*] [] [] []
[get] [/swaggerapi/*] [] [] []
[get] [/version] [] [] []
[get] [/version] [] [] []
[get] [/version] [] [] []
[get] [/version/*] [] [] []
[get] [/version/*] [] [] []
[get] [/version/*] [] [] []
[create get] [] [] [] [buildconfigs/webhooks]
[create get] [] [] [build.openshift.io] [buildconfigs/webhooks]
[create] [] [] [] [builds/docker]
[create] [] [] [build.openshift.io] [builds/docker]
[create] [] [] [] [builds/jenkinspipeline]
[create] [] [] [build.openshift.io] [builds/jenkinspipeline]
[create] [] [] [] [builds/optimizeddocker]
[create] [] [] [build.openshift.io] [builds/optimizeddocker]
[create] [] [] [] [builds/source]
[create] [] [] [build.openshift.io] [builds/source]
[get list] [] [] [] [clusterroles]
[get list] [] [] [authorization.openshift.io] [clusterroles]
[get list watch] [] [] [rbac.authorization.k8s.io] [clusterroles]
[get list watch] [] [] [servicecatalog.k8s.io] [clusterserviceclasses]
[get list watch] [] [] [servicecatalog.k8s.io] [clusterserviceplans]
[delete] [] [] [] [oauthaccesstokens]
[delete] [] [] [oauth.openshift.io] [oauthaccesstokens]
[delete] [] [] [] [oauthauthorizetokens]
[delete] [] [] [oauth.openshift.io] [oauthauthorizetokens]
[create list] [] [] [] [projectrequests]
[create list] [] [] [project.openshift.io] [projectrequests]
[list watch] [] [] [] [projects]
[list watch] [] [] [project.openshift.io] [projects]
[create] [] [] [authorization.k8s.io] [selfsubjectaccessreviews]
[create] [] [] [] [selfsubjectrulesreviews]
[create] [] [] [authorization.k8s.io] [selfsubjectrulesreviews]
[create] [] [] [authorization.openshift.io] [selfsubjectrulesreviews]
[get list] [] [] [storage.k8s.io] [storageclasses]
[impersonate] [] [] [authentication.k8s.io] [userextras/scopes.authorization.openshift.io]
[get] [] [~] [] [users]
[get] [] [~] [user.openshift.io] [users]
なにやら大量に出てきましたが、明示的に権限を付与せずともある程度の操作は可能なようです。
今回はRESOUCESに絞ってみていきたいと思います。
表にすると下記のような形に。(○は権限あり)
API GROUPS | RESOURCES | get | list | watch | create | delete | impersonate |
---|---|---|---|---|---|---|---|
buildconfigs/webhooks | ○ | ○ | |||||
build.openshift.io | buildconfigs/webhooks | ○ | ○ | ||||
builds/docker | ○ | ||||||
build.openshift.io | builds/docker | ○ | |||||
builds/jenkinspipeline | ○ | ||||||
build.openshift.io | builds/jenkinspipeline | ○ | |||||
builds/optimizeddocker | ○ | ||||||
build.openshift.io | builds/optimizeddocker | ○ | |||||
builds/source | ○ | ||||||
build.openshift.io | builds/source | ○ | |||||
clusterroles | ○ | ○ | |||||
authorization.openshift.io | clusterroles | ○ | ○ | ||||
rbac.authorization.k8s.io | clusterroles | ○ | ○ | ○ | |||
servicecatalog.k8s.io | clusterserviceclasses | ○ | ○ | ○ | |||
servicecatalog.k8s.io | clusterserviceplans | ○ | ○ | ○ | |||
oauthaccesstokens | ○ | ||||||
oauth.openshift.io | oauthaccesstokens | ○ | |||||
oauthauthorizetokens | ○ | ||||||
oauth.openshift.io | oauthauthorizetokens | ○ | |||||
projectrequests | ○ | ○ | |||||
project.openshift.io | projectrequests | ○ | ○ | ||||
projects | ○ | ○ | |||||
project.openshift.io | projects | ○ | ○ | ||||
authorization.k8s.io | selfsubjectaccessreviews | ○ | |||||
selfsubjectrulesreviews | ○ | ||||||
authorization.k8s.io | selfsubjectrulesreviews | ○ | |||||
authorization.openshift.io | selfsubjectrulesreviews | ○ | |||||
storage.k8s.io | storageclasses | ○ | ○ | ||||
authentication.k8s.io | userextras/scopes.authorization.openshift.io | ○ | |||||
users | ○ | ||||||
user.openshift.io | users | ○ |
※users
はget可能になっていますが、ResouceNamesに[~]
とあるように、自分自身の情報しか取得できません。
※他にもVerbはあるのですが、いったん出てきたものだけあげています。
OpenShift(Kubernetes)お馴染みのPodなどのリソースが表示されていないので、この状態では参照もできません。
ポイントとなるのはProjectRequests
がCreate
になっている点です。
このおかげでユーザーはProjectを作成することができます。
「なにができるのか」は上の表で概要はつかめるので、「なぜできるのか」を追っていきます。
なぜできるのか
ClusterRoleBindingの確認
上記をみる限り、自動でなにかしらのClusterRoleがBindingされているようなのでoc get clusterrolebinding.rbac -o wide
で確認してみます。
Error from server (Forbidden): clusterrolebindings.rbac.authorization.k8s.io is forbidden: User "[ユーザ名]" cannot list clusterrolebindings.rbac.authorization.k8s.io at the cluster scope: User "[ユーザ名]" cannot list all clusterrolebindings.rbac.authorization.k8s.io in the cluster
おっと、デフォルトのユーザーのままだったので上記のようなエラーが出てしまいました。
表を見る限りClusterRoleの参照はできますが、ClusterRoleBindingの参照は(can-iで確認した通り)できません。
oc login -u [ユーザ名]
で参照可能なユーザに変更し、再度コマンドを実行します。
NAME AGE ROLE USERS GROUPS SERVICEACCOUNTS
admin 6h ClusterRole/admin openshift-infra/template-instance-controller
...
たくさん情報が表示されると思いますが、USERS
のところには作成したユーザー名は表示されていませんでした。
その代わり、GROUPS
欄にいくつかグループが表示されているのがわかると思います。
ざっくりした予想ですが、
- ユーザーが自動的に属するグループがある
- そのグループに対してClusterRoleがBindingされている
となっていそうです。
仮想グループ
OpenShiftでは、明示的に指定したグループのほかにも、仮想グループというものが自動的にプロビジョニングされ、ユーザに適用されます。
仮想グループ | 説明 |
---|---|
system:authenticated | 認証されたすべてのユーザーに自動的に関連付けられます。 |
system:authenticated:oauth | OAuthアクセストークンで認証されたすべてのユーザーに自動的に関連付けられます。 |
system:unauthenticated | 認証されていないすべてのユーザーに自動的に関連付けられます。 |
今回は認証済みユーザについて調査しているので、system:authenticated
とsystem:authenticated:oauth
関連をみていけばわかりそうです。
先ほどのClusterRoleBinding
の出力でGROUPS
にsystem:authenticated
またはsystem:authenticated:oauth
があるものを抜き出してみます。
ClusterRoleBinding | ClusterRole | GROUPS |
---|---|---|
basic-users | basic-user | system:authenticated |
cluster-status-binding | cluster-status | system:authenticated |
self-access-reviewers | self-access-reviewer | system:authenticated |
self-provisioners | self-provisioner | system:authenticated:oauth |
servicecatalog-serviceclass-viewer-binding | servicecatalog-serviceclass-viewer | system:authenticated |
system:basic-user | system:basic-user | system:authenticated |
system:build-strategy-docker-binding | system:build-strategy-docker | system:authenticated |
system:build-strategy-jenkinspipeline-binding | system:build-strategy-jenkinspipeline | system:authenticated |
system:build-strategy-source-binding | system:build-strategy-source | system:authenticated |
system:discovery | system:discovery | system:authenticated |
system:discovery-binding | system:discovery | system:authenticated |
system:oauth-token-deleters | system:oauth-token-deleter | system:authenticated |
system:scope-impersonation | system:scope-impersonation | system:authenticated |
system:webhooks | system:webhook | system:authenticated |
ClusterRole
を確認していけば、どのようなResourceにどのようなVerbが許可されているのかわかります。
oc describe clusterrole.rbac [ClusterRole名]
で確認し、権限の表に「どのClusterRoleが権限を担っているのか」を追加してみます。
API GROUPS | RESOURCES | get | list | watch | create | delete | impersonate | ClusterRole |
---|---|---|---|---|---|---|---|---|
buildconfigs/webhooks | ○ | ○ | system:webhook | |||||
build.openshift.io | buildconfigs/webhooks | ○ | ○ | system:webhook | ||||
builds/docker | ○ | system:build-strategy-jenkinspipeline | ||||||
build.openshift.io | builds/docker | ○ | system:build-strategy-jenkinspipeline | |||||
builds/jenkinspipeline | ○ | system:build-strategy-jenkinspipeline | ||||||
build.openshift.io | builds/jenkinspipeline | ○ | system:build-strategy-jenkinspipeline | |||||
builds/optimizeddocker | ○ | system:build-strategy-jenkinspipeline | ||||||
build.openshift.io | builds/optimizeddocker | ○ | system:build-strategy-jenkinspipeline | |||||
builds/source | ○ | system:build-strategy-source | ||||||
build.openshift.io | builds/source | ○ | system:build-strategy-source | |||||
clusterroles | ○ | ○ | basic-user | |||||
authorization.openshift.io | clusterroles | ○ | ○ | basic-user | ||||
rbac.authorization.k8s.io | clusterroles | ○ | ○ | ○ | basic-user | |||
servicecatalog.k8s.io | clusterserviceclasses | ○ | ○ | ○ | servicecatalog-serviceclass-viewer | |||
servicecatalog.k8s.io | clusterserviceplans | ○ | ○ | ○ | servicecatalog-serviceclass-viewer | |||
oauthaccesstokens | ○ | system:oauth-token-deleter | ||||||
oauth.openshift.io | oauthaccesstokens | ○ | system:oauth-token-deleter | |||||
oauthauthorizetokens | ○ | system:oauth-token-deleter | ||||||
oauth.openshift.io | oauthauthorizetokens | ○ | system:oauth-token-deleter | |||||
projectrequests | ○ | ○ | basic-user(list), self-provisioner(create) | |||||
project.openshift.io | projectrequests | ○ | ○ | basic-user(list), self-provisioner(create) | ||||
projects | ○ | ○ | basic-user | |||||
project.openshift.io | projects | ○ | ○ | basic-user | ||||
authorization.k8s.io | selfsubjectaccessreviews | ○ | system:basic-user | |||||
selfsubjectrulesreviews | ○ | basic-user | ||||||
authorization.k8s.io | selfsubjectrulesreviews | ○ | system:basic-user | |||||
authorization.openshift.io | selfsubjectrulesreviews | ○ | basic-user | |||||
storage.k8s.io | storageclasses | ○ | ○ | basic-user | ||||
authentication.k8s.io | userextras/scopes.authorization.openshift.io | ○ | system:scope-impersonation | |||||
users | ○ | basic-user | ||||||
user.openshift.io | users | ○ | basic-user |
※ClusterStatus
、system:discovery
はNon-Resource URLs関連のため、上記表には登場せず。
きれいに埋まりました。
まとめ
-
デフォルトのユーザーはなにができるのか
表を参照 -
なぜそれができるのか
ユーザーは自動的にOpenShiftの仮想グループに属しており、
その仮想グループにClusterRoleがBindingされているから。
さらなる疑問-TODO
「デフォルトユーザのままだと結局Podが作れない?」
「チュートリアルだとPodとかService作れるけど、どこかで権限が付与されている?」
Projectの作成時、Projectローカルなadmin権限が割り当てられてるような気がしています。
「can-iではProjectにlist可と書いてあるのに、defaultやkube-publicが見えない」
自分もよくわかりません。誰か教えてください...。
なにかKubernetesの基本的なところを見落としている気がします。
「どのResouceがなにをあらわしているのか。実際に運用するときに制限を検討した方がいいResourceは?」
Resourceは有名なものしかよくわかりません...どれを制限すべきかは難しいところです。
「クラスタ管理用、プロジェクト管理用、参照用みたいなClusterRoleプリセットはある?」
公式でいくつか用意されています。
ARCHITECTURE 4.2.4. Cluster Roles and Local Roles
ClusterRole | 説明 |
---|---|
admin | プロジェクトマネージャーです。ローカルバインディングで使用されている場合、admin ユーザーにはプロジェクトのリソースを閲覧し、クォータを除くプロジェクトのすべてのリソースを変更する権限があります。 |
basic-user | プロジェクトおよびユーザーについての基本的な情報を取得できるユーザーです。 |
cluster-admin | プロジェクトですべてのアクションを実行できるスーパーユーザーです。ローカルバインディングでユーザーにバインドされる場合、クォータおよびプロジェクトのすべてのリソースに対するすべてのアクションに対するフルコントロールがあります。 |
cluster-status | 基本的なクラスターのステータス情報を取得できるユーザーです。 |
edit | プロジェクトのほとんどのオブジェクトを変更できるが、ロールまたはバインディングを表示したり、変更したりする機能を持たないユーザーです。 |
self-provisioner | 独自のプロジェクトを作成できるユーザーです。 |
view | 変更はできないが、プロジェクトでほとんどのオブジェクトを確認できるユーザーです。これらのユーザーはロールまたはバインディングを表示したり、変更したりできません。 |
「○○のcreateを"拒否"したい」
「どれを許可するか」が考え方のベースのはずなので、既につけられている権限をなにかしらで拒否するというのはできないような気がします。
「独自のClusterRoleを作りたい」
参考の「How to customize OpenShift RBAC permissions」をどうぞ。
「K8sとの違いはある?」
調べていませんが、多分そんなに違いはないと思いたいです...。
参考
非常に勉強になった記事。必読。
OpenShiftのRBACを完全に理解する - nekop's blog
How to customize OpenShift RBAC permissions - RedHat Developer Blog
おまけ
「Projectの作成を制限したい」というのは公式ドキュメントで方法が紹介されています。
https://docs.openshift.com/container-platform/3.9/admin_guide/managing_projects.html
oc adm policy remove-cluster-role-from-group self-provisioner system:authenticated:oauth
system:authenticated:oauth
仮想グループからself-provisionerのRoleを削除しています。
(ちょっと乱暴な気も...「クラスタを更新したら元に戻ってた」とかありそう)