Open michalnicp opened 1 year ago
Adding a note that this is also recommended by RFC 8894:
It is RECOMMENDED that the challengePassword be a one- time authenticator value to limit the ability of an attacker who can capture the authenticator from the client or CA and reuse it to request further certificates.
@roperzh @michalnicp If the dynamic SCEP token expires, then after downloading the mobileconfig file, the user must install and accept it within a certain time frame right?
@zhumo that's right. For DEP enrollment that shouldn't be a problem, but I can see manual enrollment failing because of that.
In that case, the user must get another enrollment profile with a new token.
@roperzh What is the expiration time that we should apply? And so if I install a mobileconfig then I try to install that same mobileconfig on another device, the second device should refuse it, if I'm doing dynamic SCEP?
What is the expiration time that we should apply?
@zhumo what I have seen other solutions do is 1 hour, which makes sense to me, but I can investigate and give you better data. cc: @GuillaumeRoss maybe has opinions?
And so if I install a mobileconfig then I try to install that same mobileconfig on another device, the second device should refuse it, if I'm doing dynamic SCEP?
exactly, you'll get an error in the macOS UI saying that the challenge is invalid. I can try to make it happen and capture a screenshot if that helps!
@roperzh yes please
@roperzh @noahtalerman @zhumo I think at a high level it can be pretty straightforward, as I understand it it would go like this:
POST /fleet/device/{token}/mdm/apple/manual_enrollment_profile
would generate and save in the DB a new dynamic SCEP challenge associated with the device, and would return the enrollment profile with that challenge token embedded in it (this is the same endpoint that was implemented in #8997 , changed from GET to POST since it would now have side-effects and wouldn't be idempotent)I do have some questions for Roberto about the implementation details. What happens as part of the 3rd bullet above (when the user actually installs the profile in their settings) is a bit blurry to me. Does that call the SCEP URL that is embedded in the enrollment profile (i.e. <key>URL</key><string>{{ .SCEPURL }}</string>
in the profile template)? Can you point me where we handle those requests in the prototype (is that here: https://github.com/fleetdm/fleet/blob/main/cmd/fleet/apple_mdm.go#L68-L90)? And do you know what the operation code is, and what we actually receive as part of the request (i.e. is it just the challenge token)?
Does that call the SCEP URL that is embedded in the enrollment profile (i.e.
URL {{ .SCEPURL }} in the profile template)?
exactly! it calls that URL, but the process has many steps, which are differentiated by the operation
query` param (I think this the operation code you mention so apologies if you already know this.)
those details are all handled by github.com/micromdm/scep/v2/server
Can you point me where we handle those requests in the prototype (is that here: https://github.com/fleetdm/fleet/blob/main/cmd/fleet/apple_mdm.go#L68-L90)?
that's correct, that's where we "delegate" the SCEP endpoints, I think the way to go about this is to use challenge.Middleware
(declared in github.com/micromdm/scep/v2/challenge
) instead of scepserver.ChallengeMiddleware
, this middleware receives an store with this interface:
type Store interface {
SCEPChallenge() (string, error)
HasChallenge(pw string) (bool, error)
}
then it's a matter of defining the methods somewhere, if we follow https://github.com/jessepeterson/mysqlscepserver (linked above) the functions could go in apple_mdm.SCEPMySQLDepot
but I think that's up to you.
edit: challenge.Middleware
is so simple that if we don't like that store interface we could make our own 🤔 , as long as we reject the request in a middleware somehow if the challenge is invalid, we should be alright.
edit II: and seems like challenge.Middleware
is doing the check on all SCEP operations, but there's a TODO to maybe do it only for PKCSReq
@mna forgot to mention you! ☝️
@roperzh many thanks, that clears up a lot of things about that workflow! One thing about this:
edit II: and seems like challenge.Middleware is doing the check on all SCEP operations, but there's a TODO to maybe do it only for PKCSReq
This would be a problem if we want the challenge token to be single-use, time-limited. It looks like the initial operation is PKCSReq
(or actually "PKIOperation") so that would be the time to validate and delete the token so it can't be reused. I'm guessing that from then on the challenge becomes irrelevant, but the description in the RFC has me worried a bit re: RenewalReq: https://datatracker.ietf.org/doc/html/rfc8894#name-pkcsreq-renewalreq. Do you know if a renewal implies a new enrollment profile? If not, the old enrollment profile will have a now-invalid challenge token and the renewal request would fail.
@mna my understanding (which can be wrong) is that macOS won't ping the MDM server for renewals, instead the server has to send a InstallProfile
command with a new enrollment profile before the current certificate expires.
This new enrollment profile will contain the new challenge, and the host will request a new certificate instead of a renewal.
A few things to note:
InstallProfile
cannot update some fields like the server url and the restrictions/permissions.@roperzh Yeah reading a bit more, that seems to be covered in the RFC (that renewal is an optionally supported feature):
If the CA supports certificate renewal and the CA policy permits, then a new certificate with new validity dates can be issued, even though the old one is still valid. To renew an existing certificate, the client uses the RenewalReq message[...]
FWIW, I like the idea of trying to match the MicroMDM SCEP server interfaces where we can.
See if smallstep/ca has support for dynamic challenges (proposed in https://github.com/fleetdm/fleet/issues/8269)
@roperzh @mna have y'all had a chance to look at smallstep? I just had a quick look and it looks like it could be really handy for lots of the certificate management/public key infrastructure stuff.
@roperzh @gillespi314
have y'all had a chance to look at smallstep?
I took an admittedly quick look at it, but it seemed to me like it would be a lot of work to swap out our code based on micromdm for it, for (what seems from that quick look like) not much benefit. I don't think implementing the dynamic scep challenge on our own will be very hard (we already have the db table for it AFAICT). That's assuming that we haven't run into any major issues with micromdm.
That being said it's possible that I missed some important benefit that would make it worth the switch!
@mna Two questions for upcoming sprint planning:
Roberto mentioned you already started work on this ticket. About how much work do you feel remains? We may decide to defer this to the next sprint unless you have already made significant progress.
Is this ticket strictly needed to complete the associated epic? If not, we may separate this ticket from that epic and address this later.
Thanks for your feedback!
@lukeheath there's probably a couple of days left on this, I haven't started coding much, just had time to explore the problem and figure out what would need to be done. I can certainly park it and come back to it later if there's more urgent things that require my attention.
I don't think it's strictly needed to complete the epic, the only thing is that as long as we don't have this, then we still need to keep around the (prototype) flag to set a static SCEP challenge on the fleet instance.
@mna Thanks for the update! Let's discuss on sprint planning.
@lukeheath sounds good, in the meantime I've added some pointers (in the form of TODO(mna):
) in the code as reminders of the changes needed when I (or someone else) comes back to implement this ticket. It's in the mna-8477-dynamic-scep-challenge
branch.
UPDATE: During today's sprint planning call (2022-01-16) we decided to defer working on this issue. It's not required to call the "Turn on MDM" story done.
TODO Noah: Decide if this should stay prioritized or get deferred further in the future.
Hey @lukeheath @mna @roperzh I think we should punt on this now.
That said, I think this is something we should come back to before the April public launch of MDM so I left the ":product" label applied.
Also, I added this goal to the issue description that describes the story: "As a IT admin, I want to know that Fleet secures their MDM enrollment profiles so that I can provide this as argument to the security team when pitching Fleet."
Curious to hear your thoughts on this^
@noahtalerman the big drawback of not doing this is that anyone with the secret will be able to enroll into MDM and get things like certificates, secrets, passwords, etc.
One example that comes to mind: if you unenroll somebody, but they grabbed the secret, they can use it to enroll again silently.
big drawback of not doing this is that anyone with the secret will be able to enroll into MDM and get things like certificates, secrets, passwords, etc.
Makes sense 👍
We will address this before the public launch. Let's punt for now because it's not required to test/dogfood enrollment, profiles, and OS updates.
@lukeheath heads up, I think this is a good issue to estimate and bring into a sprint if we have extra capacity.
cc @roperzh ^
Noah: We need to finish this before public MDM launch on 4/7.
Hi @noahtalerman , this story did not make it into the current sprint, so I'm de-prioritizing it. Please bring it back to FF if necessary.
Hey @roperzh, do you know if Jamf has dynamic SCEP challenges?
@noahtalerman as far as I remember it does, but there might be an option to turn it off.
Hey @zayhanlon heads up that we didn't get to designing this in the current design sprint. Pulling it off the drafting board for now.
I think we'll get to this (or something similar soon). It contributes to Jamf parity.
@noahtalerman okay thanks - are you recommending that i don't bring this back to FF?
@zayhanlon yes!
Goal
As a IT admin, I want to know that Fleet secures their MDM enrollment profiles so that I can provide this as argument to the security team when pitching Fleet.
Problem
SCEP challenges should be considered sensitive. If compromised, the SCEP challenge can be used to get a valid certificate from the SCEP server and used to enroll with MDM.
See https://github.com/micromdm/micromdm/pull/642#issuecomment-586377065
https://support.apple.com/en-ca/guide/deployment/dep24dbdcf9e/web https://macadmins.slack.com/archives/C023Z6A2DL0/p1665684709030399?thread_ts=1665682926.697109&cid=C023Z6A2DL0 https://macadmins.slack.com/archives/C023Z6A2DL0/p1658861677026219
How?
Requirements