Help with creating Terraform for configuring Keycloak for Netbird

Hey all,

After recently watching the Level1techs video on Tailscale, I thought it would be a good time to pull my thumb out and finish looking into hooking up Netbird (which I believe is an opensource alternative to Tailscale).

This led me down the path of configuring Keycloak, as the open source SSO of choice to hook into Netbird (for which they have instructions for manually configuring), after having deployed it using Docker. I wanted to automate the configuration with Terraform/Tofu, so that I could repeat this quickly, and know that if I made a mistake, I could easily rectify and rollout this simple adjustment in code. I got pretty far with it, but got stuck with trying to “convert” step 9 to Terraform code, which revolves around assigning the already existing view-users role to the service accounts of the netbird backend client. For this step, I used the following code:

resource "keycloak_openid_client_service_account_realm_role" "service_account_role_assignment" {
    realm_id                = keycloak_realm.realm.id
    service_account_user_id = keycloak_openid_client.netbird_backend_client.service_account_user_id
    role                    = "view-users"
}

… but this doesn’t work. I either need to use a different resource type, or somehow identify the existing role not by that string name.

If any of you know what I need to do (it’s simple once you know how, I’m sure its something really simple that I missed), then I would love your help so I can finish my work and publish it to GitHub for others. I also posted this question yesterday to Stack Overflow if you want to get credit for the answer.

1 Like

Did you try with the example in the docs?

resource "keycloak_realm" "realm" {
  realm   = "my-realm"
  enabled = true
}

resource "keycloak_role" "realm_role" {
  realm_id    = keycloak_realm.realm.id
  name        = "my-realm-role"
}

resource "keycloak_openid_client" "client" {
  realm_id = keycloak_realm.realm.id
  name     = "client"

  service_accounts_enabled = true
}

resource "keycloak_openid_client_service_account_realm_role" "client_service_account_role" {
  realm_id                = keycloak_realm.realm.id
  service_account_user_id = keycloak_openid_client.client.service_account_user_id
  role                    = keycloak_role.realm_role.name
}
1 Like

I’m pretty sure I covered that in the stack overflow post (sorry I didnt include that info here on this forum) as shown below, unless there is something you are saying you did differently?

The key thing is that I need to assign it the existing “realm management” view-users role, not create a new one.

If the resource is already existing then you don’t need to create it, but you need to ‘find’ it using the appropriate datasource:

resource "keycloak_realm" "realm" {
  realm   = "my-realm"
  enabled = true
}

data "keycloak_role" "offline_access" {
  realm_id = keycloak_realm.realm.id
  name     = "offline_access"
}

# use the data source

resource "keycloak_group" "group" {
  realm_id = keycloak_realm.realm.id
  name     = "group"
}

resource "keycloak_group_roles" "group_roles" {
  realm_id = keycloak_realm.realm.id
  group_id = keycloak_group.group.id

    role_ids = [
      data.keycloak_role.offline_access.id
    ]
}

but given that then you are only using the role name and not the id, it should not be necessary and the string “view-users” should work. … did you set

service_accounts_enabled = true

in the keycloak_openid_client resource?

yep, i tried using the data source, and it claimed that it could not be found, and yes, I have service_accounts_enabled set to true. I have taken the liberty of uploading my progress thus far to a branch with the relevant client configuration here: https://github.com/programster/tutorial-terraform-examples/blob/keycloak-addition/keycloak-netbird-setup/backendClient.tf

Obviously I haven’t commited every permutation I have tried that failed, but it seems that “offline access” is somewhat different as I was able to pick that one up by name, but there is something special about “view-users” that has to do with that “realm-management” pill that shows up beside it in the UI as shown below:

i don’t know what I need to do to somehow grab that. Is it somehow attached to the name? What would the string be?

I managed to figure out the solution to my problem in the end and posted the answer on the stack overflow post. It turns out that the “realm-management” pill indicated the name of an additional client that got created in the realm automatically that “owns” the view-users role. So I just needed to identify the role that way and assign it with this code:

# load in the existing realm-management client
data "keycloak_openid_client" "realm_management_client" {
    realm_id = keycloak_realm.realm.id
    client_id = "realm-management"
}


# Assign the realm-management view-users role to the netbird backend client's service management
resource "keycloak_openid_client_service_account_role" "service_account_role_assignment" {
    realm_id                = keycloak_realm.realm.id
    service_account_user_id = keycloak_openid_client.netbird_backend_client.service_account_user_id
    client_id               = data.keycloak_openid_client.realm_management_client.id // ID of the client the role belongs to, not ID of client assigning to.
    role                    = "view-users"
}
1 Like