KEMBAR78
Introduction to Kubernetes RBAC | PDF
Introduction to Kubernetes RBAC
Oleg Chunikhin | CTO, Kublr
Tuesday September 15, 2020
Thursday March 18, 2021 (alternative date)
@ Red Cross Square in Downtown DC
DC Meetup Slack Channel
Join our meetup-dc channel on the
Kubernetes Slack
Introductions
Oleg Chunikhin
CTO, Kublr
• 20 years in software architecture &
development
• Working w/ Kubernetes since its release in 2015
• Software architect behind Kublr—an enterprise
ready container management platform
• Twitter @olgch
Enterprise Kubernetes Needs
Developers SRE/Ops/DevOps/SecOps
• Self-service
• Compatible
• Conformant
• Configurable
• Open & Flexible
• Governance
• Org multi-tenancy
• Single pane of glass
• Operations
• Monitoring
• Log collection
• Image management
• Identity management
• Security
• Reliability
• Performance
• Portability
@olgch; @kublr
@olgch; @kublr
Automation
Ingress
Custom
Clusters
Infrastructure
Logging Monitoring
Observability
API
Usage
Reporting
RBAC IAM
Air Gap TLS
Certificate
Rotation
Audit
Storage Networking Container
Registry
CI / CD App Mgmt
Infrastructure
Container Runtime Kubernetes
OPERATIONS SECURITY &
GOVERNANCE
Kubernetes Access Control
• Who can do what with which resource
• Authentication
• Authorization
• RBAC
• Use-cases and gotchas
@olgch; @kublr
Who Can Do What in a Cluster
Three groups
Connected through access control
@olgch; @kublr
Subjects
User
Group
Service account
Resources
Pods
Nodes
ConfigMaps
Secrets
Deployments
…
Operations
list
get
create
update
delete
watch
patch
get
post
put
delete
Kubernetes API Request Attributes
• Authentication
• User – the user string
• Group – the list of group names
• Extra – a map of arbitrary keys
• API – non-resource or API resource flag
• API resource request
• API request verb – lowercased resource verb
• Namespace – the namespace
• API group - The API Group being accessed
• Resource – the resource ID
• Subresource – the sub-resource
• Non-resource request
• HTTP request verb – lowercased HTTP method
• Request path – non-resource request path.
Verbs
• Common API resource request :
get, list, watch,
create, update, patch,
delete, deletecollection
• Special API resource request:
use (PodSecurityPolicy),
bind, escalate (Role, ClusterRole),
impersonate (User, Group, SA),
userextras
• HTTP request verbs:
get, head, post, put,
patch, delete
@olgch; @kublr
Kubernetes API Client, Tools
• Any HTTP client
• curl – good for experiments
• kubectl – Kubernetes CLI
• jq – honorable mention – JSON visualization and processing
@olgch; @kublr
Client Kubernetes API
HTTP Request
Kubernetes API Client, Example
• curl
• kubectl
@olgch; @kublr
curl -k -v -XGET -H 'Authorization: Bearer ***' 
'https://52.44.121.181:443/api/v1/nodes?limit=50' | jq .
kubectl --kubeconfig=kc.yaml get nodes
export KUBECONFIG="$(pwd)/config.yaml"
kubectl get nodes
kubectl get nodes –-v=9
apiVersion: v1
kind: Config
clusters:
- name: demo-rbac
cluster:
certificate-authority-data: ***
server: https://52.44.121.181:443
users:
- name: demo-rbac-admin-token
user:
token: ***
contexts:
- name: demo-rbac
context:
cluster: demo-rbac
user: demo-rbac-admin-token
current-context: demo-rbac
Authentication: Mechanisms
Mechanism Secret Source Usage
X509 Client Certs CSR generated externally and
signed with the cluster CA key
Enterprise CA / PKI
Via Kubernetes API
CertificateSigningRequest
Kubernetes cluster admin
Bearer token Bootstrap token Internal use
Node authentication token Internal use
Static token file Insecure
ServiceAccount token Pods, containers, applications, users
OIDC token Users
HTTP Basic auth Static password file Insecure
Auth proxy N/A (trust proxy) Integration
Impersonate N/A (trust account) Integration and administration
Authentication: X509 Client Cert, PKI
Client Kubernetes API
3. HTTPS/TLS handshake with client cert
4. Request
Admin
1. client.csr 2. client.crt
client.key k8s-api-server-client-ca.key
k8s-api-server-client-ca.crt
--client-ca-file=k8s-api-server-client-ca.key
k8s-api-server-client-ca.key
Admin (issuer) must has access to
the server CA private key
@olgch; @kublr
Authentication: X509 Client Cert, PKI Example
• User: generate user private key (if not exist)
• User: generate user CSR
• Admin: sign user client cert
• User: use with kubectl via options or kubeconfig
openssl genrsa -out user1.key 2048
openssl req -new -key user1.key -out user1.csr -subj "/CN=user1/O=group1/O=group2"
openssl x509 -req -in user1.csr -CA cluster-ca.crt -CAkey cluster-ca.key 
-set_serial 101 -extensions client -days 365 -outform PEM -out user1.crt
kubectl --client-key=user1.key --client-certificate=user1.crt get nodes
kubectl config set-credentials user1 --client-key user1.key --client-certificate user1.crt --embed-certs
kubectl config set-context user1 --cluster demo-rbac --user user1
kubectl --context=user1 get nodes
kubectl config use-context user1
kubectl config get-contexts
kubectl get nodes
@olgch; @kublr
Authentication: X509 Client Cert, K8S CSR
Client Kubernetes API
7. HTTPS/TLS handshake with client cert
8. Request
Admin
1. client.csr 6. client.crt
client.key k8s-api-server-client-ca.key
k8s-api-server-client-ca.crt
--client-ca-file=k8s-api-server-client-ca.key
3. kubectl create csr ...
4. kubectl certificate approve csr ...
5. kubectl get csr ...
@olgch; @kublr
Authentication: X509 Client Cert, K8S CSR
• User: generate user CSR
• Admin: use Kubernetes API server to sign the CSR
• User: use with kubectl via options or kubeconfig
openssl req -new -key user2.key -out user2.csr -subj "/CN=user2/O=group1/O=group2"
kubectl apply -f - <<EOF
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: user2
spec:
request: $(cat user2.csr | base64 | tr -d 'n')
usages: ['digital signature', 'key encipherment',
'client auth']
EOF
kubectl certificate approve user2
kubectl certificate deny user2
kubectl get csr user2 –o jsonpath='{.status.certificate}' | 
base64 --decode > user2.crt
kubectl --client-key=user2.key --client-certificate=user2.crt get nodes
kubectl config set-credentials user2 --client-key user2.key --client-certificate user2.crt --embed-certs
kubectl config set-context user2 --cluster demo-rbac --user user2
@olgch; @kublr
Authentication: Service Account
Client Kubernetes API
1. create service account
2. get service account token
3. Request (token in Authorization header)
@olgch; @kublr
Authentication: Service Account, Example
• Create service account
• Get service account token
• Send request
kubectl create serviceaccount sa1
kubectl "--token=${SA_TOKEN}" get nodes
kubectl config set-credentials sa1 "--token=${SA_TOKEN}"
kubectl config set-context sa1 --cluster demo-rbac --user sa1
kubectl get –o yaml sa sa1
SA_SECRET="$(kubectl get sa sa1 -o jsonpath='{.secrets[0].name}')"
kubectl get -o yaml secret "${SA_SECRET}"
SA_TOKEN="$(kubectl get secret "${SA_SECRET}" -o jsonpath='{.data.token}' | base64 -d)"
@olgch; @kublr
Authentication: OIDC
Client Kubernetes API
3. Request with the token
1. auth / refresh token
2. Tokens
--oidc-client-id=kubernetes
--oidc-groups-claim=user_groups
--oidc-issuer-url=https://idp.example.com
--oidc-username-claim=preferred_username
OIDC IdP
4. Verify token
@olgch; @kublr
Authentication: OIDC, Demo
Kublr uses Keycloak by default
• Multiple “realms”
• OIDC, SAML, LDAP, AD, Kerberos support
• User federation and Identity Broker support
Demo
• “demo-app” realm
• “kubernetes” OIDC client
• “demo-rbac” Kublr cluster with OIDC auth configured for the client
spec:
master:
kublrAgentConfig:
kublr:
kube_api_server_flag:
oidc_client_id: '--oidc-client-id=kubernetes'
oidc_groups_claim: '--oidc-groups-claim=user_groups'
oidc_issuer_url: '--oidc-issuer-url=https://***'
oidc_username_claim: '--oidc-username-claim=preferred_username'
@olgch; @kublr
Authentication: OIDC, Example
Login (visualization)
Login (CLI)
curl 
-d "grant_type=password" 
-d "scope=openid" 
-d "client_id=kubernetes" 
-d "client_secret=${CLIENT_SECRET}" 
-d "username=da-admin" 
-d "password=${USER_PASSWORD}" 
https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | jq .
eval "$(curl -d "grant_type=password" -d "scope=openid" -d "client_id=kubernetes" 
-d "client_secret=${CLIENT_SECRET}" -d "username=da-admin" -d "password=${USER_PASSWORD}" 
https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | 
jq -r '"REFRESH_TOKEN="+.refresh_token,"TOKEN="+.access_token,"ID_TOKEN="+.id_token')" ; 
echo ; echo "TOKEN=${TOKEN}" ; echo ; echo "ID_TOKEN=${ID_TOKEN}" ; echo ; 
echo "REFRESH_TOKEN=${REFRESH_TOKEN}" ; echo
@olgch; @kublr
Authentication: OIDC, Example
Refresh (visualization)
Refresh (CLI)
curl 
-d "grant_type=refresh_token" 
-d "client_id=kubernetes" 
-d "client_secret=${CLIENT_SECRET}" 
-d "refresh_token=${REFRESH_TOKEN}" 
https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | jq -r .
eval "$(curl -d "grant_type=refresh_token" -d "client_id=kubernetes" 
-d "client_secret=${CLIENT_SECRET}" -d "refresh_token=${REFRESH_TOKEN}" 
https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | 
jq -r '"REFRESH_TOKEN="+.refresh_token,"TOKEN="+.access_token,"ID_TOKEN="+.id_token')" ; 
echo ; echo "TOKEN=${TOKEN}" ; echo ; echo "ID_TOKEN=${ID_TOKEN}" ; echo ; 
echo "REFRESH_TOKEN=${REFRESH_TOKEN}"
@olgch; @kublr
Authentication: OIDC, Example
Token introspection
kubectl configuration
curl 
--user "kubernetes:${CLIENT_SECRET}" 
-d "token=${TOKEN}" 
https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token/introspect | jq .
kubectl config set-credentials da-admin 
"--auth-provider=oidc" 
"--auth-provider-arg=idp-issuer-url=https://kcp.kublr-demo.com/auth/realms/demo-app" 
"--auth-provider-arg=client-id=kubernetes" 
"--auth-provider-arg=client-secret=${CLIENT_SECRET}" 
"--auth-provider-arg=refresh-token=${REFRESH_TOKEN}" 
"--auth-provider-arg=id-token=${ID_TOKEN}"
kubectl config set-context da-admin --cluster=demo-rbac --user=da-admin
kubectl --context=da-admin get nodes
@olgch; @kublr
Authentication: Authenticating Proxy
Client Kubernetes API
2. Request “X-Remote-*” headers
X-Remote-User: user1
X-Remote-Groups: group1
X-Remote-Extra-Key1: value11. Request
--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-
Auth Proxy
@olgch; @kublr
Authentication: Impersonation
Client Kubernetes API
1. Request with “Impersonate-*” headers
Impersonate-User: jane.doe@example.com
Impersonate-Group: developers
Impersonate-Group: admins
Impersonate-Extra-dn: cn=jane,ou=engineers
Impersonate-Extra-scopes: view
kubectl get nodes 
--as "system:serviceaccount:default:sa1" 
--as-group g1 
--as-group g2
@olgch; @kublr
Authorization: Mechanisms
Mechanism Decision source Usage
Node API Server built-in Internal use (kubelets)
ABAC Static file Insecure, deprecated
RBAC API Objects Users and administrators
WebHook External services Integration
AlwaysDeny
AlwaysAllow
API Server built-in Testing
@olgch; @kublr
Authorization, tools
• kubectl auth can-i ...
• kubectl whoami
• kubectl --v=8 ...
@olgch; @kublr
Authorization: WebHook
Client Kubernetes API
1. Request
--authorization-webhook-config-file=auth-cfg.yaml
Authorization
Service
2. Verify
Config file in kubeconfig format
@olgch; @kublr
Authorization: RBAC
Three groups
Connected through RBAC
@olgch; @kublr
Subjects
User
Group
Service Account
Resources
Pods
Nodes
ConfigMaps
Secrets
Deployments
…
Operations
list
get
create
update
delete
watch
patch
get
post
put
delete
Roles and ClusterRoles
• Roles and ClusterRoles define a set of
allowed actions on resources
• Role is namespaced
• Cannot include non-namespaces
resources or non-resource URLs
@olgch; @kublr
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: role1
rules:
- apiGroups: ['*']
resources: ['nodes', 'pods', 'pods/log']
verbs: ['get', 'list']
- apiGroups: ['*']
resources: ['configmaps']
resourceNames: ['my-configmap']
verbs: ['get', 'list']
ClusterRoles
• ClusterRole is not namespaced
• non-namespaced resources access
• non-resource URLs access
@olgch; @kublr
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: clusterRole1
rules:
- apiGroups: ['*']
resources: ['nodes', ‘pods']
verbs: ['get', 'list']
- nonResourceURLs: ['/api', '/healthz*']
verbs: ['get', 'head']
Aggregated ClusterRoles
Aggregated ClusterRole combines rules from other cluster roles
@olgch; @kublr
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: aggregatedClusterRole1
aggregationRule:
clusterRoleSelectors:
- matchLabels:
label1: value1
# The control plane automatically fills in the rules
rules: []
Aggregated
ClusterRole
clusterRole1
aggregationRule:
clusterRoleSelectors:
- matchLabels:
label1: value1
metadata:
labels:
label1: value1
clusterRole1
metadata:
labels:
label1: value1
label2: value2
clusterRole1
metadata:
labels:
label2: value2
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleBinding1
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role1
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user1
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: group1
- kind: ServiceAccount
name: sa1
namespace: default
RoleBinding
@olgch; @kublr
user1 user2
group
RoleBinding
namespace
resources only
ClusterRole
Role
namespace
ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: roleBinding1
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: clusterRole1
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user1
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: group1
- kind: ServiceAccount
name: sa1
namespace: default
ClusterRoleBinding
@olgch; @kublr
user1 user2
group
ClusterRole
Role
namespace
ServiceAccount
ClusterRoleBinding
Built-in ClusterRoles
Role Access Can do
cluster-admin Full access to all cluster resources Anything in the cluster
admin Full access to all namespace resources Anything in a namespace
edit Full access to all namespace resources
except Role, RoleBinding,
LocalSubjectAccessReviews
Anything in a namespace except granting and
checking access
view RO access to all namespace resources
except sensitive ones
View and list non-sensitive objects in a
namespace
@olgch; @kublr
Use-cases
• Start with build-in roles
•Cluster admin
•Namespace admin
•Namespace developer
•Namespace read-only user
• Define new roles as needed
• Beware of “gotchas”
@olgch; @kublr
“Gotchas”
• Privilege escalation via pod creation
• Non-namespaced objects
• CRD, PriorityClass, PodSecurityPolicy
• Often needed for development, especially in advanced DevOps / SRE culture
• As a result, developers need self-service dev cluster management capabilities
• Role and role binding conventions
• Name
• Role bindings – one per subject, one per role, or mixed
@olgch; @kublr
Next steps
• PodSecurityPolicy
• NetworkPolicy
• Limits and Quotas
• Admission Controllers
• Dynamic admission control
• Dynamic policies, OPA
@olgch; @kublr
Kubernetes API Groups and Objects
API Group API Obects
rbac.authorization.k8s.io/v1 ClusterRole
Role
ClusterRoleBinding
RoleBinding
authentication.k8s.io/v1 TokenReview
admissionregistration.k8s.io/v1 MutatingWebhookConfiguration
ValidatingWebhookConfiguration
authorization.k8s.io/v1 LocalSubjectAccessReview
SelfSubjectAccessReview
SelfSubjectRulesReview
SubjectAccessReview
certificates.k8s.io/v1beta1 CertificateSigningRequest
policy/v1beta1 PodSecurityPolicy
@olgch; @kublr
References
https://github.com/rajatjindal/kubectl-whoami
https://kubernetes.io/docs/reference/access-authn-authz/rbac/
https://kubernetes.io/docs/concepts/cluster-administration/certificates/
https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/
@olgch; @kublr
Q&A
@olgch; @kublr
Oleg Chunikhin
CTO
oleg@kublr.com
@olgch
Kublr | kublr.com
@kublr
Signup for our newsletter
at kublr.com
@olgch; @kublr

Introduction to Kubernetes RBAC

  • 1.
    Introduction to KubernetesRBAC Oleg Chunikhin | CTO, Kublr
  • 2.
    Tuesday September 15,2020 Thursday March 18, 2021 (alternative date) @ Red Cross Square in Downtown DC
  • 3.
    DC Meetup SlackChannel Join our meetup-dc channel on the Kubernetes Slack
  • 4.
    Introductions Oleg Chunikhin CTO, Kublr •20 years in software architecture & development • Working w/ Kubernetes since its release in 2015 • Software architect behind Kublr—an enterprise ready container management platform • Twitter @olgch
  • 5.
    Enterprise Kubernetes Needs DevelopersSRE/Ops/DevOps/SecOps • Self-service • Compatible • Conformant • Configurable • Open & Flexible • Governance • Org multi-tenancy • Single pane of glass • Operations • Monitoring • Log collection • Image management • Identity management • Security • Reliability • Performance • Portability @olgch; @kublr
  • 6.
    @olgch; @kublr Automation Ingress Custom Clusters Infrastructure Logging Monitoring Observability API Usage Reporting RBACIAM Air Gap TLS Certificate Rotation Audit Storage Networking Container Registry CI / CD App Mgmt Infrastructure Container Runtime Kubernetes OPERATIONS SECURITY & GOVERNANCE
  • 7.
    Kubernetes Access Control •Who can do what with which resource • Authentication • Authorization • RBAC • Use-cases and gotchas @olgch; @kublr
  • 8.
    Who Can DoWhat in a Cluster Three groups Connected through access control @olgch; @kublr Subjects User Group Service account Resources Pods Nodes ConfigMaps Secrets Deployments … Operations list get create update delete watch patch get post put delete
  • 9.
    Kubernetes API RequestAttributes • Authentication • User – the user string • Group – the list of group names • Extra – a map of arbitrary keys • API – non-resource or API resource flag • API resource request • API request verb – lowercased resource verb • Namespace – the namespace • API group - The API Group being accessed • Resource – the resource ID • Subresource – the sub-resource • Non-resource request • HTTP request verb – lowercased HTTP method • Request path – non-resource request path. Verbs • Common API resource request : get, list, watch, create, update, patch, delete, deletecollection • Special API resource request: use (PodSecurityPolicy), bind, escalate (Role, ClusterRole), impersonate (User, Group, SA), userextras • HTTP request verbs: get, head, post, put, patch, delete @olgch; @kublr
  • 10.
    Kubernetes API Client,Tools • Any HTTP client • curl – good for experiments • kubectl – Kubernetes CLI • jq – honorable mention – JSON visualization and processing @olgch; @kublr Client Kubernetes API HTTP Request
  • 11.
    Kubernetes API Client,Example • curl • kubectl @olgch; @kublr curl -k -v -XGET -H 'Authorization: Bearer ***' 'https://52.44.121.181:443/api/v1/nodes?limit=50' | jq . kubectl --kubeconfig=kc.yaml get nodes export KUBECONFIG="$(pwd)/config.yaml" kubectl get nodes kubectl get nodes –-v=9 apiVersion: v1 kind: Config clusters: - name: demo-rbac cluster: certificate-authority-data: *** server: https://52.44.121.181:443 users: - name: demo-rbac-admin-token user: token: *** contexts: - name: demo-rbac context: cluster: demo-rbac user: demo-rbac-admin-token current-context: demo-rbac
  • 12.
    Authentication: Mechanisms Mechanism SecretSource Usage X509 Client Certs CSR generated externally and signed with the cluster CA key Enterprise CA / PKI Via Kubernetes API CertificateSigningRequest Kubernetes cluster admin Bearer token Bootstrap token Internal use Node authentication token Internal use Static token file Insecure ServiceAccount token Pods, containers, applications, users OIDC token Users HTTP Basic auth Static password file Insecure Auth proxy N/A (trust proxy) Integration Impersonate N/A (trust account) Integration and administration
  • 13.
    Authentication: X509 ClientCert, PKI Client Kubernetes API 3. HTTPS/TLS handshake with client cert 4. Request Admin 1. client.csr 2. client.crt client.key k8s-api-server-client-ca.key k8s-api-server-client-ca.crt --client-ca-file=k8s-api-server-client-ca.key k8s-api-server-client-ca.key Admin (issuer) must has access to the server CA private key @olgch; @kublr
  • 14.
    Authentication: X509 ClientCert, PKI Example • User: generate user private key (if not exist) • User: generate user CSR • Admin: sign user client cert • User: use with kubectl via options or kubeconfig openssl genrsa -out user1.key 2048 openssl req -new -key user1.key -out user1.csr -subj "/CN=user1/O=group1/O=group2" openssl x509 -req -in user1.csr -CA cluster-ca.crt -CAkey cluster-ca.key -set_serial 101 -extensions client -days 365 -outform PEM -out user1.crt kubectl --client-key=user1.key --client-certificate=user1.crt get nodes kubectl config set-credentials user1 --client-key user1.key --client-certificate user1.crt --embed-certs kubectl config set-context user1 --cluster demo-rbac --user user1 kubectl --context=user1 get nodes kubectl config use-context user1 kubectl config get-contexts kubectl get nodes @olgch; @kublr
  • 15.
    Authentication: X509 ClientCert, K8S CSR Client Kubernetes API 7. HTTPS/TLS handshake with client cert 8. Request Admin 1. client.csr 6. client.crt client.key k8s-api-server-client-ca.key k8s-api-server-client-ca.crt --client-ca-file=k8s-api-server-client-ca.key 3. kubectl create csr ... 4. kubectl certificate approve csr ... 5. kubectl get csr ... @olgch; @kublr
  • 16.
    Authentication: X509 ClientCert, K8S CSR • User: generate user CSR • Admin: use Kubernetes API server to sign the CSR • User: use with kubectl via options or kubeconfig openssl req -new -key user2.key -out user2.csr -subj "/CN=user2/O=group1/O=group2" kubectl apply -f - <<EOF apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: user2 spec: request: $(cat user2.csr | base64 | tr -d 'n') usages: ['digital signature', 'key encipherment', 'client auth'] EOF kubectl certificate approve user2 kubectl certificate deny user2 kubectl get csr user2 –o jsonpath='{.status.certificate}' | base64 --decode > user2.crt kubectl --client-key=user2.key --client-certificate=user2.crt get nodes kubectl config set-credentials user2 --client-key user2.key --client-certificate user2.crt --embed-certs kubectl config set-context user2 --cluster demo-rbac --user user2 @olgch; @kublr
  • 17.
    Authentication: Service Account ClientKubernetes API 1. create service account 2. get service account token 3. Request (token in Authorization header) @olgch; @kublr
  • 18.
    Authentication: Service Account,Example • Create service account • Get service account token • Send request kubectl create serviceaccount sa1 kubectl "--token=${SA_TOKEN}" get nodes kubectl config set-credentials sa1 "--token=${SA_TOKEN}" kubectl config set-context sa1 --cluster demo-rbac --user sa1 kubectl get –o yaml sa sa1 SA_SECRET="$(kubectl get sa sa1 -o jsonpath='{.secrets[0].name}')" kubectl get -o yaml secret "${SA_SECRET}" SA_TOKEN="$(kubectl get secret "${SA_SECRET}" -o jsonpath='{.data.token}' | base64 -d)" @olgch; @kublr
  • 19.
    Authentication: OIDC Client KubernetesAPI 3. Request with the token 1. auth / refresh token 2. Tokens --oidc-client-id=kubernetes --oidc-groups-claim=user_groups --oidc-issuer-url=https://idp.example.com --oidc-username-claim=preferred_username OIDC IdP 4. Verify token @olgch; @kublr
  • 20.
    Authentication: OIDC, Demo Kublruses Keycloak by default • Multiple “realms” • OIDC, SAML, LDAP, AD, Kerberos support • User federation and Identity Broker support Demo • “demo-app” realm • “kubernetes” OIDC client • “demo-rbac” Kublr cluster with OIDC auth configured for the client spec: master: kublrAgentConfig: kublr: kube_api_server_flag: oidc_client_id: '--oidc-client-id=kubernetes' oidc_groups_claim: '--oidc-groups-claim=user_groups' oidc_issuer_url: '--oidc-issuer-url=https://***' oidc_username_claim: '--oidc-username-claim=preferred_username' @olgch; @kublr
  • 21.
    Authentication: OIDC, Example Login(visualization) Login (CLI) curl -d "grant_type=password" -d "scope=openid" -d "client_id=kubernetes" -d "client_secret=${CLIENT_SECRET}" -d "username=da-admin" -d "password=${USER_PASSWORD}" https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | jq . eval "$(curl -d "grant_type=password" -d "scope=openid" -d "client_id=kubernetes" -d "client_secret=${CLIENT_SECRET}" -d "username=da-admin" -d "password=${USER_PASSWORD}" https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | jq -r '"REFRESH_TOKEN="+.refresh_token,"TOKEN="+.access_token,"ID_TOKEN="+.id_token')" ; echo ; echo "TOKEN=${TOKEN}" ; echo ; echo "ID_TOKEN=${ID_TOKEN}" ; echo ; echo "REFRESH_TOKEN=${REFRESH_TOKEN}" ; echo @olgch; @kublr
  • 22.
    Authentication: OIDC, Example Refresh(visualization) Refresh (CLI) curl -d "grant_type=refresh_token" -d "client_id=kubernetes" -d "client_secret=${CLIENT_SECRET}" -d "refresh_token=${REFRESH_TOKEN}" https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | jq -r . eval "$(curl -d "grant_type=refresh_token" -d "client_id=kubernetes" -d "client_secret=${CLIENT_SECRET}" -d "refresh_token=${REFRESH_TOKEN}" https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token | jq -r '"REFRESH_TOKEN="+.refresh_token,"TOKEN="+.access_token,"ID_TOKEN="+.id_token')" ; echo ; echo "TOKEN=${TOKEN}" ; echo ; echo "ID_TOKEN=${ID_TOKEN}" ; echo ; echo "REFRESH_TOKEN=${REFRESH_TOKEN}" @olgch; @kublr
  • 23.
    Authentication: OIDC, Example Tokenintrospection kubectl configuration curl --user "kubernetes:${CLIENT_SECRET}" -d "token=${TOKEN}" https://kcp.kublr-demo.com/auth/realms/demo-app/protocol/openid-connect/token/introspect | jq . kubectl config set-credentials da-admin "--auth-provider=oidc" "--auth-provider-arg=idp-issuer-url=https://kcp.kublr-demo.com/auth/realms/demo-app" "--auth-provider-arg=client-id=kubernetes" "--auth-provider-arg=client-secret=${CLIENT_SECRET}" "--auth-provider-arg=refresh-token=${REFRESH_TOKEN}" "--auth-provider-arg=id-token=${ID_TOKEN}" kubectl config set-context da-admin --cluster=demo-rbac --user=da-admin kubectl --context=da-admin get nodes @olgch; @kublr
  • 24.
    Authentication: Authenticating Proxy ClientKubernetes API 2. Request “X-Remote-*” headers X-Remote-User: user1 X-Remote-Groups: group1 X-Remote-Extra-Key1: value11. Request --requestheader-username-headers=X-Remote-User --requestheader-group-headers=X-Remote-Group --requestheader-extra-headers-prefix=X-Remote-Extra- Auth Proxy @olgch; @kublr
  • 25.
    Authentication: Impersonation Client KubernetesAPI 1. Request with “Impersonate-*” headers Impersonate-User: jane.doe@example.com Impersonate-Group: developers Impersonate-Group: admins Impersonate-Extra-dn: cn=jane,ou=engineers Impersonate-Extra-scopes: view kubectl get nodes --as "system:serviceaccount:default:sa1" --as-group g1 --as-group g2 @olgch; @kublr
  • 26.
    Authorization: Mechanisms Mechanism Decisionsource Usage Node API Server built-in Internal use (kubelets) ABAC Static file Insecure, deprecated RBAC API Objects Users and administrators WebHook External services Integration AlwaysDeny AlwaysAllow API Server built-in Testing @olgch; @kublr
  • 27.
    Authorization, tools • kubectlauth can-i ... • kubectl whoami • kubectl --v=8 ... @olgch; @kublr
  • 28.
    Authorization: WebHook Client KubernetesAPI 1. Request --authorization-webhook-config-file=auth-cfg.yaml Authorization Service 2. Verify Config file in kubeconfig format @olgch; @kublr
  • 29.
    Authorization: RBAC Three groups Connectedthrough RBAC @olgch; @kublr Subjects User Group Service Account Resources Pods Nodes ConfigMaps Secrets Deployments … Operations list get create update delete watch patch get post put delete
  • 30.
    Roles and ClusterRoles •Roles and ClusterRoles define a set of allowed actions on resources • Role is namespaced • Cannot include non-namespaces resources or non-resource URLs @olgch; @kublr apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: role1 rules: - apiGroups: ['*'] resources: ['nodes', 'pods', 'pods/log'] verbs: ['get', 'list'] - apiGroups: ['*'] resources: ['configmaps'] resourceNames: ['my-configmap'] verbs: ['get', 'list']
  • 31.
    ClusterRoles • ClusterRole isnot namespaced • non-namespaced resources access • non-resource URLs access @olgch; @kublr apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: namespace: default name: clusterRole1 rules: - apiGroups: ['*'] resources: ['nodes', ‘pods'] verbs: ['get', 'list'] - nonResourceURLs: ['/api', '/healthz*'] verbs: ['get', 'head']
  • 32.
    Aggregated ClusterRoles Aggregated ClusterRolecombines rules from other cluster roles @olgch; @kublr apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: aggregatedClusterRole1 aggregationRule: clusterRoleSelectors: - matchLabels: label1: value1 # The control plane automatically fills in the rules rules: [] Aggregated ClusterRole clusterRole1 aggregationRule: clusterRoleSelectors: - matchLabels: label1: value1 metadata: labels: label1: value1 clusterRole1 metadata: labels: label1: value1 label2: value2 clusterRole1 metadata: labels: label2: value2
  • 33.
    apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name:roleBinding1 namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: role1 subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: user1 - apiGroup: rbac.authorization.k8s.io kind: Group name: group1 - kind: ServiceAccount name: sa1 namespace: default RoleBinding @olgch; @kublr user1 user2 group RoleBinding namespace resources only ClusterRole Role namespace ServiceAccount
  • 34.
    apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name:roleBinding1 namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: clusterRole1 subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: user1 - apiGroup: rbac.authorization.k8s.io kind: Group name: group1 - kind: ServiceAccount name: sa1 namespace: default ClusterRoleBinding @olgch; @kublr user1 user2 group ClusterRole Role namespace ServiceAccount ClusterRoleBinding
  • 35.
    Built-in ClusterRoles Role AccessCan do cluster-admin Full access to all cluster resources Anything in the cluster admin Full access to all namespace resources Anything in a namespace edit Full access to all namespace resources except Role, RoleBinding, LocalSubjectAccessReviews Anything in a namespace except granting and checking access view RO access to all namespace resources except sensitive ones View and list non-sensitive objects in a namespace @olgch; @kublr
  • 36.
    Use-cases • Start withbuild-in roles •Cluster admin •Namespace admin •Namespace developer •Namespace read-only user • Define new roles as needed • Beware of “gotchas” @olgch; @kublr
  • 37.
    “Gotchas” • Privilege escalationvia pod creation • Non-namespaced objects • CRD, PriorityClass, PodSecurityPolicy • Often needed for development, especially in advanced DevOps / SRE culture • As a result, developers need self-service dev cluster management capabilities • Role and role binding conventions • Name • Role bindings – one per subject, one per role, or mixed @olgch; @kublr
  • 38.
    Next steps • PodSecurityPolicy •NetworkPolicy • Limits and Quotas • Admission Controllers • Dynamic admission control • Dynamic policies, OPA @olgch; @kublr
  • 39.
    Kubernetes API Groupsand Objects API Group API Obects rbac.authorization.k8s.io/v1 ClusterRole Role ClusterRoleBinding RoleBinding authentication.k8s.io/v1 TokenReview admissionregistration.k8s.io/v1 MutatingWebhookConfiguration ValidatingWebhookConfiguration authorization.k8s.io/v1 LocalSubjectAccessReview SelfSubjectAccessReview SelfSubjectRulesReview SubjectAccessReview certificates.k8s.io/v1beta1 CertificateSigningRequest policy/v1beta1 PodSecurityPolicy @olgch; @kublr
  • 40.
  • 41.
  • 42.
    Oleg Chunikhin CTO oleg@kublr.com @olgch Kublr |kublr.com @kublr Signup for our newsletter at kublr.com @olgch; @kublr