Inquiry about Enrollment JWT Generation and Its Relationship with Controller Certificates

Hello ,

site Endpoint Registration | OpenZiti

I have a question regarding the process when a client registers, and the Controller returns an enrollment JWT file, which then needs to be manually placed into the registration terminal. As shown in the figure, my questions are:

  1. What is the specific mechanism or logic behind the generation of this enrollment JWT file?
  2. What is the relationship between the generation of the enrollment JWT and the various certificates of the Controller? Are the fields in the JWT derived from one of the Controller's certificates (or generated by it)?

I would like to know if there is any documentation or if there has been any discussion within the community that I can learn from.

Thank you all very much.

While I am sure others have a much better answer, I would definitely reading the 5 part blog on bootstrapping trust. I have pasted it below, within the context of a response I gave to a customer the other day when they asked about continuous authorisation.

OpenZiti's implementation of continuous authorization is called Posture Checks, a dynamic part of OpenZiti's policies. Policies without Posture Checks provide static authorization. Policies with Posture Checks provide dynamic authorization.

In many systems, JWTs contain the entire security access list or a metaset of claims that describes it so that access can be determined from the JWT alone.

OpenZiti doesn't do this, as that approach does not work for continuous authorization implementations. We put enough information in the JWT to assert identity and connection requirements to even talk with routers/controllers, and that is it - i.e., the bootstrapping trust process (see 5-part blog - Bootstrapping Trust Part 1). After that, we use communication and internal data models inside the controllers and routers to make decisions (i.e., policies).

JWTs are just some JSON data packaged and signed by the issuer. you can look at the content of JWT on jwt.io site. In OpenZiti enrollment JWT there are several important pieces that are used for enrollment:

{
  "iss": "https://my-controller:443",
  "sub": "qILdqSU7X",
  "aud": [
    ""
  ],
  "exp": 1723306033,
  "jti": "50024e6e-a435-4341-9224-6e0c44fc47f0",
  "em": "ott",
  "ctrls": null
}
  • iss is the address of ziti controller that issued the enrollment token
  • sub is the internal id of the identity, enrollment CSR must include this id in CN field
  • em - enrollment method

Enrollment JWT are signed by the private key of the ziti controller certificate. This is done so that enrolling endpoint can verify the controller it is enrolling with.

2 Likes

Thank you, @PhilipGriffiths , for a truly excellent article. I spent almost an entire day trying to understand the information within. Thanks also to @ekoby .

Your responses have been very helpful in my understanding of ZITI's security system, and they have led to the following questions:

  1. The fifth article mentions, "This life cycle encompasses all the concerns from part one of this series, including bootstrapping, revoking, renewing, and rotating keys. Link to article". Could you please explain how the Ziti Controller performs revoking, renewing, and rotating keys?

  2. As shown in the diagram below, I understand the detailed process within the red box to be as follows:
    The CSR sends the SDK's own public key and information to the Controller. The Controller verifies whether the information is valid, then uses the CA's private key to sign the public key of the SDK within the CSR, creating an SSL/TLS certificate. It then encrypts this certificate with the SDK's public key and returns the encrypted result (certificate ciphertext) to the SDK. Once the SDK receives this encrypted certificate, it decrypts it with its own private key to obtain the specific content of the TLS certificate, and can then communicate with other SDKs. During this communication, the TLS certificate can be verified as originating from a trusted CA using the Controller CA's public key. I'm not sure if my understanding is correct?

  1. The process not covered in the fifth article is how the SDK uses the Controller's TLS certificate to verify the trustworthiness of other components after obtaining it (the mTLS in the fourth article was not very detailed), and how it encrypts subsequent business data. (I'm not clear which key the SDK uses to encrypt the business data at this time, or it's public/private?)

Thank you very much.

Looking forward to your responses.

Your understanding is generally correct, except for some minor points.

  • Certificates do not have to be encrypted (but they are delivered back to SDK over TLS connection) since they cannot be used for identification without corresponding private key.
  • ziti SDK instance does not directly communicate to other instances. All communication is done over ziti fabric, i.e. Edge routers.
  • as part of the enrollment SDK downloads a CA bundle from controller -- that CA bundle is used for verification of Ziti Controller(s) and Edge Routers

End-to-end data is encrypted using libsodium stream protocol
this is covered here: Connection Security

1 Like

Thank you @ekoby for pointing out the misunderstanding in my comprehension. Previously, I thought that since the SDK has already sent its public key to the Controller via CSR, the Controller could naturally use that public key to encrypt the certificate and return it to the SDK, which could then decrypt it with its private key. I understand now that your point is that the Controller does not need to encrypt the certificate when returning it, I get it.

Additionally, I found that this document PKI Troubleshooting | OpenZiti has relevant information, so I will study it myself first.

Thanks again!