add support for user impersonation for k8s modules (#250)

add support for user impersonation for k8s modules

SUMMARY

k8s module should not allow user to perform operation using impersonation as describe here
https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation
This pull request closes #40

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Abhijeet Kasurde <None>
Reviewed-by: None <None>
This commit is contained in:
abikouo
2021-11-17 14:25:06 +01:00
committed by GitHub
parent b0f1501cd4
commit 39b6c43ab7
6 changed files with 304 additions and 8 deletions

View File

@@ -205,6 +205,14 @@
tags:
- always
- name: Include user_impersonation.yml
include_tasks:
file: tasks/user_impersonation.yml
apply:
tags: [ user_impersonation, k8s ]
tags:
- always
roles:
- role: helm
tags:

View File

@@ -0,0 +1,211 @@
- block:
- set_fact:
test_ns: "impersonate"
pod_name: "impersonate-pod"
# this use will have authorization to list/create pods in the namespace
user_01: "authorized-sa-01"
# No authorization attached to this user, will use 'user_01' for impersonation
user_02: "unauthorize-sa-01"
- name: Ensure namespace
kubernetes.core.k8s:
kind: Namespace
name: "{{ test_ns }}"
- name: Get cluster information
kubernetes.core.k8s_cluster_info:
register: cluster_info
no_log: true
- set_fact:
cluster_host: "{{ cluster_info['connection']['host'] }}"
- name: Create Service account
kubernetes.core.k8s:
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: "{{ item }}"
namespace: "{{ test_ns }}"
with_items:
- "{{ user_01 }}"
- "{{ user_02 }}"
- name: Read Service Account - user_01
kubernetes.core.k8s_info:
kind: ServiceAccount
namespace: "{{ test_ns }}"
name: "{{ user_01 }}"
register: result
- name: Get secret details
kubernetes.core.k8s_info:
kind: Secret
namespace: '{{ test_ns }}'
name: '{{ result.resources[0].secrets[0].name }}'
no_log: true
register: _secret
- set_fact:
user_01_api_token: "{{ _secret.resources[0]['data']['token'] | b64decode }}"
- name: Read Service Account - user_02
kubernetes.core.k8s_info:
kind: ServiceAccount
namespace: "{{ test_ns }}"
name: "{{ user_02 }}"
register: result
- name: Get secret details
kubernetes.core.k8s_info:
kind: Secret
namespace: '{{ test_ns }}'
name: '{{ result.resources[0].secrets[0].name }}'
no_log: true
register: _secret
- set_fact:
user_02_api_token: "{{ _secret.resources[0]['data']['token'] | b64decode }}"
- name: Create Role to manage pod on the namespace
kubernetes.core.k8s:
namespace: "{{ test_ns }}"
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-manager
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "delete", "list", "patch"]
- name: Attach Role to the user_01
kubernetes.core.k8s:
namespace: "{{ test_ns }}"
definition:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-manager-binding
subjects:
- kind: ServiceAccount
name: "{{ user_01 }}"
roleRef:
kind: Role
name: pod-manager
apiGroup: rbac.authorization.k8s.io
- name: Create Pod using user_01 credentials
kubernetes.core.k8s:
api_key: "{{ user_01_api_token }}"
host: "{{ cluster_host }}"
validate_certs: no
namespace: "{{ test_ns }}"
name: "{{ pod_name }}"
definition:
apiVersion: v1
kind: Pod
metadata:
labels:
test: "impersonate"
spec:
containers:
- name: c0
image: busybox
command:
- /bin/sh
- -c
- while true;do date;sleep 5; done
- name: Delete Pod using user_02 credentials should failed
kubernetes.core.k8s:
api_key: "{{ user_02_api_token }}"
host: "{{ cluster_host }}"
validate_certs: no
namespace: "{{ test_ns }}"
name: "{{ pod_name }}"
kind: Pod
state: absent
register: delete_pod
ignore_errors: true
- name: Assert that operation has failed
assert:
that:
- delete_pod is failed
- delete_pod.reason == 'Forbidden'
- name: Delete Pod using user_02 credentials and impersonation to user_01
kubernetes.core.k8s:
api_key: "{{ user_02_api_token }}"
host: "{{ cluster_host }}"
validate_certs: no
impersonate_user: "system:serviceaccount:{{ test_ns }}:{{ user_01 }}"
namespace: "{{ test_ns }}"
name: "{{ pod_name }}"
kind: Pod
state: absent
ignore_errors: true
register: delete_pod_2
- name: Assert that operation has failed
assert:
that:
- delete_pod_2 is failed
- delete_pod_2.reason == 'Forbidden'
- '"cannot impersonate resource" in delete_pod_2.msg'
- name: Create Role to impersonate user_01
kubernetes.core.k8s:
namespace: "{{ test_ns }}"
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: sa-impersonate
rules:
- apiGroups: [""]
resources:
- serviceaccounts
verbs:
- impersonate
resourceNames:
- "{{ user_01 }}"
- name: Attach Role to the user_02
kubernetes.core.k8s:
namespace: "{{ test_ns }}"
definition:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: sa-impersonate-binding
subjects:
- kind: ServiceAccount
name: "{{ user_02 }}"
roleRef:
kind: Role
name: sa-impersonate
apiGroup: rbac.authorization.k8s.io
- name: Delete Pod using user_02 credentials should succeed now
kubernetes.core.k8s:
api_key: "{{ user_02_api_token }}"
host: "{{ cluster_host }}"
validate_certs: no
impersonate_user: "system:serviceaccount:{{ test_ns }}:{{ user_01 }}"
namespace: "{{ test_ns }}"
name: "{{ pod_name }}"
kind: Pod
state: absent
always:
- name: Ensure namespace is deleted
kubernetes.core.k8s:
state: absent
kind: Namespace
name: "{{ test_ns }}"
wait: yes
ignore_errors: true