Documentationcurrent version
Help us improve the docs by fixing typos and proposing enhancements.

Nikita

Action "ldap.acl"

Create new ACLs for the OpenLDAP server.

Example

const {$status} = await nikita.ldap.acl({
  dn: '',
  acls: [{
    place_before: 'dn.subtree="dc=domain,dc=com"',
    to: 'dn.subtree="ou=users,dc=domain,dc=com"',
    by: [
      'dn.exact="ou=users,dc=domain,dc=com" write',
      'dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read',
      '* none'
    ]
  },{
    to: 'dn.subtree="dc=domain,dc=com"',
    by: [
      'dn.exact="ou=kerberos,dc=domain,dc=com" write'
    ]
  }]
})
console.info(`ACL modified: ${$status}`)

Hooks

on_action = ({config}) ->
  config.acls = [config.acls] if is_object_literal config.acls

Schema definitions

definitions =
  config:
    type: 'object'
    properties:
      'acls':
        type: 'array'
        description: '''
        In case of multiple acls, regroup "place_before", "to" and "by" as an
        array.
        '''
        items:
          type: 'object'
          properties:
            'by':
              type: 'array'
              items: type: 'string'
              description: '''
              Who to grant access to and the access to grant as an array (eg:
              `{..., by:["ssf=64 anonymous auth"]}`).
              '''
            'first':
              type: 'boolean'
              description: '''
              Please ACL in the first position.
              '''
            'place_before':
              type: 'string'
              description: '''
              Place before another rule defined by "to".
              '''
            'to':
              type: 'string'
              description: '''
              What to control access to as a string.
              '''
      'dn':
        type: 'string'
        description: '''
        Distinguish name storing the "olcAccess" property, using the database
        address (eg: "olcDatabase={2}bdb,cn=config").
        '''
      'suffix':
        type: 'string'
        description: '''
        The suffix associated with the database (eg: "dc=example,dc=org"),
        used as an alternative to the `dn` configuration.
        '''
    required: ['acls']

Handler

handler = ({config, tools: {log}}) ->
  $status = false
  # Get DN
  unless config.dn
    log message: "Get DN of the database to modify", level: 'DEBUG'
    {dn} = await @ldap.tools.database config,
      suffix: config.suffix
    config.dn = dn
    log message: "Database DN is #{dn}", level: 'INFO'
  for acl in config.acls
    # Get ACLs
    log message: "List all ACL of the directory", level: 'DEBUG'
    {stdout} = await @ldap.search config,
      attributes: ['olcAccess']
      base: "#{config.dn}"
      filter: '(olcAccess=*)'
    current = null
    olcAccesses = []
    for line in utils.string.lines stdout
      if match = /^olcAccess: (.*)$/.exec line
        olcAccesses.push current if current? # Push previous rule
        current = match[1] # Create new rule
      else if current?
        if /^ /.test line # Append to existing rule
          current += line.substr 1
        else # Close the rule
          olcAccesses.push current
          current = null
    olcAccesses = utils.ldap.acl.parse olcAccesses
    # Diff
    olcAccess = null
    # Find match "to" property
    for access, i in olcAccesses
      if acl.to is access.to
        olcAccess = merge access
        olcAccess.old = access
        break
    if olcAccess # Modify rule or bypass perfect match
      is_perfect_match = true
      not_found_acl = []
      if acl.by.length isnt olcAccess.by.length
        is_perfect_match = false
      else
        for acl_by, i in acl.by
          is_perfect_match = false if acl_by isnt olcAccess.by[i]
          found = true
          for access_by in olcAccess.by
            found = false if acl_by isnt access_by
          not_found_acl.push acl_by unless found
      if is_perfect_match
        log message: "No modification to apply", level: 'INFO'
        continue
      if not_found_acl.length
        log message: "Modify access after undefined acl", level: 'INFO'
        for access_by in olcAccess.by
          not_found_acl.push access_by
        olcAccess.by = not_found_acl
      else
        log message: "Modify access after reorder", level: 'INFO'
        log? 'nikita `ldap.acl`: m'
        olcAccess.by = acl.by
    else
      log message: "Insert a new access", level: 'INFO'
      index = olcAccesses.length
      if acl.first # not tested
        index = 0
      if acl.place_before
        for access, i in olcAccesses
          index = i if access.to is acl.place_before
      else if acl.after
        for access, i in olcAccesses
          index = i+1 if access.to is config.after
      olcAccess = index: index, to: acl.to, by: acl.by, add: true
    # Save
    old = utils.ldap.acl.stringify olcAccess.old if olcAccess.old
    olcAccess = utils.ldap.acl.stringify olcAccess
    
    operations =
      dn: config.dn
      changetype: 'modify'
      attributes: []
    if old
      operations.attributes.push
        type: 'delete'
        name: 'olcAccess'
      operations.attributes.push
        type: 'add'
        name: 'olcAccess'
        value: olcAccess
    else
      operations.attributes.push
        type: 'add'
        name: 'olcAccess'
        value: olcAccess
    await @ldap.modify config,
      operations: operations
    $status = true
  $status

Exports

module.exports =
  handler: handler
  hooks:
    on_action: on_action
  metadata:
    global: 'ldap'
    definitions: definitions

Dependencies

{is_object_literal, merge} = require 'mixme'
utils = require './utils'
Edit on GitHub
Navigate
About

Nikita is an open source project hosted on GitHub and developed by Adaltas.