certificates icon indicating copy to clipboard operation
certificates copied to clipboard

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

Open gzm55 opened this issue 4 years ago • 6 comments

What would you like to be added

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

Why this is needed

  • On private clouds, step-ca should be easily integrated without transferring jwk private key or secret
  • Easy to deploy the whole flow

Rationale

  • use nonce and short/one time certs to exchange a jwk token securely
  • every server root are authorized to request certs for his server
  • TOFU security model: each host cert should be sign once on the first time (cons: cannot verify birth age)

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
  4. 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
  5. 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

gzm55 avatar Feb 19 '21 08:02 gzm55

@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.

maraino avatar Feb 23 '21 19:02 maraino

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

gzm55 avatar Feb 24 '21 02:02 gzm55

@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.

maraino avatar Feb 24 '21 19:02 maraino

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.

dopey avatar Mar 03 '21 05:03 dopey

@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.

gzm55 avatar Mar 03 '21 07:03 gzm55

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.

dopey avatar Mar 09 '21 23:03 dopey