Skip to content

A small utility to help with kanidm provisioning

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

oddlama/kanidm-provision

Repository files navigation

About | Usage | JSON Schema

🦀 Kanidm Provisioning Tool

This is a tiny helper utility that uses kanidm's API to provision users, groups and oauth2 systems. This tool is needed to allow declarative provisioning of kanidm in NixOS, but can be used on any other system as well. This tool is not affiliated with kanidm itself. Use at your own discretion.

Two optional patches are provided for kanidm that allow you to:

  • provision oauth2 basic secrets
  • use a specific password when recovering admin account credentials.

Currently this tool supports the following provisioning operations which should suffice for basic SSO and OIDC needs. PRs are of course welcome!

Provisioning Feature
👪 Groups
Create/delete
Members
Unix attributes
🧑 Persons
Create/delete
Attributes (displayname, legalname, mail)
Credentials
SSH
Unix attributes
Radius
🌐 Oauth2
Create/delete (basic, public)
Attributes (origin url, origin landing, pkce enable, prefer short username)
✅* Basic secret
Scope maps
Supplementary scope maps
Claim maps

(*): Requires patch, see below.

Usage

Build the utility simply by running:

> cargo build

Afterwards you can apply a state file to your kanidm instance by executing:

KANIDM_PROVISION_IDM_ADMIN_TOKEN="your-idm-admin-token" \
  kanidm-provision --url 'https://auth.example.com' --state state.json

Orphan removal

This tool automatically adds all created entities to a tracking group so whenever something is removed from the state file in the future, the change can be reflected in kanidm automatically.

To prevent this kind of orphan removal, you can to pass --no-auto-remove. Removing for example a group from the state file will then not cause any changes in kanidm, unless the state file explicitly specifies present: false.

This automatic tracking does not work for oauth2 claim maps, since claim maps are not a separate entity in kanidm. To work around that, each oauth2 resource server has a removeOrphanedClaimMaps option that will delete any claim maps on the resource server that haven't been created by this tool. --no-auto-remove has no effect on that option.

Provisioning oauth2 basic secrets

This tool is able to provision basic secrets if you build kanidm with the patch provided in ./patches. This adds a new endpoint that allows modifying the basic secret of any oauth2 resource server via a new API endpoint, instead of only allowing to read the value generated by kanidm.

Caution

You need to reset your kanidm database after applying this change, otherwise the access control profile will not be updated and any call to the new endpoint will fail!

Provisioning (idm_)admin credentials

The second provided patch is a standalone kanidm patch that adds the ability to specify a password when recovering account credentials. Useful to provision the idm_admin password and avoid dynamic state that needs to be known to run the provisioning tool.

KANIDM_RECOVER_ACCOUNT_PASSWORD=V3kACDdwPjYUgYuLdlRfBqeBWf3TyJmv9h0f6CP3E3dv2B4S \
  kanidmd recover-account idm_admin --from-environment >/dev/null

JSON Schema

This is the schema consumed by this application

{
  # Specifies the provisioned groups
  "groups": {
    # One entry per group
    "group1": {
      # Optional. Defaults to true if not given.
      # Whether the group should be present or absent.
      "present": true,
      # The exhaustive list of group members.
      "members": [
        "person1",
        "person2",
        "group1"
      ]
    },
    # ...
  },
  # Specifies the provisioned persons
  "persons": {
    # One entry per person
    "person1": {
      # Optional. Defaults to true if not given.
      # Whether the person should be present or absent.
      "present": true,
      # Required.
      "displayName": "Person1",
      # Optional.
      "legalName": "Per Son",
      # Optional.
      "mailAddresses": [
        "person1@example.com"
        # ...
      ],
    },
    # ...
  },
  "systems": {
    "oauth2": {
      # One entry per oauth2 resource server
      "forgejo": {
        # Optional. Defaults to true if not given.
        # Whether the oauth2 resource server should be present or absent.
        "present": true,
        # Optional. Defaults to false if not given.
        # Whether the oauth2 resource server should be a public one (i.e. no basic secret, enforces PKCE and can allow localhost redirect).
        "public": false,
        # Required.
        "displayName": "Forgejo",
        # Required. Must end with a '/'
        "originUrl": "https://git.example.com/",
        # Landing page url (for web interface)
        "originLanding": "https://git.example.com/",
        # Optional. Only works when using the patch. Do not specify otherwise!
        # Will set the basic secret to the contents of the given file. Whitespace will be trimmed from both ends.
        # Only for non-public clients
        "basicSecretFile": "./secret1",
        # Optional. Defaults to false. Use name instead of spn for the preferred_username claim
        "preferShortUsername": false,
        # Optional. Defaults to false. Allows localhost redirects. Only for public resource servers.
        "enableLocalhostRedirects": false,
        # Optional. Defaults to false. Allows legacy jwt crypto like RS256.
        "enableLegacyCrypto": false,
        # Optional. Defaults to false. Disables PKCE for this resource server (can only be used on non-public resoure servers).
        "allowInsecureClientDisablePkce": false,
        # Optional.
        # Scope maps will map kanidm groups to returned oauth scopes.
        "scopeMaps": {
          # One entry per scope map.
          "group1": [
            "openid",
            "email",
            "profile"
          ]
        },
        # Optional.
        # Supplementary scope maps will map kanidm groups to additionally returned oauth scopes.
        "supplementaryScopeMaps": {
          # One entry per supplementary scope map.
          "group2": [
            "additional_scope"
          ]
        },
        # Optional. Defaults to true.
        # If true, any claim maps found on the resource server that are
        # not explicitly specified in here will be removed.
        "removeOrphanedClaimMaps": true,
        # Optional.
        # Claim maps will add a new claim with values depending on the
        # kanidm groups of the authenticating party.
        "claimMaps": {
          # One entry per claim, the key is the new claim name.
          "groups": {
            # Required.
            # The strategy used to join multiple values. One of:
            #   - "ssv" (space separated: one two three)
            #   - "csv" (comma separated: one,two,three)
            #   - "array" (array notation: ["one", "two", "three"])
            "joinType": "array",
            # Assign values based on kanidm groups.
            # At least one entry is required.
            "valuesByGroup": {
              "group1": [
                "user"
              ],
              "group2": [
                "user",
                "important_user"
              ],
              "group3": [
                "admin"
              ]
              # ...
            }
          }
          # ...
        }
      }
    }
  }
}

License

Licensed under either of

at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

A small utility to help with kanidm provisioning

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks