Save internally issued wildcard certificate in Consul?

1. Caddy version (caddy version):

v2.3.0

2. How I run Caddy:

systemd

a. System environment:

Ubuntu 20.04 LTS

b. Command:

/usr/local/bin/caddy run --environ --config $CONFIG --adapter=caddyfile
or
sudo systemctl start caddy

c. Service/unit/compose file:

# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.

[Unit]
Description=Caddy Reverse Proxy and Load Balancer
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
EnvironmentFile=/etc/default/caddy
User=caddy
Group=caddy
ExecStart=/usr/local/bin/caddy run --environ --config $CONFIG --adapter=caddyfile
ExecReload=/usr/local/bin/caddy reload --config $CONFIG --adapter=caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

d. My complete Caddyfile or JSON config:

storage consul {
  address       "127.0.0.1:8500"
  #token        "consul-access-token"
  timeout       10
  prefix        "caddy.internal"
  #value_prefix "myprefix"
  #aes_key      "consultls-1234567890-caddytls-32"
  tls_enabled   "false"
  tls_insecure  "true"
}

3. The problem I’m having:

I want to issue a wildcard cert from my internal CA and have caddy store it for use in its configured TLS store, in this case, consul. Consul is configured correctly, and caddy creates the right k/v in consul, but I don’t know how to add a manually signed cert so it can be used by multiple nodes.

4. Error messages and/or full log output:

N/A - there is no error, I just don’t know how to do this

5. What I already tried:

search documentation, github issues, and googled for solutions

6. Links to relevant resources:

I’m not totally sure I understand what you’re trying to do. Is that your whole Caddyfile? Are you trying to have Caddy manage some certificates but not serve the content?

It’s not the whole caddyfile but I’m not sure if it’s relevant? it’s split into a number of files, but I can post a concatenated version if you need it. But my issue isn’t with the config I think.

Basically, you can use Hashicorp Consul as a TLS store. It seems like it works automatically, if you are getting your certs automatically via ACME. However, I am not, instead I will be signing a wildcart certificate with an internal certificate authority. So, my question is “Where do I put a manual cert in the consul K/V store so that it can be used by all valid hostnames?”

Oh, I see. Hmm. I think what you want is to augment the tlsconsul plugin such that it provides a tls.certificates.consul module that can load a certificate from an arbitrary key in consul.

There’s currently four built-in certificate loader modules, you can see them here:

Are you saying that one of those 4 can solve my problem, or that I need to write my own module in that manner of those other ones? Unfortunately, I don’t really have time to write a new module.

Yeah, I think a new module would need to be written for this (or be included in the caddy-tlsconsul package).

Maybe @matt would know if theres a way for Caddy to pick up a certificate in storage without automating issuance for it, but I don’t think there is at this time.

Maybe a generic tls.certificates.load_storage module could be included in Caddy in a future version to allow grabbing certificates from some arbitrary location in the configured storage module :man_shrugging:

Huh. Okay. I was thinking maybe I could just copy the keys to some preset K/V and call it a day. IIRC, traefik worked like that, you could just paste the cert into a key in consul and if that key existed and the SNIs matched, it would be used before any ACME stuff.

Maybe I could deploy an instance of caddy with an signed intermediate to act as an ACME server for other caddy instances? But I’m wondering if such a deployment could be clustered / highly-available / made to coordinate cert issuance? And ideally, restricted to what hosts to request certs.

Yep, you could definitely do that. You would need to configure the pki app to use your own root/intermediate. Right now, pki app configuration isn’t available via the Caddyfile, but it may come in a later version. For now, you’ll need to use JSON config. You can adapt your current config to JSON with caddy adapt --pretty then add the pki bits. You could even pipe into jq to append the pki stuff to build your JSON config.

pki app: JSON Config Structure - Caddy Documentation

acme_server http handler: JSON Config Structure - Caddy Documentation (and the equivalent in the Caddyfile: acme_server (Caddyfile directive) — Caddy Documentation)

Thanks for the links. Can the ACME server be secured? I.E. can I control what/who can request certs?

Yeah, I think you could turn on basicauth on the site you serve it on, then you’d use an ACME URL like this (where acme.local is the hostname you might use):

https://user:pass@acme.local/acme/local/directory

The acme_server is just a regular HTTP handler, so you can use any other HTTP handler and/or request matcher to restrict access.

This topic was automatically closed after 30 days. New replies are no longer allowed.