Skip to main content

LDAP Data Source

LDAP data source reads the data from a configured LDAP service.

Configuration

To create the LDAP data source plugin, run the following curl command:

curl -H 'authorization: bearer XXX' -H 'Content-Type: application/json' https://styra-das-id.styra.com/v1/datasources/ldap/main -XPUT -d'
{
"category": "ldap",
"type": "pull",
"urls": ["<url to main replica>", "<url to secondary replica>", "..."],
"credentials": "<secret id wiht LDAP credentials>",
"polling_interval: "60s",
"search": {
"base_DN": "<base DN>",
"filter": "<search filter>",
}
}'

The following shows the list of available configuration parameters:

  • category: must be ldap. Required
  • description: free form text that describes the configured data source
  • enabled: flag that allows to disable/enable data source. Default value: true
  • on_premises: flag that tells us ho and where to run the data source. If set to true then datasource-agent will run on premise setup, otherwise on SaaS. Required
  • type: must be pull. The plugin does not support push operations. Required
  • polling_interval: how often the plugin polls the data. Default value: 30s (30 seconds)
  • policy_filter: an ID of a policy bundle you want to use for filtering downloaded data. (Required if policy_query has been set)
  • policy_query: a Rego query you want to evaluate. (Required if policy_filter has been set)
  • ca_certificate: Custom CA certificate
  • skip_tls_verification: Skip TLS verification
  • rate_limit: number of requests per second. Default value: 3 (3 requests per second)
  • credentials: Secret ID with credentials. Same credentials are used for all replicas. If no credentials are provided, then plugin will make an attempt to poll the data without a bind request. Also, the password can be empty, in this case the plugin will make a bind request with AllowEmptyPassword flag set to true.
  • urls: list of ldap urls to replicas. Required
  • search: object to define a search request.
    • base_DN: base distinguished name. Required
    • filter: search filter. See examples. Required
    • attributes: list of attributes.
    • deref: dereference policy. Enum: never, searching , finding, always. Default value: never
    • scope: search scope. Enum: base-object , single-level, whole-subtree. Default value: whole-subtree
    • page_size: the number of returned objects per single request. According to the benchmarks, the higher number is better. Default value: 0 (all data in one request)
    • size_limit: the maximum number of returned objects. Default value: 0 (no limit)

Use Rego to Filter and Transform the Data

A policy_filter is used to poll from a data source that you want to transform captured data source information before storing it. Specifying a policy_filter and policy_query will allow you to apply Rego transformations before it is persisted as data. This mechanism is useful for filtering out data that you no longer want to store or for any other mutations that you want to perform.

It works by specifying a policy that will be evaluated via Rego with captured data as input. You also specify a query to apply to that policy and data. The result of that query will be stored as data, instead of what is polled by the data source plugin.

Raw Data Returned by Plugin

[
{
"ou": [
"Users"
],
"objectClass": [
"organizationalUnit"
],
"dn": {
"ou": [
"Users"
],
"dc": [
"test",
"styra",
"com"
],
"_raw": "ou=Users,dc=test,dc=styra,dc=com"
}
},
{
"cn": [
"Foo Bar"
],
"sn": [
"Bar"
],
"uid": [
"fbar"
],
"objectClass": [
"inetOrgPerson"
],
"dn": {
"cn": [
"Foo Bar"
],
"ou": [
"Users"
],
"dc": [
"test",
"styra",
"com"
],
"_raw": "cn=Foo Bar,ou=Users,dc=test,dc=styra,dc=com"
}
},
{
"cn": [
"IT"
],
"member": [
"cn=Foo Bar,ou=Users,dc=test,dc=styra,dc=com"
],
"objectClass": [
"groupOfNames"
],
"dn": {
"cn": [
"IT"
],
"ou": [
"Users"
],
"dc": [
"test",
"styra",
"com"
],
"_raw": "cn=IT,ou=Users,dc=test,dc=styra,dc=com"
}
}
]

Policy Bundle

package tmp.policy

import input

users[record] {
in := input[_]
in.objectClass[_] == "inetOrgPerson"

record := {
"dn": in.dn._raw,
"name": concat(" ", in.cn),
"id": concat(" ", in.uid),
"units": in.dn.ou
}
}

groups[record] {
in := input[_]
in.objectClass[_] == "groupOfNames"

record := {
"dn": in.dn._raw,
"name": in.cn[_],
"members": in.member,
}
}

units[record] {
in := input[_]
in.objectClass[_] == "organizationalUnit"

record := {
"dn": in.dn._raw,
"name": concat(" ", in.ou),
}
}

Output

The following shows the final result after applying the Rego Bundle.

{
"groups": [
{
"dn": "cn=IT,ou=Users,dc=test,dc=styra,dc=com",
"members": [
"cn=Foo Bar,ou=Users,dc=test,dc=styra,dc=com"
],
"name": "IT"
}
],
"units": [
{
"dn": "ou=Users,dc=test,dc=styra,dc=com",
"name": "Users"
}
],
"users": [
{
"dn": "cn=Foo Bar,ou=Users,dc=test,dc=styra,dc=com",
"id": "fbar",
"name": "Foo Bar",
"units": [
"Users"
]
}
]
}