42 my $ME = basename $0; |
45 my $ME = basename $0; |
43 my $NAME = "LDAPREPL"; |
46 my $NAME = "LDAPREPL"; |
44 my $VERSION = "0.3.3"; |
47 my $VERSION = "0.3.3"; |
45 |
48 |
46 my $defaults = { |
49 my $defaults = { |
47 'init|i!' => 0, |
50 'attribute|a=s' => 'description', |
48 'delete|d!' => 0, |
51 'dn|d=s' => undef, |
49 'refresh|r!' => 1, |
|
50 'dn=s' => undef, |
|
51 'binddn|D=s' => undef, |
52 'binddn|D=s' => undef, |
52 'password=s' => undef, |
53 'password=s' => undef, |
53 'wait|w=i' => 1, |
|
54 'config=s' => '/etc/nagios/ius/plugins/config/check_ldap_repl.cfg', |
54 'config=s' => '/etc/nagios/ius/plugins/config/check_ldap_repl.cfg', |
55 'provider|p=s' => 'ldap://provider:389', |
55 'provider|p=s' => 'ldap://provider:389', |
56 'consumer|c=s@' => 'ldap://consumer:389', |
56 'consumer|c=s@' => 'ldap://consumer:389', |
|
57 'wait|w=i' => 1, |
57 'help|h!' => sub { pod2usage(-verbose => 1, -exitval => $ERRORS{OK}) }, |
58 'help|h!' => sub { pod2usage(-verbose => 1, -exitval => $ERRORS{OK}) }, |
58 'man|m!' => sub { pod2usage(-verbose => 2, -exitval => $ERRORS{OK}) }, |
59 'man|m!' => sub { pod2usage(-verbose => 2, -exitval => $ERRORS{OK}) }, |
59 'version|V!' => sub { version($ME, $VERSION); exit $ERRORS{OK}; } |
60 'version|V!' => sub { version($ME, $VERSION); exit $ERRORS{OK}; } |
60 }; |
61 }; |
61 |
62 |
62 my $attr = 'description'; |
|
63 |
|
64 sub critical { print STDERR "$NAME CRITICAL: ", @_; exit $ERRORS{CRITICAL}; } |
63 sub critical { print STDERR "$NAME CRITICAL: ", @_; exit $ERRORS{CRITICAL}; } |
65 $SIG{__DIE__} = sub { print STDERR "$NAME UNKNOWN: ", @_; exit $ERRORS{UNKNOWN}; }; |
64 $SIG{__DIE__} = sub { print STDERR "$NAME UNKNOWN: ", @_; exit $ERRORS{UNKNOWN}; }; |
66 |
65 |
67 sub stamp { |
66 sub stamp { |
68 my ($u, $dn) = @_; |
67 my ($u, $dn, $attr) = @_; |
69 |
68 |
70 my $l = ref $u eq 'Net::LDAP' ? $u : Net::LDAP->new($u, onerror => 'die') or die "$@"; |
69 my $l = ref $u eq 'Net::LDAP' ? $u : Net::LDAP->new($u, onerror => 'die') or die "$@"; |
71 my $r = $l->search(base => $dn, scope => 'base', filter => '(objectClass=*)'); |
70 my $r = $l->search(base => $dn, scope => 'base', filter => '(objectClass=*)'); |
72 die "unexpected result count: ", $r->count unless $r->count == 1; |
71 die "unexpected result count: ", $r->count unless $r->count == 1; |
73 my @v = $r->entry(0)->get_value($attr); |
72 my @v = $r->entry(0)->get_value($attr); |
109 my %o = $c->varlist('.'); |
108 my %o = $c->varlist('.'); |
110 my $t = time(); |
109 my $t = time(); |
111 |
110 |
112 my $p = Net::LDAP->new($o{provider}, onerror => 'die' ) or die $@; |
111 my $p = Net::LDAP->new($o{provider}, onerror => 'die' ) or die $@; |
113 $p->bind($o{binddn}, password => $o{password}); |
112 $p->bind($o{binddn}, password => $o{password}); |
114 $p->modify($o{dn}, replace => { $attr => $t }); |
113 $p->modify($o{dn}, replace => { $o{attribute} => $t }); |
115 |
114 |
116 my $tp = stamp($p, $o{dn}); |
115 my $tp = stamp($p, $o{dn}, $o{attribute}); |
117 if ($o{refresh}) { |
116 die "Provider update failed for unknown reason\n" unless $tp == $t; |
118 die "Provider update failed for unknown reason\n" unless $tp == $t; |
117 sleep $o{wait}; |
119 sleep $o{wait}; |
118 for (@{$o{consumer}}) { critical "'$_' out of sync\n" unless $tp == stamp($_, $o{dn}, $o{attribute}); } |
120 } |
|
121 for (@{$o{consumer}}) { critical "'$_' out of sync\n" unless $tp == stamp($_, $o{dn}); } |
|
122 |
119 |
123 print "$NAME OK: servers are in sync\n"; |
120 print "$NAME OK: servers are in sync\n"; |
124 exit $ERRORS{OK}; |
121 exit $ERRORS{OK}; |
125 |
122 |
126 } |
123 } |
127 |
124 |
128 __END__ |
125 __END__ |
129 |
126 |
|
127 =pod |
|
128 |
130 =head1 NAME |
129 =head1 NAME |
131 |
130 |
132 check_ldap_repl - nagios/icinga plugin to check correctly working of ldap replication. |
131 check_ldap_repl - nagios/icinga plugin to check ldap replication. This works by |
|
132 updating an entry on the provider and checking whether the update is replicated |
|
133 by querying the consumers for the updated entry after a short waiting period. |
133 |
134 |
134 =head1 SYNOPSIS |
135 =head1 SYNOPSIS |
135 |
136 |
136 check_ldap_repl [-c|--cn string] |
137 check_ldap_repl [-d|--dn string] |
137 [-b|--binddn string] |
138 [-D|--binddn string] |
138 [-p|--password string] |
139 [--password string] |
139 [-f|--file string] |
140 [--config string] |
140 [-M|--master string] |
141 [-p|--provider string] |
141 [-S|--slave string] |
142 [-c|--consumer string] |
142 [-w|--wait integer] |
143 [-w|--wait integer] |
143 [-h|--help] |
144 [-h|--help] |
144 [-m|--man] |
145 [-m|--man] |
145 [-V|--version] |
146 [-V|--version] |
146 |
147 |
147 =head1 OPTIONS |
148 =head1 OPTIONS |
148 |
149 |
149 =over |
150 =over |
150 |
151 |
151 =item B<-c>|B<--cn> I<string> |
152 =item B<-a>|B<--attribute> I<string> |
152 |
153 |
153 cn for the initialized object. See also the B<--init> option. (default: replcheck) |
154 Attribute of the entry that will be updated and checked for replication. (default: description) |
|
155 |
|
156 =item B<-d>|B<--dn> I<string> |
|
157 |
|
158 DN of the entry whose attribute will be updated and checked for replication. |
154 |
159 |
155 =item B<-b>|B<--binddn> I<string> |
160 =item B<-b>|B<--binddn> I<string> |
156 |
161 |
157 DN to bind to ldap master server. |
162 DN to use when binding to provider for update. |
158 |
163 |
159 =item B<-p>|B<--password> I<string> |
164 =item B<--password> I<string> |
160 |
165 |
161 Password for binddn to ldap master server. B<PASSWORD IS SHOWN IN PROCESSES, USE CONFIG FILE!> |
166 Password to use when binding to provider for update. B<PASSWORD IS SHOWN IN PROCESSES, USE CONFIG FILE!> |
162 |
167 |
163 =item B<-M>|B<--master> I<string> |
168 =item B<-p>|B<--provider> I<string> |
164 |
169 |
165 LDAP master server (provider) (default: ldap://ldap-master:389/) |
170 provider uri (default: ldap://provider:389/) |
166 |
171 |
167 =item B<-S>|B<--slave> I<string> |
172 =item B<-S>|B<--consumer> I<string> |
168 |
173 |
169 LDAP slave server (consumer), multiple slaves can be specified as a comma-separate list (default: ldap://ldap-slave:389/) |
174 consumer uri. Multiple consumers can be specified as a comma separated list (see below). (default: ldap://ldap-consumer:389/) |
170 |
175 |
171 =item B<-f>|B<--file> I<string> |
176 =item B<--config> I<string> |
172 |
177 |
173 Config file with B<binddn> and B<password>. Verify the file B<owner>/B<group> and B<permissions>, B<(0400)> is a good choice! |
178 Path to configuration file. Use this to store the binddn and its password. |
174 You can also set B<master,slave> and B<cn> options. (default: /etc/nagios/ius/plugins/config/check_ldap_repl.cfg) |
179 Verify the ownership and B<permissions>, B<(0400)> is a good choice! (default: |
175 |
180 /etc/nagios/ius/plugins/config/check_ldap_repl.cfg) |
176 [bind] |
181 |
177 dn = cn=admin,dc=local,dc=site |
182 |
|
183 Example: |
|
184 |
|
185 binddn = cn=admin,dc=local,dc=site |
178 password = secret |
186 password = secret |
179 |
187 provider = ldap://provider:389/ |
180 [master] |
188 consumer = ldap://consumer-01:389/,ldap://consumer-02:389/,... |
181 server = ldap://ldap-master:389/ |
189 dn = cn=replcheck |
182 |
190 wait = 2 |
183 [slave] |
|
184 server = ldap://ldap-slave01:389/,ldap://ldap-slave02:389/,... |
|
185 |
|
186 [object] |
|
187 cn = replcheck |
|
188 |
191 |
189 =item B<-w>|B<--wait> I<integer> |
192 =item B<-w>|B<--wait> I<integer> |
190 |
193 |
191 Wait I<n> seconds before check the slave servers. (default: 1) |
194 Wait I<n> seconds before checking the consumer servers. (default: 1) |
192 |
195 |
193 =item B<-h>|B<--help> |
196 =item B<-h>|B<--help> |
194 |
197 |
195 Print detailed help screen. |
198 Print detailed help screen. |
196 |
199 |