身份认证和访问控制包含两部分基本功能:认证和授权。认证即判断用户是否为能够访问集群的合法用户,授权负责管理指定用户对资源的访问权限。
ACK集群的认证和授权
Kubernetes使用X.509证书、Bearer Tokens、身份验证代理或者OIDC认证等方式来对API请求进行身份验证。关于ACK原生、访问ACK集群的两种方式,请参见客户端证书、服务账户令牌。
客户端证书KubeConfig可以通过阿里云控制台、ACK的OpenAPI接口等方式获取。更多信息,请参见获取集群KubeConfig接口。
容器服务 Kubernetes 版授权包含RAM授权和RBAC授权两部分。当您需要对集群进行可见性、扩缩容、添加节点等操作时,需要进行自定义RAM授权策略。目前RAM主要支持RAM系统策略授权和RAM自定义策略授权两种授权方式。当RAM用户需要操作指定集群内K8s资源时(例如,获取集群Pod和Node信息),需要在容器服务管理控制台的授权管理页面对指定RAM用户进行数据平面资源的RBAC授权。更多信息,请参见授权概述。
使用临时KubeConfig和Apiserver认证
ACK默认返回的集群访问凭证KubeConfig中的证书有效期是3年,若KubeConfig发生泄露,攻击者可以直接获得集群Apiserver的访问权限。默认的ServiceAccount Token同样是一种长期有效的静态凭据,如果泄露,攻击者同样可以获得该ServiceAccount绑定的集群访问权限,直到该ServiceAccount被删除。
因此请您及时吊销可能发生泄露的已下发KubeConfig凭证。具体操作,请参见吊销集群的KubeConfig凭证。关于ACK集群的访问凭证,请参见生成临时的KubeConfig。
遵循权限最小化原则访问阿里云资源
如果某个用户需要访问ACK集群,无需为用户分配访问其他云产品资源的权限,保证用户访问云产品资源权限最小化。可以通过配置RAM和RBAC为该用户授予访问ACK集群的权限。
在创建RoleBindings和ClusterRoleBindings时使用最低访问权限
和授予访问云资源的权限一样,在创建
RoleBindings
和ClusterRoleBindings
时,同样需要遵循权限最小化原则。应该尽量避免在创建Role
和ClusterRole
时使用["*"]
,应该明确到具体的Verbs
。如果您不确定要分配哪些权限,请考虑使用类似audit2rbac之类的工具,根据Kubernetes
审计日志中观察到的API调用自动生成角色和绑定。控制ACK集群Endpoint的访问范围
默认情况下,当您配置ACK集群时,集群的Apiserver Endpoint仅为内网访问,即仅可以集群和VPC内部访问。关于创建出来的Service能够实现公网访问并控制Endpoint的访问范围,请参见通过Annotation配置传统型负载均衡CLB。
定期对集群的访问权限进行审计
对集群的访问权限可能会随着时间的推移而改变。需要集群的安全管理运维人员定期审核RAM配置以及为RAM用户配置的RBAC权限,来查看指定RAM用户是否被分配了合适的权限,或者使用开源工具来检查绑定到特定服务账户、用户或组的RBAC权限,并及时收敛不符合需要的过大权限配置。请参见kubectl-who-can和rbac-lookup。
Pods认证
在Kubernetes集群中运行的某些应用程序需要调用Kubernetes API的权限才能正常运行。ACK CCM组件需要对Nodes资源进行增删改查权限。
Kubernetes Service Accounts
服务账户(Service Accounts)是一种特殊类型的对象,允许您将Kubernetes RBAC角色分配给Pod。K8s会为集群中的每个命名空间自动创建一个默认服务账户。当您在不引用特定服务账户的情况下将Pod部署到命名空间时,该命名空间的默认服务账户将自动分配给Pod和Secret,即该服务账户的服务账户(JWT)令牌,将挂载到Pod作为一个卷位于/var/run/secrets/kubernetes.io/serviceaccount。解码该目录中的服务账户令牌将显示以下元数据:
{ "iss": "kubernetes/serviceaccount", "kubernetes.io/serviceaccount/namespace": "default", "kubernetes.io/serviceaccount/secret.name": "default-token-vpc2x", "kubernetes.io/serviceaccount/service-account.name": "default", "kubernetes.io/serviceaccount/service-account.uid": "1d059c50-0818-4b15-905d-bbf05e1d****", "sub": "system:serviceaccount:default:default" }
默认服务账户对Kubernetes API具有以下权限:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults name: system:discovery rules: - nonResourceURLs: - /api - /api/* - /apis - /apis/* - /healthz - /openapi - /openapi/* - /version - /version/ verbs: - get
此角色授予未经身份验证和经过身份验证的用户读取API信息,并被视为可公开访问的安全角色。
当在Pod中运行的应用程序调用Kubernetes API时,需要为Pod分配一个服务账户,明确授予其调用API的权限。绑定到服务账户的Role或ClusterRole应仅限于应用程序运行所需的API资源和方法,遵循权限最小化原则。要使用非默认服务账户,只需将Pod的
spec.serviceAccountName
字段设置为您希望使用的服务账户。有关创建服务账户的其他信息,请参见ServiceAccount permissions。部署服务账户令牌卷投影
您可以在容器服务ACK中开启服务账户令牌卷投影功能以降低在Pod中使用ServiceAccount遇到的安全性问题,此功能使得Kubelet支持基于Pod粒度的Token签发,并且支持Token audience和过期时间的配置。当Token即将过期(过期时间的80%或者Token存在大于24小时),Kubelet支持对Token的自动刷新。具体操作,请参见使用ServiceAccount Token卷投影。
限制节点对实例元数据API的访问
ECS实例元数据概述包含了ECS实例在阿里云系统中的信息,您可以在运行中的实例内方便地查看实例元数据,并基于实例元数据配置或管理实例。实例元数据中能够查询到用户使用的云资源和用户数据等敏感信息,若不加限制地暴露给节点,在多租户等场景下很容易被攻击者利用。对于没有出网需求的应用Pod,可以通过NetworkPolicy限制Pod对于meta-server的访问。可以通过如下规则使用
podSelector
控制指定Pod对包括meta-server在内的所有出网访问。apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-metadata-access namespace: example spec: podSelector: matchLabels: app: myapp policyTypes: - Egress egress: []
更多信息,请参见在ACK集群使用网络策略。
禁止Pod对Service Account令牌的自动挂载
可通过以下两种方式取消Pod对Service Account令牌的自动挂载。
方式一:通过修改YAML将应用程序PodSpec字段中的
automountServiceAccountToken
属性设置为false
。apiVersion: v1 kind: Pod metadata: name: my-pod spec: serviceAccountName: build-robot automountServiceAccountToken: false ...
方式二:执行以下命令,patch命名空间中的默认服务账户,将
automountServiceAccountToken
属性设置为false
。kubectl patch serviceaccount default -p $'automountServiceAccountToken: false'
为每个应用分配独立的Service Account
每个应用程序都应该有自己专用的服务账户,便于不同应用之间的授权管理,实现应用维度的细粒度权限隔离。关于为应用分配独立的服务账户,请参见为Pod配置服务账户。
以非root用户运行应用
默认情况下,容器以root身份运行。这允许容器中的进程对容器中的文件进行任意的读取和写入,但以root身份运行容器并不是最佳安全实践。作为替代方案,请考虑将
spec.securityContext.runAsUser
属性添加到PodSpec
。runAsUser
的值为任意值。在以下示例中,Pod中的所有进程都将在
runAsUser
字段中指定的用户ID下运行。apiVersion: v1 kind: Pod metadata: name: security-test spec: securityContext: runAsUser: 1000 runAsGroup: 3000 containers: - name: sec-test image: busybox command: [ "sh", "-c", "sleep 1h" ]
此时,对于容器中需要root权限才能访问的文件,容器中的进程则无法访问。如果您更新容器的
securityContext
,使其包含fsgroup=65534 [Nobody]
,将允许读取容器中的文件。spec: securityContext: fsGroup: 65534
遵循权限最小化原则分配应用对云上阿里云资源的访问权限
避免为应用所在节点分配不必要的RAM权限,遵循权限最小化原则细粒度定制应用所需的RAM策略,避免在权限策略中出现
["*"]
等可能扩大访问权限的配置。
Authenticator Webhook认证
对于通过RAM SSO集成以及对Kubernetes RBAC授权管理有独立运维经验的用户,推荐通过ack-ram-authenticator完成ACK托管集群API Server的Webhook认证,通过使用ack-ram-authenticator,可以实现如下优势:
对于使用Authenticator KubeConfig的Apiserver请求,审计日志会记录SSO场景下企业IDP中的身份信息,对扮演同一角色的不同IDP用户的行为进行审计。
灵活可控的数据面RBAC授权体验。
当删除RAM用户或角色时,可自动吊销其已下发的Authenticator KubeConfig凭据权限。