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.
https://smallstep.com/certificates
Apache License 2.0
6.76k stars 441 forks source link

Provisioner Request: ssh host cert enrollment by ACME-like challenge #486

Open gzm55 opened 3 years ago

gzm55 commented 3 years ago

What would you like to be added

An automatic and secure private cloud provisioner based on an ACME-like chanllenge.

Why this is needed

Rationale

Flow proposal

  1. Prepare: parameters:
    • access root account of a server with running sshd service on :22 port
    • internal ip and fqdn hostnames, dns names
    • an existing sshd host pubkey fingerprint
    • ca server should create tcp connection directly back to the server
  2. Req nonce:
    • http GET with query parameters of the step 1
    • ca provisioner validates that all hostnames and dns names can be resolved to the given ips (CNAME/A/AAAA)
    • scan each requested ip on port 22 with ssh protocol to get all pubkey fingerprint, every fingerprint sets of each ip contains the the submitted host pubkey fingerprint
    • generate a nonce
    • create a payload json containing all submitted parameters and the nonce
    • sign and return the payload json with ssh host ca key, the valid life should less than 5 min
  3. Prove the root access:
    • client got the response, extract the signature and payload
    • client optional verify the signature and the payload content
    • client sign the payload content and the ca signature together with the requested sshd host private key, this should be the evidence of the root access since the ssh private keys must have permissions of 600
      1. Request JWT Token:
    • http POST with the payload json, server signature and the client signature in step 3
    • ca server scans the full pub key from the :22 port of a request ip
    • ca server verifies the client signature, the payload json and the previous server signature with the full client ssh host pubkey
    • ca server verifies the valid life of server signature
    • if passed, sign the payload json as a valid JWT token
      1. Certificate with the token:
    • with the returned token in step 4, the client call the comand step ca certificate ... to sign the ssh pubkey
    • ca server verifies JWT token
    • ca server verifies the fingerprint of the request pubkey, and prepare ssh sign options from payload json
    • ca server signs and returns the certificate for the pubkey
    • ca server saves the ip+fingerprint as the certificate id to avoid duplicate cert
maraino commented 3 years ago

@mmalone Currently a combination of ACME and the X5C provisioners can be used to sign an SSH certificate:

step ca certificate internal.smallstep.com internal.crt internal.key
step ssh certificate --host --x5c-cert internal.crt --x5c-key internal.key internal.smallstep.com internal

The first command can use any provisioner, but let's say it uses ACME, so the HTTP challenge is validated, and the host is trusted. The second command creates a valid certificate, but the principal internal.smallstep.com is not validated against the SANs in the certificate, so we would be able to use any principal.

gzm55 commented 3 years ago

@mmalone not only the hostname and ip principal should be verify, it is also better to verify the host and the pubkey pair.

maraino commented 3 years ago

@gzm55 One option is to verify the X509 SANs with the principals. The main problem is that we're not doing it right now. So we have a couple of options, making it configurable through templates (https://github.com/smallstep/certificates/issues/433), or make it mandatory using some provisioner configuration.

dopey commented 3 years ago

Hey @gzm55, assuming that we are able to deliver on #433, would that appropriately address your use case?

You won't be able to do the pubkey verification but we're not convinced that the pubkey verification would make the protocol any more secure.

gzm55 commented 3 years ago

@dopey if x5c provisioner can use the variables from acme cert via #433 in the templates, that could address that every server root could got a ssh host cert for his server. It is also appreciate to see more document for this use case.

The down side of acme method, imo, could be that the port 80/443 of some servers may be already used which blocks the http01 challenge of acme. Meanwhile, the new challenge only depend on the admin can access the server host private key to sign a cert. This way should have the same security as the acme way, but more native and general for ssh cert.

dopey commented 3 years ago

We've got a project on the roadmap that will enable the use of x5c variables in subsequent certificate templates. Once that project is complete we'll be able to document this process more completely (I'll open up a documentation request now).

I'll come back and update this issue once that project has been scheduled.