OKD 权限认证 电脑版发表于:2021/8/15 15:53  >#OKD 权限认证 [TOC] tn2>Openshift API Server 利用管理员配置的认证模块来认证每个达到的请求。认证过程及用户、API认证方式、身份提供程序等多个概念。认证过程涉及用户、API认证方式、身份提供程序等多个概念。 | | | | ------------ | ------------ | | 用户(User) | 典型用户:管理员和开发人员。用户可以被分配到一个或多个用户组中。 | | API认证方式 | 一种方式上OAuth Access Token.<br/>另一种方式是x.509 ClientCertificate. | | 身份(Identity) | 就像身份证一样,Identity 用于确认用户身份的信息。 |  tn2>OpenShift 中的user对象代表集群中的一个用户,在用户第一次登录集群时自动创建,或通过API手动创建。 | | | | ------------ | ------------ | | Identity | 表示用户身份 | | useridentitymapping | 将user对象和identity对象关联在一起。 | HtPasswd ------------ tn2>OKD 一般是在开发测试环境中,可利用HTPasswd作为身份提供程序,它将用户名和密码保存在一个使用htpasswd工具创建的文本文件中。要在Master配置文件中配置htpasswd身份提供程序,可通过编辑`/etc/origin/master/master-config.yaml`,在identityProviders部分添加以下内容来实现。 ```bash identityProviders: - challenge: true login: true mappingMethod: claim name: htpasswd_auth provider: apiVersion: v1 file: /etc/origin/master/htpasswd kind: HTPasswdPasswordIdentityProvider ```  tn2>修改后,重启Master API和Controllers服务 ```bash master-restart api master-restart controllers ``` tn2>然后创建用户tom及有关对象。 1.在Master节点上运行htpasswd命令来创建文件并添加用户tom,需要输入tom的密码。 ```bash # 一般没有该文件需要这样进行创建 htpasswd -c /etc/origin/master/htpasswd tom # 如果该文件已存在 htpasswd -b /etc/origin/master/htpasswd tom tom # 如果有多个节点 ansible -m shell -a 'htpasswd -b /etc/origin/master/htpasswd tom tom' masters ``` tn2>第一次一般需要登录一下。 | 登录方式 | oc登录命令 | | ------------ | ------------ | | 客户端证书 | `oc login <API Server 地址和端口> --certificate-authority=<客户端证书绝对路径>` | | Bearer Token | `oc login <API Server 地址和端口> --token=<Bearer token>` | | 用户名和密码 | `oc login <API Server 地址和端口> -u <用户名> -p <密码>` | ```bash # 先登录到tom用户 oc login -u tom -p tom # 再登录到admin用户 oc login -u admin -p admin ``` tn2>或者我们也可以通过不用登录直接创建也可以 ```bash oc create user tom oc create identity htpasswd_auth:tom ``` tn2>查看用户信息 ```bash oc get user oc get identity htpasswd_auth:tom ```  服务账户(Service Account) ------------ tn2>当一个普通用户访问OpenShift API时,OpenShift对它进行用户认证和权限控制。但是,在Openshift集群中又时做操作的并不是自然人用户,例如: - Replication Controller 调用API去创建或者删除Pod。 - 容器中的应用调用OpenShift API。 - 外部应用调用OpenShift API来进行监控或者整合。 tn2>为了管理这种非普通用户进行的操作,OpenShift创造了服务账户(sa)的概念。服务属于项目范畴。每个项目默认都会自动创建3个服务账户,如下表所示: | 服务账户 | 说明 | | ------------ | ------------ | | builder | 用于构建Pod(build Pod)。它被授予`system:image-build`角色,因此被允许向内部镜像仓库中的任意镜像流上推送构建过程中生成的镜像 | | deployer | 用于部署Pod(deployment Pod)。它被授予了`system:deployer`角色,因此被允许查看和修改集群中ReplicationController对象及其管理的Pod | | default | 当Pod没有显示指定服务账户时,默认使用该账户 | tn2>每个项目都需要使用服务账户来运行构建Pod、部署和其他Pod操作。Master配置文件中的 serviceAccountConfig 部分的managedNames定义了为每个项目自动创建的服务账户的名称。可通过`oc get sa`命令来获取当前项目中的服务账户列表。  tn2>通过`oc create sa <sa_name>`命令来创建一个新服务账户。 ```bash # 创建hmy服务账户 oc create sa hmy oc get sa ```  tn2>服务账户利用一个被私有RSA密钥签名的Token来进行认证。API Server中的认证模块用RSA公钥来签证签名。在Master配置文件的`serviceAccountConfig`部分,配置了用于签名的私钥文件`privateKeyFile`和用于验证的公钥文件`publicKeyFiles`。 `vim /etc/origin/master/master-config.yaml`  tn2>那么服务账户的Token是怎么来的呢?服务账户被创建后,OpenShift自动为它创建两个Secret,一个包含用于API访问的Token;另一个包含用于从OpenShift内置镜像仓库中拉取镜像的Token。 tn>OpenShift中的Secret对象类型用来保存敏感信息,如密码、OAuth令牌和SSH密钥。将这些信息放在Secret中比放在Pod的定义或者容器镜像中更加安全和灵活。Secret通常有如下3种类型。 ——Opaque: base64编码格式的Secret,通常用于存储密码密钥等。 ——kubernetes.io/dockerconfigjson:用来存储私有Docker镜像仓库的认证信息。 ——kubernetes.io/service-account-token:被服务账户使用。服务账户创建时Openshift会默认创建对应的Secret。 通过`oc describe sa <sa_name>`命令可查看服务账户的详细信息。 ```bash oc describe sa hmy ```  tn2>查看hmy-token-lndvh这个Secret的详细信息,可看到其用于访问OpenShift API的Token。 ```bash oc describe secret hmy-token-lndvh ```  tn2>在API Token Secret 中有4个部分的内容。 | | | | ------------ | ------------ | | service-ca.crt | 安全的访问服务所需的证书。 | | token | 该服务账户用于OpenShift API身份验证的Token | | ca.crt | OpenShift API Server的CA公钥证书。 | | namespace | Secret所在namespace名称的base64编码。 | tn2>每个Pod的运行都需要有一个服务账户。Pod的服务账户决定了Pod可用的Token,它使用服务账户的镜像拉取Token然后去拉取Pod要用到的镜像,将API Token挂载到Pod内部目录中供Pod内的应用使用。默认情况下,当Pod实例被创建后,其服务账户的API Secret会被挂载到Pod中的目录`/var/run/secrets/kubernetes.io/serviceaccount`下,从而使得Pod中的应用可读取其中的Token去访问OpenShift API。 ```bash oc rsh my-web-app ```  tn2>Pod中的应用可读取该文件夹下的Token等信息去访问OpenShift API。以下示例代码展示了简单的使用方式。 ```bash TOKEN="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt "https://openshift.default.svc.cluster.local/oapi/v1/users/~" -H "Authorization: Bearer $TOKEN" ```  tn>在Kubernetes 1.6或者更新版本的OpenShift容器云环境下,可将服务账户定义的`automoutServiceAccountToken`值设置为false以禁止自动在Pod中挂载服务账户的Token: ```bash apiVersion: v1 imagePullSecrets: - name: default-dockercfg-kr6q7 kind: ServiceAccount metadata: creationTimestamp: 2021-08-07T08:40:38Z name: default namespace: mynetcore resourceVersion: "10329" selfLink: /api/v1/namespaces/mynetcore/serviceaccounts/default uid: 24091a15-f75b-11eb-ae81-001c42adbe97 automoutServiceAccountToken: false secrets: - name: default-dockercfg-kr6q7 - name: default-token-8snbs ``` 基于角色的权限访问控制 ------------ tn2>OpenShift RBAC是OpenShift支持的众多授权模块中的一种,它通过给用户绑定相应的角色,使用户获得对资源的操作权限,从而实现了授权功能。 RBAC适用于普通账户和服务账户。 RBAC利用Rule(规则)、角色(Role)和Binding来实现用户操作授权。 >### 相关概念 tn2>角色策略规则,是对一组资源的操作集合,比如增删改查(get、list、delete)等。每个角色定义了受控制的对象(Subject)、允许的操作(Verb)和范围(集群和集群的项目)。 角色安装其范围分为两类: 1.集群范围内存在的角色被称为集群角色(ClusterRole);存在于某个项目中的角色被称为本地角色(Role)。OpenShift默认会创建很多的集群角色,常用角色的简单描述如下表: | 角色 | 描述 | | ------------ | ------------ | | admin | 项目经理。如果用于本地RoleBindin,那么用户将能查看和修改所在项目中的所有资源 | | basic-user | 用户可以获取关于项目和用户的基本信息 | | cluster-admin | 超级用户,可在任何项目中做任何操作。若用于本地RoleBinding,那么用户将拥有所在的Project的所有权限,包括控制配额(Quota)和角色 | | cluster-status | 用户可以获取集群的基本状态信息 | | edit | 用户可以修改项目中的大部分对象,但不能查看或修改Role和RoleBinding | | self-provisioner | 所有用户的默认Role,可以创建自己的Project | | view | 用户可以查看项目中的大部分对象,除了Role和RoleBinding。用户不能对任何对象做任何修改。 | tn2>通过`oc get clusterrole`命令可以查看所有集群角色。`system:router`角色的详细信息如下。  ```bash oc describe clusterrole system:router ```  tn2>用户、用户组和角色之间通过OpenShift RoleBinding 资源类型连接起来。为 User/Group、Role、RoleBinding这几个概念之间的关系。  tn2>下图为用户通过Local Role Binding或Cluster Role Binding绑定给项目角色或集群角色而产生的不同权限。  >### 权限给予 tn2>OpenShift用户默认不具有任何权限。要使得用户具有所需要的权限,需要给其授予相应的角色。OpenShift具有很多默认角色,用户也可以自定义角色。比如创建一个只能查看Pod的Role。 ```bash # 创建podview角色且只能查看pod的权限 oc create role podview --verb=get --resource=pod # 查看role oc describe role podview ```  tn2>确认角色以后,通过`oc adm policy <子命令>`命令向用户、服务账户和用户组授予项目或集群角色。 | 子命令 | 描述 | | ------------ | ------------ | | add-role-to-user | 授予当前项目的角色给用户或服务账户 | | add-role-to-group | 授予当前项目的角色给用户组 | | remove-role-from-user | 删除用户或服务账户的当前项目的角色 | | remove-role-from-group | 删除用户组的当前项目的角色 | | add-cluster-role-to-user | 授予集群角色给用户或服务账户 | | add-cluster-role-to-group | 授予集群角色给用户组 | | remove-cluster-role-from-user | 删除集群角色给用户或服务账户 | | remove-cluster-role-from-group | 删除用户组的集群角色 | tn2>通过以下命令查看当前项目`mynetcore`中默认的服务账户的rolebinding。 ```bash oc get rolebinding ```  tn2>从上面的输出可以看出,deployer服务账户被赋予了 system:deployer 角色,builder 被赋予了system:image-builder 角色,而3个服务账户都在用户组 `system: serviceaccounts:mynetcore` 中因而都被赋予了 system:image-puller 角色。利用 default 服务账户来做如下实验: 1》获取其API token secret default-token-8snbs ```bash oc describe secrets default-token-8snbs ``` tn2>2》利用该Token登录进OpenShift集群。 ```bash oc login --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9........xthblMyBHUIFz8uYs_qXwOUXvlDnWk0OC9FecQZY0PGsRXNw_4BD640K6iALN8cw6y6_AA8M6cJ5BT3qXFnBgR6TQ ```  tn2>3》调用API获取Pod,结果失败,因为它不具有Pod对象的list权限。 ```bash oc get pod ```  tn2>4》向Default服务账户授予 cluster-reader 角色。 ```bash oc adm policy add-cluster-role-to-user cluster-reader system:serviceaccount:mynetcore:default ``` tn2>5》这时就有权查看集群信息了。  >### 权限校验 tn2>Openshift API Server利用以下对象来校验用户是否有权对目标对象进行访问。 ——Identity:用户的用户名和群组列表。 ——Action:用户期望执行的操作。通常包括Project(目标对象所在的项目)、Verb(期望对象,比如get、list、create、update、delete等)、ResourceName(目标对象的名称)等。 ——Binding:用户/组与角色对象之间的绑定关系。 OpenShift API Server校验授权的过程如下:<br/> 1》利用Identity和Project找到该用户或组的所有Binding 2》利用Binding去找出所有的Role 3》通过Role找到所有的Rule 4》比对Action和每一条Rule,直到找到匹配的。 5》如果没有匹配的Rule,那么该操作将被拒绝。 OpenShift安全上下文的约束 ------------ tn2>利用RBAC控制用户访问资源权限类似,管理员可利用SCC来控制Pod的权限,包括Pod能做什么事情、能访问声明资源。Pod中的应用除了要有权限访问OpenShift API和内部镜像仓库之外,还可能有访问部分系统资源的需求。比如: ——要求以任意用户甚至是root来运行Pod中的主进程 ——要求访问宿主机上的文件系统 ——要求访问宿主机上的网络 利用SCC,管理员能对Pod做如下控制: ——运行特权容器 ——为容器增加能力 ——使用主机上的目录作为卷。 ——容器的SELinux上下文 ——用户ID。 ——主机命名空间和网络 ——为Pod的卷分配FSGroup ——配置允许的补充组。 ——要求使用只读文件系统。 ——控制允许使用的卷类型。 ——控制允许使用的安全计算模式配置文件。 ——控制允许使用的安全计算模式配置文件。 可见,SCC的功能非常强大,但配置也非常复杂。为了减少其复杂性,OpenShift容器云平台默认创建了7种SCC,只对集群管理员可见: ```bash oc get scc ```  tn2>每种预定义的SCC都针对其面向的某种场景所需的各种功能进行了定制。SCC定义中的users和groups字段用于控制对SCC对象的访问权限。默认情况下,集群管理员和节点能使用anyuid SCC,而普通用户默认只能使用restricted SCC。而restricted SCC的权限非常有限: ——不能作为特权容器运行。 ——不能将主机文件夹用作卷。 ——UID只能在预定的UID范围内。 ——可使用FSGroup和补充组。 OpenShift将容器所需要的各项能力授予运行容器的用户。在Pod定义中没有显示指定服务账户和SCC的情况下,根据创建pod用户的不同情形,Pod会使用不同的默认SCC: ——非集群管理员角色的用户创建的Pod,默认使用default服务账户和restricted SCC。 ——集群管理员角色用户创建的Pod,默认使用default服务账户和anyuid SCC。 tn>可在允中的Pod的Spec中查看它使用的SCC。例如:  tn2>对于由普通用户创建的Pod,要授权Pod除了restricted SCC定义的权限以外的权限,通常会将运行该Pod的用户放到目标SCC的用户列表中。注意,这里说的“用户”说直接创建Pod的用户。如果是普通用户直接创建了Pod,那么“用户”是这个普通用户:如果说Deployments、StatefulSets、DaemonSets等控制器代表不同用户创建的Pod,那么“用户”说Pod的服务账户。可将spec.serviceAccountName的纸设置为服务账户名称以制定服务账户,不指定的话将末日使用default服务账户。<br/> 对于直接用户是服务账户这种情形,考虑到对现有Pod的影响,如果需要修改服务账户的SCC,建议创建一个新服务账户而不要使用默认账户。确定好直接创建Pod的直接用户后,可运行 `oc adm policy add-scc-to-user <scc_name> <user_name>`或`oc adm policy add-scc-to-group <scc_name> <group_name>`命令授权用户或用户组访问指定SCC的权限。<br/> 比如,因为Registry和Router服务的Pod需要使用主机网络模式,因此为它们创建了单独的服务账户`system: serviceaccount: default: router` 和 `system: serviceaccount: default: registry` 并将他们加入hostnetwork scc的用户列表中。  tn2>另一个很常见的例子说运行要使用root用户的容器。很多Docker镜像使用的都是root用户。但是,OpenShift restricted SCC不允许使用root用户,而是要使用一个用户区间内的用户。通常的修复做法如下: 1》创建一个新的服务账户,比如 userroot:`oc create serviceaccount useroot` 2》将该服务账户加入anyuid SCC的用户列表中:`oc adm policy add-scc-to-user anyuid -z useroot` 3》在应用的DeploymentConfig中指定serviceAccountName为userroot OpenShift服务目录 ------------ tn2>OpenShift3.7版本中引入两个概念:Service Catalog(服务目录)和 Service Broker(服务中介)。可将服务目录看作OpenShift的服务市场(Service Marketplace),用户(服务消费者)可在市场内找到所需要的服务,并方便地创建出服务实例,将其绑定到自己的应用服务上;服务中介说服务目录中服务的提供者和管理者。<br/> 假设你是一个开发者,正在开发一个应用程序,该程序需要一个数据库来保存用户数据。你不是一个数据库管理员,因此不知道如何搭建一个数据库服务。现在,在你们公司的OpenShift容器云平台的服务中,有某个提供商(服务中介)提供的数据库服务。你只需要找到该服务,单击几下鼠标就可创建出一个服务实例,再单击几下鼠标将绑定到你的应用程序上,你的程序就可以使用数据库了。等应用程序开发结束后,你只需要解除绑并删除该服务实例即可。<br/> OpenShift服务目标是提供一个服务市场,终端用户可以方便地消费市场中的服务而不用关注服务背后的细节,比如服务是怎么被创建的,以及是如何进行管理的;同时为服务中介提供售卖服务的平台,只需要他们遵循统一规范Open Service Brocker API(OSB API)。 >### OpenShift 服务目录概述 tn2>在本书所用到的OpenShift 3.11 版本中会默认安装两个服务中介:ansible-service-broker 和 template-service-broker.两个中介都提供了多个服务,两者的区别是,前者通过Ansible playbook部署服务,后者通过OpenShift template部署服务。服务中介甚至不必在企业内部,公有云提供商AWS、Azure和Google已实现了服务中介,用于在他们的公有云上创建各种服务实例,然后将服务中介注册到企业OpenShift容器云平台上,这样企业内用户就可以搜索这些服务,按需创建并绑定到企业应用上了。 在OpenShift容器云平台中启动服务目录功能之前,需要在Ansible 清单文件中添加如下配置。 ```bash openshift_enable_service_catalog=true openshift_service_catalog_image_prefix=openshift/origin- openshift_service_catalog_image_version="3.11" ```