I have a couple of questions about edge-client certificate extension:
Assuming the client certificate is managed by Openziti, do the Openziti tunnellers currently extend client certificates automatically?
What is the correct procedure for extending a 3rd-party client certificate? I understand that the new certificate would be obtained from the CA. However, when replacing it on the client do we need to perform any manual steps (like updating an authenticator)?
Hi @plakdawa. Welcome to the community and to OpenZiti!
Currently, by default, client certificate expiration is not enforced. You can change the controller to enforce client certificate expiration time, but it's not enabled by default. As such, the edge clients do not extend their certificates at this time.
With a third-party cert, if you use an external-id, then all that matters it the cert is signed by an appropriate ca and contains the expected claim. So you'd just replace the cert, ensure the same claim, and there'd be no problem. You'd have to restart the client, most likely. I expect all the tunnelers do not monitor identities at this time. I could see that changing in the future perhaps, but that's how it is right now, I believe.
Does this mean that we must use an external-id with an identity when using a 3rd-party CA? Is there a way to avoid it, if we prefer to use the default authenticator?
I can see a situation where we use the certificate as the first-factor for authentication and a JWT from an external JWKS signer as the second factor. Since an identity currently supports just one external-id this would mean that the two factors would have to have a common attribute to match (which may not be possible).
No you don't need to. If you enroll the 3rd party ca though, and change it, I do think the fingerprint changes and the enrollment would need to be updated to reflect the new fingerprint but to be entirely frank, I actually don't know. I've never expired a cert for client auth in this way. I was trying to provide a way that would be easy to accommodate rolling the certs. I'd have to defer to someone else who might have either done this in practice or who knows for sure. Your scenario makes perfect sense, yeah. I would say in that situation, I'd not enfoce the cert expiration and instead leave the time-based aspect to the JWT, perhaps?
I'll try to get @andrew.martinez to comment to see if there's more nuances here, he spends a lot more time thinking about these things than I do.
Certificate authentication requires that an x509 certificate is matched to an identity. There are two main approaches to do this:
fingerprint matching (hash of the raw cert bytes compares)
x509 claims (matching some data in the x509 certificate to an identity's external id)
When OpenZiti issues certificates are used, only fingerprint matching is used.
If certificates are being issued by a 3rd party CA and fingerprint matching is being used, it is up to whoever is managing the certificate life cycle to update the fingerprint in OpenZiti. This can be done via re-enrollment indirectly or via the Management API by doing an PATCH/PUT to /authenticators/<id> and providing the certificate.
To avoid having to manage the certificate fingerprint for 3rd Party CAs (i.e. in environments that use fast rolling certs), x509 claims can be used. x509 claims allow an externalId to be described on an identity and additionally be described in x509 certificates.
I am still unclear around the mechanics of client re-enrollment when the certificate is 3rd-party managed:
Is that possible from the edge-client API? Or is this process reserved for edge-clients certificates that are ziti managed? The docs don't seem to be clear about this:
The Client API doesn't allow the direct management of certificates. Direct manipulation of certificate authentication configuration is considered management action and only exposed in the Management API for use by administrators.
The Client API allows indirect management of certificates through the enrollment process and extension process only. The extension process only works for the internal OpenZiti CA as it use a CSR based process which requires access to a signing CA's private key.
When using 3rd party CAs, you are taking on the responsibility of issuing and managing the certificates. This involves the entire lifecycle of the certificates as well as managing the registration of them with OpenZiti. If certificates are short lived or you want to alleviate the need to register new certificates, I suggest using x509 claims.
@andrew.martinez
A few more points of confusion around this:
Unless I am misunderstanding something, if an externalID is used with a 3rd-party CA, it would require that the externalID be unique across all identities. Otherwise, I do not see how ziti would find an identity that matches the certificate?
However, a typical situation is one in which a single user has multiple devices (say a laptop and a phone). We create two identities associated with these devices. Both require 2FA with the same ext-jwt-signer. So the email address of the user would be associated as the externalID for both identities.
Since ziti only allows a single externalID to be associated with an identity, I cannot see how this situation can be handled. The X509 certs will need different externalIDs and the JWT will require the same. The only way this would work if it were possible to associate different externalIDs for X509 and ext-jwt-signer for the same identity, which is currently not possible.
I'm somewhat shocked we haven't come across this particular scenenrio yet, but yeah that seems like it'd be a problem to me as well. Phone's, at this time don't support ext-jwt-signers. The thinking was that the phone was most likely the place where the 2fa would live and thus requiring that 2fa feels strange, but there are other mechanisms for 2fa. Regardless, right now, we don't support 2fa for mobile android/iOS.
Still the point remains, two different laptops with the same external identity would sure seem like it would be a problem....
externalId must be unique and you only have one Ziti identity with any given value for externalId and use it with any number of devices where you're able to supply the identifying document that asserts the externalId (external JWT, x509 cert).
Ziti identities with externalId are not necessarily "enrolled," which entails a long-lived certificate and is typically used to identity a specific device where that certificate is stored.
On the flipside, different devices that are enrolled and store a long-lived client certificate they obtained indirectly from Ziti's edge enrollment signer CA through the client API do not necessarily use externalId.
Finally, any given Ziti identity may have both an externalId and enrollment(s). These are distinct but not conflicting, ways of "assuming" or "becoming" a particular Ziti identity, i.e., to obtain an API session token for some identity.
@qrkourier
The following enhancement would likely remove the problem that I am referring to:
Add a new optional attribute on identities (named say external-id-jwks). If this attribute is set then it should be used to match the claimsProperty on the ext-jwt-signer. If it is not set, then fall back to the existing logic of matching the external-id against the claimsProperty.
Moreoever, the external-id-jwks attribute is not enforced to be unique across all identities. The external-id attribute continues to be enforced as unique across all identities (this is required since this attribute works as an authenticator for X509 certificate authentication).
With this enhancement it would be possible to have multiple edge-clients owned by the same user in the external JWT signer. Currently it is not possible to do this in a sensible way.
Thinking about this a little further, I realize that my proposal above is not quite correct.
The distinction is not between cert and ext-jwt as authentication types but rather between the primary and secondary factors of authentication.
The primary authentication factor (whether cert or ext-jwt) must always be associated with a unique external-id, since the external-id serves as the authenticator that determines the identity to be used. However, once the identity associated with the device has been established, there is no longer any reason to enforce uniqueness on the claims attribute for the second factor.
So to correct my proposal:
Add a new optional attribute on identities (named say external-id-secondary). If this attribute is set then it should be used to match the claimsProperty on the second factor. If it is not set, then fall back to the existing logic of matching the external-id against the claimsProperty for the second factor as well. Moreoever, the external-id-secondary attribute is not enforced to be unique across all identities.
This will allow the use-case where we have a per-device X509 certificate used as the primary authentication factor and a per-user ext-jwt used as the secondary authentication factor and still allow multiple devices to be owned by the same user.