Active Directory (AD) reference
COMMERCIAL FEATURE: Access active directory (AD) authentication for single sign-on (SSO) in the packaged Sensu Go distribution.
For more information, read Get started with commercial features.
Sensu requires username and password authentication to access the web UI, API, and sensuctl command line tool.
In addition to the built-in basic authentication, Sensu offers commercial support for using Microsoft Active Directory (AD) for single sign-on (SSO) authentication.
The AD authentication provider is based on the LDAP authentication provider.
To use AD authentication for Azure, follow Microsoft’s tutorial to set up secure LDAP in your Azure account and create the host and certificates you need.
For general information about configuring authentication providers, read Configure single sign-on (SSO) authentication.
AD configuration examples
Example AD configuration: Minimum required attributes
---
type: ad
api_version: authentication/v2
metadata:
name: activedirectory
spec:
servers:
- group_search:
base_dn: dc=acme,dc=org
host: 127.0.0.1
user_search:
base_dn: dc=acme,dc=org
{
"type": "ad",
"api_version": "authentication/v2",
"spec": {
"servers": [
{
"host": "127.0.0.1",
"group_search": {
"base_dn": "dc=acme,dc=org"
},
"user_search": {
"base_dn": "dc=acme,dc=org"
}
}
]
},
"metadata": {
"name": "activedirectory"
}
}
Example AD configuration: All attributes
---
type: ad
api_version: authentication/v2
metadata:
name: activedirectory
spec:
allowed_groups: []
groups_prefix: ad
servers:
- binding:
password: YOUR_PASSWORD
user_dn: cn=binder,cn=users,dc=acme,dc=org
client_cert_file: /path/to/ssl/cert.pem
client_key_file: /path/to/ssl/key.pem
default_upn_domain: example.org
include_nested_groups: true
group_search:
attribute: member
base_dn: dc=acme,dc=org
name_attribute: cn
object_class: group
host: 127.0.0.1
insecure: false
port: 636
security: tls
trusted_ca_file: /path/to/trusted-certificate-authorities.pem
user_search:
attribute: sAMAccountName
base_dn: dc=acme,dc=org
name_attribute: displayName
object_class: person
username_prefix: ad
{
"type": "ad",
"api_version": "authentication/v2",
"spec": {
"servers": [
{
"host": "127.0.0.1",
"port": 636,
"insecure": false,
"security": "tls",
"trusted_ca_file": "/path/to/trusted-certificate-authorities.pem",
"client_cert_file": "/path/to/ssl/cert.pem",
"client_key_file": "/path/to/ssl/key.pem",
"default_upn_domain": "example.org",
"include_nested_groups": true,
"binding": {
"user_dn": "cn=binder,cn=users,dc=acme,dc=org",
"password": "YOUR_PASSWORD"
},
"group_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "member",
"name_attribute": "cn",
"object_class": "group"
},
"user_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "sAMAccountName",
"name_attribute": "displayName",
"object_class": "person"
}
}
],
"allowed_groups": [],
"groups_prefix": "ad",
"username_prefix": "ad"
},
"metadata": {
"name": "activedirectory"
}
}
NOTE: If you specify allowed groups, the group names must exactly match the names the authentication provider returns to the Sensu backend.
Example AD configuration: Use memberOf
attribute instead of group_search
AD automatically returns a memberOf
attribute in users’ accounts.
The memberOf
attribute contains the user’s group membership, which effectively removes the requirement to look up the user’s groups.
To use the memberOf
attribute in your AD implementation, remove the group_search
object from your AD config:
---
type: ad
api_version: authentication/v2
metadata:
name: activedirectory
spec:
servers:
host: 127.0.0.1
user_search:
base_dn: dc=acme,dc=org
{
"type": "ad",
"api_version": "authentication/v2",
"spec": {
"servers": [
{
"host": "127.0.0.1",
"user_search": {
"base_dn": "dc=acme,dc=org"
}
}
]
},
"metadata": {
"name": "activedirectory"
}
}
After you configure AD to use the memberOf
attribute, the debug
log level will include the following log entries:
{"component":"authentication/v2","level":"debug","msg":"using the \"memberOf\" attribute to determine the group membership of user \"user1\"","time":"2020-06-25T14:10:58-04:00"}
{"component":"authentication/v2","level":"debug","msg":"found 1 LDAP group(s): [\"sensu\"]","time":"2020-06-25T14:10:58-04:00"}
AD specification
AD top-level attributes
type |
|
description |
Top-level attribute that specifies the sensuctl create resource type. For AD definitions, the type should always be ad . |
required |
true |
type |
String |
example |
|
api_version |
|
description |
Top-level attribute that specifies the Sensu API group and version. For AD definitions, the api_version should always be authentication/v2 . |
required |
true |
type |
String |
example |
api_version: authentication/v2
{
"api_version": "authentication/v2"
}
|
metadata |
|
description |
Top-level map that contains the AD definition name . Review the metadata attributes for details. |
required |
true |
type |
Map of key-value pairs |
example |
metadata:
name: activedirectory
{
"metadata": {
"name": "activedirectory"
}
}
|
spec |
|
description |
Top-level map that includes the AD spec attributes. |
required |
true |
type |
Map of key-value pairs |
example |
spec:
servers:
- host: 127.0.0.1
port: 636
insecure: false
security: tls
trusted_ca_file: "/path/to/trusted-certificate-authorities.pem"
client_cert_file: "/path/to/ssl/cert.pem"
client_key_file: "/path/to/ssl/key.pem"
default_upn_domain: example.org
include_nested_groups: true
binding:
user_dn: cn=binder,cn=users,dc=acme,dc=org
password: YOUR_PASSWORD
group_search:
base_dn: dc=acme,dc=org
attribute: member
name_attribute: cn
object_class: group
user_search:
base_dn: dc=acme,dc=org
attribute: sAMAccountName
name_attribute: displayName
object_class: person
allowed_groups: []
groups_prefix: ad
username_prefix: ad
{
"spec": {
"servers": [
{
"host": "127.0.0.1",
"port": 636,
"insecure": false,
"security": "tls",
"trusted_ca_file": "/path/to/trusted-certificate-authorities.pem",
"client_cert_file": "/path/to/ssl/cert.pem",
"client_key_file": "/path/to/ssl/key.pem",
"default_upn_domain": "example.org",
"include_nested_groups": true,
"binding": {
"user_dn": "cn=binder,cn=users,dc=acme,dc=org",
"password": "YOUR_PASSWORD"
},
"group_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "member",
"name_attribute": "cn",
"object_class": "group"
},
"user_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "sAMAccountName",
"name_attribute": "displayName",
"object_class": "person"
}
}
],
"allowed_groups": [],
"groups_prefix": "ad",
"username_prefix": "ad"
}
}
|
name |
|
description |
A unique string used to identify the AD configuration. Names cannot contain special characters or spaces (validated with Go regex \A[\w\.\-]+\z ). |
required |
true |
type |
String |
example |
{
"name": "activedirectory"
}
|
AD spec attributes
servers |
|
description |
The list of AD servers to use. During the authentication process, Sensu attempts to authenticate against each AD server in sequence until authentication is successful or there are no more servers to try. |
required |
true |
type |
Array |
example |
servers:
- host: 127.0.0.1
port: 636
insecure: false
security: tls
trusted_ca_file: "/path/to/trusted-certificate-authorities.pem"
client_cert_file: "/path/to/ssl/cert.pem"
client_key_file: "/path/to/ssl/key.pem"
default_upn_domain: example.org
include_nested_groups: true
binding:
user_dn: cn=binder,cn=users,dc=acme,dc=org
password: YOUR_PASSWORD
group_search:
base_dn: dc=acme,dc=org
attribute: member
name_attribute: cn
object_class: group
user_search:
base_dn: dc=acme,dc=org
attribute: sAMAccountName
name_attribute: displayName
object_class: person
{
"servers": [
{
"host": "127.0.0.1",
"port": 636,
"insecure": false,
"security": "tls",
"trusted_ca_file": "/path/to/trusted-certificate-authorities.pem",
"client_cert_file": "/path/to/ssl/cert.pem",
"client_key_file": "/path/to/ssl/key.pem",
"default_upn_domain": "example.org",
"include_nested_groups": true,
"binding": {
"user_dn": "cn=binder,cn=users,dc=acme,dc=org",
"password": "YOUR_PASSWORD"
},
"group_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "member",
"name_attribute": "cn",
"object_class": "group"
},
"user_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "sAMAccountName",
"name_attribute": "displayName",
"object_class": "person"
}
}
]
}
|
allowed_groups |
|
description |
An array of allowed AD group strings to include in the tokenized identity claim. Use to specify which groups to encode in the authentication provider’s JSON Web Token (JWT) when the authenticated AD user is a member of many groups and the tokenized identity claim would be too large for correct web client operation.
NOTE: Allowed group names are case-sensitive and must exactly match the group names the authentication provider returns to the Sensu backend.
|
required |
false |
type |
Array |
example |
allowed_groups:
- Sensu_Viewers
- Sensu_Operators
{
"allowed_groups": [
"Sensu_Viewers",
"Sensu_Operators"
]
}
|
groups_prefix |
|
description |
The prefix added to all AD groups. Sensu appends the groups_prefix with a colon. For example, for the groups_prefix ad and the group dev , the resulting group name in Sensu is ad:dev . Use the groups_prefix when integrating AD groups with Sensu RBAC role bindings and cluster role bindings. |
required |
false |
type |
String |
example |
{
"groups_prefix": "ad"
}
|
username_prefix |
|
description |
The prefix added to all AD usernames. Sensu appends the username_prefix with a colon. For example, for the username_prefix ad and the user alice , the resulting username in Sensu is ad:alice . Use the username_prefix when integrating AD users with Sensu RBAC role bindings and cluster role bindings. Users do not need to provide the username_prefix when logging in to Sensu. |
required |
false |
type |
String |
example |
{
"username_prefix": "ad"
}
|
AD server attributes
port |
|
description |
AD server port. |
required |
true |
type |
Integer |
default |
389 for insecure connections; 636 for TLS connections |
example |
|
insecure |
|
description |
Skips SSL certificate verification when set to true .
WARNING: Do not use an insecure connection in production environments.
|
required |
false |
type |
Boolean |
default |
false |
example |
|
security |
|
description |
Determines the encryption type to be used for the connection to the AD server: insecure (unencrypted connection; not recommended for production), tls (secure encrypted connection), or starttls (unencrypted connection upgrades to a secure connection). |
type |
String |
default |
tls |
example |
|
trusted_ca_file |
|
description |
Path to an alternative CA bundle file in PEM format to be used instead of the system’s default bundle. This CA bundle is used to verify the server’s certificate. |
required |
false |
type |
String |
example |
trusted_ca_file: /path/to/trusted-certificate-authorities.pem
{
"trusted_ca_file": "/path/to/trusted-certificate-authorities.pem"
}
|
client_cert_file |
|
description |
Path to the certificate that should be sent to the server if requested. |
required |
false |
type |
String |
example |
client_cert_file: /path/to/ssl/cert.pem
{
"client_cert_file": "/path/to/ssl/cert.pem"
}
|
client_key_file |
|
description |
Path to the key file associated with the client_cert_file . |
required |
false |
type |
String |
example |
client_key_file: /path/to/ssl/key.pem
{
"client_key_file": "/path/to/ssl/key.pem"
}
|
binding |
|
description |
The AD account that performs user and group lookups. If your server supports anonymous binding, you can omit the user_dn or password attributes to query the directory without credentials. To use anonymous binding with AD, the ANONYMOUS LOGON object requires read permissions for users and groups. Review the binding attributes for details. |
required |
false |
type |
Map |
example |
binding:
user_dn: cn=binder,cn=users,dc=acme,dc=org
password: YOUR_PASSWORD
{
"binding": {
"user_dn": "cn=binder,cn=users,dc=acme,dc=org",
"password": "YOUR_PASSWORD"
}
}
|
group_search |
|
description |
Search configuration for groups. Review the group search attributes for more information. Remove the group_search object from your configuration to use the memberOf attribute instead. |
required |
false |
type |
Map |
example |
group_search:
base_dn: dc=acme,dc=org
attribute: member
name_attribute: cn
object_class: group
{
"group_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "member",
"name_attribute": "cn",
"object_class": "group"
}
}
|
user_search |
|
description |
Search configuration for users. Review the user search attributes for more information. |
required |
true |
type |
Map |
example |
user_search:
base_dn: dc=acme,dc=org
attribute: sAMAccountName
name_attribute: displayName
object_class: person
{
"user_search": {
"base_dn": "dc=acme,dc=org",
"attribute": "sAMAccountName",
"name_attribute": "displayName",
"object_class": "person"
}
}
|
default_upn_domain |
|
description |
Enables UPN authentication when set. The default UPN suffix that will be appended to the username when a domain is not specified during login (for example, user becomes user@defaultdomain.xyz ).
WARNING: When using UPN authentication, users must re-authenticate to apply any changes to group membership on the AD server since their last authentication. For example, if you remove a user from a group with administrator permissions for the current session (such as a terminated employee), Sensu will not apply the change until the user logs out and tries to start a new session. Likewise, under UPN, users cannot be forced to log out of Sensu. To apply group membership updates without re-authentication, specify a binding account or enable anonymous binding.
|
required |
false |
type |
String |
example |
default_upn_domain: example.org
{
"default_upn_domain": "example.org"
}
|
include_nested_groups |
|
description |
If true , the group search includes any nested groups a user is a member of. If false , the group search includes only the top-level groups a user is a member of. |
required |
false |
type |
Boolean |
example |
include_nested_groups: true
{
"include_nested_groups": true
}
|
AD binding attributes
user_dn |
|
description |
The AD account that performs user and group lookups. We recommend using a read-only account. Use the distinguished name (DN) format, such as cn=binder,cn=users,dc=domain,dc=tld . If your server supports anonymous binding, you can omit this attribute to query the directory without credentials. |
required |
false |
type |
String |
example |
user_dn: cn=binder,cn=users,dc=acme,dc=org
{
"user_dn": "cn=binder,cn=users,dc=acme,dc=org"
}
|
password |
|
description |
Password for the user_dn account. If your server supports anonymous binding, you can omit this attribute to query the directory without credentials. |
required |
false |
type |
String |
example |
{
"password": "YOUR_PASSWORD"
}
|
AD group search attributes
base_dn |
|
description |
Tells Sensu which part of the directory tree to search. For example, dc=acme,dc=org searches within the acme.org directory. |
required |
true |
type |
String |
example |
{
"base_dn": "dc=acme,dc=org"
}
|
attribute |
|
description |
Used for comparing result entries. Combined with other filters as "(<Attribute>=<value>)" . |
required |
false |
type |
String |
default |
member |
example |
{
"attribute": "member"
}
|
name_attribute |
|
description |
Represents the attribute to use as the entry name. |
required |
false |
type |
String |
default |
cn |
example |
{
"name_attribute": "cn"
}
|
object_class |
|
description |
Identifies the class of objects returned in the search result. Combined with other filters as "(objectClass=<ObjectClass>)" . |
required |
false |
type |
String |
default |
group |
example |
{
"object_class": "group"
}
|
AD user search attributes
base_dn |
|
description |
Tells Sensu which part of the directory tree to search. For example, dc=acme,dc=org searches within the acme.org directory. |
required |
true |
type |
String |
example |
{
"base_dn": "dc=acme,dc=org"
}
|
attribute |
|
description |
Used for comparing result entries. Combined with other filters as "(<Attribute>=<value>)" . |
required |
false |
type |
String |
default |
sAMAccountName |
example |
attribute: sAMAccountName
{
"attribute": "sAMAccountName"
}
|
name_attribute |
|
description |
Represents the attribute to use as the entry name. |
required |
false |
type |
String |
default |
displayName |
example |
name_attribute: displayName
{
"name_attribute": "displayName"
}
|
object_class |
|
description |
Identifies the class of objects returned in the search result. Combined with other filters as "(objectClass=<ObjectClass>)" . |
required |
false |
type |
String |
default |
person |
example |
{
"object_class": "person"
}
|
AD troubleshooting
To troubleshoot any issue with AD authentication, start by increasing the log verbosity of sensu-backend to the debug log level.
Most authentication and authorization errors are only displayed on the debug log level to avoid flooding the log files.
NOTE: If you can’t locate any log entries referencing AD authentication, run sensuctl auth list to make sure that you successfully installed the AD provider.
Authentication
This section lists common authentication error messages and describes possible solutions for each of them.
failed to connect: AD Result Code 200 "Network Error"
The AD provider couldn’t establish a TCP connection to the AD server.
Verify the host
and port
attributes.
If you are not using AD over TLS/SSL, make sure to set the value of the security
attribute to insecure
for plaintext communication.
certificate signed by unknown authority
If you are using a self-signed certificate, make sure to set the insecure
attribute to true
.
This will bypass verification of the certificate’s signing authority.
failed to bind: ...
The first step for authenticating a user with the AD provider is to bind to the AD server using the service account specified in the binding
object.
Make sure the user_dn
attribute specifies a valid DN and that its password is correct.
user <username> was not found
The user search failed.
No user account could be found with the given username.
Check the user_search
object and make sure that:
- The specified
base_dn
contains the requested user entry DN
- The specified
attribute
contains the username as its value in the user entry
- The
object_class
attribute corresponds to the user entry object class
ad search for user <username> returned x results, expected only 1
The user search returned more than one user entry, so the provider could not determine which of these entries to use.
Change the user_search
object so the provided username
can be used to uniquely identify a user entry.
Here are two methods to try:
- Adjust the
attribute
so its value (which corresponds to the username
) is unique among the user entries
- Adjust the
base_dn
so it only includes one of the user entries
ad entry <DN> missing required attribute <name_attribute>
The user entry returned (identified by <DN>
) doesn’t include the attribute specified by name_attribute
object, so the AD provider could not determine which attribute to use as the username in the user entry.
Adjust the name_attribute
so it specifies a human-readable name for the user.
ad group entry <DN> missing <name_attribute> and cn attributes
The group search returned a group entry (identified by <DN>
) that doesn’t have the name_attribute
object or a cn
attribute, so the AD provider could not determine which attribute to use as the group name in the group entry.
Adjust the name_attribute
so it specifies a human-readable name for the group.
Authorization
Once authenticated, each user needs to be granted permissions via either a ClusterRoleBinding
or a RoleBinding
.
The way AD users and AD groups can be referred as subjects of a cluster role or role binding depends on the groups_prefix
and username_prefix
configuration attributes values of the AD provider.
For example, for the groups_prefix ad
and the group dev
, the resulting group name in Sensu is ad:dev
.
Permissions are not granted via the AD group(s)
During authentication, the AD provider will print all groups found in AD (for example, found 1 group(s): [dev]
) in the logs.
Keep in mind that this group name does not contain the groups_prefix
at this point.
The Sensu backend logs each attempt made to authorize an RBAC request.
This is useful for determining why a specific binding didn’t grant the request.
For example:
[...] the user is not a subject of the ClusterRoleBinding cluster-admin [...]
[...] could not authorize the request with the ClusterRoleBinding system:user [...]
[...] could not authorize the request with any ClusterRoleBindings [...]