fleetdm / fleet

Open-source platform for IT, security, and infrastructure teams. (Linux, macOS, Chrome, Windows, cloud, data center)
https://fleetdm.com
Other
3.01k stars 418 forks source link

Create endpoint that triggers the CSR request for APNs to fleetdm.com #9202

Closed lukeheath closed 1 year ago

lukeheath commented 1 year ago

Problem

The Fleet UI requires an API endpoint that will allow users to request a CSR be generated and emailed to them in order to power the "Request CSR" modal.

image

Related

Requirements

lukeheath commented 1 year ago

@roperzh Would you please review these specs and add/edit as necessary to close the loop on this process? Once it is spec'd, please assign back to me.

Because there was confusion around this process I want to make sure we're spec'ing properly. Please let me know if you have any concerns.

roperzh commented 1 year ago

@lukeheath done! assigning back to you, I left a couple of TODOs with your name on them.

lukeheath commented 1 year ago

@noahtalerman Heads up, I've set the permissions to access the "Request CSR" endpoint to global admins only. Feel free to modify the specs if that is incorrect.

lukeheath commented 1 year ago

@roperzh Noah and I noticed that the modal is setting the expectation with the user that three files will be downloaded as a result of clicking the "Request" button:

"fleetdm.com will send your CSR to the below email. Your APNs key and SCEP certificate and key will be downloaded in the browser."

We currently have spec'd that the API will return the APNs key. Is it possible for it to also return the SCEP certificate and key in the response?

roperzh commented 1 year ago

We currently have spec'd that the API will return the APNs key. Is it possible for it to also return the SCEP certificate and key in the response?

over-communicating that we ended up chatting about this via zoom, and the spec was updated accordingly

mna commented 1 year ago

Given the latest discussions about the mdm-related API, and the fact that this API here is for Fleet's MDM, I'll change the endpoint from :

Create POST /fleet/apple/mdm/request_csr that accepts emailAddress and organization parameters.

to POST /fleet/mdm/apple/request_csr. Let me know if I shouldn't for some reason! @lukeheath @roperzh

lukeheath commented 1 year ago

@mna Thank you, that's correct! And all of the other Apple endpoints are /fleet/mdm/apple/*, so this looks an incorrect spec.

mna commented 1 year ago

Modify fleetctl generate mdm-apple to use this endpoint instead of directly calling the functions defined in cert.go

@lukeheath @roperzh Note that doing this means that the Fleet server will need to be up-and-running in order to use this command. I think that's fine but just something worth pointing out as the previous implementation of the generate mdm-apple could work without fleet running.

roperzh commented 1 year ago

@mna that's right, I added that mainly so "Access policy: Global admins only" is enforced, but I don't have a strong preference either way.

mna commented 1 year ago

I don't have a strong preference either way.

FWIW I think it's better this way, to reuse the API endpoint so that the exact same process is used to request a CSR as via the UI.

mna commented 1 year ago

Manual testing of the fleetctl generate mdm-apple command:

# fleetctl not logged in
$ ./build/fleetctl generate mdm-apple --email martin --org test
Token missing. Please log in with: fleetctl login
Error: token config value missing

# user not a global admin
$ ./build/fleetctl generate mdm-apple --email martin --org test
Sending certificate signing request (CSR) for Apple Push Notification service (APNs) to martin...
Generating APNs key, Simple Certificate Enrollment Protocol (SCEP) certificate, and SCEP key...

Error: POST /api/latest/fleet/mdm/apple/request_csr received status 403 forbidden: forbidden

# invalid email address
$ ./build/fleetctl generate mdm-apple --email martin --org test
Sending certificate signing request (CSR) for Apple Push Notification service (APNs) to martin...
Generating APNs key, Simple Certificate Enrollment Protocol (SCEP) certificate, and SCEP key...

Error: POST /api/latest/fleet/mdm/apple/request_csr received status 422 Validation Failed: invalid email address: mail: missing '@' or angle-addr

# missing organization
$ ./build/fleetctl generate mdm-apple --email martin.n.angers+test@gmail.com --org ' '
Sending certificate signing request (CSR) for Apple Push Notification service (APNs) to martin.n.angers+test@gmail.com...
Generating APNs key, Simple Certificate Enrollment Protocol (SCEP) certificate, and SCEP key...

Error: POST /api/latest/fleet/mdm/apple/request_csr received status 422 Validation Failed: missing organization

# invalid email as verified in fleetdm.com endpoint (gmail)
$ ./build/fleetctl generate mdm-apple --email martin.n.angers+test@gmail.com --org testfleet
Sending certificate signing request (CSR) for Apple Push Notification service (APNs) to martin.n.angers+test@gmail.com...
Generating APNs key, Simple Certificate Enrollment Protocol (SCEP) certificate, and SCEP key...

Error: POST /api/latest/fleet/mdm/apple/request_csr received status 502 Bad Gateway: FleetDM CSR request failed: api responded with 400: {"code":"E_MISSING_OR_INVALID_PARAMS","problems":["\"unsignedCsrData\" is required, but it was not defined."],"message":"The server could not fulfill this request (`POST /api/v1/deliver-apple-csr`) due to 1 missing or invalid parameter."}

That last one is not the one I was expecting - we do provide the unsigned CSR, so I'm not sure what's going on there, maybe there's more than the path that changed in the fleetdm CSR endpoint? I'll investigate...

mna commented 1 year ago

Allright, the endpoint's CSR parameter name was changed. So now I get this:

# invalid email as verified in fleetdm.com (gmail)
$ ./build/fleetctl generate mdm-apple --email martin.n.angers+test@gmail.com --org testfleet
Sending certificate signing request (CSR) for Apple Push Notification service (APNs) to martin.n.angers+test@gmail.com...
Generating APNs key, Simple Certificate Enrollment Protocol (SCEP) certificate, and SCEP key...

Error: POST /api/latest/fleet/mdm/apple/request_csr received status 502 Bad Gateway: FleetDM CSR request failed: api responded with 500: Internal Server Error

# valid email, success
$ ./build/fleetctl generate mdm-apple --email martin+test@fleetdm.com --org testfleet
Sending certificate signing request (CSR) for Apple Push Notification service (APNs) to martin+test@fleetdm.com...
Generating APNs key, Simple Certificate Enrollment Protocol (SCEP) certificate, and SCEP key...

Success!

Generated your APNs key at fleet-mdm-apple-apns.key

Generated your SCEP certificate at fleet-mdm-apple-scep.crt

Generated your SCEP key at fleet-mdm-apple-scep.key

Go to your email to download a CSR from Fleet. Then, visit https://identity.apple.com/pushcert to upload the CSR. You should receive an APNs certificate in return from Apple.

Next, use the generated certificates to deploy Fleet with `mdm` configuration: https://fleetdm.com/docs/deploying/configuration#mobile-device-management-mdm

Not sure why it returns 500 for the invalid email, will look at that, maybe the status code is not properly set in that case.

Otherwise, the success case correctly sends me the email :tada: .

mna commented 1 year ago

@eashaw when testing the deliver-apple-csr endpoint from the sails fleetdm.com website, I get a 500 response when I pass an email with a banned domain (e.g. martin@gmail.com, see full example in my comment above). Is that to be expected? It seems like this line would be the cause: https://github.com/fleetdm/fleet/blob/main/website/api/controllers/deliver-apple-csr.js#L122-L124

Ideally, a 4xx response with a message indicating what validation failed would be best so the fleetctl user knows what to do for the action to succeed. If it's a simple change, maybe you can just tell me what to modify and I can make it part of my PR, otherwise let me know if you'd prefer that I create a distinct issue for this.

lukeheath commented 1 year ago

@mna You found the right spot in the Sails code. You just need to add a statusCode to the exits object in the controller. So it would look like this:

    invalidEmailDomain: {
      description: 'This email address is on a denylist of domains and was not delivered.'
      statusCode: 400
    },

(or whatever 4xx code you think is most appropriate)

mna commented 1 year ago

@lukeheath oooh nice and simple! Thanks!

fleet-release commented 1 year ago

Beneath the clouds in sky, New endpoint, secure CSR fly Faster, fewer steps.