From fc134096370c94bc1312060c42ed69b2665f0f95 Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Tue, 7 Aug 2018 12:39:38 +0000 Subject: Resolve "Mutual SSL Auth For Helm TIller" --- lib/gitlab/kubernetes/config_map.rb | 8 +-- lib/gitlab/kubernetes/helm/api.rb | 2 +- lib/gitlab/kubernetes/helm/base_command.rb | 32 ++++++++---- lib/gitlab/kubernetes/helm/certificate.rb | 73 +++++++++++++++++++++++++++ lib/gitlab/kubernetes/helm/init_command.rb | 18 ++++++- lib/gitlab/kubernetes/helm/install_command.rb | 35 +++++++------ lib/gitlab/kubernetes/helm/pod.rb | 8 ++- 7 files changed, 138 insertions(+), 38 deletions(-) create mode 100644 lib/gitlab/kubernetes/helm/certificate.rb (limited to 'lib') diff --git a/lib/gitlab/kubernetes/config_map.rb b/lib/gitlab/kubernetes/config_map.rb index 8a8a59a9cd4..9e55dae137c 100644 --- a/lib/gitlab/kubernetes/config_map.rb +++ b/lib/gitlab/kubernetes/config_map.rb @@ -1,15 +1,15 @@ module Gitlab module Kubernetes class ConfigMap - def initialize(name, values = "") + def initialize(name, files) @name = name - @values = values + @files = files end def generate resource = ::Kubeclient::Resource.new resource.metadata = metadata - resource.data = { values: values } + resource.data = files resource end @@ -19,7 +19,7 @@ module Gitlab private - attr_reader :name, :values + attr_reader :name, :files def metadata { diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb index c4de9a398cc..d65374cc23b 100644 --- a/lib/gitlab/kubernetes/helm/api.rb +++ b/lib/gitlab/kubernetes/helm/api.rb @@ -9,7 +9,7 @@ module Gitlab def install(command) namespace.ensure_exists! - create_config_map(command) if command.config_map? + create_config_map(command) kubeclient.create_pod(command.pod_resource) end diff --git a/lib/gitlab/kubernetes/helm/base_command.rb b/lib/gitlab/kubernetes/helm/base_command.rb index f9ebe53d6af..afcfd109de0 100644 --- a/lib/gitlab/kubernetes/helm/base_command.rb +++ b/lib/gitlab/kubernetes/helm/base_command.rb @@ -1,13 +1,7 @@ module Gitlab module Kubernetes module Helm - class BaseCommand - attr_reader :name - - def initialize(name) - @name = name - end - + module BaseCommand def pod_resource Gitlab::Kubernetes::Helm::Pod.new(self, namespace).generate end @@ -24,16 +18,32 @@ module Gitlab HEREDOC end - def config_map? - false - end - def pod_name "install-#{name}" end + def config_map_resource + Gitlab::Kubernetes::ConfigMap.new(name, files).generate + end + + def file_names + files.keys + end + + def name + raise "Not implemented" + end + + def files + raise "Not implemented" + end + private + def files_dir + "/data/helm/#{name}/config" + end + def namespace Gitlab::Kubernetes::Helm::NAMESPACE end diff --git a/lib/gitlab/kubernetes/helm/certificate.rb b/lib/gitlab/kubernetes/helm/certificate.rb new file mode 100644 index 00000000000..598714e0874 --- /dev/null +++ b/lib/gitlab/kubernetes/helm/certificate.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true +module Gitlab + module Kubernetes + module Helm + class Certificate + INFINITE_EXPIRY = 1000.years + SHORT_EXPIRY = 30.minutes + + attr_reader :key, :cert + + def key_string + @key.to_s + end + + def cert_string + @cert.to_pem + end + + def self.from_strings(key_string, cert_string) + key = OpenSSL::PKey::RSA.new(key_string) + cert = OpenSSL::X509::Certificate.new(cert_string) + new(key, cert) + end + + def self.generate_root + _issue(signed_by: nil, expires_in: INFINITE_EXPIRY, certificate_authority: true) + end + + def issue(expires_in: SHORT_EXPIRY) + self.class._issue(signed_by: self, expires_in: expires_in, certificate_authority: false) + end + + private + + def self._issue(signed_by:, expires_in:, certificate_authority:) + key = OpenSSL::PKey::RSA.new(4096) + public_key = key.public_key + + subject = OpenSSL::X509::Name.parse("/C=US") + + cert = OpenSSL::X509::Certificate.new + cert.subject = subject + + cert.issuer = signed_by&.cert&.subject || subject + + cert.not_before = Time.now + cert.not_after = expires_in.from_now + cert.public_key = public_key + cert.serial = 0x0 + cert.version = 2 + + if certificate_authority + extension_factory = OpenSSL::X509::ExtensionFactory.new + extension_factory.subject_certificate = cert + extension_factory.issuer_certificate = cert + cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash')) + cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)) + cert.add_extension(extension_factory.create_extension('keyUsage', 'cRLSign,keyCertSign', true)) + end + + cert.sign(signed_by&.key || key, OpenSSL::Digest::SHA256.new) + + new(key, cert) + end + + def initialize(key, cert) + @key = key + @cert = cert + end + end + end + end +end diff --git a/lib/gitlab/kubernetes/helm/init_command.rb b/lib/gitlab/kubernetes/helm/init_command.rb index a02e64561f6..a4546509515 100644 --- a/lib/gitlab/kubernetes/helm/init_command.rb +++ b/lib/gitlab/kubernetes/helm/init_command.rb @@ -1,7 +1,16 @@ module Gitlab module Kubernetes module Helm - class InitCommand < BaseCommand + class InitCommand + include BaseCommand + + attr_reader :name, :files + + def initialize(name:, files:) + @name = name + @files = files + end + def generate_script super + [ init_helm_command @@ -11,7 +20,12 @@ module Gitlab private def init_helm_command - "helm init >/dev/null" + 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" + + "helm init #{tls_flags} >/dev/null" end end end diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb index d2133a6d65b..9672f80687e 100644 --- a/lib/gitlab/kubernetes/helm/install_command.rb +++ b/lib/gitlab/kubernetes/helm/install_command.rb @@ -1,14 +1,16 @@ module Gitlab module Kubernetes module Helm - class InstallCommand < BaseCommand - attr_reader :name, :chart, :version, :repository, :values + class InstallCommand + include BaseCommand - def initialize(name, chart:, values:, version: nil, repository: nil) + attr_reader :name, :files, :chart, :version, :repository + + def initialize(name:, chart:, files:, version: nil, repository: nil) @name = name @chart = chart @version = version - @values = values + @files = files @repository = repository end @@ -20,14 +22,6 @@ module Gitlab ].compact.join("\n") end - def config_map? - true - end - - def config_map_resource - Gitlab::Kubernetes::ConfigMap.new(name, values).generate - end - private def init_command @@ -39,14 +33,25 @@ module Gitlab end def script_command - <<~HEREDOC - helm install #{chart} --name #{name}#{optional_version_flag} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null - HEREDOC + init_flags = "--name #{name}#{optional_tls_flags}#{optional_version_flag}" \ + " --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE}" \ + " -f /data/helm/#{name}/config/values.yaml" + + "helm install #{chart} #{init_flags} >/dev/null\n" end def optional_version_flag " --version #{version}" if version end + + def optional_tls_flags + return unless files.key?(:'ca.pem') + + " --tls" \ + " --tls-ca-cert #{files_dir}/ca.pem" \ + " --tls-cert #{files_dir}/cert.pem" \ + " --tls-key #{files_dir}/key.pem" + end end end end diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb index 1e12299eefd..6e5d3388405 100644 --- a/lib/gitlab/kubernetes/helm/pod.rb +++ b/lib/gitlab/kubernetes/helm/pod.rb @@ -10,10 +10,8 @@ module Gitlab def generate spec = { containers: [container_specification], restartPolicy: 'Never' } - if command.config_map? - spec[:volumes] = volumes_specification - spec[:containers][0][:volumeMounts] = volume_mounts_specification - end + spec[:volumes] = volumes_specification + spec[:containers][0][:volumeMounts] = volume_mounts_specification ::Kubeclient::Resource.new(metadata: metadata, spec: spec) end @@ -61,7 +59,7 @@ module Gitlab name: 'configuration-volume', configMap: { name: "values-content-configuration-#{command.name}", - items: [{ key: 'values', path: 'values.yaml' }] + items: command.file_names.map { |name| { key: name, path: name } } } } ] -- cgit v1.2.3