理解OpenShift(4):用戶及權限管理

理解OpenShift(1):網絡之 Router 和 Routehtml

理解OpenShift(2):網絡之 DNS(域名服務)node

理解OpenShift(3):網絡之 SDNgit

理解OpenShift(4):用戶及權限管理github

理解OpenShift(5):從 Docker Volume 到 OpenShift Persistent Volume微信

 

** 本文基於 OpenShift 3.11,Kubernetes 1.11 進行測試 ***網絡

 

OpenShift 支持 RBAC(Role Based Access Controll),基於角色的訪問控制。它涉及諸多概念,本文嘗試着作一些概念上的梳理,不少細節還須要進一步研究。app

1. 主要概念及其之間的聯繫

1.1 用戶(User)

我試着把一個OpenShift 環境中的全部用戶分爲三大類:ide

  • 應用用戶:部署在集羣之中的應用本身的用戶。通常來講每一個應用都有本身的用戶管理系統,與平臺無關。也有一些應用,好比 Jenkins,支持與OpenShift 用戶系統集成,也就是Jenkins容許用戶在經過了OpenShift 用戶認證後對其進行訪問。這部分不是本文的討論範圍以內。
  • OpenShift 用戶:訪問OpenShift 資源的用戶。根據其特徵,又將其分爲三個子類:
    • Regular user:表明一個天然人用戶,好比部署應用的一個開發者。
    • System user:OpenShift 系統用戶,大部分在集羣建立時被自動建立,好比每一個node都有一個system user。由於這部分主要和OpenShift自身系統相關,與通常用戶關係不太大,所以本文不會具體介紹這部分。
    • Service account:服務帳戶。這是跟一個項目關聯的特殊系統用戶,每一個用戶被一個 ServiceAccount 對象表示,一般是指 pod 中運行主進程的用戶。後文會有具體介紹。
  • 操做系統用戶:訪問操做系統資源的用戶,又分爲容器內的操做系統用戶,和宿主機上的操做系統用戶。

1.2 身份(Identity)與認證(Authentication)

認證是確認用戶身份是否合法的過程。這能夠有多種實現方式,好比用戶名/密碼、令牌(token)、證書等。不一樣類型的用戶有不一樣的身份管理方式:post

  • 對於 regular user,每一個用戶有一個身份(identity)用於認證。OpenShift  以插件形式支持多種 identity provider,好比在測試環境中經常使用的 htpasswd,生產環境中經常使用的 LDAP 等。這些 provider 中會保存用戶身份信息,好比用戶名和密碼。useridentitymapping 對象將 user 對象和 identity 對象聯繫在一塊兒。
  • 對於 service account,一方面它須要訪問 OpenShift 集羣資源好比 API 和內部鏡像倉庫中的鏡像,另外一方面它可能須要訪問 pod 中和宿主機上的操做系統資源,好比宿主機上的文件或網絡。對於前者,每一個 service account 使用 secret 來進行身份認證,包括用戶 API 訪問的 token 和用於從鏡像倉庫拉取代碼的 secret。對於後者,原本有 user namespace(用戶命名空間)來支持,可是彷佛OpenShift 還不支持該功能。

1.3 角色(Role)/權限(Permission)與受權(Authorization)

受權是對被認證了的用戶訪問受控制的資源的權限進行控制。按照資源類型,OpenShift 將受權管理方式分爲兩大類:測試

  • 對於 OpenShift 集羣資源,好比 pod,deployment,route 等,經過 role (角色)進行控制。從範圍(scope)上分,role 可分爲集羣角色(clusterRole)和項目角色(role)。每一個角色定義了受控制的對象(subject)、容許的操做(verb)和範圍(集羣仍是項目)。用戶(user)和角色(role/clusterRole)之間經過 rolebinding/clusterrolebinding 對象進行綁定。
  • 對於操做系統資源,這隻針對服務帳戶。宿主機上的用戶訪問宿主機上的資源,這由宿主機操做系統進行控制。pod 中的用戶(serviceaccount)訪問pod內和宿主機上操做系統資源,由 scc(security context constraints)進行控制。

2. 身份 (Identity) 與認證(Authentication)

就像人的身份證同樣,identity 是一個 user 的身份信息,該信息用於用戶認證。OpenShift 本身並無實現用戶身份信息庫,而是經過靈活支持多種 identity provider,來實現各類不一樣的身份管理方案。每種實現都以不一樣的方式保存着用戶的身份信息,好比保存在LDAP 中,保存在  htpasswd 文件中,保存在 OpenStack Keystone 中。

 

所以,OpenShift 對 user 身份的校驗是經過這些配置了的 identity provider 進行的。所以,還須要 OpenShift user 和這些 provider 裏面的 identity 的映射關係。OpenShfit 支持四種映射管理,claim,lookup,generate,add。具體請參考官網 https://docs.openshift.com/container-platform/3.11/install_config/configuring_authentication.html#identity-providers_parameters

上圖中以 htpasswd 這種 identity provider 爲例,說明了從零建立一個 openshift user,在 htpasswd 中建立 user 及其密碼,而後建立 openshift identity 對象以及 useridentitymapping 對象的過程。

用戶獲取用於身份認證的token的過程:

  • 全部申請 OAuth token 的請求都要發到 <master>/oauth/authorize和<master>/oauth/token。每一個申請 OAuth token 的請求中都必須帶有 OAuth client 標識,這是一個 OAuthClient  對象。具體請參閱官方文檔。
  • OpenShift master 節點上內置有一個 OAuth server。用戶從 OAuth 獲取 token 後再用它去訪問 API 就能夠認證經過了。當一個 user 申請一個 OAuth token 時,OAuth 使用配置的 identity provider 去肯定該申請用戶的身份。它在肯定該用戶所映射到的 identity後,會爲該用戶建立一個 token,而後返回該token。

3. 角色(Role)和受權(Authorization)

前文說了,角色用於控制對 OpenShift 資源的訪問權限,它分爲項目角色和集羣角色。

OpenShift 系統默認會建立不少的集羣角色。經常使用的角色的簡單描述以下: 

admin
  • project manager
  • 若是用於本地 rolebinding,那麼用戶將能查看和修改所在項目中的全部資源
basic-user
  • user 能夠獲取關於項目和用戶的基本信息
cluster-admin
  • 用戶能夠在任何項目中作任何操做(超級用戶)
  • 如何用於本地 rolebinding,那麼用戶將擁有所在project的全部權限,包括控制quota和role
cluster-status
  • 用戶能夠獲取集羣的基本狀態信息
edit
  • 用戶能夠修改項目中的大部分對象;可是不能查看或修改 role 和 rolebinding
self-provisioner
  • 全部用戶的默認role,能夠建立本身的project
view
  • 用戶能夠查看項目中的大部分對象,除了 role 和 rolebinding
  • 用戶不能作任何修改任何對象 

能夠查看全部角色,好比 system:router 角色:

可使用 oc adm policy 命令向用戶或用戶授予角色:

user、group、role、rolebinding 之間的關係:

更多對 role 的說明,可參見官方文檔。 

4. Service Account 用戶

 

OpenShift 的 service account 比較複雜,和不少概念都有關聯。官方文檔在  https://docs.openshift.com/container-platform/3.11/dev_guide/service_accounts.html。該文檔對爲何須要這個概念的說明是:當一個天然人用戶訪問 OpenShfit API 時,OpenShift 對它進行用戶認證和權限控制。可是,有時候作操做的並非天然人用戶,好比:

  • Replication Controller 調用 API 去建立或者刪除 pod
  • 容器中的應用調用 API
  • 外部應用調用 API 去進行監控或者整合

爲了這種訪問,OpenShift 創造了 Service Account (簡稱sa)概念。每一個項目(project)默認都會自動建立3個sa user: 

Service Account Usage

builder

用於 build pod。它被授予了 system:image-builder 角色,所以被容許向內部鏡像倉庫中的任意 image stream 上push 鏡像。

deployer

用於 deployment pod。被授予了 system:deployer 角色,所以被容許查看和修改集羣中的 RC 及其 pod。

default

當一個 pod 沒有顯式指定 service account 默認都會使用該 sa user。

4.1 身份

sa 利用 secret(token)來保存其身份信息。默認狀況下,每一個 sa 用戶都有兩種token,即訪問 OpenShift API 的token和訪問內部鏡像倉庫的token。以系統默認的 『builder』 sa user 爲例,它包含一個用於拉取鏡像的token secret,兩個訪問API 的token secret,三個secret 中只有兩個能被以卷的形式掛接給pod:

能夠按需求修改一個 sa 帳戶的這些token。可參考 https://docs.openshift.com/enterprise/3.0/dev_guide/image_pull_secrets.html 爲service account 建立和添加新的用於拉取鏡像的token secret。具體請參考官方文檔。

其中,sa 的 API token 會被掛接到 pod 的 目錄的 token 文件,從而使得 pod 中的應用能夠讀取該 token 去訪問 OpenShift API:

image pull secret 是如何掛載到 pod 的,我尚未找到。並且在 pod spec 中,只看到 API token secret 的 mountpoint,而並無 imagePullSecret 的 mountpoint:

4.2 權限 - 訪問OpenShift 集羣資源的權限

和天然人 user 相似,對 sa 用戶訪問OpenShift 集羣資源的權限控制是經過 role 進行的。前面的表格代表,項目的兩個默認 sa builder 和 deployer 都被授予了相應的 role,從而能訪問指定的資源。而默認的 sa 用戶,只被授予了 /system:image-puller 角色。這意味着默認的 sa 用戶只能拉取鏡像,而不能訪問集羣其它資源。

下圖是項目 stage 中的 rolebinding:

用戶組 system:serviceaccounts:stage 中包括該項目中的全部 sa 用戶。利用 default sa user 來作下實驗。先獲取其 API token,而後登陸進 OpenShift 集羣:

調用 API 獲取 pod,結果失敗:

向 default sa user 授予 cluster-reader 角色:

而後就能夠作集羣資源查詢操做了。 

4.3 權限 - 訪問系統資源的權限

pod 中的應用除了有訪問 OpenShift API 和內部鏡像倉庫以外,還有一些系統資源訪問要求。好比:

  • 要求以任意用戶甚至是 root 來運行 pod 中的主進程
  • 要求訪問宿主機上的文件系統
  • 要求訪問宿主機上的網絡

對於這些操做系統資源的訪問權限,OpenShift 利用 scc 來進行控制。這就要求:

  • 在 scc 中進行權限控制。這部分在後面介紹。
  • 在 servie account 和 sa 之間創建聯繫。每一個 scc 都有指定使用它的用戶列表。全部經過身份認證了的用戶都只在 restricted 這個 scc 的用戶列表之中,包括 service account。所以,pod 默認使用的是 restricted scc。要使它使用其它的scc,就要將它的 service account user 加入到要使用的 scc 的用戶列表之中。這在 scc 部分具體介紹。

5. Security Context Constraint(SCC)

前面說過,SCC 用於控制訪問系統資源的權限,那說明只有  service account  才須要使用 scc。沒在文檔中看到天然人用戶 user 使用 scc 的例子。

Linux 中的權限控制非常複雜,這裏就不說明了,我本身也沒怎麼弄清楚。OpenShift scc 將系統權限分爲幾大類,具體見上圖中的『權限』部分,而後能夠建立 scc 對象來精細地控制對每種權限的控制。

5.1 OpenShift默認的 scc

由於這很是繁瑣,所以 OpenShift 默認建立了幾個典型的 scc,列表以下。上圖中的『系統預約義scc』部分有簡要說明,這裏再也不重複。

其中,若是 pod 所使用的 scc 的 runAsUser 策略被設置爲了 MustRunAsRange,那麼 pod 所使用的 uid 和 supplemental-group id 必須在某區間以內。

集羣管理員能夠在 scc 中設置區間,好比:

可是,OpenShift 默認提供的 scc 都沒有設置該區間,而是使用 pod 所在的 project 中定義的區間以內。好比:

[root@master2 cloud-user]# oc describe project dev
Name:                   dev
Created:                3 weeks ago
Labels:                 <none>
Annotations:            openshift.io/description=
                        openshift.io/display-name=
                        openshift.io/requester=demo
                        openshift.io/sa.scc.mcs=s0:c16,c0
                        openshift.io/sa.scc.supplemental-groups=1000000000/10000
                        openshift.io/sa.scc.uid-range=1000000000/10000

每一個 project 會被分配不一樣的 ID 區間。當未指定 uid 和 supplemental gid 時,會默認使用區間的最小值。

每一個 pod 中,運行主進程的用戶都有三個屬性:

  • uid 即 user id,上面例子中uid 爲 100000000,使用的是 project 定義的 uid 區間的第一個值。其策略分爲三種:
    • MustRunAs - 須要配置一個區間,要麼在 project 中配置,要麼在 scc 中指定。默認使用區間的第一個值。指定特定值的話,會檢查是否在該區間內。
    • MustRunAsNonRoot - 要求指定非 root user id,不提供默認值。
    • RunAsAny - 容許全部用戶,不提供默認值。
  • gid 即用戶的primary group id(主組ID)。上面例子中 gid 爲 0,組名字爲 root。從 https://github.com/kubernetes/enhancements/issues/213 上看,目前 Kubernetes 還不支持設置 gid,其值固定爲 0.
  • fsGroup 定義 pod 的 文件系統 group ID,用於塊存儲,好比 Ceph RDB 和 iSCSI。supplementalGroups ID 用於共享存儲,也是組/group ID 的一種,用於共享存儲,好比 NFS 和 GlusterFS。上面例子中的 supplementalGroup ID 爲 10000000,取的也是默認值。這兩種 group ID 支持 MustRunAs 和 RunAsAny 兩種策略。會在下一篇存儲部分詳細介紹。

備註:Supplemental group(附加組)也是Linux 組的一種。當一個進程運行在 Linux 中時,它會擁有一個 UID,一個 GID,以及一個或多個附加組ID。具體請查閱Linux 相關文檔。

若是某 scc 設置的 RunAsUser 策略爲 MustRunAsRange,它會要求配置合法的 uid 區間(要麼在 project 中配置,要麼在 scc 中指定)。若是你要指定特定的 uid ,你能夠在 pod 定義 yaml 中使用 securityContext: runAsUser <uid> 來指定特定的 user id,可是該 id 必須在區間以內。不然會報錯:

Error from server (Forbidden): error when creating "testcontainervolume-restricted.yaml": pods "test-pod-volume-restricted2" is forbidden: unable to validate against any security context constraint: [spec.containers[0].securityContext.securityContext.runAsUser: Invalid value: 65534: must be in the ranges: [1000000000, 1000009999]]

5.2 容器使用的默認 scc

根據建立 pod 的用戶不一樣,pod 使用不一樣的默認 scc:

  • 非 cluster admin 角色的 openshift 用戶建立的沒有顯式指定 service account 和 scc 的 pod,其默認使用的 sa user 爲 default,默認使用的 scc 爲 restricted。
  • cluster admin 用戶,根據 scc 優先級,anyuid 將是這種 pod 默認使用的 scc。

SCC 優先級:一個 sa user 能夠被加到多的 scc 當中。當一個 service account user 有多個 SCC 可用時,其 scc 按照下面的規則排序

  • 最高優先級的scc排在最前面。默認地,對於 cluster admin 角色的用戶的 pod,anyuid scc 會被授予最高優先級,排在最前面。這會容許集羣管理員可以以任意 user 運行 pod,而不須要指定 pod 的 SecurityContext 中的 RunAsUser 字段。
  • 若是優先級相同,scc 將從限制最高的向限制最少的順序排序。
  • 若是優先級和限制都同樣,那麼將按照名字排序。

每一個 scc 有其用戶/用戶組列表。以 restricted 爲例,全部經過身份驗證的用戶都在列表中;而 anyuid,只有 cluster-admins 用戶組中的用戶在裏面。

  

5.3 修改容器使用的scc

要受權 pod 有除了 restricted 定義的權限以外的權限,主要有兩種作法:

  • 一是將其 service account 放到目標 scc 的用戶列表中。此時建議建立一個新的 service account,而不要使用已有的,考慮到對現有 pod 的影響。好比由於 registry 和 router 服務的 pod 須要使用 host networkinig 網絡模式,所以有爲它們建立單獨的 sa user 而且加入到了 hostnetwork scc 的用戶列表中。

  • 二是將 service account 加入到目標 scc 的用戶組中。

官方建議採用第一種。一個很經常使用的例子是運行要使用 root 用戶的容器。不少的Docker 鏡像都使用的是 root 用戶。可是,openshift restricted scc 不容許使用 root 用戶,而要使用一個用戶區間內的用戶:

修復步驟:

$ oc create serviceaccount useroot
$ oc adm policy add-scc-to-user anyuid -z useroot
$ oc patch dc/myAppNeedsRoot --patch '{"spec":{"template":{"spec":{"serviceAccountName": "useroot"}}}}'

備註:

  • 第二個語句中的 -z userroot 用於指定當前project 中的 sa user,它和使用 system:serviceaccount:<project>:userroot 效果相同。
  • 在 pod 中設置 service account,其屬性名字爲 serviceAccount,不是 dc 中的 serviceAccount。

說明:

  • 第一步建立名爲 userroot 的 sa user
  • 第二步將該 sa user 加入到 anyuid scc 的 user 列表中
  • 第三步在應用的 DeploymentConfig 中指定 serviceAccountName 爲 userroot

 

感謝您的閱讀,歡迎關注個人微信公衆號:

相關文章
相關標籤/搜索