Add state to control rbac
Change-Id: Ie6ae4d9bc5a91f2609ab9206d41d469a4594abc8
diff --git a/README.rst b/README.rst
index b0b8e7d..7f4dedc 100644
--- a/README.rst
+++ b/README.rst
@@ -1073,6 +1073,79 @@
value: one
image_pull_secretes: password
+Role-based access control
+=========================
+
+To enable RBAC, you need to set following option on your apiserver:
+
+.. code-block:: yaml
+
+ kubernetes:
+ master:
+ auth:
+ mode: RBAC
+
+Then you can use ``kubernetes.control.role`` state to orchestrate role and
+rolebindings. Following example shows how to create brand new role and binding
+for service account:
+
+.. code-block:: yaml
+
+ control:
+ role:
+ etcd-operator:
+ kind: ClusterRole
+ rules:
+ - apiGroups:
+ - etcd.coreos.com
+ resources:
+ - clusters
+ verbs:
+ - "*"
+ - apiGroups:
+ - extensions
+ resources:
+ - thirdpartyresources
+ verbs:
+ - create
+ - apiGroups:
+ - storage.k8s.io
+ resources:
+ - storageclasses
+ verbs:
+ - create
+ - apiGroups:
+ - ""
+ resources:
+ - replicasets
+ verbs:
+ - "*"
+ binding:
+ etcd-operator:
+ kind: ClusterRoleBinding
+ namespace: test # <-- if no namespace, then it's clusterrolebinding
+ subject:
+ etcd-operator:
+ kind: ServiceAccount
+
+Simplest possible use-case, add user test edit permissions on it's test
+namespace:
+
+.. code-block:: yaml
+
+ kubernetes:
+ control:
+ role:
+ edit:
+ kind: ClusterRole
+ # No rules defined, so only binding will be created assuming role
+ # already exists
+ binding:
+ test:
+ namespace: test
+ subject:
+ test:
+ kind: User
More Information
================
diff --git a/kubernetes/control/init.sls b/kubernetes/control/init.sls
index ea56c42..be31c21 100644
--- a/kubernetes/control/init.sls
+++ b/kubernetes/control/init.sls
@@ -1,6 +1,5 @@
{% from "kubernetes/map.jinja" import control with context %}
include:
- - kubernetes.control.cluster
{%- if control.job is defined %}
- kubernetes.control.job
{%- endif %}
@@ -10,6 +9,9 @@
{%- if control.configmap is defined %}
- kubernetes.control.configmap
{%- endif %}
+ {%- if control.role is defined %}
+ - kubernetes.control.role
+ {%- endif %}
/srv/kubernetes:
file.directory:
diff --git a/kubernetes/control/role.sls b/kubernetes/control/role.sls
new file mode 100644
index 0000000..ce7248d
--- /dev/null
+++ b/kubernetes/control/role.sls
@@ -0,0 +1,56 @@
+{% from "kubernetes/map.jinja" import control with context %}
+include:
+ - kubernetes.control
+
+{%- for role_name, role in control.role.iteritems() %}
+ {%- set role_name = role.name|default(role_name) %}
+
+ {%- if role.get('namespace') or role.get('kind') == 'Role' %}
+ {%- set role_kind = 'Role' %}
+ {%- else %}
+ {%- set role_kind = 'ClusterRole' %}
+ {%- endif %}
+
+ {%- if role.enabled|default(True) %}
+
+ {%- if role.get('rules') %}
+/srv/kubernetes/roles/{{ role_name }}/{{ role_name }}-role.yml:
+ file.managed:
+ - source: salt://kubernetes/files/role.yml
+ - template: jinja
+ - makedirs: true
+ - require:
+ - file: /srv/kubernetes
+ - defaults:
+ role_name: {{ role_name }}
+ role_kind: {{ role_kind }}
+ role: {{ role|yaml }}
+ {%- endif %}
+
+ {%- for binding_name, binding in role.get('binding', {}).iteritems() %}
+ {%- set binding_name = binding.name|default(binding_name) %}
+ {%- if binding.get('namespace') or binding.get('kind') == 'RoleBinding' %}
+ {%- set binding_kind = 'RoleBinding' %}
+ {%- else %}
+ {%- set binding_kind = 'ClusterRoleBinding' %}
+ {%- endif %}
+
+/srv/kubernetes/roles/{{ role_name }}/{{ binding_name }}-rolebinding.yml:
+ file.managed:
+ - source: salt://kubernetes/files/rolebinding.yml
+ - template: jinja
+ - makedirs: true
+ - require:
+ - file: /srv/kubernetes
+ - defaults:
+ role_name: {{ role_name }}
+ role_kind: {{ role_kind }}
+ role: {{ role|yaml }}
+ binding_name: {{ binding_name }}
+ binding_kind: {{ binding_kind }}
+ binding: {{ binding|yaml }}
+
+ {%- endfor %}
+
+ {%- endif %}
+{%- endfor %}
diff --git a/kubernetes/files/role.yml b/kubernetes/files/role.yml
new file mode 100644
index 0000000..335a5e5
--- /dev/null
+++ b/kubernetes/files/role.yml
@@ -0,0 +1,17 @@
+kind: {{ role_kind }}
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ {%- if role.get('namespace') %}
+ namespace: {{ role.namespace }}
+ {%- endif %}
+ name: {{ role_name }}
+{%- if role.get('rules') %}
+rules:
+ {%- for rule in role.rules %}
+ - {{ rule|yaml|indent(2) }}
+ {%- endfor %}
+{%- endif %}
+
+{#-
+vim: syntax=jinja
+-#}
diff --git a/kubernetes/files/rolebinding.yml b/kubernetes/files/rolebinding.yml
new file mode 100644
index 0000000..1befc8d
--- /dev/null
+++ b/kubernetes/files/rolebinding.yml
@@ -0,0 +1,21 @@
+kind: {{ binding_kind }}
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: {{ binding_name }}
+ {%- if binding.get('namespace') %}
+ namespace: {{ binding.namespace }}
+ {%- endif %}
+subjects:
+ {%- for subject_name, subject in binding.subject.iteritems() %}
+ - kind: {{ subject.kind }}
+ name: {{ subject.name|default(subject_name) }}
+ apiGroup: rbac.authorization.k8s.io
+ {%- endfor %}
+roleRef:
+ kind: {{ role_kind }}
+ name: {{ role_name }}
+ apiGroup: rbac.authorization.k8s.io
+
+{#-
+vim: syntax=jinja
+-#}