diff --git a/charts/catalog/templates/apiserver-deployment.yaml b/charts/catalog/templates/apiserver-deployment.yaml index 3d7ca00184c..629c4416bd2 100644 --- a/charts/catalog/templates/apiserver-deployment.yaml +++ b/charts/catalog/templates/apiserver-deployment.yaml @@ -20,6 +20,7 @@ spec: release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" spec: + serviceAccountName: "{{ .Values.apiserver.serviceAccount }}" containers: - name: apiserver image: {{ .Values.apiserver.image }} diff --git a/charts/catalog/templates/controller-manager-deployment.yaml b/charts/catalog/templates/controller-manager-deployment.yaml index 56a660c11ea..40a54a1603b 100644 --- a/charts/catalog/templates/controller-manager-deployment.yaml +++ b/charts/catalog/templates/controller-manager-deployment.yaml @@ -20,6 +20,7 @@ spec: release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" spec: + serviceAccountName: "{{ .Values.controllerManager.serviceAccount }}" containers: - name: controller-manager image: {{ .Values.controllerManager.image }} diff --git a/charts/catalog/templates/rbac.yaml b/charts/catalog/templates/rbac.yaml new file mode 100644 index 00000000000..ecafb16b01d --- /dev/null +++ b/charts/catalog/templates/rbac.yaml @@ -0,0 +1,141 @@ +{{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1beta1" }} +apiVersion: v1 +kind: List +items: + +### API Server ### + +# TODO: if this is just for namespace lifecycle admission, move to a generic role +# the role for the apiserver +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: ClusterRole + metadata: + name: "servicecatalog.k8s.io:apiserver" + # this rule defined on the role for specifically the + # namespace-lifecycle admission-controller + rules: + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["get", "list", "watch"] +# API-server service-account gets its own role +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: ClusterRoleBinding + metadata: + name: "servicecatalog.k8s.io:apiserver" + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: "servicecatalog.k8s.io:apiserver" + subjects: + - apiGroup: "" + kind: ServiceAccount + name: "{{ .Values.apiserver.serviceAccount }}" + namespace: "{{ .Release.Namespace }}" +# apiserver gets the auth-delegator role to delegate auth decisions to +# the core apiserver +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: ClusterRoleBinding + metadata: + name: "servicecatalog.k8s.io:apiserver-auth-delegator" + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator + subjects: + - apiGroup: "" + kind: ServiceAccount + name: "{{ .Values.apiserver.serviceAccount }}" + namespace: "{{ .Release.Namespace }}" +# apiserver gets the ability to read authentication. This allows it to +# read the specific configmap that has the requestheader-* entries to +# enable api aggregation +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: RoleBinding + metadata: + name: "servicecatalog.k8s.io:apiserver-authentication-reader" + namespace: kube-system + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader + subjects: + - apiGroup: "" + kind: ServiceAccount + name: "{{ .Values.apiserver.serviceAccount }}" + namespace: "{{ .Release.Namespace }}" + +### Controller-Manager ### + +# controller-manager role defines what access the service-catalog +# controller-manager needs to manage the resources of the +# service-catalog +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: ClusterRole + metadata: + name: "servicecatalog.k8s.io:controller-manager" + rules: + - apiGroups: [""] + resources: ["events"] + verbs: ["create","patch","update"] + # TODO: do not grant global access, limit to particular secrets referenced from bindings + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get","create","delete"] + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["get","list","watch"] + # access to our service-catalog types + - apiGroups: ["servicecatalog.k8s.io"] + resources: ["serviceclasses"] + verbs: ["get","list","watch","create","patch","update","delete"] + - apiGroups: ["servicecatalog.k8s.io"] + resources: ["bindings","brokers","instances"] + verbs: ["get","list","watch"] + - apiGroups: ["servicecatalog.k8s.io"] + resources: ["bindings/status","brokers/status","instances/status"] + verbs: ["update"] +# give the controller-manager service account access to whats defined in its role. +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: ClusterRoleBinding + metadata: + name: "servicecatalog.k8s.io:controller-manager" + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: "servicecatalog.k8s.io:controller-manager" + subjects: + - apiGroup: "" + kind: ServiceAccount + name: "{{ .Values.controllerManager.serviceAccount }}" + namespace: "{{ .Release.Namespace }}" + +# This gives create/update access to an endpoint in kube-system for leader election +# TODO: use an object other than endpoints, and in the same namespace as the service catalog, not in kube-system +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: Role + metadata: + name: "servicecatalog.k8s.io::leader-locking-controller-manager" + namespace: kube-system + rules: + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create"] + - apiGroups: [""] + resources: ["endpoints"] + resourceNames: ["service-catalog-controller-manager"] + verbs: ["get","update"] +- apiVersion: rbac.authorization.k8s.io/v1beta1 + kind: RoleBinding + metadata: + name: service-catalog-controller-manager + namespace: kube-system + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: service-catalog-controller-manager + subjects: + - apiGroup: "" + kind: ServiceAccount + name: "{{ .Values.controllerManager.serviceAccount }}" + namespace: "{{ .Release.Namespace }}" +{{ end }} diff --git a/charts/catalog/templates/serviceaccounts.yaml b/charts/catalog/templates/serviceaccounts.yaml new file mode 100644 index 00000000000..6686f1334ed --- /dev/null +++ b/charts/catalog/templates/serviceaccounts.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: List +items: + # The SA for the apiserver + - apiVersion: v1 + kind: ServiceAccount + metadata: + name: "{{ .Values.apiserver.serviceAccount }}" + # The SA for the controller-manager + - apiVersion: v1 + kind: ServiceAccount + metadata: + name: "{{ .Values.controllerManager.serviceAccount }}" diff --git a/charts/catalog/values.yaml b/charts/catalog/values.yaml index dc9a5ac8278..6539a8fdabf 100644 --- a/charts/catalog/values.yaml +++ b/charts/catalog/values.yaml @@ -73,6 +73,7 @@ apiserver: activated: false # If specified, audit log goes to specified path. logPath: "/tmp/service-catalog-apiserver-audit.log" + serviceAccount: service-catalog-apiserver controllerManager: # controller-manager image to use image: quay.io/kubernetes-service-catalog/controller-manager:v0.0.13 @@ -97,4 +98,5 @@ controllerManager: leaderElection: # Whether the controller has option to set leader election namespace. activated: false + serviceAccount: service-catalog-controller-manager useAggregator: false diff --git a/contrib/jenkins/init_cluster.sh b/contrib/jenkins/init_cluster.sh index 5d0e4c5fbd7..00fdbd7eeb9 100755 --- a/contrib/jenkins/init_cluster.sh +++ b/contrib/jenkins/init_cluster.sh @@ -16,6 +16,8 @@ set -o nounset set -o errexit +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" + while [[ $# -ne 0 ]]; do case "$1" in --project) PROJECT="$2"; shift ;; @@ -54,5 +56,12 @@ echo "Using cluster ${CLUSTERNAME}." gcloud container clusters get-credentials "${CLUSTERNAME}" --project="${PROJECT}" --zone="${ZONE}" \ || { echo 'Cannot get credentials for cluster.'; exit 1; } +# On GKE you need to give your user proper permissions in order to create new +# cluster roles. Needed for RBAC setup. +ACCOUNT_NAME="$(gcloud info | grep Account | sed 's/.*\[\(.*\)\]/\1/')" +kubectl create clusterrolebinding jenkins-cluster-admin-binding \ + --clusterrole=cluster-admin --user="${ACCOUNT_NAME}" \ + || { echo 'Cannot not create cluster-admin role for service account.'; exit 1; } + helm init \ || { echo 'Cannot initialize Helm.'; exit 1; }