One device/application enrolls in multiple controllers

Is it possible to enroll a device/application to multiple ZiTi controllers or ZiTi networks ?

Hi Nick.

Yes you can definitely have more than one identity in use with all OpenZiti tunneler apps (or SDK app, if you are building your own apps).

Hereyou can see i have three identities for three different networks. (new ui on left, current ui on the right)

One important point that’s not clear until it bites you… If you do this, make sure your identities don’t have overlapping intercepts or you’ll get unpredictable/non-deterministic behavior…

So you can’t have three identities all configured to intercept “my.ziti.service” and have three different targets on the back end. That should be obvious, maybe, but it’s a very common thing to get confused in single, large networks and harder to detect with more than one network. :slight_smile:

Thank you for the help.
I have three more questions:

  1. If a device enrolls into 3 different ZiTi networks, which one controls the network traffic ?
  2. The Linux tunneller can also enroll into multiple ZiTi networks ? So, I just use the Tunneller the enroll multiple JWT, right ?
  3. Can I let a service/application enrolls into multiple ZiTi controller through SDK ?

Hi Nick,

I’m just going to assume you’re not using application embedded zero trust, and you’re using a tunneling application.

  1. If a device enrolls into 3 different ZiTi networks, which one controls the network traffic ?

Technically “all of them”. OpenZiti allows you to enroll multiple networks and that’s why it’s important not to overlap intercepts when using our tunneling applications. Since OpenZiti is capable of segmenting traffic all the way down to the port, only the traffic you specify gets sent over that network. Think of it like a “multi-split-tunnel” setup if that helps?

  1. The Linux tunneller can also enroll into multiple ZiTi networks ? So, I just use the Tunneller the enroll multiple JWT, right ?

Yep. That’s what I’d do

  1. Can I let a service/application enrolls into multiple ZiTi controller through SDK ?

Most definitely. All the SDKs have an ‘enroll’ function of some kind to produce the identity.

Thank you for detailed answers. It is helpful!

I asked those questions because I got a idea of hierarchical controllers. For example, when two controllers are responsible for two separate networks, lets say, device A want to communicate device D under the control of the other controller; In order to let them communicate, a top-controller may be introduced, which get the request and build the connection upon the two controllers.

So the core idea is that the top controller can manage the connection between devices in the sub-network. By this way, we can make devices in two separate network, i.e home and school, to communicate while keeping the privacy.

My intuition is to add a connector in the controller and the connector can enroll the sub-controller into the top-controller.

Do you think this idea will work? And will it be achieved by python-SDK?
Please feel free to leave any comments. I will be glad to hear.

Hmmm. I can’t say I’ve had this particular idea before and I don’t think anyone has mentioned it. We have talked about a similar, but different idea of federating controllers. OpenZiti has the concept of a “3rd party CA”. This allows you to delegate identities from some of CA. It’s really not what you’re getting at here, though. I always think about that as if you had two disparate networks and you wanted to ‘merge’ them (in a way) into one bigger network.

I think I would probably try to accomplish what you’re describing with just one OpenZiti network. I think through clever use of service policy and attributes you’d find you can do what you need… It’s hard to say for sure without knowing more.

For the scenario you describe though, I would make identities and I would give the identities attributes like “home” and “work” and “school”. Any identity could have “home” or “work” or “work and school” etc. So you could combine the access for any identity that way.

If you haven’t thought about that, maybe that’d accomplish what you’re looking for?

Thank you for your patience.

Yes, I do believe your solution with policy and attributes will work. But the hierarchical controller idea is more about explore the overlay network structure. So compared with actually solving the problem, what interests me is whether and how I can modify the structure.

I have try some examples in the sdk, but they are more about enrolling and connecting to the controller(excuse me if my view is limited, I haven’t read through all the codes). So I just wonder is it possible to modify or send messages to controller by SDK. Or the only way to add the connector is to dive deep into the source codes.

Oh, sure. You do this via the ‘management’ api. It’s the API that allows you to automate the model. Adding identities, adding services, policies etc. You can read about the management api here Edge Management API Reference | OpenZiti. You can get to the live docs at https://<your-controller>:<port>/edge/management/v1/docs if you want to explore the API further.

You can see a basic usage of this with the go-based quickstart test (and much more detailed use in the edge tests) here ziti/quickstart/test/quickstart_test.go at release-next · openziti/ziti · GitHub as an example.

That what you’re looking for?

Thank you so much! Let me try.
Never thought of API, I just try SDK a lot.
Thank you for pointing this out. Have a good night.

Thank you for your reply.

Just a further question:

Is there any difference between using the management API and CLI / GUI ZiTi Controller ?

For example, if I create a ZiTi controller on an AWS EC2, then I connect it’s API through : “https://{Public DNS Name}:8441/edge/management/v1”, in this case, I can see there are some GET or PUT functions I can use.

More specifically, is there any function that API has but the host controller’s CLI / ZAC doesn’t ?

Yes… and no… but mostly no :slight_smile: The CLI uses the management API under the hood. So from that perspective, there are no differences.

The differences will come with the CLI nomenclature, not always 100% lined up with the REST api because what looks good on CLI (like: --role-attributes) is not necessarily the same that you’d use for a REST api (roleAttributes) so there’s minor differences like that. The biggest difference you’ll find is that the APIs are what get developed first so they are always the most feature complete. You’ll find the CLI sometimes lacks an option that exists in the API. Those are the types of differences you’ll notice.

As answered - yes. We try to keep them all aligned but sometimes things slip through or other priorities come up… ZAC is also much more like the ziti CLI in that way. It also tries to implement all the APIs and surface them as UI screens in ZAC but sometimes APIs are missed for the same sorts of reasons.

Thanks a lot, it is much clear.

About the API, for example “Authenticate via a method supplied via a query string parameter”, it has required → Enum: “password” “cert” “ext-jwt”. And, the POST need specific payload:

"configTypes": [
"envInfo": {
"arch": "string",
"os": "string",
"osRelease": "string",
"osVersion": "string"
"password": "string",
"sdkInfo": {
"appId": "string",
"appVersion": "string",
"branch": "string",
"revision": "string",
"type": "string",
"version": "string"
"username": "string"

To use above function, I received “400 Bad Request”:

    "error": {
        "cause": {
            "field": "Content-Type",
            "reason": "unsupported media type \"text/plain\", only [application/json] are allowed",
            "value": "text/plain"
        "code": "COULD_NOT_VALIDATE",
        "message": "The supplied request contains an invalid document or no valid accept content were available, see cause",
        "requestId": "J7nWOrVLEp"
    "meta": {
        "apiEnrollmentVersion": "0.0.1",
        "apiVersion": "0.0.1"

Is there any sample request we can learn ?
Or could you please show an example ?

Thank you

Up on this post I linked you to the doc and to the ‘live’ docs you can find on your controller: One device/application enrolls in multiple controllers - #9 by TheLumberjack

I don’t have a server live on the internet right now for you to learn from but if you go to:


You should see something that looks like this:

Hopefully that will give you what you need?

Yes, I can see this page from my controller.

In the right side, payload part, what all the “string” should be ?

I think I should find the information about “configTypes”, “envInfo”, “sdkInfo” from somewhere, right ?

Ah, I see what you are asking now. I expanded the middle section, but it looks like the individual fields do not have corresponding documentation :frowning:

Looking through the rest of the doc, most of the fields don’t have the corresponding doc. I’ll file an issue to get these documented…