Kubernetes 账户
所有Kubernetes集群有两类用户:由Kubernetes管理的Service Accounts (服务账户)和(Users Accounts) 普通账户。
普通账户是假定被外部或独立服务管理的,由管理员分配keys,用户像使用Keystone或google账号一样,被存储在包含usernames和passwords的list的文件里。
需要注意:在Kubernetes中不能通过API调用将普通用户添加到集群中。
相比之下,Service Accounts是由Kubernetes API管理的帐户。它们被绑定到特定的命名空间,并由APIserver自动创建或通过API调用手动创建。Service Accounts与存储为Secrets的一组证书相关联,这些凭据被挂载到pod中,以便集群进程与Kubernetes API通信。
验证策略
Kubernetes用户可以使用client certificates、bearer tokens、authenticating proxy、HTTP basic auth等认证插件来验证API请求。比如HTTP请求到达API Server,插件会尝试将以下属性与请求关联:
- UserName:普通用户的字符串。比如“kube-admin”或“[email protected]”。
- UID:普通用户的字符串,比UserName更具有唯一性。
- Groups:一组字符串,将常用的user分组的组合字符串。
- Extra fields:将一些有用的字符串信息映射成的列表。
所有values值对于认证系统都是不透明的,只有当授权解释后才有意义。
可以同时启用多个认证方法。最少使用两种:
- 为Service Accounts使用service account tokens方法。
- 使用另外一种用户认证方法。
system:authenticated组被包括在所有已认证用户的组列表中。
X509 客户证书
使用API Server启动时配置–client-ca-file = SOMEFILE选项来启用客户端证书认证。引用的文件必须包含,提交给API Server的客户端证书的证书颁发机构。如果客户端提交的证书通过,通用名称(common name)将被用作请求的用户名。
例如,使用openssl命令管理工具生成证书签名请求:
openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"
将为“jbeda”用户名创建一个CSR,所属组为”app1”和“app2”的签名请求。
Static Token File
启动静态Token文件需要API Server启动时配置- -token-auth-file=SOMEFILE选项时,目前,tokens状态可以持续存在,需要重新启用 API server,token last 才会重启。
token文件是至少包含3列的csv格式文件: token, user name, user uid,第四列为可选group 名项。注意:如果有多个group名,列必须用””双引号包含其中,例如
token,user,uid,"group1,group2,group3"
Putting a Bearer Token in a Request
当http客户端使用 bearer token 认证时,API Server需要一个值为Bearer THETOKEN的授权头。bearer token必须可以放在HTTP请求头中且值不需要转码和引用的一个字符串。例如:bearer token :31ada4fd-adec-460c-809a-9e56ceb75269,会在HTTP header中按下面的方式呈现:
Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269
Bootstrap Tokens
功能目前为Alpha级别
Kubernetes包括一个dynamically-managed的Bearer token类型,称为Bootstrap Token。这些token作为Secret存储在kube-system namespace中,可以动态管理和创建。Controller Manager包含一个TokenCleaner Controller,如果到期时可以删除Bootstrap Tokens Controller。
Tokens的形式是[a-z0-9]{6}.[a-z0-9]{16}。第一个组件是Token ID,第二个组件是Token Secret。可以在HTTP header中指定Token,如下所示:
Authorization: Bearer 781292.db7bc3a58fc5f07e
如何使用Kubeadm来管理Token,以及想了解更多BootstrapToken文档,请参考Bootstrap Token
Static Password File
Basic Authentication是通过在API Server启动是配置-Basic-authfile=file选项实现,Basic认证凭证一直有效,并且如果没有重新启动API Server,密码将无法更改。
Basic Authentication文件csv也是格式文件,且必须包含:password, user, uid
。在Kubernetes 1.6+版本中,可以指定一个可选的第四列,使用逗号来分隔group名,如果有多个组,必须使用双引号(“)。参考以下示例:
password,user,uid,"group1,group2,group3"
当从http客户端使用Basic Authentication时,API Server需要在请求头加入Basic BASE64ENCODED(USER:PASSWORD)
。
OpenID Connect Tokens
OpenID Connect 是由一些云提供商支持的OAuth2认证机制,特别是Azure Active Directory,Salesforce和Google。OAuth2协议的主要扩展是增加一个额外字段,返回ID Token的access token。这个token被服务器签名的JSON Web Token (JWT) ,常见的字段如user’s email。
为了鉴定user,认证器使用OAuth2 token响应的id_token 步骤如下:
- 登录identity provider
- identity provider提供一个access_token,id_token和refresh_token
- 在使用kubectl时,使用id_token的—token flag或者直接添加到kubeconfig
- kubectl 在header通过Authorization字段将id_token发送到 API server
- API Server检查配置中证书来确保JWT签名的有效性
- 检查id_token是否过期
- 确保user被授权
- 当被授权API Server会返回对kubectl响应
- kubectl向user提供反馈
由于所有认证需要的数据在id_token中,所以Kubernetes不需要向身份提供者“phone home”,每个请求都是在无状态的模型中,它为认证提供可扩展的解决方案。 也带来了一些挑战:
- Kubernetes没有“web interface”来触发认证过程,没有任何浏览器或接口来收集凭据,这就是为什么需要首先向身份提供者进行认证的原因。
- id_token不能被撤销,它像一个certificate持续时间非常短(只有几分钟),所以每隔几分钟就得到一个新的token。
- 如果不使用kubectl -proxy命令或注入id_token的反向代理,将无法向Kubernetes dashboard 进行认证。
Configuring the API Server
启用插件,请在API Server上配置如下的选项:
Parameter | Description | Example | Required |
- -oidc-issuer-url | URL of the provider which allows the API server to discover public signing keys. Only URLs which use the https:// scheme are accepted. This is typically the provider’s discovery URL without a path, for example “https://accounts.google.com” or “https://login.salesforce.com”. This URL should point to the level below .well-known/openid-configuration |
If the discovery URL is https://accounts.google.com/.well-known/openid-configuration the value should be https://accounts.google.com | 是 |
- -oidc-client-id | A client id that all tokens must be issued for. | kubernetes | 是 |
- -oidc-username-claim | WT claim to use as the user name. By default sub , which is expected to be a unique identifier of the end user. Admins can choose other claims, such as email or name , depending on their provider. However, claims other than email will be prefixed with the issuer URL to prevent naming clashes with other plugins. |
sub | 否 |
- -oidc-groups-claim | JWT claim to use as the user’s group. If the claim is present it must be an array of strings. | groups | 否 |
- -oidc-ca-file | The path to the certificate for the CA that signed your identity provider’s web certificate. Defaults to the host’s root CAs. | /etc/kubernetes/ssl/kc-ca.pem | 否 |
如果--oidc-username-claim选择除Email以外的声明,该值将以--oidc-issuer-url为前缀,以防止与现有Kubernetes名称(例如system:users)的冲突。 例如,如果提供商URL是https://accounts.google.com,username声明映射到jane,该插件对user进行认证为:
https://accounts.google.com#jane
Kubernetes不提供OpenID Connect Identity Provider。可以使用现有公开的OpenID Connect Identity Provider(如Google或其他)。或者可以使用者些CoreOS dex,Keycloak,CloudFoundry UAA或Tremolo Security的OpenUnison。
For an identity provider to work with Kubernetes it must
- 支持OpenID connect discovery;(not all do)
- 在TLS中确保密码有效
- 一个CA签名的证书(商业或个人的)
其他安装设置说明:
使用kubectl
选项1-OIDC AUTHENTICATOR
第一个选择使用oidc authenticator。这个认证需要使用id_token,refresh_token和OIDC client_secret,并会自动更新你的token令牌。
kubectl config set-credentials USER_NAME \ --auth-provider=oidc \ --auth-provider-arg=idp-issuer-url=( issuer url ) \ --auth-provider-arg=client-id=( your client id ) \ --auth-provider-arg=client-secret=( your client secret ) \ --auth-provider-arg=refresh-token=( your refresh token ) \ --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \ --auth-provider-arg=id-token=( your id_token ) \ --auth-provider-arg=extra-scopes=( comma separated list of scopes to add to "openid email profile", optional )
例如,在对身份提供商进行认证之后,运行下面的命令:
kubectl config set-credentials mmosley \ --auth-provider=oidc \ --auth-provider-arg=idp-issuer-url=https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP \ --auth-provider-arg=client-id=kubernetes \ --auth-provider-arg=client-secret=1db158f6-177d-4d9c-8a8b-d36869918ec5 \ --auth-provider-arg=refresh-token=q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXqHega4GAXlF+ma+vmYpFcHe5eZR+slBFpZKtQA= \ --auth-provider-arg=idp-certificate-authority=/root/ca.pem \ --auth-provider-arg=extra-scopes=groups \ --auth-provider-arg=id-token=eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knw
将产生如下配置:
users: - name: mmosley user: auth-provider: config: client-id: kubernetes client-secret: 1db158f6-177d-4d9c-8a8b-d36869918ec5 extra-scopes: groups id-token: eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knw idp-certificate-authority: /root/ca.pem idp-issuer-url: https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP refresh-token: q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXq name: oidc
如果id_token过期,kubectl将尝试使用refresh_token和client_secret来刷新id_token,在kube/.config中存储refresh_token和id_token新的值。
选项 2 - USE THE --TOKEN OPTION
kubectl命令允许你使用--token选项传入一个token。只需将idtoken粘贴到这个选项中:
kubectl --token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL21sYi50cmVtb2xvLmxhbjo4MDQzL2F1dGgvaWRwL29pZGMiLCJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNDc0NTk2NjY5LCJqdGkiOiI2RDUzNXoxUEpFNjJOR3QxaWVyYm9RIiwiaWF0IjoxNDc0NTk2MzY5LCJuYmYiOjE0NzQ1OTYyNDksInN1YiI6Im13aW5kdSIsInVzZXJfcm9sZSI6WyJ1c2VycyIsIm5ldy1uYW1lc3BhY2Utdmlld2VyIl0sImVtYWlsIjoibXdpbmR1QG5vbW9yZWplZGkuY29tIn0.f2As579n9VNoaKzoF-dOQGmXkFKf1FMyNV0-va_B63jn-_n9LGSCca_6IVMP8pO-Zb4KvRqGyTP0r3HkHxYy5c81AnIh8ijarruczl-TK_yF5akjSTHFZD-0gRzlevBDiH8Q79NAr-ky0P4iIXS8lY9Vnjch5MF74Zx0c3alKJHJUnnpjIACByfF2SCaYzbWFMUNat-K1PaUk5-ujMBG7yYnr95xD-63n8CO8teGUAAEMx6zRjzfhnhbzX-ajwZLGwGUBT4WqjMs70-6a7_8gZmLZb2az1cZynkFRj2BaCkVT3A2RrjeEwZEtGXlMqKJ1_I2ulrOVsYx01_yD35-rw get nodes
Webhook Token Authentication
Webhook authentication is a hook for verifying bearer tokens
- - -authentication-token-webhook-config-file 配置文件描述了如何访问远程webhook服务
- - -authentication-token-webhook-cache-ttl 缓存认证时间。默认2分钟
配置文件使用kubeconfig file format。在文件中,“users”指的是API服务器的webhook,“clusters”指的是远程服务。示例如下:
# clusters refers to the remote service. clusters: - name: name-of-remote-authn-service cluster: certificate-authority: /path/to/ca.pem # CA for verifying the remote service. server: https://authn.example.com/authenticate # URL of remote service to query. Must use 'https'. # users refers to the API server's webhook configuration. users: - name: name-of-api-server user: client-certificate: /path/to/cert.pem # cert for the webhook plugin to use client-key: /path/to/key.pem # key matching the cert # kubeconfig files require a context. Provide one for the API server. current-context: webhook contexts: - context: cluster: name-of-remote-authn-service user: name-of-api-sever name: webhook
当客户端使用如上所述的bearer token与API服务器进行认证时,认证webhook通过一个包含token的review 对象来查询远程服务。Kubernetes不会对缺少这样的头的请求提出质疑。( Kubernetes will not challenge a request that lacks such a header.)??
注意 webhook API对象与其他Kubernetes API对象一样受版本兼容性规则的约束,选择需谨慎。
请求主体采用的格式:
{ "apiVersion": "authentication.k8s.io/v1beta1", "kind": "TokenReview", "spec": { "token": "(BEARERTOKEN)" } }
远程服务预计将填写请求的TokenAccessReviewStatus字段,以示登录成功。 响应主体体的“spec”字段被忽略。 bearer token认证成功将返回:
{ "apiVersion": "authentication.k8s.io/v1beta1", "kind": "TokenReview", "status": { "authenticated": true, "user": { "username": "[email protected]", "uid": "42", "groups": [ "developers", "qa" ], "extra": { "extrafield1": [ "extravalue1", "extravalue2" ] } } } }
不成功的请求将返回:
{ "apiVersion": "authentication.k8s.io/v1beta1", "kind": "TokenReview", "status": { "authenticated": false } }
HTTP status codes can be used to supply additional error context
Authenticating Proxy
API服务器可以根据header values配置来识别users ,如X-Remote-User。
- –requestheader-username-headers 必选,不区分大小写。按顺序检查Header names用于识别用户身份,第一包含Value的Header用于username。
- –requestheader-group-headers 1.6+以上,可选,不区分大小写。 建议使用“X-Remote-Group”。按顺序检查Header Names用于识别user’s groups。Header中指定的所有Value均用作Group Names。
- –requestheader-extra-headers-prefix 1.6+以上,可选,不区分大小写。 建议使用“X-Remote-Extra-”。用于查找关于用户的额外信息(通常由配置的授权插件使用)。
例如,使用此配置:
--requestheader-username-headers=X-Remote-User--requestheader-group-headers=X-Remote-Group--requestheader-extra-headers-prefix=X-Remote-Extra-
请求:
GET / HTTP/1.1X-Remote-User: fidoX-Remote-Group: dogsX-Remote-Group: dachshundsX-Remote-Extra-Scopes: openidX-Remote-Extra-Scopes: profile
将会产生的用户信息:
name: fidogroups:- dogs- dachshundsextra: scopes: - openid - profile
为了防止header欺骗,Authenticating Proxy需要在检查请求header之前,向API服务器提交有效的客户端证书,以针对指定的CA进行验证。
–requestheader-client-ca-file 必选, PEM-encoded的证书包。在为用户名检查请求header之前,必须根据指定文件中的证书颁发机构呈现和验证有效的客户端证书。
–requestheader-allowed-names 可选,(common names)通用名称(cn)List。如果设置,则在检查请求header用户名之前,必须提交List中指定(common names)通用名中有效的客户端证书。
Keystone Password
Keystone认证通过--experimental-keystone-url=<AuthURL> 在启动期间将选项传递给API服务器来启用。该插件已实现,plugin/pkg/auth/authenticator/password/keystone/keystone.go目前使用basic auth来验证用户名和密码。
如果为Keystone服务器配置了自签名证书,则需要--experimental-keystone-ca-file=SOMEFILE在启动Kubernetes API服务器时设置该选项。设置完成后Keystone服务器的证书将由其中一个authorities进行验证 experimental-keystone-ca-file。否则将由主机的根证书颁发机构验证。
有关如何使用keystone管理项目和users的详细信息,请参阅 Keystone文档。需要注意此插件目前处于测试开发阶段。
更多详细信息,请参阅 discussion、blueprint、proposed changes