diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index dcafb8a..2b58180 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -17,6 +17,7 @@ services: VAULT_CREATE_ROOT: true VAULT_ROOT_CA_MOUNT: pki VAULT_ROOT_CA_REF: root-ca + VAULT_SSL_CERT: cert/vault.pem JWT_SIGNING_KEY: jwt_secret APP_REGISTRY_ADDR: http://app_registry:8800 APP_REGISTRY_TOKEN: app_reg_token @@ -26,9 +27,26 @@ services: restart: unless-stopped ports: - 8200:8200 + - 8443:8443 + volumes: + - ../cert:/vault/cert environment: VAULT_DEV_ROOT_TOKEN_ID: root_token - VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200 + VAULT_LOCAL_CONFIG: > + { + "listener": [ + { + "tcp": { + "address": "0.0.0.0:8443", + "tls_disable": "0", + "tls_cert_file": "/vault/cert/vault.pem", + "tls_key_file": "/vault/cert/vault.key" + } + } + ], + "default_lease_ttl": "168h", + "max_lease_ttl": "720h" + } app_registry: image: node:latest diff --git a/README.md b/README.md index 26177f6..00ca829 100644 --- a/README.md +++ b/README.md @@ -61,3 +61,29 @@ docker build -t astral:latest . ``` docker run -p 3000:3000 astral:latest ``` + +# Configuration +Astral is configured in `config/astral.yml` -- all availble +configuration options are listed in the `shared` section. Note that +configuration values can be supplied in this file or as process +environment variables with the same names (but +UPPER_CASE). Environment vars will override any values in the config +file. Per-environment settings in the config file(development, test, +production) will override the shared values for that type. + +## mTLS connections +Astral can connect to Vault with mTLS. Just +set the following values in `config/astral.yml`: +``` + vault_ssl_cert: + vault_ssl_client_cert: + vault_ssl_client_key: +``` +A self-signed server cert for Vault can be generated with the following +command: +``` +rake configure:ssl +``` + +To use SSL in the devcontainer, edit `.devcontainer/docker-compose.yml` so +that the `app` service has `VAULT_ADDRESS` of `https://vault:8443`. diff --git a/app/lib/clients/vault.rb b/app/lib/clients/vault.rb index 5f0c5e0..10ec7d9 100644 --- a/app/lib/clients/vault.rb +++ b/app/lib/clients/vault.rb @@ -14,7 +14,10 @@ class << self def client ::Vault::Client.new( address: address, - token: token + token: token, + ssl_ca_cert: ssl_cert, + ssl_pem_file: ssl_client_cert, + ssl_key_file: ssl_client_key ) end @@ -22,6 +25,18 @@ def address Config[:vault_addr] end + def ssl_cert + Config[:vault_ssl_cert] + end + + def ssl_client_cert + Config[:vault_ssl_client_cert] + end + + def ssl_client_key + Config[:vault_ssl_client_key] + end + def enable_engine(mount, type) client.sys.mount(mount, type, "#{type} secrets engine") end diff --git a/cert/.keep b/cert/.keep new file mode 100644 index 0000000..e69de29 diff --git a/cert/vault.csr b/cert/vault.csr new file mode 100644 index 0000000..3b882f7 --- /dev/null +++ b/cert/vault.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIElzCCAn8CAQAwUjELMAkGA1UEBhMCVVMxDzANBgNVBAgMBkRlbmlhbDEUMBIG +A1UEBwwLU3ByaW5nZmllbGQxDDAKBgNVBAoMA0RpczEOMAwGA1UEAwwFdmF1bHQw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC4GT1p/wZyxvMsZ/N7g6Hb +SNqTCA6W+JbPryhy2YjVwdH+JwYQGy4GbXYxbKZp5ZXAf5/9/y6j8BnsHrxv5pvC +Ob08aArhQE6ht0NTqaIYsSf/7TeW1e+da5ikLbrcFUcXVzKWtZPcbz4Y42G1AS9T +Lyyw01y6LUGK5WWy3ztD/8fyYVImG7q+8JGYKJpxI0fsLaEpDvHq5ZpOPMJqT0tb +aWwK8CtDcLEjv1bxmXUpD6c8FzffRwuy1SM6USMyAFFLdIVizjgekhRJPOQTeO8N +yR8O3ViT4Eq+ED051qk+oT99xvfHLOLk7BFMVYK3bYMmaOHlb9g060Og32lFbcuD +gGaGI2d+0cQrWemQiWjEMi55dIqXDmGiA3o18r7s0bEt7lPKFBqjrRfPh9/+Eqqp +YkWjp623vOW+vHPgxUNcyGMXl/nZTcvhpJLOgBkjQnq7dSpV3LzrGNN3mJFpKxQy +e7rccbZPa82ln5Y6+g97H/oy1FNkzNcI+Fv3BOCSQOoM9uPB6NP5b3seJC8GW1eh +LV/byfuwXSJJYo7csNiem90UTRR7ZDzjE8clbzATR0d+qJTf0idA5xDKU+JwxqzW ++ktBZwwS2t+A1QaHj7frJt0FuN1Us+bX6GcJ6X+JJsjxEp+WbKIncgQVk6mcbVJm +T6a4LyiFCN9oeDnkLM6L/wIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBAGU4/K0+ +d85R/Y1ov3MJTmpOC0fGJ8/H7U/MIk0qlSfqzRMYIjHHFRqslMzGaRZG/XZN4grj +FvceoYBTH2NUip4HF+PRwxkUlwAFFea/h2noT5Ca0X00roHCf/uhJYY5OGxS5TD6 +CkP6nbCpD9oVDePlLehMuvNtJBt50QQsBUyK3FCXTsunNSVrMdVQ6zlyJVo0limQ ++eQy4u/bvG0BzsIj6+HnvMTxC1gQCOsfieiJyrF51EbGZJUms89k8Oli9mgJxdaC +6sh/s+FfF0m0tp449Qv/mAy57Z5EC6SUBuAICYd/bSHXWuzAi/9jTJeyTbNpN0F8 +615CWN+sIuiGG9JLdCCbJE/WxGAa4/3Ry1gtYrcrSz+i1NXT422RZfxTASLl9fT6 +NlUu2DN3UQQmbxG8ujzKdZ2o746vovFWGtECh6oj0dZ2vhKAKDgIlT2ZOaZzp4mk +b7tpfXBhUsVVG2rIhHXh7HAa9YDFGNufZ+p+b2GI+i5ll6+XUsXSM0SGnM+E1VLh +wnz3krI1tFTNBUu3+n9UbQhBgCWt4bj2Ax0LCgd6sHClcHa0q07FlRVIa/edXu/p +Xt2yr1xhdsK0ss9kRyXg2AMHVTs0ES8rKxcvAmdbic4ygg7MfRhnT/B4HFSKKyoU +JCy4FPyt1+iqfDzjtS74h261lVm6bHnW+7bI +-----END CERTIFICATE REQUEST----- diff --git a/cert/vault.key b/cert/vault.key new file mode 100644 index 0000000..20ddc1b --- /dev/null +++ b/cert/vault.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +7sscXOjF3wtZdFCFacS9FPm9KRjD7AU= +-----END PRIVATE KEY----- diff --git a/cert/vault.pem b/cert/vault.pem new file mode 100644 index 0000000..b7c6371 --- /dev/null +++ b/cert/vault.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFKzCCAxMCFDxrZQdK60TK6QxY01Y0QdRFrbdpMA0GCSqGSIb3DQEBCwUAMFIx +CzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZEZW5pYWwxFDASBgNVBAcMC1NwcmluZ2Zp +ZWxkMQwwCgYDVQQKDANEaXMxDjAMBgNVBAMMBXZhdWx0MB4XDTI0MTAxNTE4NTk1 +N1oXDTI1MTAxNTE4NTk1N1owUjELMAkGA1UEBhMCVVMxDzANBgNVBAgMBkRlbmlh +bDEUMBIGA1UEBwwLU3ByaW5nZmllbGQxDDAKBgNVBAoMA0RpczEOMAwGA1UEAwwF +dmF1bHQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC4GT1p/wZyxvMs +Z/N7g6HbSNqTCA6W+JbPryhy2YjVwdH+JwYQGy4GbXYxbKZp5ZXAf5/9/y6j8Bns +Hrxv5pvCOb08aArhQE6ht0NTqaIYsSf/7TeW1e+da5ikLbrcFUcXVzKWtZPcbz4Y +42G1AS9TLyyw01y6LUGK5WWy3ztD/8fyYVImG7q+8JGYKJpxI0fsLaEpDvHq5ZpO +PMJqT0tbaWwK8CtDcLEjv1bxmXUpD6c8FzffRwuy1SM6USMyAFFLdIVizjgekhRJ +POQTeO8NyR8O3ViT4Eq+ED051qk+oT99xvfHLOLk7BFMVYK3bYMmaOHlb9g060Og +32lFbcuDgGaGI2d+0cQrWemQiWjEMi55dIqXDmGiA3o18r7s0bEt7lPKFBqjrRfP +h9/+EqqpYkWjp623vOW+vHPgxUNcyGMXl/nZTcvhpJLOgBkjQnq7dSpV3LzrGNN3 +mJFpKxQye7rccbZPa82ln5Y6+g97H/oy1FNkzNcI+Fv3BOCSQOoM9uPB6NP5b3se +JC8GW1ehLV/byfuwXSJJYo7csNiem90UTRR7ZDzjE8clbzATR0d+qJTf0idA5xDK +U+JwxqzW+ktBZwwS2t+A1QaHj7frJt0FuN1Us+bX6GcJ6X+JJsjxEp+WbKIncgQV +k6mcbVJmT6a4LyiFCN9oeDnkLM6L/wIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBi +hcNthicAeN726BwOSt87q7T/MLJp543CtGcL8m0Z5N6ZlQhCdS3/aPKHXtksbtyY +3oXcMcXaROPkYDOn6F5bNmsLpkC6v/lZpN7yxFbNN2QZ9kqDquRoyIg9EQmOazIl +daahg7UoI3n2u/Rb5AJ0MmsfiKx2ybFTNwdI1Pg84Tp5k/VuvQ33bCxErIXjaaE0 +60w7xUkus2WbrMTLgJOS+GdVIa+RmJVivK5c+ejJcE81bGEVuCnCxvPy7aIcwKy4 +BGYxsVDW/9/rlm+z92KKcnvWFIxxlU+FTeXeOoIXAyRydOn9Eh7Is8Y6LoWf7U5S +n2uxMsjJ2kf08/2FcYjkPfgQm3PYKUS+xOBOE9ykT4t84v32c6sVvGMWMeHMJfMZ +CPF/Ok9CzvqWaMcVzLOeCQT4AAAT1yyNN0WaTMlx8UZthB/axR1uR5xcs/4VsVfq +K0ToIh9dmH4LLr5GB+RPLXLdoyS9JneMekkJHqq7PngcJztuhmq6EESVgdaEiQC4 +HgMaWV9SLku7OxFa050qiCZGDvJU5emNkizWIkm91f3sXliLF9sl5BSnr/4UtlnA +ExU8iaglghbA0wfyGfXIUYtENGLh6b7PVOvT0eirSLgAvHijdCL0tiwssfl8a4W/ +sYs2JyeEa3Dpf7qU6uHbg8TWEfZsulezprneVmgG4Q== +-----END CERTIFICATE----- diff --git a/config/astral.yml b/config/astral.yml index a574607..15eda38 100644 --- a/config/astral.yml +++ b/config/astral.yml @@ -1,23 +1,34 @@ +# Astral configuration +# Note that values can be supplied here or as environment vars (UPPER_CASE). shared: - vault_addr: vault_token: + vault_addr: + # if VAULT_ADDR is https with self-signed cert, need to provide + # CA cert (path to file) in "vault_ssl_cert" below: + vault_ssl_cert: + # Vault client cert if required (path to file) + vault_ssl_client_cert: + vault_ssl_client_key: - # Pre-existing root CA, or create new if requested + # Vault PKI configuration -- create root CA when true, or reference an existing vault_create_root: true vault_root_ca_ref: root_ca vault_root_ca_mount: pki_root + cert_ttl: jwt_signing_key: - cert_ttl: + # When using AppRegistry for Domain Ownership information app_registry_addr: app_registry_token: app_registry_ca_file: app_registry_client_cert: app_registry_client_key: + # User activity logging audit_log_file: <%= "#{Rails.root.join('log')}/astral-audit.log" %> +# Per-environment overrides of shared configs test: cert_ttl: <%= 24.hours.in_seconds %> diff --git a/lib/tasks/configure.rake b/lib/tasks/configure.rake new file mode 100644 index 0000000..80ad985 --- /dev/null +++ b/lib/tasks/configure.rake @@ -0,0 +1,17 @@ +require "rake" + +# Rake tasks for making a vault cert +namespace :configure do + desc "Make the server cert for vault" + task :ssl do + %x( + openssl req -new -newkey rsa:4096 -nodes \ + -keyout cert/vault.key -out cert/vault.csr \ + -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=vault" + openssl x509 -req -days 365 -in cert/vault.csr \ + -signkey cert/vault.key \ + -out cert/vault.pem + ) + puts "SSL key for vault created" + end +end diff --git a/lib/tasks/redoc.rake b/lib/tasks/redoc.rake index 8810fa6..0452fc6 100644 --- a/lib/tasks/redoc.rake +++ b/lib/tasks/redoc.rake @@ -6,8 +6,8 @@ namespace :redoc do task :bundle do %x( docker run -v /workspaces/astral/doc/openapi:/data -w /data \ - redocly/cli bundle openapi.yml \ - --output openapi-bundled.yml + redocly/cli bundle openapi.yml \ + --output openapi-bundled.yml ) puts "openapi.yml and references bundled to openapi-bundled.yml" end diff --git a/test/lib/clients/vault_test.rb b/test/lib/clients/vault_test.rb index e18337c..51ca0a8 100644 --- a/test/lib/clients/vault_test.rb +++ b/test/lib/clients/vault_test.rb @@ -115,7 +115,10 @@ class VaultTest < ActiveSupport::TestCase def vault_client ::Vault::Client.new( address: vault_addr, - token: vault_token + token: vault_token, + ssl_ca_cert: ssl_cert, + ssl_pem_file: ssl_client_cert, + ssl_key_file: ssl_client_key ) end @@ -126,4 +129,16 @@ def vault_addr def vault_token Config[:vault_token] end + + def ssl_cert + Config[:vault_ssl_cert] + end + + def ssl_client_cert + Config[:vault_ssl_client_cert] + end + + def ssl_client_key + Config[:vault_ssl_client_key] + end end