sbs2003_contacts 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +11 -0
- data/Manifest.txt +6 -0
- data/README.txt +68 -0
- data/Rakefile +13 -0
- data/lib/sbs2003_contacts.rb +159 -0
- data/test/test_sbs2003_contacts.rb +123 -0
- metadata +81 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
= SBS2003Contacts
|
2
|
+
|
3
|
+
* http://rubyforge.org/projects/uwruby/
|
4
|
+
* http://urwuby.rubyforge.org/sbs2003_contacts/
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
* A small utiltity library to help alleviate the tedium of managing the contacts and e-mail lists from a Small Business Server 2003 Active Directory.
|
9
|
+
|
10
|
+
== FEATURES/PROBLEMS:
|
11
|
+
|
12
|
+
* Query AD and find out user info ( email, which lists they belong to )
|
13
|
+
* Query AD and find out e-mail list info ( list member e-mails )
|
14
|
+
* Manage lists ( add/remove e-mails )
|
15
|
+
* TODO: Reverse engineer SBS2003 AD schema's and figure out proper way to add new users/lists
|
16
|
+
|
17
|
+
== SYNOPSIS:
|
18
|
+
|
19
|
+
#!/usr/bin/env ruby -w
|
20
|
+
|
21
|
+
require 'rubygems'
|
22
|
+
require 'sbs2003_contacts'
|
23
|
+
|
24
|
+
# new(username, password, base_dn, server, port)
|
25
|
+
# assumes dc=com, localhost, 389
|
26
|
+
contact = SBS2003Contacts.new("username", "password", "dc=sbs2003,dc=local")
|
27
|
+
|
28
|
+
contact.find_user_dn_by_name("Some User")
|
29
|
+
# => CN=Some User,OU=...
|
30
|
+
|
31
|
+
contact.list_user_lists("Some User")
|
32
|
+
# => [ "CN=List One,OU=...." ]
|
33
|
+
|
34
|
+
contact.list_lists_member_emails("list@sbs2003.local")
|
35
|
+
# => [ [ "CN=User One,OU=...", "user_one@sbs2003.local" ], ... ]
|
36
|
+
|
37
|
+
== REQUIREMENTS:
|
38
|
+
|
39
|
+
* ruby-net-ldap >= 0.0.4
|
40
|
+
|
41
|
+
== INSTALL:
|
42
|
+
|
43
|
+
* sudo gem install sbs2003_contacts
|
44
|
+
|
45
|
+
== LICENSE:
|
46
|
+
|
47
|
+
(The MIT License)
|
48
|
+
|
49
|
+
Copyright (c) 2008 FIX
|
50
|
+
|
51
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
52
|
+
a copy of this software and associated documentation files (the
|
53
|
+
'Software'), to deal in the Software without restriction, including
|
54
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
55
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
56
|
+
permit persons to whom the Software is furnished to do so, subject to
|
57
|
+
the following conditions:
|
58
|
+
|
59
|
+
The above copyright notice and this permission notice shall be
|
60
|
+
included in all copies or substantial portions of the Software.
|
61
|
+
|
62
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
63
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
64
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
65
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
66
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
67
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
68
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/sbs2003_contacts.rb'
|
6
|
+
|
7
|
+
Hoe.new('sbs2003_contacts', SBS2003Contacts::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'uwruby'
|
9
|
+
p.developer('John Howe', 'elf-rubyforge@arashi.com')
|
10
|
+
p.extra_deps << [ 'ruby-net-ldap' , '>= 0.0.4' ]
|
11
|
+
end
|
12
|
+
|
13
|
+
# vim: syntax=Ruby
|
@@ -0,0 +1,159 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'net/ldap'
|
5
|
+
|
6
|
+
SERVER = "localhost"
|
7
|
+
PORT = 389
|
8
|
+
BASEDN = "dc=com"
|
9
|
+
ADMIN = "Manager"
|
10
|
+
PASSWD = "secret"
|
11
|
+
|
12
|
+
class SBS2003Contacts
|
13
|
+
VERSION = '0.2.0'
|
14
|
+
|
15
|
+
attr_accessor :ldap
|
16
|
+
|
17
|
+
def initialize(user = ADMIN, pass = PASSWD, base = BASEDN, server = SERVER, port = PORT)
|
18
|
+
@ldap = Net::LDAP.new :host => server,
|
19
|
+
:port => port,
|
20
|
+
:base => base,
|
21
|
+
:auth => {
|
22
|
+
:method => :simple,
|
23
|
+
:username => user,
|
24
|
+
:password => pass
|
25
|
+
}
|
26
|
+
# @ldap.bind ? true : false
|
27
|
+
end
|
28
|
+
|
29
|
+
# meta
|
30
|
+
|
31
|
+
def set_filter(attribute, search_term)
|
32
|
+
Net::LDAP::Filter.eq(attribute, search_term)
|
33
|
+
end
|
34
|
+
|
35
|
+
# User management
|
36
|
+
|
37
|
+
def find_user_dn_by_name(user_name)
|
38
|
+
results = ''
|
39
|
+
filter = set_filter( "cn", user_name)
|
40
|
+
@ldap.search( :filter => filter ) do |entry|
|
41
|
+
results = entry.dn
|
42
|
+
end
|
43
|
+
raise UserNameNotFoundException, "No DN found for user: #{user_name}" if results.empty?
|
44
|
+
results
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_user_dn_by_email(user_email)
|
48
|
+
results = ''
|
49
|
+
filter = set_filter( "mail", user_email)
|
50
|
+
@ldap.search( :filter => filter ) do |entry|
|
51
|
+
results = entry.dn
|
52
|
+
end
|
53
|
+
raise UserEmailNotFoundException, "No DN found for e-mail: #{user_email}" if results.empty?
|
54
|
+
results
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_user_email_by_cn(user_cn)
|
58
|
+
result = ''
|
59
|
+
filter = set_filter("cn", user_cn)
|
60
|
+
attrs = [ "cn", "mail" ]
|
61
|
+
@ldap.search( :filter => filter, :attributes => attrs ) do |entry|
|
62
|
+
entry.each do |attr,values|
|
63
|
+
if attr.to_s == "mail" then
|
64
|
+
values.each do |value|
|
65
|
+
result = value.downcase
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def update_user_email(user_name, new_email)
|
73
|
+
target_dn = find_user_dn_by_name(user_name)
|
74
|
+
ldap.replace_attribute target_dn, :mail, new_email
|
75
|
+
ldap.replace_attribute target_dn, :proxyAddresses, "SMTP:#{new_email}"
|
76
|
+
ldap.replace_attribute target_dn, :targetAddress, "SMTP:#{new_email}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def list_user_lists(user_name)
|
80
|
+
results = []
|
81
|
+
filter = set_filter("cn", user_name)
|
82
|
+
attrs = [ "memberOf", "mail", "cn"]
|
83
|
+
@ldap.search( :filter => filter, :attributes => attrs ) do |entry|
|
84
|
+
entry.each do |attr, values|
|
85
|
+
if attr.to_s == "memberof" then
|
86
|
+
values.each do |value|
|
87
|
+
results.push(value.dup)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
results.sort
|
93
|
+
end
|
94
|
+
|
95
|
+
# def add_new_user
|
96
|
+
# # TODO, need to reverse engineer all of AD's magical madness first
|
97
|
+
# # since M$ went way off the fraking reservation and changed stadard LDAP schemas
|
98
|
+
# end
|
99
|
+
|
100
|
+
def find_list_dn_by_email(list_email)
|
101
|
+
result = ""
|
102
|
+
filter = set_filter( "mail", list_email)
|
103
|
+
@ldap.search( :filter => filter ) do |entry|
|
104
|
+
result = entry.dn
|
105
|
+
end
|
106
|
+
raise ListEmailNotFoundException, "List e-mail not found: #{list_email}" if result.empty?
|
107
|
+
result
|
108
|
+
end
|
109
|
+
|
110
|
+
def list_lists_member_emails(list_email)
|
111
|
+
results = []
|
112
|
+
filter = set_filter( "mail", list_email)
|
113
|
+
attrs = [ "mail", "member", "cn", "objectClass"]
|
114
|
+
@ldap.search( :filter => filter, :attributes => attrs ) do |entry|
|
115
|
+
entry.each do |attr, values|
|
116
|
+
if attr.to_s == "member" then
|
117
|
+
values.each do |value|
|
118
|
+
user_cn = value.dup.split(",").first.split("=").last
|
119
|
+
results.push( [ value.dup, self.find_user_email_by_cn(user_cn) ] )
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
results.sort
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_email_to_list(list_email, user_email)
|
128
|
+
# 0. Assumes User already exists!
|
129
|
+
# 1. Check to see if user is already a member?
|
130
|
+
# 2. Add user_dn to list#member:
|
131
|
+
# 3. Add list_dn to user#memberOf:
|
132
|
+
|
133
|
+
list_dn = find_list_dn_by_email(list_email)
|
134
|
+
user_dn = find_user_dn_by_email(user_email)
|
135
|
+
|
136
|
+
if list_lists_member_emails(list_email).include?([user_dn, user_email])
|
137
|
+
raise AlreadyListMemberException, "User e-mail already a member: user_email"
|
138
|
+
else
|
139
|
+
@ldap.add_attribute list_dn, :member, user_dn
|
140
|
+
@ldap.add_attribute user_dn, :memberOf, list_dn
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def remove_email_from_list(list_email, user_email)
|
145
|
+
list_dn = find_list_dn_by_email(list_email)
|
146
|
+
user_dn = find_user_dn_by_email(user_email)
|
147
|
+
|
148
|
+
list_ops = [ [ :delete, :member, user_dn ] ]
|
149
|
+
user_ops = [ [ :delete, :memberof, list_dn ] ]
|
150
|
+
|
151
|
+
@ldap.modify :dn => list_dn, :operations => list_ops
|
152
|
+
@ldap.modify :dn => user_dn, :operations => user_ops
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class UserNameNotFoundException < StandardError; end
|
157
|
+
class UserEmailNotFoundException < StandardError; end
|
158
|
+
class ListEmailNotFoundException < StandardError; end
|
159
|
+
class AlreadyListMemberException < StandardError; end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
|
3
|
+
$: << 'lib'
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
require 'sbs2003_contacts'
|
7
|
+
|
8
|
+
##
|
9
|
+
# Student Name: John Howe
|
10
|
+
# Homework Week: 9a
|
11
|
+
#
|
12
|
+
# To make these tests pass, you will need a working SBS 2003 server and a login
|
13
|
+
# capable of making changes to Active Directory
|
14
|
+
#
|
15
|
+
# I have left examples as an exercise to the reader...
|
16
|
+
# You could speed up LDAP searches using the following base DN:
|
17
|
+
# OU=MyBusiness,DC=SBS_Domain,DC=local
|
18
|
+
#
|
19
|
+
# Note, net-ldap returns attributes lowered from AD, I ran into a gotcha with
|
20
|
+
# memberOf previously...
|
21
|
+
#
|
22
|
+
|
23
|
+
class TestSBS2003Contacts < Test::Unit::TestCase
|
24
|
+
def setup
|
25
|
+
@ldap = SBS2003Contacts.new("ldap-admin@sbsdomain.local", "secret", "dc=sbs_domain,dc=local","127.0.0.1",389)
|
26
|
+
# this is kind of a race condition for tests below that use the Test User
|
27
|
+
@ldap.update_user_email("Test User", "testuser@sbsdomain.tld")
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_set_filter
|
31
|
+
actual = @ldap.set_filter("cn", "Admin User")
|
32
|
+
assert_instance_of Net::LDAP::Filter, actual
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_find_user_dn_by_name
|
36
|
+
actual = @ldap.find_user_dn_by_name("Admin User")
|
37
|
+
expected = "CN=Admin User,OU=SBSUsers,OU=Users,OU=MyBusiness,DC=SBS_Domain,DC=local"
|
38
|
+
assert_equal expected, actual
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_find_user_dn_by_name_unknown
|
42
|
+
assert_raise UserNameNotFoundException do
|
43
|
+
@test = @ldap.find_user_dn_by_name("Bogus Dude")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_find_user_dn_by_email
|
48
|
+
actual = @ldap.find_user_dn_by_email("admin@sbsdomain.tld")
|
49
|
+
expected = "CN=Admin User,OU=SBSUsers,OU=Users,OU=MyBusiness,DC=SBS_Domain,DC=local"
|
50
|
+
assert_equal expected, actual
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_find_user_dn_by_email_unknown
|
54
|
+
assert_raise UserEmailNotFoundException do
|
55
|
+
@test = @ldap.find_user_dn_by_email("bdude@sbsdomain.tld")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_find_user_email_by_cn
|
60
|
+
actual = @ldap.find_user_email_by_cn("Company CEO")
|
61
|
+
expected = "ceo@sbsdomain.tld"
|
62
|
+
assert_equal expected, actual
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_update_user_email
|
66
|
+
actual = @ldap.update_user_email("Test User", "testusertest@sbsdomain.tld")
|
67
|
+
expected = true
|
68
|
+
assert_equal expected, actual
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_lists_user_lists
|
72
|
+
actual = @ldap.list_user_lists("Company CEO")
|
73
|
+
expected = [
|
74
|
+
"CN=Remote Web Workplace Users,OU=Security Groups,OU=MyBusiness,DC=SBS_Domain,DC=local",
|
75
|
+
"CN=Staff Group,OU=Security Groups,OU=MyBusiness,DC=SBS_Domain,DC=local",
|
76
|
+
"CN=Staff,OU=Distribution Groups,OU=MyBusiness,DC=SBS_Domain,DC=local"
|
77
|
+
]
|
78
|
+
assert_equal expected, actual
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_find_list_dn_by_email
|
82
|
+
actual = @ldap.find_list_dn_by_email("leadership@sbsdomain.tld")
|
83
|
+
expected = "CN=Leadership,OU=Distribution Groups,OU=MyBusiness,DC=SBS_Domain,DC=local"
|
84
|
+
assert_equal expected, actual
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_find_list_dn_by_email_not_found
|
88
|
+
assert_raise ListEmailNotFoundException do
|
89
|
+
@test = @ldap.find_list_dn_by_email("bogus-list@sbsdomain.tld")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_list_lists_member_emails
|
94
|
+
actual = @ldap.list_lists_member_emails("leadership@sbsdomain.tld")
|
95
|
+
expected = [
|
96
|
+
["CN=Company CEO,OU=SBSUsers,OU=Users,OU=MyBusiness,DC=SBS_Domain,DC=local","ceo@sbsdomain.tld"],
|
97
|
+
]
|
98
|
+
assert_equal expected, actual
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_add_email_to_list
|
102
|
+
@ldap.remove_email_from_list("testlist@sbsdomain.tld", "testuser@sbsdomain.tld")
|
103
|
+
@ldap.add_email_to_list("testlist@sbsdomain.tld", "testuser@sbsdomain.tld")
|
104
|
+
actual = @ldap.list_lists_member_emails("testlist@sbsdomain.tld")
|
105
|
+
expected = [
|
106
|
+
["CN=Test User,OU=SBSUsers,OU=Users,OU=MyBusiness,DC=SBS_Domain,DC=local","testuser@sbsdomain.tld"]
|
107
|
+
]
|
108
|
+
assert_equal expected, actual
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_add_email_to_list_dup
|
112
|
+
assert_raise AlreadyListMemberException do
|
113
|
+
@test = @ldap.add_email_to_list("testlist@sbsdomain.tld", "testuser@sbsdomain.tld")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_remove_email_from_list
|
118
|
+
@ldap.remove_email_from_list("testlist@sbsdomain.tld", "testuser@sbsdomain.tld")
|
119
|
+
actual = @ldap.list_lists_member_emails("testlist@sbsdomain.tld")
|
120
|
+
expected = []
|
121
|
+
assert_equal expected, actual
|
122
|
+
end
|
123
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sbs2003_contacts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Howe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-23 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ruby-net-ldap
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.4
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.2
|
34
|
+
version:
|
35
|
+
description: "* A small utiltity library to help alleviate the tedium of managing the contacts and e-mail lists from a Small Business Server 2003 Active Directory."
|
36
|
+
email:
|
37
|
+
- elf-rubyforge@arashi.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- History.txt
|
44
|
+
- Manifest.txt
|
45
|
+
- README.txt
|
46
|
+
files:
|
47
|
+
- History.txt
|
48
|
+
- Manifest.txt
|
49
|
+
- README.txt
|
50
|
+
- Rakefile
|
51
|
+
- lib/sbs2003_contacts.rb
|
52
|
+
- test/test_sbs2003_contacts.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://rubyforge.org/projects/uwruby/
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --main
|
58
|
+
- README.txt
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: uwruby
|
76
|
+
rubygems_version: 1.3.1
|
77
|
+
signing_key:
|
78
|
+
specification_version: 2
|
79
|
+
summary: "* A small utiltity library to help alleviate the tedium of managing the contacts and e-mail lists from a Small Business Server 2003 Active Directory."
|
80
|
+
test_files:
|
81
|
+
- test/test_sbs2003_contacts.rb
|