summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHordur Freyr Yngvason <hfyngvason@gitlab.com>2019-06-28 14:02:35 +0200
committerHordur Freyr Yngvason <hfyngvason@gitlab.com>2019-07-09 22:01:20 +0200
commit1f71bc143b23fc8defb195f0712743e73628713b (patch)
treed7a6c2e3c3c89cd654d6e5e5a1d1a2a1a2407755
parent6e106f66ad9d692b88e90506c0b35c4281f2b600 (diff)
downloadgitlab-ce-1f71bc143b23fc8defb195f0712743e73628713b.tar.gz
Create Knative cluster role with service account
GitLab managed clusters use a service account to perform deployments. For serverless deployments to work as expected, this account requires additional permissions in the serving.knative.dev API group.
-rw-r--r--app/services/clusters/gcp/kubernetes.rb1
-rw-r--r--app/services/clusters/gcp/kubernetes/create_or_update_service_account_service.rb22
-rw-r--r--changelogs/unreleased/hfy-apply-knative-cluster-role-on-service-account-creation.yml5
-rw-r--r--lib/gitlab/kubernetes/cluster_role.rb22
-rw-r--r--lib/gitlab/kubernetes/kube_client.rb7
-rw-r--r--spec/lib/gitlab/kubernetes/cluster_role_spec.rb30
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb3
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb1
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb1
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_service_account_service_spec.rb26
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb10
11 files changed, 127 insertions, 1 deletions
diff --git a/app/services/clusters/gcp/kubernetes.rb b/app/services/clusters/gcp/kubernetes.rb
index 90ed529670c..102784c4c58 100644
--- a/app/services/clusters/gcp/kubernetes.rb
+++ b/app/services/clusters/gcp/kubernetes.rb
@@ -9,6 +9,7 @@ module Clusters
GITLAB_CLUSTER_ROLE_BINDING_NAME = 'gitlab-admin'
GITLAB_CLUSTER_ROLE_NAME = 'cluster-admin'
PROJECT_CLUSTER_ROLE_NAME = 'edit'
+ GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME = 'gitlab-knative-serving-only-role'
end
end
end
diff --git a/app/services/clusters/gcp/kubernetes/create_or_update_service_account_service.rb b/app/services/clusters/gcp/kubernetes/create_or_update_service_account_service.rb
index 49e766cbf13..df4458382d3 100644
--- a/app/services/clusters/gcp/kubernetes/create_or_update_service_account_service.rb
+++ b/app/services/clusters/gcp/kubernetes/create_or_update_service_account_service.rb
@@ -41,7 +41,11 @@ module Clusters
kubeclient.create_or_update_service_account(service_account_resource)
kubeclient.create_or_update_secret(service_account_token_resource)
- create_role_or_cluster_role_binding if rbac
+
+ if rbac
+ create_role_or_cluster_role_binding
+ create_knative_serving_only_cluster_role
+ end
end
private
@@ -63,6 +67,10 @@ module Clusters
end
end
+ def create_knative_serving_only_cluster_role
+ kubeclient.update_cluster_role(knative_serving_only_cluster_role_resource)
+ end
+
def service_account_resource
Gitlab::Kubernetes::ServiceAccount.new(
service_account_name,
@@ -96,6 +104,18 @@ module Clusters
service_account_name: service_account_name
).generate
end
+
+ def knative_serving_only_cluster_role_resource
+ Gitlab::Kubernetes::ClusterRole.new(
+ name: Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME,
+ labels: { 'rbac.authorization.k8s.io/aggregate-to-edit' => 'true' },
+ rules: [{
+ apiGroups: %w(serving.knative.dev),
+ resources: %w(configurations configurationgenerations routes revisions revisionuids autoscalers services),
+ verbs: %w(get list create update delete patch watch)
+ }]
+ ).generate
+ end
end
end
end
diff --git a/changelogs/unreleased/hfy-apply-knative-cluster-role-on-service-account-creation.yml b/changelogs/unreleased/hfy-apply-knative-cluster-role-on-service-account-creation.yml
new file mode 100644
index 00000000000..96a90caf02f
--- /dev/null
+++ b/changelogs/unreleased/hfy-apply-knative-cluster-role-on-service-account-creation.yml
@@ -0,0 +1,5 @@
+---
+title: Create Knative cluster role on service account creation
+merge_request: 30235
+author:
+type: changed
diff --git a/lib/gitlab/kubernetes/cluster_role.rb b/lib/gitlab/kubernetes/cluster_role.rb
new file mode 100644
index 00000000000..1f3e962ae13
--- /dev/null
+++ b/lib/gitlab/kubernetes/cluster_role.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class ClusterRole
+ attr_reader :name, :labels, :rules
+
+ def initialize(name:, labels:, rules:)
+ @name = name
+ @labels = labels
+ @rules = rules
+ end
+
+ def generate
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, labels: labels },
+ rules: rules
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb
index de14df56555..199612b22fb 100644
--- a/lib/gitlab/kubernetes/kube_client.rb
+++ b/lib/gitlab/kubernetes/kube_client.rb
@@ -52,6 +52,13 @@ module Gitlab
# RBAC methods delegates to the apis/rbac.authorization.k8s.io api
# group client
+ delegate :create_cluster_role,
+ :get_cluster_role,
+ :update_cluster_role,
+ to: :rbac_client
+
+ # RBAC methods delegates to the apis/rbac.authorization.k8s.io api
+ # group client
delegate :create_cluster_role_binding,
:get_cluster_role_binding,
:update_cluster_role_binding,
diff --git a/spec/lib/gitlab/kubernetes/cluster_role_spec.rb b/spec/lib/gitlab/kubernetes/cluster_role_spec.rb
new file mode 100644
index 00000000000..620180d6c58
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/cluster_role_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Kubernetes::ClusterRole do
+ let(:cluster_role) { described_class.new(name: name, labels: labels, rules: rules) }
+
+ let(:name) { 'example-cluster-role' }
+ let(:labels) { { 'rbac.authorization.k8s.io/aggregate-to-edit' => 'true' } }
+ let(:rules) do
+ [{
+ apiGroups: %w(serving.knative.dev),
+ resources: %w(configurations configurationgenerations routes revisions revisionuids autoscalers services),
+ verbs: %w(get list create update delete patch watch)
+ }]
+ end
+
+ describe '#generate' do
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, labels: labels },
+ rules: rules
+ )
+ end
+
+ subject { cluster_role.generate }
+
+ it { is_expected.to eq(resource) }
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 978e64c4407..ecdfd337c50 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -176,6 +176,9 @@ describe Gitlab::Kubernetes::KubeClient do
let(:rbac_client) { client.rbac_client }
[
+ :create_cluster_role,
+ :get_cluster_role,
+ :update_cluster_role,
:create_cluster_role_binding,
:get_cluster_role_binding,
:update_cluster_role_binding
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index 5f91acb8e84..7d5231e979f 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -136,6 +136,7 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
stub_kubeclient_get_cluster_role_binding_error(api_url, 'gitlab-admin')
stub_kubeclient_create_cluster_role_binding(api_url)
+ stub_kubeclient_update_cluster_role(api_url, Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME)
end
include_context 'kubernetes information successfully fetched'
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
index be052a07da7..f187c1c9c07 100644
--- a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
@@ -34,6 +34,7 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
stub_kubeclient_create_service_account(api_url, namespace: namespace)
stub_kubeclient_create_secret(api_url, namespace: namespace)
stub_kubeclient_put_secret(api_url, "#{namespace}-token", namespace: namespace)
+ stub_kubeclient_update_cluster_role(api_url, Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME)
stub_kubeclient_get_secret(
api_url,
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_service_account_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_service_account_service_spec.rb
index 382b9043566..f56af409eaa 100644
--- a/spec/services/clusters/gcp/kubernetes/create_or_update_service_account_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_service_account_service_spec.rb
@@ -52,6 +52,26 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService do
end
end
+ shared_examples 'creates a knative serving role' do
+ it 'creates a cluster role aggregating knative serving permissions to the edit role' do
+ subject
+
+ expect(WebMock).to have_requested(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/clusterroles/#{Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME}").with(
+ body: hash_including(
+ metadata: {
+ name: Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME,
+ labels: { 'rbac.authorization.k8s.io/aggregate-to-edit' => 'true' }
+ },
+ rules: [{
+ apiGroups: %w(serving.knative.dev),
+ resources: %w(configurations configurationgenerations routes revisions revisionuids autoscalers services),
+ verbs: %w(get list create update delete patch watch)
+ }]
+ )
+ )
+ end
+ end
+
before do
stub_kubeclient_discover(api_url)
stub_kubeclient_get_namespace(api_url, namespace: namespace)
@@ -85,6 +105,7 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService do
stub_kubeclient_get_cluster_role_binding_error(api_url, cluster_role_binding_name)
stub_kubeclient_create_cluster_role_binding(api_url)
+ stub_kubeclient_update_cluster_role(api_url, Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME)
end
it_behaves_like 'creates service account and token'
@@ -111,6 +132,8 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService do
)
)
end
+
+ it_behaves_like 'creates a knative serving role'
end
end
@@ -143,6 +166,7 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService do
stub_kubeclient_get_role_binding_error(api_url, role_binding_name, namespace: namespace)
stub_kubeclient_create_role_binding(api_url, namespace: namespace)
+ stub_kubeclient_update_cluster_role(api_url, Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ONLY_CLUSTER_ROLE_NAME)
end
it_behaves_like 'creates service account and token'
@@ -169,6 +193,8 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService do
)
)
end
+
+ it_behaves_like 'creates a knative serving role'
end
end
end
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 3c7bcba2b42..21fa1baa844 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -199,6 +199,16 @@ module KubernetesHelpers
.to_return(kube_response({}))
end
+ def stub_kubeclient_create_cluster_role(api_url, name)
+ WebMock.stub_request(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/clusterroles/#{name}")
+ .to_return(kube_response({}))
+ end
+
+ def stub_kubeclient_update_cluster_role(api_url, name)
+ WebMock.stub_request(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/clusterroles/#{name}")
+ .to_return(kube_response({}))
+ end
+
def kube_v1_secret_body(**options)
{
"kind" => "SecretList",