Single sign-on and directory accounts
Gardience supports three ways for people to sign in besides local accounts:
- OpenID Connect (OIDC), for example Microsoft Entra ID, Okta, Google, Keycloak or Ping.
- SAML 2.0, with any identity provider that publishes SAML metadata.
- LDAP or Active Directory, where each directory user is added to Gardience by name.
Local accounts keep working when you turn any of these on.
An identity provider (IdP) is the service that checks a person's password and tells Gardience who they are, for example Entra ID or Okta.
How single sign-on works
- The person clicks Sign in with ... on the console's sign-in page.
- Their browser goes to the identity provider, then comes back with a signed answer.
- Gardience checks the signature and reads the person's user name and groups.
- Gardience picks one role from the groups (see Map groups to roles).
- Gardience opens a Salt session for that person, held to that role's permissions.
Each person gets their own Salt session, so the audit log names them, not a shared account. Every successful sign-in is recorded in the audit log as sso.login, and every refused one as sso.denied.
Only one protocol (OIDC or SAML) can be active at a time.
Before you start
- You need the
adminrole. The Single sign-on card appears only for admins. - Decide the public URL of the console: the address people type, for example
https://gardience.example.com. It must start withhttps://and have no path. Add the port if it is not 443. - In attach mode, your own Salt master needs Gardience's single sign-on module. Follow step 4 of the
ATTACH.mdfile in the install directory.
Set up OpenID Connect
- In your identity provider, create an application (often called a "web app" or "confidential client").
- In the console, open Settings and scroll to Single sign-on.
- Set Protocol to OpenID Connect.
- Set Public URL of this Gardience.
- Give your identity provider the redirect URI the card shows. It is the public URL followed by
/gardience/sso/callback. Fill in:
- Issuer URL: for Entra ID this looks like
https://login.microsoftonline.com/TENANT-ID/v2.0. Gardience reads<issuer>/.well-known/openid-configurationfrom it. - Client ID and Client secret from the application you created.
- Scopes:
openid profile emailby default.
- Issuer URL: for Entra ID this looks like
Set the claim names if yours differ from the defaults:
- User name claim:
preferred_usernameby default. If the token has no such claim, Gardience usesemail, thensub. - Groups claim:
groupsby default. Gardience also reads therolesclaim, so app roles work too.
- User name claim:
- Add at least one group mapping (see below).
- Click Save, then Test connection. A good result names the issuer and how many signing keys it found.
- Tick Turn on single sign-on and click Save again.
What Gardience checks on every OIDC sign-in:
- The authorization code flow with PKCE (S256), plus
stateandnoncevalues. - The ID token signature (RS256, RS384, RS512, PS256, ES256 or ES384) against the provider's published keys.
- The issuer, the audience (your client ID) and the nonce. Clocks may differ by up to 60 seconds.
The client secret is encrypted with the vault key before it is saved. The card never shows it again; leave the field empty to keep the saved one.
Set up SAML 2.0
- In the console, open Settings and scroll to Single sign-on.
- Set Protocol to SAML 2.0 and set Public URL of this Gardience. Click Save.
Give your identity provider the values the card shows:
- Entity ID: the public URL followed by
/gardience/sso/saml/metadata. - ACS (reply) URL: the public URL followed by
/gardience/sso/saml/acs. - Or give it Gardience's metadata, served at
/gardience/sso/saml/metadata.
- Entity ID: the public URL followed by
- Give Gardience your identity provider's metadata. Either enter the IdP metadata URL, or paste the metadata XML into the box below it.
Set the attribute names:
- User name claim / attribute: if the assertion carries this attribute, Gardience uses it. Otherwise it uses the assertion's NameID.
- Groups claim / attribute:
groupsby default. Gardience also reads the Microsoft group and role claims (http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsand.../claims/role).
- Add at least one group mapping, click Save, then Test connection. A good result names the identity provider found in the metadata.
- Tick Turn on single sign-on and click Save.
What Gardience checks on every SAML sign-in:
- The response or the assertion must be signed.
- The response must answer a sign-in that Gardience started. Unsolicited responses are refused.
- Clocks may differ by up to 60 seconds.
Gardience does not sign its own requests to the identity provider.
Map groups to roles
Under Groups to roles, add one row per group:
- IdP group: the group name or ID exactly as your provider sends it. For Entra ID this is often the group's object ID, not its display name. Matching ignores upper and lower case and spaces at either end.
- Gardience role:
admin,approver,operator,helpdesk-windowsorviewer. - Limit to node groups (optional): node groups, separated by commas, that people in this IdP group see and change; empty for the whole fleet. See Team scopes. If someone matches several mappings for their role, they get every group those mappings list, and the whole fleet if any of them has none. Admin mappings are never limited.
If a person is in several mapped groups, the highest role wins, in this order:
adminapproveroperatorhelpdesk-windowsviewer
A person in no mapped group can authenticate with the identity provider but cannot sign in to Gardience. They see "No Gardience access".
The role is worked out again at every sign-in. To change someone's role, change their groups in the identity provider; it takes effect the next time they sign in. People who signed in through single sign-on count as admins or approvers according to the role from their latest sign-in.
The card lists the 50 most recent single sign-on users, with their role and last sign-in time.
Rules for single sign-on user names
- User names are changed to lower case.
- They may use letters, digits,
_,.,@,+and-, up to 128 characters. - Reserved names are refused.
- A name that matches a local account (including admins and approvers set with
gardience roles) is refused. Rename one of the two.
A sign-in must be finished within 10 minutes, in the same browser that started it.
Step-by-step guides for Okta and Entra ID
Okta and Microsoft Entra ID were each tested with both OIDC and SAML, including group-to-role mapping, in October
- For every click on the provider's side:
Turning off or removing access
- To turn single sign-on off, clear Turn on single sign-on and click Save. Local and directory accounts keep working.
- To remove a person, remove them (or their group) in the identity provider. Gardience cannot see that removal. Their console session ends within the hour. Their API keys pause after 7 days without a sign-in. See API keys and the REST API.
Set up LDAP or Active Directory accounts
This applies to all-in-one installs. In attach mode, set up LDAP on your own Salt master instead.
Directory accounts work differently from single sign-on. There is no group mapping: you add each person by name with a role, and they sign in with their directory password on the normal sign-in page.
- Open
config/users.yamlin the install directory (for example/opt/gardience/config/users.yaml). It is readable by root only. Add an
ldap:section next to the existingusers:section. Leaveusers:as it is.ldap: server: dc1.example.com basedn: dc=example,dc=com binddn: CN=svc-gardience,OU=Service Accounts,DC=example,DC=com bindpw: the-bind-password activedirectory: true ca_file: ad-ca.pemDirectory servers usually have a certificate from your company's own certificate authority. Export that CA certificate (PEM, the
-----BEGIN CERTIFICATE-----form), save it in the config directory asad-ca.pem, and name it inca_file. Gardience checks the directory's certificate against it on every sign-in.Apply it:
/opt/gardience/gardience renderAdd each person:
/opt/gardience/gardience user add alice operator --ldap
The settings Gardience reads from the ldap: section:
| Setting | Required | Default | Meaning |
|---|---|---|---|
server | yes | Directory server host name. LDAP is on only when this is set. | |
basedn | yes | Where searches start. | |
port | no | 389, or 636 with tls: ldaps | Directory server port. |
tls | no | starttls | starttls (encrypt on the normal port), ldaps (encrypted port 636) or false. Current Active Directory refuses passwords sent without encryption, so false works only with servers that allow it. |
ca_file | no | empty | A PEM file in the config directory holding the certificate authority that signed the directory's certificate. Without it the certificate must chain to a public authority, and an untrusted certificate is refused. |
binddn | no | empty | Account used to search the directory. |
bindpw | no | empty | That account's password. Anonymous binds are not used. |
activedirectory | no | false | Set true for Active Directory. |
accountattribute | no | sAMAccountName with Active Directory, otherwise uid | The attribute that holds the user name. |
filter | no | (sAMAccountName={{ username }}) with Active Directory, otherwise (uid={{ username }}) (the account attribute above) | Search filter. {{ username }} is the name the person typed. |
Searches cover the whole subtree under basedn. Once LDAP is on, the sign-in page offers it as a sign-in type.