Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
e908c2e8de90
Commit
55477962
authored
Sep 06, 2018
by
Thong Kuah
Committed by
Kamil Trzciński
Sep 06, 2018
Browse files
Enable Kubernetes RBAC for GitLab Managed Apps for existing clusters
parent
a8bc05ccac7d
Changes
44
Hide whitespace changes
Inline
Side-by-side
app/controllers/projects/clusters_controller.rb
View file @
e908c2e8
...
...
@@ -157,7 +157,8 @@ def create_user_cluster_params
:namespace
,
:api_url
,
:token
,
:ca_cert
:ca_cert
,
:authorization_type
]).
merge
(
provider_type: :user
,
platform_type: :kubernetes
...
...
app/helpers/clusters_helper.rb
View file @
e908c2e8
...
...
@@ -11,4 +11,8 @@ def render_gcp_signup_offer
render
'projects/clusters/gcp_signup_offer_banner'
end
end
def
rbac_clusters_feature_enabled?
Feature
.
enabled?
(
:rbac_clusters
)
end
end
app/models/clusters/applications/helm.rb
View file @
e908c2e8
...
...
@@ -32,7 +32,8 @@ def set_initial_status
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
.
new
(
name:
name
,
files:
files
files:
files
,
rbac:
cluster
.
platform_kubernetes_rbac?
)
end
...
...
app/models/clusters/applications/ingress.rb
View file @
e908c2e8
...
...
@@ -39,6 +39,7 @@ def install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
)
...
...
app/models/clusters/applications/jupyter.rb
View file @
e908c2e8
...
...
@@ -40,6 +40,7 @@ def install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
,
repository:
repository
...
...
app/models/clusters/applications/prometheus.rb
View file @
e908c2e8
...
...
@@ -48,6 +48,7 @@ def install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
)
...
...
@@ -71,7 +72,7 @@ def prometheus_client
private
def
kube_client
cluster
&
.
kubeclient
cluster
&
.
kubeclient
&
.
core_client
end
end
end
...
...
app/models/clusters/applications/runner.rb
View file @
e908c2e8
...
...
@@ -33,6 +33,7 @@ def install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
,
repository:
repository
...
...
app/models/clusters/cluster.rb
View file @
e908c2e8
...
...
@@ -42,6 +42,7 @@ class Cluster < ActiveRecord::Base
delegate
:on_creation?
,
to: :provider
,
allow_nil:
true
delegate
:active?
,
to: :platform_kubernetes
,
prefix:
true
,
allow_nil:
true
delegate
:rbac?
,
to: :platform_kubernetes
,
prefix:
true
,
allow_nil:
true
delegate
:installed?
,
to: :application_helm
,
prefix:
true
,
allow_nil:
true
delegate
:installed?
,
to: :application_ingress
,
prefix:
true
,
allow_nil:
true
...
...
app/models/clusters/platforms/kubernetes.rb
View file @
e908c2e8
...
...
@@ -5,6 +5,7 @@ module Platforms
class
Kubernetes
<
ActiveRecord
::
Base
include
Gitlab
::
Kubernetes
include
ReactiveCaching
include
EnumWithNil
self
.
table_name
=
'cluster_platforms_kubernetes'
self
.
reactive_cache_key
=
->
(
kubernetes
)
{
[
kubernetes
.
class
.
model_name
.
singular
,
kubernetes
.
id
]
}
...
...
@@ -47,6 +48,12 @@ class Kubernetes < ActiveRecord::Base
alias_method
:active?
,
:enabled?
enum_with_nil
authorization_type:
{
unknown_authorization:
nil
,
rbac:
1
,
abac:
2
}
def
actual_namespace
if
namespace
.
present?
namespace
...
...
@@ -95,7 +102,7 @@ def calculate_reactive_cache
end
def
kubeclient
@kubeclient
||=
build_kubeclient!
@kubeclient
||=
build_kube
_
client!
(
api_groups:
[
'api'
,
'apis/rbac.authorization.k8s.io'
])
end
private
...
...
@@ -115,15 +122,16 @@ def default_namespace
slug
.
gsub
(
/[^-a-z0-9]/
,
'-'
).
gsub
(
/^-+/
,
''
)
end
def
build_kubeclient!
(
api_
path
:
'api'
,
api_version:
'v1'
)
def
build_kube
_
client!
(
api_
groups
:
[
'api'
]
,
api_version:
'v1'
)
raise
"Incomplete settings"
unless
api_url
&&
actual_namespace
unless
(
username
&&
password
)
||
token
raise
"Either username/password or token is required to access API"
end
::
Kubeclient
::
Client
.
new
(
join_api_url
(
api_path
),
Gitlab
::
Kubernetes
::
KubeClient
.
new
(
api_url
,
api_groups
,
api_version
,
auth_options:
kubeclient_auth_options
,
ssl_options:
kubeclient_ssl_options
,
...
...
@@ -133,7 +141,7 @@ def build_kubeclient!(api_path: 'api', api_version: 'v1')
# Returns a hash of all pods in the namespace
def
read_pods
kubeclient
=
build_kubeclient!
kubeclient
=
build_kube
_
client!
kubeclient
.
get_pods
(
namespace:
actual_namespace
).
as_json
rescue
Kubeclient
::
HttpError
=>
err
...
...
@@ -157,15 +165,6 @@ def kubeclient_auth_options
{
bearer_token:
token
}
end
def
join_api_url
(
api_path
)
url
=
URI
.
parse
(
api_url
)
prefix
=
url
.
path
.
sub
(
%r{/+
\z
}
,
''
)
url
.
path
=
[
prefix
,
api_path
].
join
(
"/"
)
url
.
to_s
end
def
terminal_auth
{
token:
token
,
...
...
app/models/project_services/kubernetes_service.rb
View file @
e908c2e8
...
...
@@ -96,10 +96,10 @@ def actual_namespace
# Check we can connect to the Kubernetes API
def
test
(
*
args
)
kubeclient
=
build_kubeclient!
kubeclient
=
build_kube
_
client!
kubeclient
.
discover
{
success:
kubeclient
.
discovered
,
result:
"Checked API discovery endpoint"
}
kubeclient
.
core_client
.
discover
{
success:
kubeclient
.
core_client
.
discovered
,
result:
"Checked API discovery endpoint"
}
rescue
=>
err
{
success:
false
,
result:
err
}
end
...
...
@@ -144,7 +144,7 @@ def calculate_reactive_cache
end
def
kubeclient
@kubeclient
||=
build_kubeclient!
@kubeclient
||=
build_kube
_
client!
(
api_groups:
[
'api'
,
'apis/rbac.authorization.k8s.io'
])
end
def
deprecated?
...
...
@@ -182,11 +182,12 @@ def default_namespace
slug
.
gsub
(
/[^-a-z0-9]/
,
'-'
).
gsub
(
/^-+/
,
''
)
end
def
build_kubeclient!
(
api_
path
:
'api'
,
api_version:
'v1'
)
def
build_kube
_
client!
(
api_
groups
:
[
'api'
]
,
api_version:
'v1'
)
raise
"Incomplete settings"
unless
api_url
&&
actual_namespace
&&
token
::
Kubeclient
::
Client
.
new
(
join_api_url
(
api_path
),
Gitlab
::
Kubernetes
::
KubeClient
.
new
(
api_url
,
api_groups
,
api_version
,
auth_options:
kubeclient_auth_options
,
ssl_options:
kubeclient_ssl_options
,
...
...
@@ -196,7 +197,7 @@ def build_kubeclient!(api_path: 'api', api_version: 'v1')
# Returns a hash of all pods in the namespace
def
read_pods
kubeclient
=
build_kubeclient!
kubeclient
=
build_kube
_
client!
kubeclient
.
get_pods
(
namespace:
actual_namespace
).
as_json
rescue
Kubeclient
::
HttpError
=>
err
...
...
@@ -220,15 +221,6 @@ def kubeclient_auth_options
{
bearer_token:
token
}
end
def
join_api_url
(
api_path
)
url
=
URI
.
parse
(
api_url
)
prefix
=
url
.
path
.
sub
(
%r{/+
\z
}
,
''
)
url
.
path
=
[
prefix
,
api_path
].
join
(
"/"
)
url
.
to_s
end
def
terminal_auth
{
token:
token
,
...
...
app/views/projects/clusters/user/_form.html.haml
View file @
e908c2e8
...
...
@@ -25,5 +25,14 @@
=
platform_kubernetes_field
.
label
:namespace
,
s_
(
'ClusterIntegration|Project namespace (optional, unique)'
),
class:
'label-bold'
=
platform_kubernetes_field
.
text_field
:namespace
,
class:
'form-control'
,
placeholder:
s_
(
'ClusterIntegration|Project namespace'
)
-
if
rbac_clusters_feature_enabled?
.form-group
.form-check
=
platform_kubernetes_field
.
check_box
:authorization_type
,
{
class:
'form-check-input'
},
'rbac'
,
'abac'
=
platform_kubernetes_field
.
label
:authorization_type
,
s_
(
'ClusterIntegration|RBAC-enabled cluster (experimental)'
),
class:
'form-check-label label-bold'
.form-text.text-muted
=
s_
(
'ClusterIntegration|Enable this setting if using role-based access control (RBAC).'
)
=
s_
(
'ClusterIntegration|This option will allow you to install applications on RBAC clusters.'
)
.form-group
=
field
.
submit
s_
(
'ClusterIntegration|Add Kubernetes cluster'
),
class:
'btn btn-success'
app/views/projects/clusters/user/_show.html.haml
View file @
e908c2e8
...
...
@@ -26,5 +26,14 @@
=
platform_kubernetes_field
.
label
:namespace
,
s_
(
'ClusterIntegration|Project namespace (optional, unique)'
),
class:
'label-bold'
=
platform_kubernetes_field
.
text_field
:namespace
,
class:
'form-control'
,
placeholder:
s_
(
'ClusterIntegration|Project namespace'
)
-
if
rbac_clusters_feature_enabled?
.form-group
.form-check
=
platform_kubernetes_field
.
check_box
:authorization_type
,
{
class:
'form-check-input'
,
disabled:
true
},
'rbac'
,
'abac'
=
platform_kubernetes_field
.
label
:authorization_type
,
s_
(
'ClusterIntegration|RBAC-enabled cluster (experimental)'
),
class:
'form-check-label label-bold'
.form-text.text-muted
=
s_
(
'ClusterIntegration|Enable this setting if using role-based access control (RBAC).'
)
=
s_
(
'ClusterIntegration|This option will allow you to install applications on RBAC clusters.'
)
.form-group
=
field
.
submit
s_
(
'ClusterIntegration|Save changes'
),
class:
'btn btn-success'
changelogs/unreleased/29398-support-kubernetes-rbac-for-gitlab-managed-apps.yml
0 → 100644
View file @
e908c2e8
---
title
:
Support Kubernetes RBAC for GitLab Managed Apps when adding a existing cluster
merge_request
:
21127
author
:
type
:
changed
db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb
0 → 100644
View file @
e908c2e8
# frozen_string_literal: true
class
AddAuthorizationTypeToClusterPlatformsKubernetes
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
add_column
:cluster_platforms_kubernetes
,
:authorization_type
,
:integer
,
limit:
2
end
end
db/schema.rb
View file @
e908c2e8
...
...
@@ -588,6 +588,7 @@
t
.
string
"encrypted_password_iv"
t
.
text
"encrypted_token"
t
.
string
"encrypted_token_iv"
t
.
integer
"authorization_type"
,
limit:
2
end
add_index
"cluster_platforms_kubernetes"
,
[
"cluster_id"
],
name:
"index_cluster_platforms_kubernetes_on_cluster_id"
,
unique:
true
,
using: :btree
...
...
lib/gitlab/kubernetes/cluster_role_binding.rb
0 → 100644
View file @
e908c2e8
# frozen_string_literal: true
module
Gitlab
module
Kubernetes
class
ClusterRoleBinding
attr_reader
:name
,
:cluster_role_name
,
:subjects
def
initialize
(
name
,
cluster_role_name
,
subjects
)
@name
=
name
@cluster_role_name
=
cluster_role_name
@subjects
=
subjects
end
def
generate
::
Kubeclient
::
Resource
.
new
.
tap
do
|
resource
|
resource
.
metadata
=
metadata
resource
.
roleRef
=
role_ref
resource
.
subjects
=
subjects
end
end
private
def
metadata
{
name:
name
}
end
def
role_ref
{
apiGroup:
'rbac.authorization.k8s.io'
,
kind:
'ClusterRole'
,
name:
cluster_role_name
}
end
end
end
end
lib/gitlab/kubernetes/helm.rb
View file @
e908c2e8
...
...
@@ -3,6 +3,9 @@ module Kubernetes
module
Helm
HELM_VERSION
=
'2.7.2'
.
freeze
NAMESPACE
=
'gitlab-managed-apps'
.
freeze
SERVICE_ACCOUNT
=
'tiller'
.
freeze
CLUSTER_ROLE_BINDING
=
'tiller-admin'
.
freeze
CLUSTER_ROLE
=
'cluster-admin'
.
freeze
end
end
end
lib/gitlab/kubernetes/helm/api.rb
View file @
e908c2e8
...
...
@@ -9,7 +9,11 @@ def initialize(kubeclient)
def
install
(
command
)
namespace
.
ensure_exists!
create_service_account
(
command
)
create_cluster_role_binding
(
command
)
create_config_map
(
command
)
kubeclient
.
create_pod
(
command
.
pod_resource
)
end
...
...
@@ -41,6 +45,50 @@ def create_config_map(command)
kubeclient
.
create_config_map
(
config_map_resource
)
end
end
def
create_service_account
(
command
)
command
.
service_account_resource
.
tap
do
|
service_account_resource
|
break
unless
service_account_resource
if
service_account_exists?
(
service_account_resource
)
kubeclient
.
update_service_account
(
service_account_resource
)
else
kubeclient
.
create_service_account
(
service_account_resource
)
end
end
end
def
create_cluster_role_binding
(
command
)
command
.
cluster_role_binding_resource
.
tap
do
|
cluster_role_binding_resource
|
break
unless
cluster_role_binding_resource
if
cluster_role_binding_exists?
(
cluster_role_binding_resource
)
kubeclient
.
update_cluster_role_binding
(
cluster_role_binding_resource
)
else
kubeclient
.
create_cluster_role_binding
(
cluster_role_binding_resource
)
end
end
end
def
service_account_exists?
(
resource
)
resource_exists?
do
kubeclient
.
get_service_account
(
resource
.
metadata
.
name
,
resource
.
metadata
.
namespace
)
end
end
def
cluster_role_binding_exists?
(
resource
)
resource_exists?
do
kubeclient
.
get_cluster_role_binding
(
resource
.
metadata
.
name
)
end
end
def
resource_exists?
yield
rescue
::
Kubeclient
::
HttpError
=>
e
raise
e
unless
e
.
error_code
==
404
false
end
end
end
end
...
...
lib/gitlab/kubernetes/helm/base_command.rb
View file @
e908c2e8
...
...
@@ -3,7 +3,9 @@ module Kubernetes
module
Helm
module
BaseCommand
def
pod_resource
Gitlab
::
Kubernetes
::
Helm
::
Pod
.
new
(
self
,
namespace
).
generate
pod_service_account_name
=
rbac?
?
service_account_name
:
nil
Gitlab
::
Kubernetes
::
Helm
::
Pod
.
new
(
self
,
namespace
,
service_account_name:
pod_service_account_name
).
generate
end
def
generate_script
...
...
@@ -26,6 +28,14 @@ def config_map_resource
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
name
,
files
).
generate
end
def
service_account_resource
nil
end
def
cluster_role_binding_resource
nil
end
def
file_names
files
.
keys
end
...
...
@@ -34,6 +44,10 @@ def name
raise
"Not implemented"
end
def
rbac?
raise
"Not implemented"
end
def
files
raise
"Not implemented"
end
...
...
@@ -47,6 +61,10 @@ def files_dir
def
namespace
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
end
def
service_account_name
Gitlab
::
Kubernetes
::
Helm
::
SERVICE_ACCOUNT
end
end
end
end
...
...
lib/gitlab/kubernetes/helm/init_command.rb
View file @
e908c2e8
...
...
@@ -6,9 +6,10 @@ class InitCommand
attr_reader
:name
,
:files
def
initialize
(
name
:,
files
:)
def
initialize
(
name
:,
files
:
,
rbac
:
)
@name
=
name
@files
=
files
@rbac
=
rbac
end
def
generate_script
...
...
@@ -17,15 +18,62 @@ def generate_script
].
join
(
"
\n
"
)
end
def
rbac?
@rbac
end
def
service_account_resource
return
unless
rbac?
Gitlab
::
Kubernetes
::
ServiceAccount
.
new
(
service_account_name
,
namespace
).
generate
end
def
cluster_role_binding_resource
return
unless
rbac?
subjects
=
[{
kind:
'ServiceAccount'
,
name:
service_account_name
,
namespace:
namespace
}]
Gitlab
::
Kubernetes
::
ClusterRoleBinding
.
new
(
cluster_role_binding_name
,
cluster_role_name
,
subjects
).
generate
end
private
def
init_helm_command
tls_flags
=
"--tiller-tls"
\
" --tiller-tls-verify --tls-ca-cert
#{
files_dir
}
/ca.pem"
\
" --tiller-tls-cert
#{
files_dir
}
/cert.pem"
\
" --tiller-tls-key
#{
files_dir
}
/key.pem"
command
=
%w[helm init]
+
init_command_flags
command
.
shelljoin
+
" >/dev/null
\n
"
end
def
init_command_flags
tls_flags
+
optional_service_account_flag
end
def
tls_flags
[
'--tiller-tls'
,
'--tiller-tls-verify'
,
'--tls-ca-cert'
,
"
#{
files_dir
}
/ca.pem"
,
'--tiller-tls-cert'
,
"
#{
files_dir
}
/cert.pem"
,
'--tiller-tls-key'
,
"
#{
files_dir
}
/key.pem"
]
end
def
optional_service_account_flag
return
[]
unless
rbac?
[
'--service-account'
,
service_account_name
]
end
def
cluster_role_binding_name
Gitlab
::
Kubernetes
::
Helm
::
CLUSTER_ROLE_BINDING
end
"helm init
#{
tls_flags
}
>/dev/null"
def
cluster_role_name
Gitlab
::
Kubernetes
::
Helm
::
CLUSTER_ROLE
end
end
end
...
...
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment