class LDAPNetgroupPlugin

Manage host membership in the LDAP ‘Security Netgroup’ subtree

Attributes

config[RW]
ldap[RW]
log[RW]

Public Class Methods

new() click to toggle source
# File lib/architect/plugin/ldap_netgroup.rb, line 10
def initialize
  @name = 'ldap_netgroup'
  @log = Architect::Log.log
  #log.level = Logger::DEBUG
end

Public Instance Methods

configure(config_hash) click to toggle source
# File lib/architect/plugin/ldap_netgroup.rb, line 16
def configure(config_hash)
  @config = OpenStruct.new({
      host: nil,
      port: nil,
      bind_dn: nil,
      bind_password: nil,
      base_dn: nil,
      nis_domain: nil,
  }.merge(config_hash))

  bind_to_server
end
instance_create(fqdn) click to toggle source

Add a [fqdn] to netgroups

# File lib/architect/plugin/ldap_netgroup.rb, line 53
def instance_create(fqdn)
  value = '(' + [fqdn.gsub(/\..*/, ''), '', config.nis_domain].join(',') + ')'
  netgroup_membership(fqdn).each do |dn|
    log.debug "adding #{value} to #{dn}"
    ops = [[:add, :nisNetgroupTriple, value]]
    ldap.modify :dn => dn, :operations => ops
    check_operation_result
  end
end
instance_delete(fqdn) click to toggle source

Delete a [fqdn] from all netgroups

# File lib/architect/plugin/ldap_netgroup.rb, line 30
def instance_delete(fqdn)
  shortname = fqdn.gsub(/\..*/, '')
  match = '(' + [shortname, '', config.nis_domain].join(',') + ')'
  treebase = config.base_dn
  filter = Net::LDAP::Filter.eq( 'nisnetgrouptriple', match )
  attrs = [ "nisnetgrouptriple" ]

  log.debug "searching for #{match}"
  ldap.search(base: treebase, filter: filter, attributes: attrs, return_result: false) do |entry|
         log.debug "deleting #{shortname} from #{entry.dn}"
         dn = entry.dn
         ops = [[:delete, :nisNetgroupTriple, match]]
         ldap.modify :dn => dn, :operations => ops
  end
end
instance_rename(old_fqdn, new_fqdn) click to toggle source

Rename an instance

# File lib/architect/plugin/ldap_netgroup.rb, line 47
def instance_rename(old_fqdn, new_fqdn)
  instance_delete old_fqdn
  instance_create new_fqdn
end

Private Instance Methods

bind_to_server() click to toggle source
# File lib/architect/plugin/ldap_netgroup.rb, line 102
def bind_to_server
  ldap = Net::LDAP.new
  ldap.host = config.host
  ldap.port = config.port
  ldap.auth config.bind_dn, config.bind_password
  if ldap.bind
    log.debug "bound to #{ldap.host}:#{ldap.port} as #{config.bind_dn}"
    @ldap = ldap
  else
    raise "Unable to connect to the LDAP server"
  end
end
check_operation_result() click to toggle source

Check the result of the previous LDAP operation

# File lib/architect/plugin/ldap_netgroup.rb, line 68
def check_operation_result
  result = ldap.get_operation_result
  return if result.code == 0
  log.warn "LDAP operation failed with error code #{result.code}: " +
    result.message
end
netgroup_membership(fqdn) click to toggle source

Given a [fqdn] return a list of netgroups it should be a member of This relies on the ‘description’ field of the netgroup being populated with information like: “role=foo,bar,baz”, and assumes that the role is the first part of the FQDN.

# File lib/architect/plugin/ldap_netgroup.rb, line 80
def netgroup_membership(fqdn)
  role = fqdn.gsub /\-.*/, ''
  filter = Net::LDAP::Filter.eq( "description", "*role=*" )
  log.debug "searching netgroups for role=#{role}"

  # Put everything in the AllServers tree by default
  result = ['cn=AllServers,' + config.base_dn]
  ldap.search( :base => config.base_dn, :filter => filter ) do |entry|
    begin
      # Parse something like "role=foo,bar" out of the description
      entry.description[0] =~ /role=([A-Za-z0-9_,]+)/
      roles = $1.split /,/
      log.debug "netgroup #{entry.dn} has roles #{roles.inspect}"
      result.push entry.dn if roles.include? role
    rescue => e
      log.warn "unable to parse #{entry.description} for #{entry.dn}"
      log.warn "#{e.inspect}"
    end
  end
  result
end