CFSSL integrated with Caddy

1. The problem I’m having:

Hi everyone. I’m deploying CFSSL CA Server integrated with Caddy but I can’t find any Caddy config or plugin that support CFSSL.
Here’s is my stack workflows:

  1. Caddy’s ACME server continues to receive certificate requests from Caddy clients.
  2. Caddy’s ACME server forwards the requested certificates to CFSSL, based on the profile you specify.
  3. CFSSL will sign the certificate according to the corresponding profile and then return the certificate to Caddy’s ACME server to provide to the client.

2. Error messages and/or full log output:

As I said above, I have no idea to integrated CFSSL with Caddy as a CA server
Below is my CFSSL instance endpoint

root@cfssl:~# ps aux | grep cfssl
  492 cfssl     0:00 /usr/sbin/cfssl serve -ca /opt/cfssl-profiles/source/ecdsa/subordinate/client/client-ca.pem -ca-key /opt/cfssl-profiles/source/ecdsa/subordinate/client/client-ca-key.pem -ca-bundle /opt/cfssl-profiles/source/ecdsa/root/root-ca.pem -int-bundle /opt/cfssl-profiles/source/ecdsa/subordinate/client/client-ca.pem -int-dir /opt/cfssl-profiles/source/ecdsa/subordinate/client/ -config /opt/cfssl-profiles/source/ecdsa/config/client-profile-config.json -address 10.10.10.11 -port 8882 -loglevel 0
  597 cfssl     0:00 /usr/sbin/cfssl serve -ca /opt/cfssl-profiles/source/ecdsa/subordinate/server/server-ca.pem -ca-key /opt/cfssl-profiles/source/ecdsa/subordinate/server/server-ca-key.pem -ca-bundle /opt/cfssl-profiles/source/ecdsa/root/root-ca.pem -int-bundle /opt/cfssl-profiles/source/ecdsa/subordinate/server/server-ca.pem -int-dir /opt/cfssl-profiles/source/ecdsa/subordinate/server/ -config /opt/cfssl-profiles/source/ecdsa/config/server-profile-config.json -address 10.10.10.11 -port 8881 -loglevel 0

3. Caddy version:

2.6.4-r7

4. How I installed and ran Caddy:

apk update
apk add caddy

a. System environment:

Running in a LXC (Linux Container) in Zorin 17.
LXC OS:

root@acme:~# cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.18.9
PRETTY_NAME="Alpine Linux v3.18"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"

b. Command:

caddy start --config /etc/caddy/Caddyfile

c. Service/unit/compose file:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

d. My complete Caddy config:

file /etc/caddy/Caddyfile:
http://ca-server.com {
	log {
		output file /var/log/caddy/cfssl_access.log {
			roll_size 10mb
			roll_keep 5
			roll_keep_for 168h
		}
	}

	# server CA
	@cfssl_server  {
	     header User-Agent "CFSSL-Server"
	}

	@cfssl_client {
	     header User-Agent "CFSSL-Client"
	}

	handle_path /private* {
		reverse_proxy @cfssl_server 10.10.10.11:8881
		reverse_proxy @cfssl_client 10.10.10.11:8882
	}
	respond 403
}

5. Links to relevant resources:

Caddy’s acme_server is GitHub - smallstep/certificates: 🛡️ A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management, so you can use TLS everywhere & SSO for SSH. under the hood. Forwarding ACME requests to another CA was never part of the intended design. It might be possible, but a lot of engineering work would need to be put into it. I don’t think it’s part of our plans right now. If you want to write a pull request for this, contributions are welcome.

2 Likes

Hi Mr. Francislavoie,
Is there another way to use Caddy to get certificate automatically from CFSSL?

example:

  1. In Caddy Instance for my custom app, I config like this:
myapp.local {
     tls {
         domain myapp.local
         cert_type server
         profile long
     }
}
  1. Then that Caddy Instance will request to the Caddy server infront CFSSL with this:
curl -X POST -H "User-Agent: CFSSL-Server" -d '{"request":{"hosts":["myapp.local"]},"profile":"long","bundle":true}' http://cfssl-server/private/api/v1/cfssl/newcert
  1. Then the Caddy server in front of CFSSL will forward the request to CFSSL and CFSSL will handle the request and issue the cert, then send back to the Caddy Instance for my app.

Please tell me if you need more info :heart:

I don’t know anything about CFSSL.

Is there any reason you can’t use Caddy’s CA (aka smallstep) that’s already built-in? Why do you think you need CFSSL specifically?

How did you come up with this? That doesn’t look anything like valid Caddyfile config. There’s no such thing as domain, profile and domain options for Caddy’s tls directive.

2 Likes

Yeah, I know this is not Caddy config. It’s just for example.
I want to use CFSSL because my organization use Private DNS with Private Local Domain Name so I can only use self sign with custom Root CA.
I can’t not use other CA like Letsencrypt though.

You can do that with Caddy/smallstep too. See Global options (Caddyfile) — Caddy Documentation, you can load in your own root CA cert/key if you want, or let Caddy generate one to use as your root and install it on your various internal clients.

2 Likes

Hi Mr. Francislavoie, is it possible for me to use a shell script to automate this process? The flow would be like this:

  1. When I define TLS in Caddy config, Caddy will trigger my script
  2. The script will use CFSSL API to create certificate and then will put it in Caddy config
    Is this way possible?

Again, why does it have to be with CFSSL? Caddy can automate this for you already using its built in CA.

2 Likes

Hi Mr. Francislavoie, is it possible for Onestep-ca (the one that you said it was built-in with Caddy) automatically create certificate and apply to Caddy with custom profile?
Example:
Assump that I have configure Onestep-ca with 3 profile certificate (long: 90days, medium: 60 days, short: 30 days).
Now I just have to config TLS in Caddy like: tls { myapp.com short } (assumption)
and then Caddy will automatically get a certificate with short profile from Onestep-ca. Is that possible?

Smallstep, not onestep.

Why do you need “profiles”? The default lifetime should be fine. See tls (Caddyfile directive) — Caddy Documentation, you just configure tls internal and Caddy will issue certs using its internal issuer (Smallstep). The default lifetime of the leaf certs is 12h. You grab Caddy’s root cert from its storage, which has iirc a 10 year lifetime, and install it on your various machines to establish trust. That’s it. The rest is automated.

2 Likes

I’ve managed to make it work by adding one more webhook server. When I define tls { get_certificate http http://my-webhook.server/cfssl_api }, it works.
Thanks very much for your support!

1 Like

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