diff --git a/app/lib/clients/vault.rb b/app/lib/clients/vault.rb index ea78ef1..6c73276 100644 --- a/app/lib/clients/vault.rb +++ b/app/lib/clients/vault.rb @@ -1,35 +1,12 @@ module Clients class Vault class << self - def issue_cert(cert_issue_request) - enable_ca - opts = cert_issue_request.attributes - # Generate the TLS certificate using the intermediate CA - tls_cert = client.logical.write(cert_path, opts) - OpenStruct.new tls_cert.data - end - - def kv_read(path) - client.kv(kv_mount).read(path) - end - - def kv_write(path, data) - unless client.sys.mounts.key?(kv_mount.to_sym) - enable_engine(kv_mount, "kv-v2") - end - client.logical.write("#{kv_mount}/data/#{path}", data: data) - end - - def kv_delete(path) - client.logical.delete("#{kv_mount}/data/#{path}") - end - private def client ::Vault::Client.new( address: vault_address, - token: Rails.configuration.astral[:vault_token] + token: vault_token ) end @@ -37,81 +14,16 @@ def vault_address Rails.configuration.astral[:vault_addr] end - def kv_mount - "kv_astral" - end - - def intermediate_ca_mount - "pki_astral" - end - - def cert_path - "#{intermediate_ca_mount}/issue/astral" - end - - def root_ca_ref - Rails.configuration.astral[:vault_root_ca_ref] - end - - def root_ca_mount - Rails.configuration.astral[:vault_root_ca_mount] + def vault_token + Rails.configuration.astral[:vault_token] end def enable_engine(mount, type) client.sys.mount(mount, type, "#{type} secrets engine") end - - def enable_ca - # if mount exists, assume configuration is done - if client.sys.mounts.key?(intermediate_ca_mount.to_sym) - return - end - - # create the mount - enable_engine(intermediate_ca_mount, "pki") - - # Generate intermediate CSR - intermediate_csr = client.logical.write("#{intermediate_ca_mount}/intermediate/generate/internal", - common_name: "astral.internal Intermediate Authority", - issuer_name: "astral-intermediate").data[:csr] - - # Save the intermediate CSR - File.write("tmp/pki_intermediate.csr", intermediate_csr) - - # Sign the intermediate certificate with the root CA - intermediate_cert = client.logical.write("#{root_ca_mount}/root/sign-intermediate", - issuer_ref: root_ca_ref, - csr: intermediate_csr, - format: "pem_bundle", - ttl: "43800h").data[:certificate] - - # Save the signed intermediate certificate - File.write("tmp/intermediate.cert.pem", intermediate_cert) - - # Set the signed intermediate certificate - client.logical.write("#{intermediate_ca_mount}/intermediate/set-signed", certificate: intermediate_cert) - - # Configure the intermediate CA - client.logical.write("#{intermediate_ca_mount}/config/cluster", - path: "#{vault_address}/v1/#{intermediate_ca_mount}", - aia_path: "#{vault_address}/v1/#{intermediate_ca_mount}") - - # Configure the role for issuing certs - issuer_ref = client.logical.read("#{intermediate_ca_mount}/config/issuers").data[:default] - client.logical.write("#{intermediate_ca_mount}/roles/astral", - issuer_ref: issuer_ref, - allow_any_name: true, - max_ttl: "720h", - no_store: false) - - client.logical.write("#{intermediate_ca_mount}/config/urls", - issuing_certificates: "{{cluster_aia_path}}/issuer/{{issuer_id}}/der", - crl_distribution_points: "{{cluster_aia_path}}/issuer/{{issuer_id}}/crl/der", - ocsp_servers: "{{cluster_path}}/ocsp", - enable_templating: true) - rescue ::Vault::HTTPError => e - Rails.logger.error "Unable to configure intermediate_cert: #{e}" - end end end + + require_relative "vault/key_value" + require_relative "vault/certificate" end diff --git a/app/lib/clients/vault/certificate.rb b/app/lib/clients/vault/certificate.rb new file mode 100644 index 0000000..a59d964 --- /dev/null +++ b/app/lib/clients/vault/certificate.rb @@ -0,0 +1,87 @@ +module Clients + class Vault + class << self + def issue_cert(cert_issue_request) + enable_ca + opts = cert_issue_request.attributes + # Generate the TLS certificate using the intermediate CA + tls_cert = client.logical.write(cert_path, opts) + OpenStruct.new tls_cert.data + end + + private + + def intermediate_ca_mount + "pki_astral" + end + + def cert_path + "#{intermediate_ca_mount}/issue/astral" + end + + def root_ca_ref + Rails.configuration.astral[:vault_root_ca_ref] + end + + def root_ca_mount + Rails.configuration.astral[:vault_root_ca_mount] + end + + def cert_engine_type + "pki" + end + + def enable_ca + # if mount exists, assume configuration is done + if client.sys.mounts.key?(intermediate_ca_mount.to_sym) + return + end + + # create the mount + enable_engine(intermediate_ca_mount, cert_engine_type) + + # Generate intermediate CSR + intermediate_csr = client.logical.write("#{intermediate_ca_mount}/intermediate/generate/internal", + common_name: "astral.internal Intermediate Authority", + issuer_name: "astral-intermediate").data[:csr] + + # Save the intermediate CSR + File.write("tmp/pki_intermediate.csr", intermediate_csr) + + # Sign the intermediate certificate with the root CA + intermediate_cert = client.logical.write("#{root_ca_mount}/root/sign-intermediate", + issuer_ref: root_ca_ref, + csr: intermediate_csr, + format: "pem_bundle", + ttl: "43800h").data[:certificate] + + # Save the signed intermediate certificate + File.write("tmp/intermediate.cert.pem", intermediate_cert) + + # Set the signed intermediate certificate + client.logical.write("#{intermediate_ca_mount}/intermediate/set-signed", certificate: intermediate_cert) + + # Configure the intermediate CA + client.logical.write("#{intermediate_ca_mount}/config/cluster", + path: "#{vault_address}/v1/#{intermediate_ca_mount}", + aia_path: "#{vault_address}/v1/#{intermediate_ca_mount}") + + # Configure the role for issuing certs + issuer_ref = client.logical.read("#{intermediate_ca_mount}/config/issuers").data[:default] + client.logical.write("#{intermediate_ca_mount}/roles/astral", + issuer_ref: issuer_ref, + allow_any_name: true, + max_ttl: "720h", + no_store: false) + + client.logical.write("#{intermediate_ca_mount}/config/urls", + issuing_certificates: "{{cluster_aia_path}}/issuer/{{issuer_id}}/der", + crl_distribution_points: "{{cluster_aia_path}}/issuer/{{issuer_id}}/crl/der", + ocsp_servers: "{{cluster_path}}/ocsp", + enable_templating: true) + rescue ::Vault::HTTPError => e + Rails.logger.error "Unable to configure intermediate_cert: #{e}" + end + end + end +end diff --git a/app/lib/clients/vault/key_value.rb b/app/lib/clients/vault/key_value.rb new file mode 100644 index 0000000..503df90 --- /dev/null +++ b/app/lib/clients/vault/key_value.rb @@ -0,0 +1,30 @@ +module Clients + class Vault + class << self + def kv_read(path) + client.kv(kv_mount).read(path) + end + + def kv_write(path, data) + unless client.sys.mounts.key?(kv_mount.to_sym) + enable_engine(kv_mount, kv_engine_type) + end + client.logical.write("#{kv_mount}/data/#{path}", data: data) + end + + def kv_delete(path) + client.logical.delete("#{kv_mount}/data/#{path}") + end + + private + + def kv_mount + "kv_astral" + end + + def kv_engine_type + "kv-v2" + end + end + end +end