Last active
August 29, 2015 13:56
-
-
Save Quintus/9119159 to your computer and use it in GitHub Desktop.
Nice tree outputter for LDAP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# -*- coding: utf-8 -*- | |
require "optparse" | |
require "base64" | |
require "pp" | |
######################################## | |
# Option handling | |
@options = { | |
:dn => "dc=pegasus-alpha,dc=eu", | |
:verbose => false, | |
:filter => "(objectclass=*)", | |
:authdn => nil | |
} | |
OptionParser.new do |op| | |
op.banner =<<-USAGE | |
lsldap [OPTIONS] | |
Prints out the LDAP tree in a nicely indented fashion. If -b | |
is specified, print only entries below that distinguished | |
name (dn). | |
Options: | |
USAGE | |
op.on("-b", "--base DN", "Specify tree root"){|dn| @options[:dn] = dn} | |
op.on("-D", "--auth-dn DN", "Specify the DN for accessing the LDAP.", "This will ask you for a password."){|dn| @options[:authdn] = dn} | |
op.on("-f", "--filter FILTER", "Use a specific filter;", "default is '#{@options[:filter]}'."){|filter| @options[:filter] = filter} | |
op.on("-h", "--help", "Show this help"){ puts(op); exit } | |
op.on("-v", "--[no-]verbose", "Run verbosely"){|bool| @options[:verbose] = bool} | |
end.parse!(ARGV) | |
######################################## | |
# Helpers | |
class Entry | |
attr_accessor :info | |
attr_accessor :rdn | |
def initialize(rdn = "·", info = nil) | |
@rdn = rdn | |
@tree = {} | |
@info = info | |
end | |
def [](key) | |
@tree[key] ||= Entry.new(key) | |
end | |
def []=(key, value) | |
@tree[key] = value | |
end | |
# call-seq: | |
# recursive_each( [yield_self] ){|rdn, entry, level, is_last| ...} | |
# | |
# Iterates recursively over the entire subtree. | |
def recursive_each(yield_self = true, level = 0, is_last = false, &block) | |
block.call(@rdn, self, level, is_last) if yield_self | |
@tree.values.each_with_index do |entry, index| | |
entry.recursive_each(true, level + 1, index + 1 == @tree.values.count, &block) | |
end | |
end | |
end | |
def ldapsearch(base = nil) | |
cmd = "ldapsearch -x -LLL -o ldif-wrap=no" | |
cmd << " " << "-b '" << base << "'" if base | |
cmd << " " << "-D '" << @options[:authdn] << "' -W" if @options[:authdn] | |
cmd << " '#{@options[:filter]}'" | |
puts cmd if @options[:verbose] | |
str = `#{cmd}` | |
result = Entry.new | |
str.split("\n\n").each do |block| | |
if block =~ /^(dn::?)\s(.*?)$/ | |
if $1.start_with?("dn::") # Base64-encoded | |
dn = Base64.decode64($2) | |
else | |
dn = $2 | |
end | |
keys = dn.split(",") | |
entry = result | |
entry = entry[keys.pop] until keys.count == 1 | |
lastkey = keys.pop | |
if entry[lastkey] | |
entry[lastkey].rdn = lastkey | |
entry[lastkey].info = block.lines.to_a.map(&:strip) | |
else | |
entry[lastkey] = Entry.new(lastkey, block.lines.to_a.map(&:strip)) | |
end | |
end | |
end | |
result | |
end | |
######################################## | |
# Program | |
ldapsearch(@options[:dn]).recursive_each do |rdn, entry, level, is_last| | |
if level > 0 | |
print(" " * (level -1)) | |
print(is_last ? "└" : "├") | |
print("── ") | |
end | |
puts entry.rdn | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment