关于Open Shift(OKD) 中 用户认证、权限管理、SCC 管理的一些笔记

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》

写在前面


  • 因为参加考试,会陆续分享一些 OpenShift 的笔记
  • 博文内容为 openshift 用户认证和权限管理以及scc管理相关笔记
  • 学习环境为 openshift v3 的版本,有些旧
  • 这里如果专门学习 openshift ,建议学习 v4 版本
  • 理解不足小伙伴帮忙指正

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》


用户认证

OpenShift 中有用户和权限的概念 。 用户需要通过登录账号及密码登录 OpenShift 才能访问相应的资源以及执行相关的操作 。 通过用户提供的登录信息确认用户身份的过程即认证的过程。

认证配置

认证相关的配置可以通过下面的文件方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@master master]# cat /etc/origin/master/master-config.yaml | grep -A 25 oauthConfig
oauthConfig:
assetPublicURL: https://master.lab.example.com/console/
grantConfig:
method: auto
identityProviders:
- challenge: true
login: true
mappingMethod: claim
name: htpasswd_auth
provider:
apiVersion: v1
file: /etc/origin/master/htpasswd
kind: HTPasswdPasswordIdentityProvider
masterCA: ca-bundle.crt
masterPublicURL: https://master.lab.example.com
masterURL: https://master.lab.example.com
sessionConfig:
sessionMaxAgeSeconds: 3600
sessionName: ssn
sessionSecretsFile: /etc/origin/master/session-secrets.yaml
tokenConfig:
accessTokenMaxAgeSeconds: 86400
authorizeTokenMaxAgeSeconds: 500
pauseControllers: false
policyConfig:
bootstrapPolicyFile: /etc/origin/master/policy.json
[root@master master]#

通过上面的配置文件,可以看到当前使用的认证方式为 HTPasswdPasswordIdentityProvider,使用 HTPasswd 身份验证插件来实现基于密码的认证。

当前版本为 openshift 3.9 的版本,有些老旧,实际上我们更多的是通 api 资源对象的方式来创建

创建一个包含 HTPasswd 文件的 Secret 对象,然后创建一个包含 HTPasswd 配置的 ConfigMap 对象。最后,我们将 HTPasswd 身份验证提供者添加到 OAuth 对象中,以便用户可以使用用户名和密码进行身份验证。类似下面这样

以下是一个使用 HTPasswd 身份验证插件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: v1
kind: Secret
metadata:
name: htpasswd-secret
data:
htpasswd: <base64-encoded-htpasswd-file>
type: Opaque

---

apiVersion: v1
kind: ConfigMap
metadata:
name: htpasswd-configmap
data:
htpasswd: |
kind: HTPasswdPasswordIdentityProvider
file: /etc/openshift/htpasswd
type: Opaque

---

apiVersion: v1
kind: OAuth
metadata:
name: oauth
spec:
identityProviders:
- name: htpasswd
mappingMethod: claim
type: HTPasswd
htpasswd:
fileData:
name: htpasswd-secret
identityProviderConfig:
name: htpasswd-configmap

我们使用 HTPasswd 身份验证插件来实现基于密码的认证。我们首先创建一个包含 HTPasswd 文件的 Secret 对象,然后创建一个包含 HTPasswd 配置的 ConfigMap 对象。最后,我们将 HTPasswd 身份验证提供者添加到 OAuth 对象中,以便用户可以使用用户名和密码进行身份验证。

了解过 k8s 的小伙伴,会发现,k8s 中并没有 OAuth 这个资源对象,也没有 identityProviders相关的,这是 OKD 所特有的,在OpenShift中,身份提供者(IDP,identityProviders)是一个组件,用于验证用户并向 OpenShift 集群提供身份信息。OpenShift支持各种IDP,包括Htpasswd、LDAP和Keystone。

比如上面的配置,如果您想使用Htpasswd作为您的IDP,您可以按照以下步骤操作:

  1. 使用用户名和密码创建Htpasswd文件。您可以使用htpasswd命令行工具来创建和管理此文件。

  2. 在OpenShift中创建包含Htpasswd文件的secret。您可以使用以下命令创建secret:

1
oc create secret generic htpass-secret --from-file=htpasswd=path/to/htpasswd

此命令创建名为htpass-secret的secret,并将htpasswd文件设置为secret中htpasswd键的值。

  1. 创建引用Htpasswd secret的OAuth自定义资源。这也就是我们在最上面的看到的那个。

认证方式

上面为基于密码的认证,常见的 Openshift 的认证方式有以下几种:

  1. 基于密码的认证:用户使用用户名和密码进行身份验证。
  2. 基于令牌的认证:用户使用令牌进行身份验证。令牌可以是 OAuth 令牌、API 密钥或其他类型的令牌。
  3. 基于证书的认证:用户使用证书进行身份验证。证书可以是客户端证书或服务端证书。

在 Openshift 中,可以使用不同的身份验证插件来实现这些认证方式。例如,可以使用 HTPasswd 身份验证插件来实现基于密码的认证,使用 OAuth 身份验证插件来实现基于令牌的认证,使用 x509 身份验证插件来实现基于证书的认证(管理员即使用的这一种)。

在 Openshift 中,还可以使用 LDAP、Kerberos、GitHub 等外部身份验证提供者来实现身份验证。这些提供者可以与身份验证插件结合使用,以实现不同的身份验证方式。

OpenShift 通过 OAuth 进行用户的认证。 OAuth 是一个开源的认证和授权的框架。 在 OpenShift 的 Master 节点上运行着一个内置的 OAuth 服务对用户的请求进行认证检查。一旦 OAuth 服务器通过登录信息确认了用户的身份, OAuth 服务器就返回用户的访问 token (令牌) 。 通过这个 token 用户可以在有效的时间内对系统进行访问

admin 是集群默认的管理员。前面提到过,该用户是一个特殊的用户,它不能通过用户名密码登录,只提供基于证书的认证,之所以的master 节点 上执行 oc、kubectl 命令,是因为在默认目录下存在 集群的 kubeconfig 文件

1
2
3
4
5
[root@master master]# oc whoami
system:admin
[root@master master]# oc whoami -t
error: no token is currently in use for this session
[root@master master]#

所以它没有 token 的认证方式,直接通过 kubeconfig 文件的方式进行认证

1
2
3
4
5
6
[root@master master]# cat /root/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate
.....

用户与组管理

用户类型

OKD 中存在以下几种用户类型:

  • Regular users:普通用户。
  • System users:OKD 平台自动创建,用于 API 安全访问。系统用户包括集群管理员(具有所有访问权限),routers 和 registries 使用的用户,系统匿名用户(用于非授权的请求)。 示例:system:admin system:openshift-registry system:node:node1.example.com
1
2
3
4
[root@master student]# oc get user
NAME UID FULL NAME IDENTITIES
admin 3300d7da-da70-11ed-a5c3-52540000fa0a htpasswd_auth:admin
liruilong b0cb659b-da74-11ed-a5c3-52540000fa0a htpasswd_auth:liruilong
  • Service accounts:与项目关联的特殊系统用户,有些是随项目创建时自劢创建。 项目管理员可以根据需要创建服务账户,用于管理项目资源。 换句话讲,给集群中的pod 访问容器的权限。每个项目会创建一个默认的 sa 账户。
    1
    2
    3
    4
    5
    6
    7
    8
    [root@master student]# oc get sa
    NAME SECRETS AGE
    builder 2 19h
    default 3 19h
    deployer 2 19h
    registry 3 19h
    router 2 19h
    [root@master student]#

在 OKD 中,每个项目都需要 sa 账户执行 build、deployment 和创建其他 pod, master-config.yml 参数 managedNames 定义了每个项目默认 sa 账户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@master student]# cat /etc/origin/master/master-config.yaml |  grep  -A 10 serviceAccountConfig
serviceAccountConfig:
limitSecretReferences: false
managedNames:
- default
- builder
- deployer
masterCA: ca-bundle.crt
privateKeyFile: serviceaccounts.private.key
publicKeyFiles:
- serviceaccounts.public.key
servingInfo:
[root@master student]#

  • builder: 构建pod需要每个项目中的构建器服务账户,并赋予其 system:image-builder 角色,允许使用内部容器注册将镜像推送到项目中的任何 image Stream。
  • deployer: 每个项目中的部署者服务Account是部署pods所必需的,并在系统中提供system:deployer角色,该角色允许查看和修改项目中的复制控制器和pod
  • default: 默认服务账户由所有其他pod使用,除非它们指定了不同的服务帐户

用户创建

在 OKD 中,可以通过面板界面的方式创建用户

在这里插入图片描述

也可以通过命令行的方式来创建

这里我们看一个 Demo,对于 HTPasswdIdentityProvider 模块,使用 htpasswd 命令创建。 htpasswd 是一个阿帕奇开源的一个创建帐密的小工具http-tools的命令,使用时需要指定创建的密码文件的位置

这里的密码文件位置通过,配置的 认证模块来获取

通过 api 资源文件获取

1
2
3
4
data:
htpasswd: |
kind: HTPasswdPasswordIdentityProvider
file: /etc/openshift/htpasswd

通过静态配置文件获取

1
2
3
4
provider:
apiVersion: v1
file: /etc/origin/master/htpasswd
kind: HTPasswdPasswordIdentityProvider

非交互式创建

1
2
3
4
5
6
[root@master master]# htpasswd -b  /etc/origin/master/htpasswd  liruilong redhat
Adding password for user liruilong
[root@master master]# cat /etc/origin/master/htpasswd
admin:$apr1$4ZbKL26l$3eKL/6AQM8O94lRwTAu611
developer:$apr1$4ZbKL26l$3eKL/6AQM8O94lRwTAu611
liruilong:$apr1$TEsPZeVC$mTKI3oehZBZrZUU74UhLn1

交互式创建

1
2
3
4
5
6
7
8
9
10
[root@master master]# htpasswd   /etc/origin/master/htpasswd  liruilong
New password:
Re-type new password:
Updating password for user liruilong
[root@master master]# cat /etc/origin/master/htpasswd
admin:$apr1$4ZbKL26l$3eKL/6AQM8O94lRwTAu611
developer:$apr1$4ZbKL26l$3eKL/6AQM8O94lRwTAu611
liruilong:$apr1$RhuXyaXn$xMo1M9CBBA2IftxBdtyHr1
[root@master master]#

也可以通过配置文件的方式来创建用户

SA 服务账号创建

sa 创建之后会生成一个默认的 token ,某些面板工具可以通过 token 来实现认证登录。但是需要对 sa 做授权

1
2
3
4
5
[root@master student]# oc create sa liruilong
serviceaccount "liruilong" created
[root@master student]# oc get sa liruilong
NAME SECRETS AGE
liruilong 2 9s

查看 sa 的详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@master student]# oc describe sa liruilong
Name: liruilong
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: liruilong-dockercfg-2bpbm
Mountable secrets: liruilong-token-rl57k
liruilong-dockercfg-2bpbm
Tokens: liruilong-token-j5v87
liruilong-token-rl57k
Events: <none>
[root@master student]# oc get secret liruilong-token-rl57k
NAME TYPE DATA AGE
liruilong-token-rl57k kubernetes.io/service-account-token 4 59s
[root@master student]#

用户登录

交互式登录

1
2
3
4
5
6
7
8
9
10
11
[root@master master]# oc login -u liruilong
Authentication required for https://master.lab.example.com:443 (openshift)
Username: liruilong
Password:
Login successful.

You don't have any projects. You can try to create a new project, by running

oc new-project <projectname>

[root@master master]#

非交互式登录

1
2
3
4
5
6
7
8
[root@master master]# oc login -u liruilong -p redhat https://master.lab.example.com:443
Login successful.

You don't have any projects. You can try to create a new project, by running

oc new-project <projectname>

[root@master master]#

登录管理账号查看用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@master student]# oc login -u  admin
Authentication required for https://master.lab.example.com:443 (openshift)
Username: admin
Password:
[root@master student]# oc login -u admin -p redhat
Login successful.

You have access to the following projects and can switch between them with 'oc project <projectname>':

* default
kube-public
kube-service-catalog
kube-system
logging
management-infra
openshift
openshift-ansible-service-broker
openshift-infra
openshift-node
openshift-template-service-broker
openshift-web-console

Using project "default".

查看当前登录用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@master student]# oc whoami
admin
[root@master student]# oc log
login logout logs
[root@master student]# oc log
login logout logs
[root@master student]# oc logout
Logged "admin" out on "https://master.lab.example.com:443"
[root@master student]# oc login -u liruilong -p redhat https://master.lab.example.com:443
Login successful.

You don't have any projects. You can try to create a new project, by running

oc new-project <projectname>

[root@master student]# oc whoami
liruilong
[root@master student]#

查看当前登录用户的 tocke

1
2
3
[root@master student]# oc whoami -t
iTYaOvc7DZVBW-vmn_6m71-TrGPiltJ210OkfjMEEi4
[root@master student]#

查看用户列表

查看用户列表

1
2
3
4
[root@master student]#  oc get user
NAME UID FULL NAME IDENTITIES
admin 3300d7da-da70-11ed-a5c3-52540000fa0a htpasswd_auth:admin
liruilong b0cb659b-da74-11ed-a5c3-52540000fa0a htpasswd_auth:liruilong

OpenShift 用户信息来源于后端的省份提供者(Indentity Provider)。 假设用户为 OpenShift 配置了某个 Indentity Provider,当用户第一次登录时, OpenShift 往会为这个用户创建一个 user 对象及一个 identity 对象。这个 identity 对象记录了用户来源于哪一个后端的 Indentity Provider,以及相关的用户信息 。

通过下面的例子可以看到当前系统中的用户,其来源 Provider 为 htpasswd auth 。

查看 identity 列表

1
2
3
4
5
[root@master student]# oc get identity
NAME IDP NAME IDP USER NAME USER NAME USER UID
htpasswd_auth:admin htpasswd_auth admin admin 3300d7da-da70-11ed-a5c3-52540000fa0a
htpasswd_auth:liruilong htpasswd_auth liruilong liruilong b0cb659b-da74-11ed-a5c3-52540000fa0a
[root@master student]#

删除用户

删除 OKD 平台中 user

1
[root@master    ~]#oc    delete    user    liruilong   

删除 liruilong 用户对应的 identity。

1
oc delete identity liruilong

删除 identity provider 中用户。

1
[root@master    ~]#    htpasswd    -D    /etc/origin/openshift-passwd    liruilong 

如果未删除 identity provider 中用户,此时还可以使用该用户登录到 ocp 平台。

如果为新创建的一个用户,不添加项目,那么这个用户没有任何权限,需要通过下面的方式添加用户权限。

  1. 将用户添加到项目中:oc adm policy add-role-to-user <role> <username> -n <project>
  2. 从项目中删除用户:oc adm policy remove-role-from-user <role> <username> -n <project>
  3. 删除用户:oc adm policy remove-role-from-user <role> <username> -n <project>

请注意,命令 1 和 2 中的 是您要分配给用户的角色,例如 admin 或 view。

组管理

组 (group)的信息的来源有两个,一是后端的 Indentity Provider ,二是通过用户在 Open Shift 中定义 。 通过 oadm groups 命令,可以在 OpenShift 中对组及组的成员进行管理。

添加组

1
2
3
[root@master student]# oc adm groups new devops
NAME USERS
devops

在组中添加用户

1
2
[root@master student]# oc adm groups add-users devops liruilong
group "devops" added: "liruilong"

查看组

1
2
3
4
5
6
7
[root@master student]# kubectl  get group
NAME USERS
devops liruilong
[root@master student]# oc get group
NAME USERS
devops liruilong
[root@master student]#

删除组

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master student]# oc adm policy remove-group devops
Groups [devops] were not bound to roles in project default.
[root@master student]# kubectl get groups
NAME USERS
devops
[root@master student]# oc get group
NAME USERS
devops
[root@master student]# kubectl delete group devops
group "devops" deleted
[root@master student]# oc get group
No resources found.
[root@master student]#

权限管理

OKD 的权限处理方式有很多中,这里和 K8s 不同的是多了 Policy ,K8s 印象中没有这一层关系, 同样使用 RBAC 的权限管理方式进行管理,不同的是弱化了绑定关系对象,进行了封装。

  • role:Role (角色)是一组权限的集
  • rule:通过过权限 Rule,系统或用户可以定义什么样的角色可以对什么资源执行什么动作
  • policy: 若干个 Role 组成一个 策略policy ,策略分为 集群级别 Clusterpolicy和命名空间Policy 级别.
  • Role Binding: 角色绑定关系,定义了角色于具体的用户以及组的关联关系,
  • Policy Binding: 若干 Role Binding组成的集合将构成一个 Policy Binding (策略绑定关系)。该对象类型同样分为集群与项目两个级别 。

关于 RBAC 以及对应的资源对象,这个不多做说明,简单来看一下当前 集群内置的一些角色

权限对象关系Demo

在这里插入图片描述

角色管理

k8s 中的 集群相关的资源有两个 roleclusterrole,OKD 中,也是一样的,角色一般用于处理命令空间,也就是okd 中的项目的资源,而 集群角色用于整个集群的角色控制。集群级别的 Clusterrole 和项目级别的 Role 。

查看当前集群的角色和集群角色

1
2
3
4
5
6
7
8
9
[root@master student]# oc get clusterrole | head -n 5
NAME
admin
asb-access
asb-auth
basic-user
[root@master student]# oc get role
No resources found.
[root@master student]#

给用户和组添加角色

给用户或组添加角色和集群角色,这里在命令使用上和 k8s 有些出入,应为 OKD 多个一层 policy ,默认情况下,需要指定策略,即 policy

为当前策略添加角色规则,看一下有什么命令

1
2
[root@master student]# oc adm policy add-cluster-role-to-
add-cluster-role-to-group add-cluster-role-to-user

通过下面的命令看到,可以把角色和集群角色添加到用户和组上面,给 liruilong 用户添加一个 admin

1
2
3
4
[root@master student]# oc adm policy add-cluster-role-to-user admin liruilong
cluster role "admin" added: "liruilong"
[root@master student]# oc adm policy add-
add-cluster-role-to-group add-cluster-role-to-user add-role-to-group add-role-to-user add-scc-to-group add-scc-to-user

devops 组添加一个 admin 的集群角色

1
2
3
4
[root@master student]# oc adm policy add-cluster-role-to-group admin devops
cluster role "admin" added: "devops"
[root@master student]#

绑定关系管理

用户和角色的绑定关系查看

1
2
3
4
[root@master student]# oc get clusterrolebinding  admin
NAME ROLE USERS GROUPS SERVICE ACCOUNTS SUBJECTS
admin /admin openshift-infra/template-instance-controller
[root@master student]#
1
2
admin-2                                                               /admin                                                                 liruilong
admin-3 /admin devops

查看哪个 user 和 group 可以执行特定 rule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[root@master student]# oc    adm    policy    who-can    delete    user
Namespace: default
Verb: delete
Resource: users.user.openshift.io

Users: admin
system:admin
system:serviceaccount:kube-system:clusterrole-aggregation-controller
system:serviceaccount:kube-system:generic-garbage-collector
system:serviceaccount:kube-system:namespace-controller

Groups: system:cluster-admins
system:masters

[root@master student]# oc adm policy who-can delete pod
Namespace: default
Verb: delete
Resource: pods

Users: admin
liruilong
system:admin
system:kube-scheduler
system:serviceaccount:kube-service-catalog:default
system:serviceaccount:kube-system:clusterrole-aggregation-controller
system:serviceaccount:kube-system:cronjob-controller
system:serviceaccount:kube-system:daemon-set-controller
system:serviceaccount:kube-system:generic-garbage-collector
system:serviceaccount:kube-system:job-controller
system:serviceaccount:kube-system:namespace-controller
system:serviceaccount:kube-system:node-controller
system:serviceaccount:kube-system:persistent-volume-binder
system:serviceaccount:kube-system:pod-garbage-collector
system:serviceaccount:kube-system:replicaset-controller
system:serviceaccount:kube-system:replication-controller
system:serviceaccount:kube-system:statefulset-controller
system:serviceaccount:openshift-ansible-service-broker:asb
system:serviceaccount:openshift-infra:build-controller
system:serviceaccount:openshift-infra:deployer-controller
system:serviceaccount:openshift-infra:pv-recycler-controller
system:serviceaccount:openshift-infra:template-instance-controller

Groups: devops
system:cluster-admins
system:masters

[root@master student]#

用户默认权限管理

用户首次登录获取什么权限?默认分配什么组和角色?每个项目绑定的角色和 用户?整个集群绑定的角色和用户?

默认情况下,系统会为用户授予这些默认组

  • 系统:已认证(system:authenticated):这被分配给API可认证的所有用户。非system:anonymous (用户) 的所有人都在这个组中
  • 系统:已认证:授权(system:authenticated:oauth):这将分配给使用嵌入式 oauth 服务器领发的 oauth 令牌进行标识的所有用户。这不适用于服务帐户(它们使用服务帐户令牌) 或证书用户
  • 系统:未经身份验证(system:unauthenticated):这将分配给尚未提交凭据的用户。无效凭据被拒绝,并显示401错误,因此这是针对根本没有尝试进行身份验证的用户.

所以正常的,如果登录成功那么系统会默认赋予 authenticated、authenticated:oauth 这两个组的权限

管理员是无法手劢改变这些组成员,想改变这些组中成员权限,可以通过更改组的角色实现。 system:authenticatedsytem:authenticated:oauth 组具有的默认角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master student]# oc    get    clusterrolebinding    |grep    -e    system:authenticated    -e    USER
NAME ROLE USERS GROUPS SERVICE ACCOUNTS SUBJECTS
basic-users /basic-user system:authenticated
cluster-status-binding /cluster-status system:authenticated, system:unauthenticated
self-access-reviewers /self-access-reviewer system:authenticated, system:unauthenticated
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:unauthenticated
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:unauthenticated
system:discovery-binding /system:discovery system:authenticated, system:unauthenticated
system:oauth-token-deleters /system:oauth-token-deleter system:authenticated, system:unauthenticated
system:scope-impersonation /system:scope-impersonation system:authenticated, system:unauthenticated
system:webhooks /system:webhook system:authenticated, system:unauthenticated

修改用户默认权限

假设现在我们有这样一个问题,我们不希望默认的登录用户有 可以创建命名空间的权限, 即项目的权限,那么我们可以把对应的绑定关系删除。

可以看到创建项目的权限目前在 self-provisioner 这个角色

1
2
3
4
5
6
7
8
9
10
[root@master student]# oc describe clusterrole self-provisioner --all-namespaces
Name: self-provisioner
Created: 24 hours ago
Labels: <none>
Annotations: authorization.openshift.io/system-only=true
openshift.io/description=A user that can request projects.
openshift.io/reconcile-protect=false
Verbs Non-Resource URLs Resource Names API Groups Resources
[create] [] [] [ project.openshift.io] [projectrequests]
[root@master student]#

即将已授权 self-provisioner 集群角色和用户组(system:authenticated:oauth)的绑定关系取消。

直接通过 kubectl 命令删除绑定关系

1
2
3
4
5
6
7
8
9
[root@master student]# kubectl  delete  clusterrolebinding self-provisioners
clusterrolebinding "self-provisioners" deleted
[root@master student]# htpasswd -b /etc/origin/master/htpasswd demo redhat
Adding password for user demo
[root@master student]# oc login -u demo -p redhat
Login successful.

You don't have any projects. Contact your system administrator to request a project.
[root@master student]#

当然也可以使用 OKD 的方式 ,移除策略中对应的绑定关系规则,下面我们通过这种方式来添加了对应的绑定关系,可以看到登录的时候拥有了创建项目的权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@master student]# oc adm policy  add-cluster-role-to-group self-provisioner system:authenticated:oauth
cluster role "self-provisioner" added: "system:authenticated:oauth"
[root@master student]# oc get clusterrolebinding |grep -e system:authenticated -e USER | grep provisioner
self-provisioner-0 /self-provisioner system:authenticated:oauth

[root@master student]# oc logout
Logged "admin" out on "https://master.lab.example.com:443"
[root@master student]# oc login -u demo -p redhat
Login successful.

You don't have any projects. You can try to create a new project, by running

oc new-project <projectname>

[root@master student]#

安全上下文(SCC)管理

Kubernetes 中的容器安全有三个主要的组件:Pod Security Policies (PSP),Pod Security Admission (PSA) 和 Security Context (SC)。 K8s 中 PSP 在1.25 的版本中被测底废除,只能使用 PSA 。

OpenShift 中的容器安全组件是 Security Context Constraints (SCC)

上面这四个组件的作用是确保容器在 Kubernetes 或 OpenShift 集群中运行时的安全性。它们的相同点和不同点如下:

相同点:

  • 都是用于保证容器安全的组件。
  • 都可以用于限制容器的权限和访问控制。
  • 都可以用于限制容器的资源使用。

不同点:

  • PSP 是一种集群级别的安全策略,可以限制 Pod 的安全上下文和访问控制。而 PSA 是一种动态的安全策略,可以在 Pod 创建时对其进行检查和限制。而 SCC 是 OpenShift 中的一种安全策略,可以限制容器的权限和访问控制。
  • PSP 和 PSA 都可以限制容器的权限和访问控制,但 PSP 更加灵活,可以根据 Pod 的标签和命名空间来进行限制。而 PSA 只能根据 Pod 的规范来进行限制。而 SCC 可以根据用户、命名空间和标签来进行限制。
  • Security Context 是一种在容器级别上设置的安全策略,可以限制容器的权限和访问控制。与 PSP、PSA 和 SCC 不同的是,Security Context 是在容器级别上设置的,而 PSP、PSA 和 SCC 是在 Pod 或集群级别上设置的。

回到 SSC,安全上下文( Security Context Constraint, SCC)要管控的是具体容器可以或不可以执行哪些操作或调用 。 SCC 是 OpenShift 规范用户运行容器行为的一个有效途径,比如相同的镜像,可能在 docker 中可以运行,在openshift 中不能运行。

换句话讲,通过 SCC 来限定 Pod 对宿主节点的资源访问,虽然通过 Linux 命名空间有对应的资源限制。

利用 SCC ,管理员能对Pod做如下的一些约束:

  • 运行特权容器 (privileged container)
  • 为容器增加能力 (capahiliticg)
  • 用主机上的目录作为卷
  • 容器的 SELinux 下文
  • 用户 TD
  • 主机命名空间和网络
  • 为Pod 的卷分配 FSGroup
  • 配置允许的补充组
  • 要求使用只读文件系统
  • 控制允许使用的卷类型
  • 控制允许使用的安全计算模式配置文件(seccop prorile)

默认情况下,任何容器的执行都只授予 restricted(受限制) 的 SCC,这个 SCC 是最严格的,适用于以 root 权限运行的 pod。它限制了 pod 对主机文件系统和网络的访问。

查看当前命名空间下的所以的 SSC ,OpenShift 有七个 SCC

1
2
3
4
5
6
7
8
9
10
[root@master student]# oc get scc
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES
anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny 10 false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
hostaccess false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir hostPath persistentVolumeClaim projected secret]
hostmount-anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir hostPath nfs persistentVolumeClaim projected secret]
hostnetwork false [] MustRunAs MustRunAsRange MustRunAs MustRunAs <none> false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
nonroot false [] MustRunAs MustRunAsNonRoot RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
privileged true [*] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*]
restricted false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
[root@master student]#

对应 的7中 SCC 限制说明:

  1. restricted:这个 SCC 是最严格的,适用于以 root 权限运行的 pod。它限制了 pod 对主机文件系统和网络的访问。
  2. privileged:这个 SCC 允许 pod 以完整的 root 权限运行,并访问所有主机资源。它适用于需要访问敏感主机资源的 pod。
  3. anyuid:这个 SCC 允许 pod 以任何用户 ID 和组 ID 运行。它适用于需要访问默认用户 ID 不可访问的主机资源的 pod。
  4. hostaccess:这个 SCC 允许 pod 挂载主机文件系统并访问主机设备。它适用于需要访问默认用户 ID 不可访问的主机资源的 pod。
  5. hostmount-anyuid:这个 SCC 允许 pod 挂载主机文件系统并以任何用户 ID 和组 ID 运行。它适用于需要访问默认用户 ID 不可访问的主机资源的 pod。
  6. nonroot:这个 SCC 适用于不需要 root 权限的 pod。它限制了 pod 对主机文件系统和网络的访问。
  7. hostnetwork: 这个 SCC 允许 pod 使用主机网络命名空间。这意味着 pod 可以访问主机上的网络接口和端口,而不是被限制在容器网络命名空间中。这个 SCC 可能会增加 pod 对主机网络的访问权限,因此需要谨慎使用。

查看当前 privileged SCC的详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@master student]# oc describe scc privileged
Name: privileged
Priority: <none>
Access:
Users: system:admin,system:serviceaccount:openshift-infra:build-controller,system:serviceaccount:management-infra:management-admin,system:serviceaccount:management-infra:inspector-admin
Groups: system:cluster-admins,system:nodes,system:masters
Settings:
Allow Privileged: true
Default Add Capabilities: <none>
Required Drop Capabilities: <none>
Allowed Capabilities: *
Allowed Seccomp Profiles: *
Allowed Volume Types: *
Allowed Flexvolumes: <all>
Allow Host Network: true
Allow Host Ports: true
Allow Host PID: true
Allow Host IPC: true
Read Only Root Filesystem: false
Run As User Strategy: RunAsAny
UID: <none>
UID Range Min: <none>
UID Range Max: <none>
SELinux Context Strategy: RunAsAny
User: <none>
Role: <none>
Type: <none>
Level: <none>
FSGroup Strategy: RunAsAny
Ranges: <none>
Supplemental Groups Strategy: RunAsAny
Ranges: <none>
[root@master student]#

详情中的 Run As User Strategy: RunAsAny 表示可以使用容器中的任意用户 ID 执行,但运行容器需要指定特定的 Service 用户

查看系统默认的restricted SCC 详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@master student]# oc describe scc  restricted
Name: restricted
Priority: <none>
Access:
Users: <none>
Groups: system:authenticated
Settings:
Allow Privileged: false
Default Add Capabilities: <none>
Required Drop Capabilities: KILL,MKNOD,SETUID,SETGID
Allowed Capabilities: <none>
Allowed Seccomp Profiles: <none>
Allowed Volume Types: configMap,downwardAPI,emptyDir,persistentVolumeClaim,projected,secret
Allowed Flexvolumes: <all>
Allow Host Network: false
Allow Host Ports: false
Allow Host PID: false
Allow Host IPC: false
Read Only Root Filesystem: false
Run As User Strategy: MustRunAsRange
UID: <none>
UID Range Min: <none>
UID Range Max: <none>
SELinux Context Strategy: MustRunAs
User: <none>
Role: <none>
Type: <none>
Level: <none>
FSGroup Strategy: MustRunAs
Ranges: <none>
Supplemental Groups Strategy: RunAsAny
Ranges: <none>
[root@master student]#

Run As User Strategy: MustRunAsRange:则表示容器必须以指定的用户 ID 运行。具体来说,MustRunAsRange 策略要求容器的用户 ID 必须在指定的范围内。这个范围由 RunAsUser 和 RunAsGroup 字段指定。如果容器的用户 ID 不在指定的范围内,容器将无法启动。

pod 以哪个用户身份执行,如果没有明确挃定,则由 pod 使用的 scc 确定。明确指定方法,下面为 K8s官网的一个Demo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: busybox:1.28
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false

SCC 使用案例

如果你有一个需要特定 capability 能力的应用,但是这个 capability 不能通过系统默认的 restricted SCC 授予,此时可以创建一个特殊的 service account,并将该账户加到 SCC 中。创建应用使用此 sa 账户。

Openshift 中容器默认是以随机用户执行 command 的,如果该容器中 command 命令要求 root 用户执行,那么容器就无法创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master student]# oc new-app --name=nginx --docker-image=registry.lab.example.com/nginx
--> Found Docker image c825216 (4 years old) from registry.lab.example.com for "registry.lab.example.com/nginx"

* An image stream will be created as "nginx:latest" that will track this image
* This image will be deployed in deployment config "nginx"
* Port 80/tcp will be load balanced by service "nginx"
* Other containers can access this service through the hostname "nginx"
* WARNING: Image "registry.lab.example.com/nginx" runs as the 'root' user which may not be permitted by your cluster administrator

--> Creating resources ...
imagestream "nginx" created
deploymentconfig "nginx" created
service "nginx" created
--> Success
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose svc/nginx'
Run 'oc status' to view your app.
1
2
3
4
5
6
7
[root@master student]# oc expose svc/nginx
route "nginx" exposed
[root@master student]# kubectl get route
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
docker-registry docker-registry-default.apps.lab.example.com docker-registry <all> passthrough None
nginx nginx-default.apps.lab.example.com nginx 80-tcp None
registry-console registry-console-default.apps.lab.example.com registry-console <all> passthrough None
1
2
3
4
5
6
7
8
[root@master student]# kubectl  get pods
NAME READY STATUS RESTARTS AGE
docker-registry-1-drmbk 1/1 Running 2 1d
nginx-1-deploy 1/1 Running 0 45s
nginx-1-h5zx8 0/1 CrashLoopBackOff 2 42s
registry-console-1-dg4h9 1/1 Running 2 1d
router-1-27wtd 1/1 Running 2 1d
router-1-lvmvk 1/1 Running 2 1d

可以看到 pod 一直创建失败。

1
2
3
4
[root@master student]# kubectl  get pods  --selector=app=nginx
NAME READY STATUS RESTARTS AGE
nginx-1-h5zx8 0/1 CrashLoopBackOff 6 6m
[root@master student]#

在最前面的 Pod 创建的时候,我们看到一个告警,提示提示,以root 的方式运行不被集群管理员所允许。所以 Pod 状态一直是 CrashLoopBackOff.

1
* WARNING: Image "registry.lab.example.com/nginx" runs as the 'root' user which may not be permitted by your cluster administrator
1
2
3
4
5
6
7
8
9
10
11
12
[root@master student]# oc describe pods nginx-1-h5zx8 | grep -i -A 20 event
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 13m default-scheduler Successfully assigned nginx-1-h5zx8 to node2.lab.example.com
Normal SuccessfulMountVolume 13m kubelet, node2.lab.example.com MountVolume.SetUp succeeded for volume "default-token-bmctn"
Normal Pulled 12m (x4 over 13m) kubelet, node2.lab.example.com Successfully pulled image "registry.lab.example.com/nginx@sha256:4ffd9758ea9ea360fd87d0cee7a2d1cf9dba630bb57ca36b3108dcd3708dc189"
Normal Created 12m (x4 over 13m) kubelet, node2.lab.example.com Created container
Normal Started 12m (x4 over 13m) kubelet, node2.lab.example.com Started container
Normal Pulling 11m (x5 over 13m) kubelet, node2.lab.example.com pulling image "registry.lab.example.com/nginx@sha256:4ffd9758ea9ea360fd87d0cee7a2d1cf9dba630bb57ca36b3108dcd3708dc189"
Warning BackOff 3m (x46 over 13m) kubelet, node2.lab.example.com Back-off restarting failed container
[root@master student]#

这个时候,我们可以修改默认的 SCC 相关的权限,或者通过创建新的 SA 的方式,创建服务帐户;将特定 SCC(如 anyuid)添加给用户;修改 dc 使用创建的 sa 用户身份运行。

这里创建的 SA ,绑定到

1
2
oc    create    sa    useroot
oc adm policy add-scc-to-user anyuid -z useroot

修改应用 dc,使用 sa-useroot 用户运行容器

1
oc    patch dc/nginx    --patch    '{"spec":{"template":{"spec":{"serviceAccountName":    " useroot"}}}}'

dc 会根据 template 的定义创建 pod。

1
serviceAccountName: useroot 

也可以直接修改 默认 sa 的绑定的 SCC 。

1
oc adm policy add-scc-to-user anyuid -z default -n test2

关于 secret 这里简单介绍,Secret 对象类型提供了一种保存敏感信息的机制,例如密码,OCP 客户端配置文件,Docker 配置文件,私有 sorce registry 凭据。

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦 :)


《OKD 3.9 DO280 Red Hat OpenShift Administration I》

《开源容器云OpenShift:构建基于Kubernetes的企业应用云平台》

https://docs.okd.io/latest/welcome/index.html


© 2018-2023 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

发布于

2023-04-14

更新于

2023-06-21

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×