summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorThong Kuah <tkuah@gitlab.com>2018-09-07 23:48:06 +1200
committerThong Kuah <tkuah@gitlab.com>2018-09-14 16:26:51 +1200
commita02e35308b97d43964ebcf7fda040da418c04ddc (patch)
tree5e7738b00b41248720298edf48e73b4c2aa9579c /spec
parent8c8ccd3167ddb63485aa9e71affc737832d3846a (diff)
downloadgitlab-ce-a02e35308b97d43964ebcf7fda040da418c04ddc.tar.gz
Always create `gitlab` service account and service account token regardless of ABAC/RBAC
This also solves the async nature of the automatic creation of default service tokens for service accounts. It also makes explicit which service account token we always use. create cluster role binding only if the provider has legacy_abac disabled.
Diffstat (limited to 'spec')
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb1
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb137
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb73
-rw-r--r--spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb50
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb42
5 files changed, 163 insertions, 140 deletions
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 7c057e66673..53c5a4e7c94 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -116,6 +116,7 @@ describe Gitlab::Kubernetes::KubeClient do
:get_config_map,
:get_pod,
:get_namespace,
+ :get_secret,
:get_service,
:get_service_account,
:delete_pod,
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index 1ea41b41771..0f484222228 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -12,9 +12,11 @@ describe Clusters::Gcp::FinalizeCreationService do
let(:zone) { provider.zone }
let(:cluster_name) { cluster.name }
+ subject { described_class.new.execute(provider) }
+
shared_examples 'success' do
it 'configures provider and kubernetes' do
- described_class.new.execute(provider)
+ subject
expect(provider).to be_created
end
@@ -22,7 +24,7 @@ describe Clusters::Gcp::FinalizeCreationService do
shared_examples 'error' do
it 'sets an error to provider object' do
- described_class.new.execute(provider)
+ subject
expect(provider.reload).to be_errored
end
@@ -33,6 +35,7 @@ describe Clusters::Gcp::FinalizeCreationService do
let(:api_url) { 'https://' + endpoint }
let(:username) { 'sample-username' }
let(:password) { 'sample-password' }
+ let(:secret_name) { 'gitlab-token' }
before do
stub_cloud_platform_get_zone_cluster(
@@ -43,124 +46,98 @@ describe Clusters::Gcp::FinalizeCreationService do
password: password
}
)
-
- stub_kubeclient_discover(api_url)
end
- context 'when suceeded to fetch kuberenetes token' do
- let(:secret_name) { 'default-token-Y1a' }
- let(:token) { 'sample-token' }
-
+ context 'service account and token created' do
before do
- stub_kubeclient_get_secrets(
- api_url,
- {
- metadata_name: secret_name,
- token: Base64.encode64(token)
- } )
- end
-
- it_behaves_like 'success'
-
- it 'has corresponded data' do
- described_class.new.execute(provider)
- cluster.reload
- provider.reload
- platform.reload
-
- expect(provider.endpoint).to eq(endpoint)
- expect(platform.api_url).to eq(api_url)
- expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert))
- expect(platform.username).to eq(username)
- expect(platform.password).to eq(password)
- expect(platform.authorization_type).to eq('abac')
- expect(platform.token).to eq(token)
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_create_service_account(api_url)
+ stub_kubeclient_create_secret(api_url)
end
- context 'rbac_clusters feature enabled' do
- let(:secret_name) { 'gitlab-token-Y1a' }
+ shared_context 'kubernetes token successfully fetched' do
+ let(:token) { 'sample-token' }
before do
- provider.legacy_abac = false
-
- stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_cluster_role_binding(api_url)
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: secret_name,
+ token: Base64.encode64(token)
+ } )
end
+ end
+
+ context 'provider legacy_abac is enabled' do
+ include_context 'kubernetes token successfully fetched'
it_behaves_like 'success'
- it 'has corresponded data' do
- described_class.new.execute(provider)
+ it 'properly configures database models' do
+ subject
+
cluster.reload
- provider.reload
- platform.reload
expect(provider.endpoint).to eq(endpoint)
expect(platform.api_url).to eq(api_url)
expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert))
expect(platform.username).to eq(username)
expect(platform.password).to eq(password)
- expect(platform.authorization_type).to eq('rbac')
+ expect(platform).to be_abac
+ expect(platform.authorization_type).to eq('abac')
expect(platform.token).to eq(token)
end
end
- end
-
- context 'when no matching token is found' do
- before do
- stub_kubeclient_get_secrets(api_url, metadata_name: 'not-default-not-gitlab')
- end
- it_behaves_like 'error'
-
- context 'rbac_clusters feature enabled' do
+ context 'provider legacy_abac is disabled' do
before do
provider.legacy_abac = false
-
- stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_cluster_role_binding(api_url)
end
- it_behaves_like 'error'
- end
- end
+ include_context 'kubernetes token successfully fetched'
- context 'when token is empty' do
- let(:secret_name) { 'default-token-123' }
+ context 'cluster role binding created' do
+ before do
+ stub_kubeclient_create_cluster_role_binding(api_url)
+ end
- before do
- stub_kubeclient_get_secrets(api_url, token: '', metadata_name: secret_name)
- end
+ it_behaves_like 'success'
- it_behaves_like 'error'
+ it 'properly configures database models' do
+ subject
- context 'rbac_clusters feature enabled' do
- let(:secret_name) { 'gitlab-token-321' }
+ cluster.reload
- before do
- provider.legacy_abac = false
+ expect(provider.endpoint).to eq(endpoint)
+ expect(platform.api_url).to eq(api_url)
+ expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert))
+ expect(platform.username).to eq(username)
+ expect(platform.password).to eq(password)
+ expect(platform).to be_rbac
+ expect(platform.token).to eq(token)
+ end
+ end
+ end
- stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_cluster_role_binding(api_url)
+ context 'when token is empty' do
+ before do
+ stub_kubeclient_get_secret(api_url, token: '', metadata_name: secret_name)
end
it_behaves_like 'error'
end
- end
- context 'when failed to fetch kuberenetes token' do
- before do
- stub_kubeclient_get_secrets_error(api_url)
- end
+ context 'when failed to fetch kubernetes token' do
+ before do
+ stub_kubeclient_get_secret_error(api_url, secret_name)
+ end
- it_behaves_like 'error'
+ it_behaves_like 'error'
+ end
- context 'rbac_clusters feature enabled' do
+ context 'when service account fails to create' do
before do
- provider.legacy_abac = false
-
- stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_cluster_role_binding(api_url)
+ stub_kubeclient_create_service_account_error(api_url)
end
it_behaves_like 'error'
diff --git a/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
index 2dd4eedaf56..5268ae8a6d7 100644
--- a/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
@@ -5,11 +5,12 @@ require 'spec_helper'
describe Clusters::Gcp::Kubernetes::CreateServiceAccountService do
include KubernetesHelpers
- let(:service) { described_class.new(kubeclient) }
+ let(:service) { described_class.new(kubeclient, rbac: rbac) }
describe '#execute' do
subject { service.execute }
+ let(:rbac) { false }
let(:api_url) { 'http://111.111.111.111' }
let(:username) { 'admin' }
let(:password) { 'xxx' }
@@ -25,29 +26,69 @@ describe Clusters::Gcp::Kubernetes::CreateServiceAccountService do
before do
stub_kubeclient_discover(api_url)
stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_cluster_role_binding(api_url)
+ stub_kubeclient_create_secret(api_url)
end
- it 'creates a kubernetes service account' do
- subject
+ shared_examples 'creates service account and token' do
+ it 'creates a kubernetes service account' do
+ subject
- expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/serviceaccounts').with(
- body: hash_including(
- metadata: { name: 'gitlab', namespace: 'default' }
+ expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/serviceaccounts').with(
+ body: hash_including(
+ kind: 'ServiceAccount',
+ metadata: { name: 'gitlab', namespace: 'default' }
+ )
)
- )
+ end
+
+ it 'creates a kubernetes secret of type ServiceAccountToken' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/secrets').with(
+ body: hash_including(
+ kind: 'Secret',
+ metadata: {
+ name: 'gitlab-token',
+ namespace: 'default',
+ annotations: {
+ 'kubernetes.io/service-account.name': 'gitlab'
+ }
+ },
+ type: 'kubernetes.io/service-account-token'
+ )
+ )
+ end
+ end
+
+ context 'abac enabled cluster' do
+ it_behaves_like 'creates service account and token'
end
- it 'creates a kubernetes cluster role binding' do
- subject
+ context 'rbac enabled cluster' do
+ let(:rbac) { true }
+
+ before do
+ stub_kubeclient_create_cluster_role_binding(api_url)
+ end
+
+ it_behaves_like 'creates service account and token'
+
+ it 'creates a kubernetes cluster role binding' do
+ subject
- expect(WebMock).to have_requested(:post, api_url + '/apis/rbac.authorization.k8s.io/v1/clusterrolebindings').with(
- body: hash_including(
- metadata: { name: 'gitlab-admin' },
- roleRef: { apiGroup: 'rbac.authorization.k8s.io', kind: 'ClusterRole', name: 'cluster-admin' },
- subjects: [{ kind: 'ServiceAccount', namespace: 'default', name: 'gitlab' }]
+ expect(WebMock).to have_requested(:post, api_url + '/apis/rbac.authorization.k8s.io/v1/clusterrolebindings').with(
+ body: hash_including(
+ kind: 'ClusterRoleBinding',
+ metadata: { name: 'gitlab-admin' },
+ roleRef: {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: 'cluster-admin'
+ },
+ subjects: [{ kind: 'ServiceAccount', namespace: 'default', name: 'gitlab' }]
+ )
)
- )
+ end
end
end
end
diff --git a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
index 74d58a6d206..4c34f21c1bc 100644
--- a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
@@ -1,10 +1,9 @@
-require 'spec_helper'
+require 'fast_spec_helper'
describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
describe '#execute' do
- subject { described_class.new(kubeclient, service_account_name).execute }
+ subject { described_class.new(kubeclient).execute }
- let(:service_account_name) { 'gitlab-sa' }
let(:api_url) { 'http://111.111.111.111' }
let(:username) { 'admin' }
let(:password) { 'xxx' }
@@ -18,42 +17,39 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
end
context 'when params correct' do
- let(:token) { 'xxx.token.xxx' }
-
- let(:secrets_json) do
- [
- {
- 'metadata': {
- name: 'default-token-123'
- },
- 'data': {
- 'token': Base64.encode64('yyy.token.yyy')
- }
+ let(:decoded_token) { 'xxx.token.xxx' }
+ let(:token) { Base64.encode64(decoded_token) }
+
+ let(:secret_json) do
+ {
+ 'metadata': {
+ name: 'gitlab-token'
},
- {
- 'metadata': {
- name: metadata_name
- },
- 'data': {
- 'token': Base64.encode64(token)
- }
+ 'data': {
+ 'token': token
}
- ]
+ }
end
before do
allow_any_instance_of(Kubeclient::Client)
- .to receive(:get_secrets).and_return(secrets_json)
+ .to receive(:get_secret).and_return(secret_json)
end
- context 'when token for service account exists' do
- let(:metadata_name) { 'gitlab-sa-token-123' }
+ context 'when gitlab-token exists' do
+ let(:metadata_name) { 'gitlab-token' }
- it { is_expected.to eq(token) }
+ it { is_expected.to eq(decoded_token) }
end
context 'when gitlab-token does not exist' do
- let(:metadata_name) { 'another-token-123' }
+ let(:secret_json) { {} }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when token is nil' do
+ let(:token) { nil }
it { is_expected.to be_nil }
end
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 30af1e7928c..2fde5c8fde4 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -33,13 +33,15 @@ module KubernetesHelpers
WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response)
end
- def stub_kubeclient_get_secrets(api_url, **options)
- WebMock.stub_request(:get, api_url + '/api/v1/secrets')
- .to_return(kube_response(kube_v1_secrets_body(options)))
+ def stub_kubeclient_get_secret(api_url, **options)
+ options[:metadata_name] ||= "default-token-1"
+
+ WebMock.stub_request(:get, api_url + "/api/v1/secrets/#{options[:metadata_name]}")
+ .to_return(kube_response(kube_v1_secret_body(options)))
end
- def stub_kubeclient_get_secrets_error(api_url)
- WebMock.stub_request(:get, api_url + '/api/v1/secrets')
+ def stub_kubeclient_get_secret_error(api_url, name)
+ WebMock.stub_request(:get, api_url + "/api/v1/secrets/#{name}")
.to_return(status: [404, "Internal Server Error"])
end
@@ -48,26 +50,32 @@ module KubernetesHelpers
.to_return(kube_response({}))
end
+ def stub_kubeclient_create_service_account_error(api_url, namespace: 'default')
+ WebMock.stub_request(:post, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts")
+ .to_return(status: [500, "Internal Server Error"])
+ end
+
+ def stub_kubeclient_create_secret(api_url, namespace: 'default')
+ WebMock.stub_request(:post, api_url + "/api/v1/namespaces/#{namespace}/secrets")
+ .to_return(kube_response({}))
+ end
+
def stub_kubeclient_create_cluster_role_binding(api_url)
WebMock.stub_request(:post, api_url + '/apis/rbac.authorization.k8s.io/v1/clusterrolebindings')
.to_return(kube_response({}))
end
- def kube_v1_secrets_body(**options)
+ def kube_v1_secret_body(**options)
{
"kind" => "SecretList",
"apiVersion": "v1",
- "items" => [
- {
- "metadata": {
- "name": options[:metadata_name] || "default-token-1",
- "namespace": "kube-system"
- },
- "data": {
- "token": options[:token] || Base64.encode64('token-sample-123')
- }
- }
- ]
+ "metadata": {
+ "name": options[:metadata_name] || "default-token-1",
+ "namespace": "kube-system"
+ },
+ "data": {
+ "token": options[:token] || Base64.encode64('token-sample-123')
+ }
}
end