diff --git a/kubernetes-keystone-webhook/values.yaml b/kubernetes-keystone-webhook/values.yaml index 01f79511d..b30a7af56 100644 --- a/kubernetes-keystone-webhook/values.yaml +++ b/kubernetes-keystone-webhook/values.yaml @@ -132,6 +132,333 @@ conf: - type: project values: - openstack-system + - resource: + verbs: + - "*" + resources: + - "*" + namespace: "*" + version: "*" + match: + - type: role + values: + - admin_k8cluster + - nonresource: + verbs: + - "*" + path: "*" + match: + - type: role + values: + - admin_k8cluster + - resource: + resources: + - pods + - pods/attach + - pods/exec + - pods/portforward + - pods/proxy + - configmaps + - endpoints + - persistentvolumeclaims + - replicationcontrollers + - replicationcontrollers/scale + - secrets + - serviceaccounts + - services + - services/proxy + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - bindings + - events + - limitranges + - namespaces/status + - pods/log + - pods/status + - replicationcontrollers/status + - resourcequotas + - resourcequotas/status + - namespaces + verbs: + - get + - list + - watch + namespace: "*" + version: "" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - serviceaccounts + verbs: + - impersonate + namespace: "*" + version: "" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - daemonsets + - deployments + - deployments/rollback + - deployments/scale + - replicasets + - replicasets/scale + - statefulsets + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "apps" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - horizontalpodautoscalers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "autoscaling" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - cronjobs + - jobs + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "batch" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - daemonsets + - deployments + - deployments/rollback + - deployments/scale + - ingresses + - networkpolicies + - replicasets + - replicasets/scale + - replicationcontrollers/scale + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "extensions" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "policy" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - networkpolicies + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + namespace: "*" + version: "networking.k8s.io" + match: + - type: role + values: + - admin_k8cluster_editor + - resource: + resources: + - configmaps + - endpoints + - persistentvolumeclaims + - pods + - replicationcontrollers + - replicationcontrollers/scale + - serviceaccounts + - services + - bindings + - events + - limitranges + - namespaces/status + - pods/log + - pods/status + - replicationcontrollers/status + - resourcequotas + - resourcequotas/status + - namespaces + verbs: + - get + - list + - watch + namespace: "*" + version: "" + match: + - type: role + values: + - admin_k8cluster_viewer + - resource: + resources: + - daemonsets + - deployments + - deployments/scale + - replicasets + - replicasets/scale + - statefulsets + verbs: + - get + - list + - watch + namespace: "*" + version: "apps" + match: + - type: role + values: + - admin_k8cluster_viewer + - resource: + resources: + - horizontalpodautoscalers + verbs: + - get + - list + - watch + namespace: "*" + version: "autoscaling" + match: + - type: role + values: + - admin_k8cluster_viewer + - resource: + resources: + - cronjobs + - jobs + verbs: + - get + - list + - watch + namespace: "*" + version: "batch" + match: + - type: role + values: + - admin_k8cluster_viewer + - resource: + resources: + - daemonsets + - deployments + - deployments/scale + - ingresses + - networkpolicies + - replicasets + - replicasets/scale + - replicationcontrollers/scale + verbs: + - get + - list + - watch + namespace: "*" + version: "extensions" + match: + - type: role + values: + - admin_k8cluster_viewer + - resource: + resources: + - poddisruptionbudgets + verbs: + - get + - list + - watch + namespace: "*" + version: "policy" + match: + - type: role + values: + - admin_k8cluster_viewer + - resource: + resources: + - networkpolicies + verbs: + - get + - list + - watch + namespace: "*" + version: "networking.k8s.io" + match: + - type: role + values: + - admin_k8cluster_viewer secrets: identity: diff --git a/tools/deployment/keystone-auth/080-check.sh b/tools/deployment/keystone-auth/080-check.sh index 5ee711b7b..8ef5f9678 100755 --- a/tools/deployment/keystone-auth/080-check.sh +++ b/tools/deployment/keystone-auth/080-check.sh @@ -20,6 +20,28 @@ export OS_CLOUD=openstack_helm function keystone_token () { openstack token issue -f value -c id } + +function report_failed_policy () { + echo "$1 was $2 to perform $3, which contradicts current policy" + exit 1 +} + +function test_user_is_authorized () { + TOKEN=$(keystone_token) + if ! kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN $1 ; then + report_failed_policy "$OS_USERNAME" "not allowed" "$1" + fi +} + +function test_user_is_unauthorized () { + TOKEN=$(keystone_token) + if ! kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN $1 ; then + echo "Denied, as expected by policy" + else + report_failed_policy "$OS_USERNAME" "allowed" "$1" + fi +} + sudo cp -va $HOME/.kube/config /tmp/kubeconfig.yaml sudo kubectl --kubeconfig /tmp/kubeconfig.yaml config unset users.kubernetes-admin @@ -30,6 +52,14 @@ kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get pods kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get pods -n openstack kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get secrets -n openstack +# This is used to grab a pod name for the following tests +TEST_POD="$(kubectl get pods -n openstack | awk 'NR==2{print $1}')" + +# create users +openstack user create --or-show --password password admin_k8cluster_user +openstack user create --or-show --password password admin_k8cluster_edit_user +openstack user create --or-show --password password admin_k8cluster_view_user + # create project openstack project create --or-show openstack-system openstack project create --or-show demoProject @@ -37,10 +67,16 @@ openstack project create --or-show demoProject # create roles openstack role create --or-show openstackRole openstack role create --or-show kube-system-admin +openstack role create --or-show admin_k8cluster +openstack role create --or-show admin_k8cluster_editor +openstack role create --or-show admin_k8cluster_viewer # assign user role to project openstack role add --project openstack-system --user bob --project-domain default --user-domain ldapdomain openstackRole openstack role add --project demoProject --user alice --project-domain default --user-domain ldapdomain kube-system-admin +openstack role add --project demoProject --user admin_k8cluster_user --project-domain default --user-domain default admin_k8cluster +openstack role add --project demoProject --user admin_k8cluster_edit_user --project-domain default --user-domain default admin_k8cluster_editor +openstack role add --project demoProject --user admin_k8cluster_view_user --project-domain default --user-domain default admin_k8cluster_viewer unset OS_CLOUD export OS_AUTH_URL="http://keystone.openstack.svc.cluster.local/v3" @@ -50,23 +86,70 @@ export OS_PASSWORD="password" export OS_USERNAME="bob" export OS_USER_DOMAIN_NAME="ldapdomain" -# See this does fail as the policy does not allow for a non-admin user +# Create files for secret generation +echo -n 'admin' > /tmp/user.txt +echo -n 'password' > /tmp/pass.txt -# Issue a member user token +# See this does fail as the policy does not allow for a non-admin user TOKEN=$(keystone_token) -kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get ingress -n openstack -if ! kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get pods ; then - echo "Denied, as expected by policy" -else - exit 1 -fi +test_user_is_unauthorized "get pods" export OS_USERNAME="alice" export OS_PROJECT_NAME="demoProject" -TOKEN=$(keystone_token) -kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get ingress -n kube-system -if ! kubectl --kubeconfig /tmp/kubeconfig.yaml --token $TOKEN get pods -n openstack ; then - echo "Denied, as expected by policy" -else - exit 1 -fi +test_user_is_unauthorized "get pods -n openstack" + +export OS_USER_DOMAIN_NAME="default" + +#admin_k8cluser_user +export OS_USERNAME="admin_k8cluster_user" +RESOURCES=("pods" "configmaps" "endpoints" "persistentvolumeclaims" \ + "replicationcontrollers" "secrets" "serviceaccounts" \ + "services" "events" "limitranges" "namespace" \ + "replicationcontrollers" "resourcequotas" "daemonsets" \ + "deployments" "replicasets" "statefulsets" "jobs" \ + "cronjobs" "poddisruptionbudgets" "serviceaccounts" \ + "networkpolicies" "horizontalpodautoscalers") +for r in "${RESOURCES[@]}" ; do + test_user_is_authorized "get $r" +done + +test_user_is_authorized "create secret generic test-secret --from-file=/tmp/user.txt --from-file=/tmp/pass.txt" +test_user_is_authorized "delete secret test-secret" + +#admin_k8cluster_edit_user +export OS_USERNAME="admin_k8cluster_edit_user" +RESOURCES=("pods" "configmaps" "endpoints" "persistentvolumeclaims" \ + "replicationcontrollers" "secrets" "serviceaccounts" \ + "services" "events" "limitranges" "namespace" \ + "replicationcontrollers" "resourcequotas" "daemonsets" \ + "deployments" "replicasets" "statefulsets" "jobs" \ + "cronjobs" "poddisruptionbudgets" "serviceaccounts" \ + "networkpolicies" "horizontalpodautoscalers") +for r in "${RESOURCES[@]}" ; do + test_user_is_authorized "get $r" +done + +test_user_is_authorized "create secret generic test-secret --from-file=/tmp/user.txt --from-file=/tmp/pass.txt" +test_user_is_authorized "delete secret test-secret" +test_user_is_authorized "logs -n openstack $TEST_POD --tail=5" + +test_user_is_unauthorized "create namespace test" + + +#admin_k8cluster_view_user +export OS_USERNAME="admin_k8cluster_view_user" +RESOURCES=("pods" "configmaps" "endpoints" "persistentvolumeclaims" \ + "replicationcontrollers" "services" "serviceaccounts" \ + "replicationcontrollers" "resourcequotas" "namespaces" \ + "daemonsets" "deployments" "replicasets" "statefulsets" \ + "poddisruptionbudgets" "networkpolicies") +for r in "${RESOURCES[@]}" ; do + test_user_is_authorized "get $r" +done + +test_user_is_authorized "logs -n openstack $TEST_POD --tail=5" + +test_user_is_unauthorized "delete pod $TEST_POD -n openstack" +test_user_is_unauthorized "create namespace test" +test_user_is_unauthorized "get secrets" +test_user_is_unauthorized "create secret generic test-secret --from-file=/tmp/user.txt --from-file=/tmp/pass.txt"