mirror of
https://github.com/philippdieter/puppet-ldapquery.git
synced 2025-10-13 12:55:48 +00:00
commit
bbda78596a
4
Gemfile
4
Gemfile
@ -4,10 +4,14 @@ group :test do
|
|||||||
gem "rake"
|
gem "rake"
|
||||||
gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.7.0'
|
gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.7.0'
|
||||||
gem "rspec", '< 3.2.0'
|
gem "rspec", '< 3.2.0'
|
||||||
|
gem 'rspec-core'
|
||||||
|
gem 'rspec-mocks'
|
||||||
|
gem 'rspec-expectations'
|
||||||
gem "rspec-puppet", :git => 'https://github.com/rodjek/rspec-puppet.git'
|
gem "rspec-puppet", :git => 'https://github.com/rodjek/rspec-puppet.git'
|
||||||
gem "puppetlabs_spec_helper"
|
gem "puppetlabs_spec_helper"
|
||||||
gem "metadata-json-lint"
|
gem "metadata-json-lint"
|
||||||
gem "rspec-puppet-facts"
|
gem "rspec-puppet-facts"
|
||||||
|
gem "net-ldap"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
2
Rakefile
2
Rakefile
@ -35,7 +35,7 @@ PuppetSyntax.exclude_paths = exclude_paths
|
|||||||
|
|
||||||
desc "Run acceptance tests"
|
desc "Run acceptance tests"
|
||||||
RSpec::Core::RakeTask.new(:acceptance) do |t|
|
RSpec::Core::RakeTask.new(:acceptance) do |t|
|
||||||
t.pattern = 'spec/acceptance'
|
t.pattern = 'spec/**/*.rb'
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Populate CONTRIBUTORS file"
|
desc "Populate CONTRIBUTORS file"
|
||||||
|
19
lib/puppet/parser/functions/ldapquery.rb
Normal file
19
lib/puppet/parser/functions/ldapquery.rb
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
require 'puppet_x/ldapquery'
|
||||||
|
|
||||||
|
begin
|
||||||
|
require 'net/ldap'
|
||||||
|
rescue
|
||||||
|
Puppet.warn("Missing net/ldap gem required for ldapquery() function")
|
||||||
|
end
|
||||||
|
|
||||||
|
Puppet::Parser::Functions.newfunction(:ldapquery,
|
||||||
|
:type => :rvalue) do |args|
|
||||||
|
|
||||||
|
if args.size > 2
|
||||||
|
raise Puppet::ParseError, "Too many arguments received in ldapquery()"
|
||||||
|
end
|
||||||
|
|
||||||
|
filter, attributes = args
|
||||||
|
|
||||||
|
return PuppetX::LDAPquery.new(filter, attributes).results
|
||||||
|
end
|
127
lib/puppet_x/ldapquery.rb
Normal file
127
lib/puppet_x/ldapquery.rb
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# Class: PuppetX::LDAPquery
|
||||||
|
#
|
||||||
|
|
||||||
|
module PuppetX
|
||||||
|
class LDAPquery
|
||||||
|
attr_reader :content
|
||||||
|
|
||||||
|
def initialize(
|
||||||
|
filter,
|
||||||
|
attributes=[],
|
||||||
|
base=Puppet[:ldapbase]
|
||||||
|
)
|
||||||
|
@filter = filter
|
||||||
|
@attributes = attributes
|
||||||
|
@base = base
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_config
|
||||||
|
# Load the configuration variables from Puppet
|
||||||
|
required_vars = [
|
||||||
|
:ldapserver,
|
||||||
|
:ldapport,
|
||||||
|
]
|
||||||
|
|
||||||
|
required_vars.each {|r|
|
||||||
|
unless Puppet[r]
|
||||||
|
raise Puppet::ParseError, "Missing required setting '#{r.to_s}' in puppet.conf"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
host = Puppet[:ldapserver]
|
||||||
|
port = Puppet[:ldapport]
|
||||||
|
|
||||||
|
if Puppet[:ldapuser] and Puppet[:ldappassword]
|
||||||
|
user = Puppet[:ldapuser]
|
||||||
|
password = Puppet[:ldappassword]
|
||||||
|
end
|
||||||
|
|
||||||
|
tls = Puppet[:ldaptls]
|
||||||
|
ca_file = "#{Puppet[:confdir]}/ldap_ca.pem"
|
||||||
|
|
||||||
|
conf = {
|
||||||
|
:host => host,
|
||||||
|
:port => port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if user != '' and password != ''
|
||||||
|
conf[:auth] = {
|
||||||
|
:method => :simple,
|
||||||
|
:username => user,
|
||||||
|
:password => password,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
if tls
|
||||||
|
conf[:encryption] = {
|
||||||
|
:method => :simple_tls,
|
||||||
|
:tls_options => { :ca_file => ca_file }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
Puppet.debug(conf)
|
||||||
|
return conf
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_entries()
|
||||||
|
# Query the LDAP server for attributes using the filter
|
||||||
|
#
|
||||||
|
# Returns: An array of Net::LDAP::Entry objects
|
||||||
|
ldapfilter = @filter
|
||||||
|
attributes = @attributes
|
||||||
|
base = @base
|
||||||
|
|
||||||
|
conf = self.get_config()
|
||||||
|
|
||||||
|
Puppet.debug("Searching ldap base #{base} using #{@filter} for #{@attributes}")
|
||||||
|
|
||||||
|
ldap = Net::LDAP.new(conf)
|
||||||
|
ldapfilter = Net::LDAP::Filter.construct(@filter)
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
begin
|
||||||
|
ldap.search(:base => base,
|
||||||
|
:filter => ldapfilter,
|
||||||
|
:attributes => attributes,
|
||||||
|
:time => 10) do |entry|
|
||||||
|
entries << entry
|
||||||
|
end
|
||||||
|
Puppet.debug(entries)
|
||||||
|
return entries
|
||||||
|
rescue
|
||||||
|
return []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_entries
|
||||||
|
data = []
|
||||||
|
entries = get_entries()
|
||||||
|
entries.each do |entry|
|
||||||
|
entry_data = {}
|
||||||
|
entry.each do |attribute, values|
|
||||||
|
|
||||||
|
attr = attribute.to_s
|
||||||
|
|
||||||
|
if values.is_a? Array and values.size > 1
|
||||||
|
entry_data[attr] = []
|
||||||
|
|
||||||
|
values.each do |v|
|
||||||
|
entry_data[attr] << v.chomp
|
||||||
|
end
|
||||||
|
elsif values.is_a? Array and values.size == 1
|
||||||
|
entry_data[attr] = values[0].chomp
|
||||||
|
else
|
||||||
|
entry_data[attr] = values.chomp
|
||||||
|
end
|
||||||
|
end
|
||||||
|
data << entry_data
|
||||||
|
end
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
def results
|
||||||
|
parse_entries
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
4
spec/fixtures/entries_multivalue.obj
vendored
Normal file
4
spec/fixtures/entries_multivalue.obj
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[Iu:Net::LDAP::Entry¯dn: uid=zach,ou=users,dc=puppetlabs,dc=com
|
||||||
|
sshpublickey:: c3NoLXJzYSBBQUFBQi4uLjE9PSB1c2VyQHNvbWV3aGVyZQo=
|
||||||
|
sshpublickey:: c3NoLXJzYSBBQUFBQi4uLjI9PSB1c2VyQHNvbWV3aGVyZWVsc2UK
|
||||||
|
:ET
|
8
spec/fixtures/entries_objectClass.obj
vendored
Normal file
8
spec/fixtures/entries_objectClass.obj
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[Iu:Net::LDAP::EntryÁdn: uid=zach,ou=users,dc=puppetlabs,dc=com
|
||||||
|
objectclass: posixAccount
|
||||||
|
objectclass: shadowAccount
|
||||||
|
objectclass: inetOrgPerson
|
||||||
|
objectclass: puppetPerson
|
||||||
|
objectclass: ldapPublicKey
|
||||||
|
objectclass: top
|
||||||
|
:ET
|
3
spec/fixtures/entries_single.obj
vendored
Normal file
3
spec/fixtures/entries_single.obj
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[Iu:Net::LDAP::Entry:dn: uid=zach,ou=users,dc=puppetlabs,dc=com
|
||||||
|
uid: zach
|
||||||
|
:ET
|
10
spec/spec_helper.rb
Normal file
10
spec/spec_helper.rb
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
require 'puppetlabs_spec_helper/module_spec_helper'
|
||||||
|
require 'rspec-puppet'
|
||||||
|
|
||||||
|
fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))
|
||||||
|
|
||||||
|
RSpec.configure do |c|
|
||||||
|
c.module_path = File.join(fixture_path, 'modules')
|
||||||
|
c.manifest_dir = File.join(fixture_path, 'manifests')
|
||||||
|
c.mock_framework = :rspec
|
||||||
|
end
|
77
spec/unit/ldapquery_spec.rb
Normal file
77
spec/unit/ldapquery_spec.rb
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
require 'puppet_x/ldapquery'
|
||||||
|
require 'net/ldap'
|
||||||
|
|
||||||
|
describe 'PuppetX::LDAPquery' do
|
||||||
|
describe 'results' do
|
||||||
|
let (:conf) { {
|
||||||
|
:host => 'ldap.example.com',
|
||||||
|
:port => 9009,
|
||||||
|
} }
|
||||||
|
|
||||||
|
let (:base) { 'dc=example,dc=com' }
|
||||||
|
|
||||||
|
it "should fail with no filter" do
|
||||||
|
filter = ''
|
||||||
|
attributes = ['uid']
|
||||||
|
expect { PuppetX::LDAPquery.new(filter, attributes).results }.to raise_error
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not fail when using defaults in puppet.conf" do
|
||||||
|
filter = '(uid=zach)'
|
||||||
|
attributes = ['uid']
|
||||||
|
l = PuppetX::LDAPquery.new(filter, attributes, base)
|
||||||
|
expect { l.get_config }.to_not raise_error
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should return the desired results' do
|
||||||
|
filter = '(uid=zach)'
|
||||||
|
attributes = ['uid']
|
||||||
|
|
||||||
|
wanted = [{"dn"=>"uid=zach,ou=users,dc=puppetlabs,dc=com", "uid"=>"zach"}]
|
||||||
|
entries = Marshal.load(File.read("spec/fixtures/entries_single.obj"))
|
||||||
|
|
||||||
|
l = PuppetX::LDAPquery.new(filter, attributes, base)
|
||||||
|
|
||||||
|
expect(l).to receive(:get_entries).and_return(entries)
|
||||||
|
expect(l.results).to match(wanted)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "a multivalued attribute is requested" do
|
||||||
|
it 'should return the attribute values as an array to the attribute' do
|
||||||
|
filter = '(uid=zach)'
|
||||||
|
attributes = ['objectClass']
|
||||||
|
|
||||||
|
wanted = [{"dn"=>"uid=zach,ou=users,dc=puppetlabs,dc=com",
|
||||||
|
"objectclass"=> [
|
||||||
|
"posixAccount",
|
||||||
|
"shadowAccount",
|
||||||
|
"inetOrgPerson",
|
||||||
|
"puppetPerson",
|
||||||
|
"ldapPublicKey",
|
||||||
|
"top"]}]
|
||||||
|
|
||||||
|
entries = Marshal.load(File.read("spec/fixtures/entries_objectClass.obj"))
|
||||||
|
|
||||||
|
l = PuppetX::LDAPquery.new(filter, attributes, base)
|
||||||
|
expect(l).to receive(:get_entries).and_return(entries)
|
||||||
|
expect(l.results).to match(wanted)
|
||||||
|
end
|
||||||
|
it 'should return the attributes without new lines' do
|
||||||
|
filter = '(uid=zach)'
|
||||||
|
attributes = ['sshPublicKey']
|
||||||
|
|
||||||
|
wanted = [{"dn"=>"uid=zach,ou=users,dc=puppetlabs,dc=com",
|
||||||
|
"sshpublickey"=>
|
||||||
|
["ssh-rsa AAAAB...1== user@somewhere",
|
||||||
|
"ssh-rsa AAAAB...2== user@somewhereelse"]}]
|
||||||
|
|
||||||
|
entries = Marshal.load(File.read("spec/fixtures/entries_multivalue.obj"))
|
||||||
|
|
||||||
|
l = PuppetX::LDAPquery.new(filter, attributes, base)
|
||||||
|
expect(l).to receive(:get_entries).and_return(entries)
|
||||||
|
expect(l.results).to match(wanted)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user