Queries
Karma allows to adjust the LDAP search queries to reduce the visibility of LDAP entries based on business requirements.
Query system is based on rules, that can be defined in a configuration file called rules.js within the configuration directory. These rules allow to add additional filter parts to each search:
exports.queries = {
async users({ viewer, IDVault, config, escapeLDAPFilter }) {
if (viewer.is('admin')) return
const allSpecialRoles = await IDVault.search(config.get('roles.base'), {
scope: config.get('roles.scope'),
filter: `(&${config.get('roles.filter')}(cn=*${escapeLDAPFilter('special role')}))`,
})
return { nrfMemberOf: { in: allSpecialRoles.map(role => role.entryDN) } }
},
}
The following queries can be adjusted: users, accounts, roles, groups and organizationalUnits
Each function receives a sandbox as first parameter and may return:
- a falsy value, indicating nothing should be added to the filter
- a plain/raw LDAP filter string (use
escapeLDAPFilter(value)for safe escaping of values) - a LDAP Filter Object - preferred solution
API
LDAP Filter Object
The LDAP Filter Object provides a way to use Javascript objects for LDAP filter definitions.
Why:
- value escaping
- composition of filters
- readability
- dynamic adjustment
Examples:
{ cn: { eq: 'kenoxa' } } // => (cn=kenoxa)
{ givenName: { eq: 'Max' }, surname: { eq: { 'Mustermann' } } } // => (&(givenName=Max)(surname=Mustermann))
Operators:
| type | js | ldap |
|---|---|---|
eq | { x: { eq: 'y' } } | (x=y) |
neq | { x: { neq: 'y' } } | (!(x=y)) |
lte | { x: { lte: 7 } } | (x<=7) |
nlte | { x: { nlte: 7 } } | (!(x<=7)) |
lt | { x: { lt: 7 } } | (&(x<=7)(!(x=7))) |
nlt | { x: { nlt: 7 } } | (!(&(x<=7)(!(x=7)))) |
gte | { x: { gte: 7 } } | (x>=7) |
ngte | { x: { ngte: 7 } } | (!(x>=7)) |
gt | { x: { gt: 7 } } | (&(x>=7)(!(x=7))) |
ngt | { x: { ngt: 7 } } | (!(&(x>=7)(!(x=7)))) |
in | { x: { in: ['y', 'z'] } } | (|(x=y)(x=z)) |
notIn | { x: { notIn: ['y', 'z'] } } | (!(|(x=y)(x=z))) |
exists | { x: { exists: true } | (x=*) |
notExists | { x: { notExists: true } | (!(x=*)) |
substring | { x: { substring: { initial: 'y' } } } | (x=y*) |
substring | { x: { substring: { any: 'y' } } } | (x=*y*) |
substring | { x: { substring: { any: ['y', 'z'] } } } | (x=*y*z*) |
substring | { x: { substring: { final: 'y' } } } | (x=*y) |
substring | { x: { substring: { initial: 'y', final: 'z' } } } | (x=y*z) |
notSubstring | { x: { notSubstring: { initial: 'y', final: 'z' } } } | (!(x=y*z)) |
startsWith | { x: { startsWith: 'y' } } | (x=y*) |
notStartsWith | { x: { notStartsWith: 'y' } } | (!(x=y*)) |
endsWith | { x: { endsWith: 'y' } } | (x=*y) |
notEndsWith | { x: { notEndsWith: 'y' } } | (!(x=*y)) |
contains | { x: { contains: 'y' } } | (x=*y*) |
notContains | { x: { notContains: 'y' } } | (!(x=*y*)) |
These operators can be combined: { age: { gte: 21, lte: 65 } } => (&(age>=21)(age<=65))
Combinators:
| type | js | ldap |
|---|---|---|
$or | { $or: { x: { eq: 'y' }, a: { eq: 'b' } } } | (|(x=y)(a=b)) |
$and | { $and: { x: { eq: 'y' }, a: { eq: 'b' } } } | (&(x=y)(a=b)) |
$not | { $not: { x: { eq: 'y' }, a: { eq: 'b' } } } | (!(&(x=y)(a=b))) |