/[pdpsoft]/trunk/nl.nikhef.ndpf.tools/mkgroup-sshlpk/mkgroup-sshlpk
ViewVC logotype

Contents of /trunk/nl.nikhef.ndpf.tools/mkgroup-sshlpk/mkgroup-sshlpk

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3096 - (show annotations) (download)
Fri Sep 2 13:18:32 2016 UTC (5 years, 4 months ago) by davidg
File size: 7969 byte(s)
Add uidname and number as comments with -U

1 #! /usr/bin/perl -w
2 #
3 use strict;
4 use Getopt::Long qw(:config no_ignore_case bundling);
5 use Net::LDAP;
6 use Net::LDAP::Util qw(ldap_error_name
7 ldap_error_text); # for error handling
8
9 my $verb=0;
10 my $force=0;
11 my $exit_on_error=0;
12 my $uid=0;
13 my $commentuid=0;
14 my $display_help;
15 my $ldapurl="ldaps://ldap.nikhef.nl/";
16 my $defldapbase="dc=farmnet,dc=nikhef,dc=nl";
17 my $ldapbase;
18 my $outputfile;
19 my $commandprefix;
20 my $uidldapfilter;
21 my $groupldapfilter;
22 my $ldapfilter;
23 my $def_ldapfilter = '(objectclass=*)';
24 my $def_groupldapfilter = '(objectclass=*)';
25 my $def_uidldapfilter = '(objectclass=*)';
26
27 &GetOptions(
28 "verbose|v+" => \$verb,
29 "url|H=s" => \$ldapurl,
30 "base|b=s" => \$ldapbase,
31 "uid|u+" => \$uid,
32 "output|o=s" => \$outputfile,
33 "command|c=s" => \$commandprefix,
34 "filter=s" => \$ldapfilter,
35 "ufilter=s" => \$uidldapfilter,
36 "gfilter=s" => \$groupldapfilter,
37 "help|h" => \$display_help,
38 "exit-on-error" => \$exit_on_error,
39 "force|f" => \$force,
40 "uidc|U" => \$commentuid
41 );
42
43 defined $ldapbase or $ldapbase = $defldapbase;
44
45 if ( $display_help ) {
46 print <<EOF;
47
48 Generate a list of all unique sshPublicKeys for all members of the
49 directory groups or uids specified on the command line.
50
51 Usage: $0 [-h] [-c|--comand strin] [-H uri] [-b DITbase] [-o file]
52 [-f] [-v[v]] RDN [RDN ...]
53 -h Display this help text
54 --uid|-u Retrieve also sshPublicKeys for uids besides also groups
55 --filter=s Use an LDAP filter to limit results (applies recursively)
56 (default: $def_ldapfilter)
57 NOTE: explicitly listed entries must all match filter
58 -H uri Connect to LDAP server at <uri>
59 (default: $ldapurl)
60 -b base Search base DIT for groups
61 (default: $ldapbase)
62 -c prfx Prefix pre-pended to each line written. Any text in the
63 original sshPublicKey attribute before the tokens " ssh-.sa "
64 or " \\d+ \\d+ " is replaced.
65 In the prefix itself, \@UID\@, \@GID\@, \@UIDNUMBER\@ are replaced
66 -o file Writing list of sshPublicKeys to <file>
67 (only when at least one sshPublicKey is retrieved, unless
68 -f is also specified)
69 -f Force writing even if the list of keys is empty
70
71 RDN name of groups (or uids) to traverse for members (list)
72 NOTE: it will search through the whole directory for these
73 group names or uids (provided there are keys there)
74
75 Example:
76 $0 systemAdministrators nDPFPrivilegedUsers
77 $0 systemAdministrators nDPFPrivilegedUsers z66
78 $0 -c 'command="svnserve -t -r /project/srv/svn --tunnel-user=\@UID\@",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty' -o ~svn/.ssh/authorized_keys nDPFSubversionUsers
79
80 Dependencies:
81 perl-LDAP, and perl-IO-Socket-SSL & perl-Net-SSLeay for ldaps
82
83 EOF
84 exit (0);
85 };
86
87 defined $ARGV[0] or die "groupRDN is a required argument\n";
88
89 my $ldap = Net::LDAP->new( $ldapurl, timeout=>20 );
90 $ldap or die "Cannot contact remote server at $ldapurl: $!\n".
91 " LDAP status: ".$ldap->error."\n";
92
93 # start collecting ssh keys from all users in all groups requested
94 my @keys = ();
95 defined $ldapfilter or $ldapfilter = $def_ldapfilter;
96 defined $groupldapfilter or $groupldapfilter = $def_groupldapfilter;
97 defined $uidldapfilter or $uidldapfilter = $def_uidldapfilter;
98
99 my $lsfilter="";
100
101 foreach my $groupRDN ( @ARGV ) {
102
103 if ( $uid ) {
104 $lsfilter="(&
105 $ldapfilter
106 (| (&(cn=$groupRDN)(|(objectclass=groupOfUniqueNames)(objectclass=groupOfNames))$groupldapfilter)
107 (&(uid=$groupRDN)(objectclass=ldapPublicKey)$uidldapfilter)
108 )
109 )";
110 } else {
111 $lsfilter="(&
112 $ldapfilter
113 (&(cn=$groupRDN)(|(objectclass=groupOfUniqueNames)(objectclass=groupOfNames))$groupldapfilter)
114 )";
115 }
116
117 $verb>1 and print STDERR "Base: $ldapbase\n";
118 $verb>1 and print STDERR "Filter: $lsfilter\n";
119 my $groupresults=$ldap->search(
120 base=>$ldapbase,
121 scope=>"sub",
122 filter=>$lsfilter
123 );
124 # one must die here, since its an explicitly requested group in ARGV
125 $groupresults->code and die "Search failed: ".$groupresults->error."\n";
126 $groupresults->count() or die "No entries found matching $groupRDN, exiting\n";
127
128 # list of entries for all groups matching this groupRDN
129 my @grouplistentries=$groupresults->entries;
130
131 # groups need to be recursively matched, uids are leaf entries
132 # but groups may have some explicit sshPublicKey attributes
133 #
134 foreach my $groupentry ( @grouplistentries ) {
135 &walkDN($groupentry->dn());
136 }
137 }
138
139 # when writing to file, there must be at least one key to indicate
140 # sanity, unless -f has been specified and you don't care
141 # otherwise, an LDAP search error or typo may accidentally wipe
142 # a authorized_keys file
143
144 ( defined $outputfile ) and ($#keys < 0) and
145 die "Empty key list will not be written to $outputfile (use \"-f\" to force)\n";
146
147 # print each key only once
148 my %uniqueKeys;
149 foreach ( @keys ) { $uniqueKeys{$_}=2; }
150
151 if ( defined $outputfile ) {
152 open OF,">$outputfile" or die "Cannot open $outputfile for writing: $!\n";
153 print OF "# Generated by $0 on ".gmtime(time())." UTC\n";
154 print OF "# from ".($uid?"groups and uids":"groups")." @ARGV\n";
155 foreach ( keys %uniqueKeys ) { print OF "$_\n"; }
156 close OF;
157 } else {
158 # just write to stdout
159 foreach ( keys %uniqueKeys ) { print "$_\n"; }
160 }
161
162
163 ##############################################################################
164 # recursively resolve sshPublicKey attributes from entries
165 #
166 sub walkDN($$) {
167 my ($dn) = @_;
168
169 my $results=$ldap->search(
170 base=>$dn,
171 scope=>"base",
172 filter=>$ldapfilter
173 );
174 # one may continue here, since it's an implicit result match
175 if ( $results->code ) {
176 &do_warn("Search failed for $dn: ".$results->error.": no entry\n");
177 } else {
178 $results->count() or &do_warn("No entries found matching $dn - entry disappeared\n");
179 }
180
181 # list of entries for all groups matching this groupRDN
182 my @entries=$results->entries;
183
184 # groups need to be recursively matched, uids are leaf entries
185 # but groups may have some explicit sshPublicKey attributes
186 #
187 foreach my $entry ( @entries ) {
188
189 my @classes = $entry->get_value("objectclass");
190
191 if ( grep /ldapPublicKey/,@classes ) {
192 push @keys, &writeUidLines($entry);
193 }
194
195 if ( grep(/groupOfUniqueNames/,@classes) || grep(/groupOfNames/,@classes) ) {
196 foreach my $subdn ( $entry->get_value("uniqueMember") ) {
197 &walkDN($subdn);
198 }
199 foreach my $subdn ( $entry->get_value("Member") ) {
200 &walkDN($subdn);
201 }
202 }
203
204 }
205 return;
206 }
207
208
209 ##############################################################################
210 # fill an array with ssh keys for a (list of) uid DNs
211 #
212 sub writeUidLines($$) {
213 my ( $uidentry, $basename ) = @_;
214 my @lines;
215
216 return () if ( ! defined $uidentry->get_value("sshPublicKey") );
217
218 foreach my $keyAttrib ( $uidentry->get_value("sshPublicKey") ) {
219 defined $commandprefix and $commandprefix ne "" and do {
220 my ($val,$cmd) = ("",$commandprefix);
221 $val = $uidentry->get_value('uid');
222 $cmd=~s/\@UID\@/$val/g;
223 $val = $uidentry->get_value('cn');
224 $cmd=~s/\@CN\@/$val/g;
225 $val = $uidentry->get_value('uidNumber');
226 $cmd=~s/\@UIDNUMBER\@/$val/g;
227 $val = $uidentry->get_value('gidNumber');
228 $cmd=~s/\@GIDNUMBER\@/$val/g;
229 $keyAttrib=~s/^.* (ssh-\wsa\s+)/$1/;
230 $keyAttrib=~s/^.* (\d+\s+\d+\s+)/$1/;
231 $keyAttrib="$cmd $keyAttrib";
232 };
233 $commentuid and $keyAttrib=$keyAttrib." ## ".$uidentry->get_value('uid')." (".$uidentry->get_value('uidNumber').")";
234 push @lines,$keyAttrib;
235 };
236
237 return @lines;
238 }
239
240 # support routines
241 sub do_warn(@) {
242 die "@_" if ($exit_on_error);
243 printf STDERR "@_";
244 }
245

Properties

Name Value
svn:executable *

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28