cloud-mu 3.6.10 → 3.6.12

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.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/Berksfile +2 -3
  3. data/Berksfile.lock +11 -14
  4. data/bin/mu-aws-setup +16 -4
  5. data/bin/mu-configure +2 -1
  6. data/cloud-mu.gemspec +3 -3
  7. data/cookbooks/mu-firewall/Berksfile +1 -1
  8. data/cookbooks/mu-firewall/attributes/default.rb +2 -2
  9. data/cookbooks/mu-firewall/metadata.rb +3 -3
  10. data/cookbooks/mu-firewall/recipes/default.rb +11 -2
  11. data/cookbooks/mu-master/Berksfile +1 -1
  12. data/cookbooks/mu-master/attributes/default.rb +14 -1
  13. data/cookbooks/mu-master/files/default/389ds-perl/ASDialogs.pm +173 -0
  14. data/cookbooks/mu-master/files/default/389ds-perl/AdminMigration.pm +569 -0
  15. data/cookbooks/mu-master/files/default/389ds-perl/AdminServer.pm +952 -0
  16. data/cookbooks/mu-master/files/default/389ds-perl/AdminUtil.pm +983 -0
  17. data/cookbooks/mu-master/files/default/389ds-perl/ConfigDSDialogs.pm +449 -0
  18. data/cookbooks/mu-master/files/default/389ds-perl/DSCreate.pm +1551 -0
  19. data/cookbooks/mu-master/files/default/389ds-perl/DSDialogs.pm +233 -0
  20. data/cookbooks/mu-master/files/default/389ds-perl/DSMigration.pm +1175 -0
  21. data/cookbooks/mu-master/files/default/389ds-perl/DSUpdate.pm +534 -0
  22. data/cookbooks/mu-master/files/default/389ds-perl/DSUpdateDialogs.pm +152 -0
  23. data/cookbooks/mu-master/files/default/389ds-perl/DSUtil.pm +1710 -0
  24. data/cookbooks/mu-master/files/default/389ds-perl/Dialog.pm +249 -0
  25. data/cookbooks/mu-master/files/default/389ds-perl/DialogManager.pm +212 -0
  26. data/cookbooks/mu-master/files/default/389ds-perl/FileConn.pm +461 -0
  27. data/cookbooks/mu-master/files/default/389ds-perl/Inf.pm +268 -0
  28. data/cookbooks/mu-master/files/default/389ds-perl/Migration.pm +327 -0
  29. data/cookbooks/mu-master/files/default/389ds-perl/RegDSDialogs.pm +94 -0
  30. data/cookbooks/mu-master/files/default/389ds-perl/Resource.pm +137 -0
  31. data/cookbooks/mu-master/files/default/389ds-perl/Setup.pm +240 -0
  32. data/cookbooks/mu-master/files/default/389ds-perl/SetupDialogs.pm +243 -0
  33. data/cookbooks/mu-master/files/default/389ds-perl/SetupLog.pm +82 -0
  34. data/cookbooks/mu-master/files/default/setCertName.ldif +4 -0
  35. data/cookbooks/mu-master/libraries/mu.rb +2 -2
  36. data/cookbooks/mu-master/metadata.rb +1 -1
  37. data/cookbooks/mu-master/recipes/389ds.rb +71 -32
  38. data/cookbooks/mu-master/recipes/basepackages.rb +5 -0
  39. data/cookbooks/mu-master/recipes/default.rb +16 -5
  40. data/cookbooks/mu-master/recipes/init.rb +36 -3
  41. data/cookbooks/mu-master/recipes/ssl-certs.rb +6 -0
  42. data/cookbooks/mu-master/recipes/sssd.rb +85 -62
  43. data/cookbooks/mu-master/recipes/update_nagios_only.rb +7 -1
  44. data/cookbooks/mu-master/templates/default/389-directory-setup.inf.erb +11 -26
  45. data/cookbooks/mu-master/templates/default/sssd.conf.erb +18 -8
  46. data/cookbooks/mu-tools/files/default/Mu_CA.pem +33 -0
  47. data/cookbooks/mu-tools/metadata.rb +0 -1
  48. data/cookbooks/mu-tools/recipes/set_local_fw.rb +7 -1
  49. data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +5 -1
  50. data/cookbooks/nagios/CHANGELOG.md +679 -0
  51. data/cookbooks/nagios/LICENSE +201 -0
  52. data/cookbooks/nagios/README.md +340 -0
  53. data/cookbooks/nagios/attributes/config.rb +163 -0
  54. data/cookbooks/nagios/attributes/default.rb +204 -0
  55. data/cookbooks/nagios/libraries/base.rb +311 -0
  56. data/cookbooks/nagios/libraries/command.rb +68 -0
  57. data/cookbooks/nagios/libraries/contact.rb +229 -0
  58. data/cookbooks/nagios/libraries/contactgroup.rb +111 -0
  59. data/cookbooks/{firewall/recipes/disable_firewall.rb → nagios/libraries/custom_option.rb} +20 -7
  60. data/cookbooks/nagios/libraries/data_bag_helper.rb +23 -0
  61. data/cookbooks/nagios/libraries/default.rb +90 -0
  62. data/cookbooks/nagios/libraries/helpers.rb +229 -0
  63. data/cookbooks/nagios/libraries/host.rb +410 -0
  64. data/cookbooks/nagios/libraries/hostdependency.rb +178 -0
  65. data/cookbooks/nagios/libraries/hostescalation.rb +170 -0
  66. data/cookbooks/nagios/libraries/hostgroup.rb +117 -0
  67. data/cookbooks/nagios/libraries/nagios.rb +277 -0
  68. data/cookbooks/nagios/libraries/resource.rb +59 -0
  69. data/cookbooks/nagios/libraries/service.rb +449 -0
  70. data/cookbooks/nagios/libraries/servicedependency.rb +213 -0
  71. data/cookbooks/nagios/libraries/serviceescalation.rb +193 -0
  72. data/cookbooks/nagios/libraries/servicegroup.rb +142 -0
  73. data/cookbooks/nagios/libraries/timeperiod.rb +159 -0
  74. data/cookbooks/nagios/libraries/users_helper.rb +54 -0
  75. data/cookbooks/nagios/metadata.json +44 -0
  76. data/cookbooks/nagios/metadata.rb +22 -0
  77. data/cookbooks/nagios/recipes/_load_databag_config.rb +153 -0
  78. data/cookbooks/nagios/recipes/_load_default_config.rb +241 -0
  79. data/cookbooks/nagios/recipes/apache.rb +114 -0
  80. data/cookbooks/nagios/recipes/default.rb +41 -0
  81. data/cookbooks/nagios/recipes/nginx.rb +114 -0
  82. data/cookbooks/nagios/recipes/pagerduty.rb +95 -0
  83. data/cookbooks/nagios/recipes/server.rb +182 -0
  84. data/cookbooks/nagios/recipes/server_package.rb +85 -0
  85. data/cookbooks/nagios/recipes/server_source.rb +137 -0
  86. data/cookbooks/nagios/resources/command.rb +34 -0
  87. data/cookbooks/nagios/resources/conf.rb +52 -0
  88. data/cookbooks/nagios/resources/contact.rb +34 -0
  89. data/cookbooks/nagios/resources/contactgroup.rb +35 -0
  90. data/cookbooks/nagios/resources/host.rb +35 -0
  91. data/cookbooks/nagios/resources/hostdependency.rb +35 -0
  92. data/cookbooks/nagios/resources/hostescalation.rb +36 -0
  93. data/cookbooks/nagios/resources/hostgroup.rb +35 -0
  94. data/cookbooks/nagios/resources/resource.rb +34 -0
  95. data/cookbooks/nagios/resources/service.rb +35 -0
  96. data/cookbooks/nagios/resources/servicedependency.rb +35 -0
  97. data/cookbooks/nagios/resources/serviceescalation.rb +35 -0
  98. data/cookbooks/nagios/resources/servicegroup.rb +35 -0
  99. data/cookbooks/nagios/resources/timeperiod.rb +35 -0
  100. data/cookbooks/nagios/templates/apache2.conf.erb +102 -0
  101. data/cookbooks/nagios/templates/cgi.cfg.erb +266 -0
  102. data/cookbooks/nagios/templates/commands.cfg.erb +13 -0
  103. data/cookbooks/nagios/templates/contacts.cfg.erb +37 -0
  104. data/cookbooks/nagios/templates/hostgroups.cfg.erb +25 -0
  105. data/cookbooks/nagios/templates/hosts.cfg.erb +15 -0
  106. data/cookbooks/nagios/templates/htpasswd.users.erb +6 -0
  107. data/cookbooks/nagios/templates/nagios.cfg.erb +22 -0
  108. data/cookbooks/nagios/templates/nginx.conf.erb +80 -0
  109. data/cookbooks/nagios/templates/pagerduty.cgi.erb +185 -0
  110. data/cookbooks/nagios/templates/resource.cfg.erb +27 -0
  111. data/cookbooks/nagios/templates/servicedependencies.cfg.erb +15 -0
  112. data/cookbooks/nagios/templates/servicegroups.cfg.erb +14 -0
  113. data/cookbooks/nagios/templates/services.cfg.erb +14 -0
  114. data/cookbooks/nagios/templates/spawn-fcgi.erb +10 -0
  115. data/cookbooks/nagios/templates/templates.cfg.erb +31 -0
  116. data/cookbooks/nagios/templates/timeperiods.cfg.erb +13 -0
  117. data/extras/platform_berksfile_base +3 -3
  118. data/extras/python_rpm/build.sh +4 -4
  119. data/extras/python_rpm/muthon.spec +2 -4
  120. data/extras/vault_tools/export_vaults.sh +11 -1
  121. data/install/installer +1 -1
  122. data/modules/mu/kittens.rb +27523 -0
  123. data/modules/mu/master/ldap.rb +48 -31
  124. data/modules/mu/master.rb +69 -0
  125. data/modules/mu/mu.yaml.rb +351 -0
  126. data/modules/mu/providers/aws/firewall_rule.rb +3 -1
  127. data/modules/mu/providers/aws.rb +11 -5
  128. data/modules/mu.rb +5 -4
  129. metadata +99 -68
  130. data/cookbooks/firewall/CHANGELOG.md +0 -488
  131. data/cookbooks/firewall/LICENSE +0 -202
  132. data/cookbooks/firewall/README.md +0 -366
  133. data/cookbooks/firewall/TODO.md +0 -6
  134. data/cookbooks/firewall/attributes/default.rb +0 -5
  135. data/cookbooks/firewall/attributes/firewalld.rb +0 -8
  136. data/cookbooks/firewall/attributes/iptables.rb +0 -17
  137. data/cookbooks/firewall/attributes/ufw.rb +0 -12
  138. data/cookbooks/firewall/attributes/windows.rb +0 -8
  139. data/cookbooks/firewall/libraries/helpers.rb +0 -105
  140. data/cookbooks/firewall/libraries/helpers_firewalld.rb +0 -116
  141. data/cookbooks/firewall/libraries/helpers_firewalld_dbus.rb +0 -72
  142. data/cookbooks/firewall/libraries/helpers_iptables.rb +0 -112
  143. data/cookbooks/firewall/libraries/helpers_nftables.rb +0 -170
  144. data/cookbooks/firewall/libraries/helpers_ufw.rb +0 -142
  145. data/cookbooks/firewall/libraries/helpers_windows.rb +0 -129
  146. data/cookbooks/firewall/libraries/provider_firewall_firewalld.rb +0 -179
  147. data/cookbooks/firewall/libraries/provider_firewall_iptables.rb +0 -171
  148. data/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb +0 -200
  149. data/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu1404.rb +0 -200
  150. data/cookbooks/firewall/libraries/provider_firewall_rule.rb +0 -34
  151. data/cookbooks/firewall/libraries/provider_firewall_ufw.rb +0 -138
  152. data/cookbooks/firewall/libraries/provider_firewall_windows.rb +0 -126
  153. data/cookbooks/firewall/libraries/resource_firewall.rb +0 -26
  154. data/cookbooks/firewall/libraries/resource_firewall_rule.rb +0 -52
  155. data/cookbooks/firewall/metadata.json +0 -40
  156. data/cookbooks/firewall/metadata.rb +0 -15
  157. data/cookbooks/firewall/recipes/default.rb +0 -76
  158. data/cookbooks/firewall/recipes/firewalld.rb +0 -87
  159. data/cookbooks/firewall/resources/firewalld.rb +0 -28
  160. data/cookbooks/firewall/resources/firewalld_config.rb +0 -39
  161. data/cookbooks/firewall/resources/firewalld_helpers.rb +0 -106
  162. data/cookbooks/firewall/resources/firewalld_icmptype.rb +0 -88
  163. data/cookbooks/firewall/resources/firewalld_ipset.rb +0 -104
  164. data/cookbooks/firewall/resources/firewalld_policy.rb +0 -115
  165. data/cookbooks/firewall/resources/firewalld_service.rb +0 -98
  166. data/cookbooks/firewall/resources/firewalld_zone.rb +0 -118
  167. data/cookbooks/firewall/resources/nftables.rb +0 -71
  168. data/cookbooks/firewall/resources/nftables_rule.rb +0 -113
  169. data/cookbooks/firewall/templates/default/ufw/default.erb +0 -13
  170. /data/cookbooks/{firewall → nagios}/chefignore +0 -0
  171. /data/cookbooks/{firewall → nagios}/renovate.json +0 -0
@@ -0,0 +1,461 @@
1
+ # BEGIN COPYRIGHT BLOCK
2
+ # Copyright (C) 2007 Red Hat, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # License: GPL (version 3 or any later version).
6
+ # See LICENSE for details.
7
+ # END COPYRIGHT BLOCK
8
+ #
9
+ # FileConn is a subclass of Mozilla::LDAP::Conn. This class does
10
+ # not use LDAP. Instead, it operates on a given LDAP file, allowing
11
+ # you to search, add, modify, and delete entries in the file.
12
+ #
13
+ package FileConn;
14
+
15
+ use Mozilla::LDAP::Conn;
16
+ use Mozilla::LDAP::API qw(:constant ldap_explode_dn ldap_err2string); # Direct access to C API
17
+ use Mozilla::LDAP::Utils qw(normalizeDN);
18
+ use Mozilla::LDAP::LDIF;
19
+
20
+ use DSUtil qw(debug);
21
+
22
+ require Exporter;
23
+ @ISA = qw(Exporter Mozilla::LDAP::Conn);
24
+ @EXPORT = qw();
25
+ @EXPORT_OK = qw();
26
+
27
+ sub new {
28
+ my $class = shift;
29
+ my $filename = shift;
30
+ my $readonly = shift;
31
+ my @namingContexts = @_;
32
+ my $self = {};
33
+
34
+ $self = bless $self, $class;
35
+
36
+ $self->{readonly} = $readonly;
37
+ for my $ctx (@namingContexts) {
38
+ $self->setNamingContext($ctx);
39
+ }
40
+ $self->setNamingContext(""); # root DSE
41
+ if (!$self->read($filename)) {
42
+ return;
43
+ }
44
+
45
+ return $self;
46
+ }
47
+
48
+ sub getParentDN {
49
+ my $dn = shift;
50
+ my @rdns = ldap_explode_dn($dn, 0);
51
+ shift @rdns;
52
+ return join(',', @rdns);
53
+ }
54
+
55
+ sub read {
56
+ my $self = shift;
57
+ my $filename = shift;
58
+
59
+ if ($filename) {
60
+ $self->{filename} = $filename;
61
+ } else {
62
+ $filename = $self->{filename};
63
+ }
64
+
65
+ if (!$self->{filename}) {
66
+ return 1; # no filename given - ok
67
+ }
68
+
69
+ if (!open( MYLDIF, "$filename" )) {
70
+ debug(1, "Could not open $filename: $!\n");
71
+ return 0;
72
+ }
73
+
74
+ my $in = new Mozilla::LDAP::LDIF(*MYLDIF);
75
+ $self->{reading} = 1;
76
+ while ($ent = readOneEntry $in) {
77
+ if (!$self->add($ent)) {
78
+ debug(1, "Error: could not add entry " . $ent->getDN() . ":" . $self->getErrorString());
79
+ }
80
+ }
81
+ delete $self->{reading};
82
+ close( MYLDIF );
83
+
84
+ return 1;
85
+ }
86
+
87
+ sub setNamingContext {
88
+ my $self = shift;
89
+ my $nc = shift;
90
+ my $ndn = normalizeDN($nc);
91
+ $self->{namingContexts}->{$ndn} = $ndn;
92
+ }
93
+
94
+ sub isNamingContext {
95
+ my $self = shift;
96
+ my $ndn = shift;
97
+ return exists($self->{namingContexts}->{$ndn});
98
+ }
99
+
100
+ # return all nodes below the given node
101
+ sub iterate {
102
+ my $self = shift;
103
+ my $dn = shift;
104
+ my $scope = shift;
105
+ my $callback = shift;
106
+ my $context = shift;
107
+ my $suppress = shift;
108
+ my $ndn = normalizeDN($dn);
109
+ my $children;
110
+ if (exists($self->{$ndn}) and exists($self->{$ndn}->{children})) {
111
+ $children = $self->{$ndn}->{children};
112
+ }
113
+ if (($scope != LDAP_SCOPE_ONELEVEL) && exists($self->{$ndn}) &&
114
+ exists($self->{$ndn}->{data}) && $self->{$ndn}->{data} && !$suppress) {
115
+ &{$callback}($self->{$ndn}->{data}, $context);
116
+ }
117
+
118
+ if ($scope == LDAP_SCOPE_BASE) {
119
+ return;
120
+ }
121
+
122
+ for my $node (@{$children}) {
123
+ &{$callback}($node->{data}, $context);
124
+ }
125
+ if ($scope == LDAP_SCOPE_SUBTREE) {
126
+ for my $node (@{$children}) {
127
+ $self->iterate($node->{data}->getDN(), $scope, $callback, $context, 1);
128
+ }
129
+ }
130
+ }
131
+
132
+ sub writecb {
133
+ my $entry = shift;
134
+ my $fh = shift;
135
+ if (! $entry->getDN()) { # rootDSE requires special hack around perldap bug
136
+ my $ary = $entry->getLDIFrecords();
137
+ shift @$ary; # remove "dn"
138
+ shift @$ary; # remove the empty dn value
139
+ print $fh "dn:\n";
140
+ print $fh (Mozilla::LDAP::LDIF::pack_LDIF (78, $ary), "\n");
141
+ } else {
142
+ Mozilla::LDAP::LDIF::put_LDIF($fh, 78, $entry);
143
+ }
144
+ }
145
+
146
+ sub write {
147
+ my $self = shift;
148
+ my $filename = shift;
149
+
150
+ if ($filename) {
151
+ $self->{filename} = $filename;
152
+ } else {
153
+ $filename = $self->{filename};
154
+ }
155
+
156
+ if (!$self->{filename} or $self->{readonly} or $self->{reading}) {
157
+ return 1; # ok - no filename given - just ignore
158
+ }
159
+
160
+ if (!open( MYLDIF, ">$filename" )) {
161
+ debug(1, "Can't write $filename: $!\n");
162
+ return 0;
163
+ }
164
+
165
+ $self->iterate("", LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF);
166
+ for my $ctx (keys %{$self->{namingContexts}}) {
167
+ next if (!$ctx); # skip "" - we already did that
168
+ $self->iterate($ctx, LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF);
169
+ }
170
+ close( MYLDIF );
171
+
172
+ return 1;
173
+ }
174
+
175
+ sub setErrorCode {
176
+ my $self = shift;
177
+ $self->{lastErrorCode} = shift;
178
+ }
179
+
180
+ sub getErrorCode {
181
+ my $self = shift;
182
+ return $self->{lastErrorCode};
183
+ }
184
+
185
+ sub getErrorString {
186
+ my $self = shift;
187
+ return ldap_err2string($self->{lastErrorCode});
188
+ }
189
+
190
+ #############################################################################
191
+ # Print the last error code...
192
+ #
193
+ sub printError
194
+ {
195
+ my ($self, $str) = @_;
196
+
197
+ $str = "LDAP error:" unless defined($str);
198
+ print "$str ", $self->getErrorString(), "\n";
199
+ }
200
+
201
+ sub DESTROY {
202
+ my $self = shift;
203
+ $self->close();
204
+ }
205
+
206
+ sub close {
207
+ my $self = shift;
208
+ return if ($self->{readonly});
209
+ $self->write();
210
+ }
211
+
212
+ sub printcb {
213
+ my $entry = shift;
214
+
215
+ print $entry->getDN(), "\n";
216
+ }
217
+
218
+ sub print {
219
+ my $self = shift;
220
+ my $dn = shift;
221
+ my $scope = shift;
222
+ $self->iterate($dn, $scope, \&printcb);
223
+ }
224
+
225
+ # for each entry, call the user provided filter callback
226
+ # with the entry and the user provided filter context
227
+ # if the filtercb returns true, add the entry to the
228
+ # list of entries to return
229
+ sub searchcb {
230
+ my $entry = shift;
231
+ my $context = shift;
232
+ my $self = $context->[0];
233
+ my $filtercb = $context->[1];
234
+ my $filtercontext = $context->[2];
235
+ if (&{$filtercb}($entry, $filtercontext)) {
236
+ push @{$self->{entries}}, $entry;
237
+ }
238
+ }
239
+
240
+ sub matchall {
241
+ return 1;
242
+ }
243
+
244
+ sub matchAttrVal {
245
+ my $entry = shift;
246
+ my $context = shift;
247
+ my $attr = $context->[0];
248
+ my $val = $context->[1];
249
+
250
+ if ($val eq "*") {
251
+ return $entry->exists($attr);
252
+ }
253
+ return $entry->hasValue($attr, $val, 1);
254
+ }
255
+
256
+ my $attrpat = '[-;.:\w]*[-;\w]';
257
+
258
+ # given a string filter, figure out which subroutine to
259
+ # use to match
260
+ sub filterToMatchSub {
261
+ my $self = shift;
262
+ my ($basedn, $scope, $filter, $attrsonly, @rest) = @_;
263
+ my ($matchsub, $context);
264
+ # do some filter processing
265
+ if (!$filter or ($filter eq "(objectclass=*)") or
266
+ ($filter eq "objectclass=*")) {
267
+ $matchsub = \&matchall;
268
+ } elsif ($filter =~ /^\(($attrpat)=(.+)\)$/o) {
269
+ push @{$context}, $1, $2;
270
+ $matchsub = \&matchAttrVal;
271
+ # } elsif ($filter =~ /^\(\|\(($attrpat)=(.+)\)\(($attrpat)=(.+)\)\)$/o) {
272
+ # $attr = $1;
273
+ # $val = $2;
274
+ # $attr1 = $1;
275
+ # $val1 = $2;
276
+ # $isand = 0;
277
+ # } elsif ($filter =~ /^\(\&\(($attrpat)=(.+)\)\(($attrpat)=(.+)\)\)$/o) {
278
+ # $attr = $1;
279
+ # $val = $2;
280
+ # $attr1 = $1;
281
+ # $val1 = $2;
282
+ # $isand = 1;
283
+ # } elsif ($filter =~ /^\(\|\(($attrpat)=(.+)\)\(($attrpat)=(.+)\)\)$/o) {) {
284
+ # # "(&(objectclass=nsBackendInstance)(|(nsslapd-suffix=$suffix)(nsslapd-suffix=$nsuffix)))");
285
+ }
286
+
287
+ $self->iterate($basedn, $scope, \&searchcb, [$self, $matchsub, $context]);
288
+ }
289
+
290
+ # simple searches only
291
+ sub search {
292
+ my $self = shift;
293
+ my ($basedn, $scope, $filter, $attrsonly, @rest) = @_;
294
+ my $attrs;
295
+ if (ref($rest[0]) eq "ARRAY") {
296
+ $attrs = $rest[0];
297
+ } elsif (scalar(@rest) > 0) {
298
+ $attrs = \@rest;
299
+ }
300
+
301
+ $scope = Mozilla::LDAP::Utils::str2Scope($scope);
302
+
303
+ $self->{entries} = [];
304
+
305
+ my $ndn = normalizeDN($basedn);
306
+ if (!exists($self->{$ndn}) or !exists($self->{$ndn}->{data})) {
307
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
308
+ return undef;
309
+ }
310
+
311
+ $self->setErrorCode(0);
312
+ if (ref($filter) eq 'CODE') {
313
+ $self->iterate($basedn, $scope, \&searchcb, [$self, $filter, $attrsonly]);
314
+ } else {
315
+ $self->filterToMatchSub($basedn, $scope, $filter, $attrsonly);
316
+ }
317
+
318
+ return $self->nextEntry();
319
+ }
320
+
321
+ sub cloneEntry {
322
+ my $src = shift;
323
+ if (!$src) {
324
+ return undef;
325
+ }
326
+ my $dest = new Mozilla::LDAP::Entry();
327
+ $dest->setDN($src->getDN());
328
+ for my $key (keys %{$src}) {
329
+ if (ref($src->{$key})) {
330
+ my @copyary = @{$src->{$key}};
331
+ $dest->{$key} = [ @copyary ]; # make a deep copy
332
+ } else {
333
+ $dest->{$key} = $src->{$key};
334
+ }
335
+ }
336
+
337
+ return $dest;
338
+ }
339
+
340
+ # have to return a copy of the entry - disallow inplace updates
341
+ sub nextEntry {
342
+ my $self = shift;
343
+ my $ent = shift @{$self->{entries}};
344
+ return cloneEntry($ent);
345
+ }
346
+
347
+ sub add {
348
+ my $self = shift;
349
+ my $entry = shift;
350
+ my $dn = $entry->getDN();
351
+ my $ndn = normalizeDN($dn);
352
+ my $parentdn = getParentDN($dn);
353
+ my $nparentdn = normalizeDN($parentdn);
354
+
355
+ $self->setErrorCode(0);
356
+ # special case of naming context - has no parent
357
+ if ($self->isNamingContext($ndn) and
358
+ !exists($self->{$ndn}->{data})) {
359
+ $self->{$ndn}->{data} = $entry;
360
+ return $self->write();
361
+ }
362
+
363
+ if ($ndn && exists($self->{$ndn})) {
364
+ $self->setErrorCode(LDAP_ALREADY_EXISTS);
365
+ return 0;
366
+ }
367
+
368
+ if ($ndn && $nparentdn && !exists($self->{$nparentdn})) {
369
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
370
+ return 0;
371
+ }
372
+ # each hash entry has two keys
373
+ # data is the actual Entry
374
+ # children is the array ref of the one level children of this dn
375
+ $self->{$ndn}->{data} = $entry;
376
+ # don't add parent to list of children
377
+ if ($nparentdn ne $ndn) {
378
+ push @{$self->{$nparentdn}->{children}}, $self->{$ndn};
379
+ }
380
+
381
+ return 1;
382
+ }
383
+
384
+ sub update {
385
+ my $self = shift;
386
+ my $entry = shift;
387
+ my $dn = $entry->getDN();
388
+ my $ndn = normalizeDN($dn);
389
+
390
+ if ($self->{readonly}) {
391
+ debug(1, "Attempt to update read only $self->{filename} entry $dn\n");
392
+ return 0;
393
+ }
394
+
395
+ $self->setErrorCode(0);
396
+ if (!exists($self->{$ndn})) {
397
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
398
+ debug(1, "Attempt to update entry $dn that does not exist\n");
399
+ return 0;
400
+ }
401
+
402
+ # The cloned entry will not contain the deleted attrs - the cloning
403
+ # process omits the deleted attrs via the Entry FETCH, FIRSTKEY, and NEXTKEY
404
+ # methods
405
+ $self->{$ndn}->{data} = cloneEntry($entry);
406
+ return $self->write();
407
+ }
408
+
409
+ sub delete {
410
+ my $self = shift;
411
+ my $dn = shift;
412
+
413
+ if ($self->{readonly}) {
414
+ debug(1, "Attempt to delete read only $self->{filename} entry $dn\n");
415
+ return 0;
416
+ }
417
+
418
+ if (ref($dn)) {
419
+ $dn = $dn->getDN(); # an Entry
420
+ }
421
+ my $ndn = normalizeDN($dn);
422
+
423
+ $self->setErrorCode(0);
424
+ if (!exists($self->{$ndn})) {
425
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
426
+ debug(1, "Attempt to delete entry $dn that does not exist\n");
427
+ return 0;
428
+ }
429
+
430
+ if (@{$self->{$ndn}->{children}}) {
431
+ $self->setErrorCode(LDAP_NOT_ALLOWED_ON_NONLEAF);
432
+ debug(1, "Attempt to delete entry $dn that has children\n");
433
+ return 0;
434
+ }
435
+
436
+ # delete the data associated with this node
437
+ delete $self->{$ndn}->{data};
438
+ delete $self->{$ndn}->{children};
439
+
440
+ my $parentdn = getParentDN($dn);
441
+ my $nparentdn = normalizeDN($parentdn);
442
+ # delete this node from its parent
443
+ if ($ndn ne $nparentdn) {
444
+ for (my $ii = 0; $ii < @{$self->{$nparentdn}->{children}}; ++$ii) {
445
+ # find matching hash ref in parent's child list
446
+ if ($self->{$nparentdn}->{children}->[$ii] eq $self->{$ndn}) {
447
+ # remove that element from the array
448
+ splice @{$self->{$nparentdn}->{children}}, $ii, 1;
449
+ # done - should only ever be one matching child
450
+ last;
451
+ }
452
+ }
453
+ }
454
+
455
+ # delete this node
456
+ delete $self->{$ndn};
457
+
458
+ return $self->write();
459
+ }
460
+
461
+ 1;
@@ -0,0 +1,268 @@
1
+ # BEGIN COPYRIGHT BLOCK
2
+ # Copyright (C) 2007 Red Hat, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # License: GPL (version 3 or any later version).
6
+ # See LICENSE for details.
7
+ # END COPYRIGHT BLOCK
8
+ #
9
+
10
+ # manages inf files - gets values
11
+ # given keys
12
+
13
+ package Inf;
14
+
15
+ use DSUtil;
16
+ use File::Temp qw(tempfile tempdir);
17
+
18
+ #require Exporter;
19
+ #@ISA = qw(Exporter);
20
+ #@EXPORT = qw();
21
+
22
+ sub new {
23
+ my $type = shift;
24
+ my $self = {};
25
+
26
+ $self->{filename} = shift;
27
+ $self->{writable} = shift; # do not overwrite user supplied file
28
+ # if you want to init an Inf with a writable file, use
29
+ # $inf = new Inf($filename, 1)
30
+
31
+ $self = bless $self, $type;
32
+
33
+ if ($self->{filename}) {
34
+ if($self->read() != 0){
35
+ undef $self;
36
+ }
37
+ }
38
+
39
+ return $self;
40
+ }
41
+
42
+ sub read {
43
+ # each key in the table is a section name
44
+ # the value is a hash ref of the items in that section
45
+ # in that hash ref, each key is the config param name,
46
+ # and the value is the config param value
47
+ my $self = shift;
48
+ my $filename = shift;
49
+ my $curSection = "";
50
+
51
+ if ($filename) {
52
+ $self->{filename} = $filename;
53
+ } else {
54
+ $filename = $self->{filename};
55
+ }
56
+
57
+ my $incontinuation = 0;
58
+ my $curkey;
59
+ my $curval;
60
+ my $inffh;
61
+ if ($filename eq "-") {
62
+ $inffh = \*STDIN;
63
+ } else {
64
+ if (!open(INF, $filename)) {
65
+ debug(0, "Error: could not open inf file $filename: $!\n");
66
+ return -1;
67
+ }
68
+ $inffh = \*INF;
69
+ }
70
+ my $line;
71
+ while ($line = <$inffh>) {
72
+ my $iscontinuation;
73
+ chop $line; # trim trailing newline
74
+ if ($line =~ /^\s*$/) { # skip blank/empty lines
75
+ $incontinuation = 0;
76
+ next;
77
+ }
78
+ if ($line =~ /^\s*\#/) { # skip comment lines
79
+ $incontinuation = 0;
80
+ next;
81
+ }
82
+ if ($line =~ /\\$/) { # line ends in \ - continued on next line
83
+ chop $line;
84
+ $iscontinuation = 1;
85
+ }
86
+ if ($incontinuation) {
87
+ if ($curval) {
88
+ $self->{$curSection}->{$curkey}->[$curval] .= "\n" . $line; # add line in entirety to current value
89
+ } else {
90
+ $self->{$curSection}->{$curkey} .= "\n" . $line; # add line in entirety to current value
91
+ }
92
+ } elsif ($line =~ /^\[(.*?)\]/) { # e.g. [General]
93
+ $curSection = $1;
94
+ $iscontinuation = 0; # disallow section continuations
95
+ } elsif ($line =~ /^\s*(.*?)\s*=\s*(.*?)\s*$/) { # key = value
96
+ $curkey = $1;
97
+ # a single value is just a single scalar
98
+ # multiple values are represented by an array ref
99
+ if (exists($self->{$curSection}->{$curkey})) {
100
+ if (!ref($self->{$curSection}->{$curkey})) {
101
+ # convert single scalar to array ref
102
+ my $ary = [$self->{$curSection}->{$curkey}];
103
+ $self->{$curSection}->{$curkey} = $ary;
104
+ }
105
+ # just push the new value
106
+ push @{$self->{$curSection}->{$curkey}}, $2;
107
+ $curval = @{$self->{$curSection}->{$curkey}} - 1; # curval is index of last item
108
+ } else {
109
+ # single value
110
+ $self->{$curSection}->{$curkey} = $2;
111
+ $curval = 0; # only 1 value
112
+ }
113
+ }
114
+ if ($iscontinuation) { # if line ends with a backslash, continue the data on the next line
115
+ $incontinuation = 1;
116
+ } else {
117
+ $incontinuation = 0;
118
+ }
119
+ }
120
+ if ($inffh ne \*STDIN) {
121
+ close $inffh;
122
+ }
123
+
124
+ return 0;
125
+ }
126
+
127
+ sub section {
128
+ my $self = shift;
129
+ my $key = shift;
130
+
131
+ if (!exists($self->{$key})) {
132
+ debug(0, "Error: unknown inf section $key\n");
133
+ return undef;
134
+ }
135
+
136
+ return $self->{$key};
137
+ }
138
+
139
+ sub writeSection {
140
+ my $self = shift;
141
+ my $name = shift;
142
+ my $fh = shift;
143
+ my $section = $self->{$name};
144
+ if (ref($section) eq 'HASH') {
145
+ print $fh "[$name]\n";
146
+ for my $key (sort keys %{$section}) {
147
+ if (exists($section->{$key}) and defined($section->{$key}) and
148
+ (length($section->{$key}) > 0)) {
149
+ my @vals = ();
150
+ if (ref($section->{$key})) {
151
+ @vals = @{$section->{$key}};
152
+ } else {
153
+ @vals = ($section->{$key});
154
+ }
155
+ for my $val (@vals) {
156
+ $val =~ s/\n/\\\n/g; # make continuation lines
157
+ print $fh "$key = $val\n";
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ sub write {
165
+ my $self = shift;
166
+ my $filename = shift;
167
+ my $fh;
168
+
169
+ return if ($filename and $filename eq "-");
170
+
171
+ # see if user wants to force use of a temp file
172
+ if ($filename and $filename eq '__temp__') {
173
+ $self->{writable} = 1;
174
+ $filename = '';
175
+ delete $self->{filename};
176
+ }
177
+
178
+ if (!$self->{writable}) {
179
+ return; # do not overwrite read only file
180
+ }
181
+
182
+ if ($filename) { # use user supplied filename
183
+ $self->{filename} = $filename;
184
+ } elsif ($self->{filename}) { # use existing filename
185
+ $filename = $self->{filename};
186
+ } else { # create temp filename
187
+ ($fh, $self->{filename}) = tempfile("setupXXXXXX", UNLINK => 0,
188
+ SUFFIX => ".inf", OPEN => 1,
189
+ DIR => File::Spec->tmpdir);
190
+ }
191
+
192
+ my $savemask = umask(0077);
193
+ if (!$fh) {
194
+ if (!open(INF, ">$filename")) {
195
+ debug(0, "Error: could not write inf file $filename: $!\n");
196
+ umask($savemask);
197
+ return;
198
+ }
199
+ $fh = *INF;
200
+ }
201
+ # write General section first
202
+ $self->writeSection('General', $fh);
203
+ for my $key (keys %{$self}) {
204
+ next if ($key eq 'General');
205
+ $self->writeSection($key, $fh);
206
+ }
207
+ close $fh;
208
+ umask($savemask);
209
+ }
210
+
211
+ sub updateFromArgs {
212
+ my $self = shift;
213
+ my $argsinf = {}; # tmp for args read in
214
+
215
+ if (!@_) {
216
+ return 1; # no args - just return
217
+ }
218
+
219
+ # read args into temp inf
220
+ for my $arg (@_) {
221
+ if ($arg =~ /^([\w_-]+)\.([\w_-]+)=(.*)$/) { # e.g. section.param=value
222
+ my $sec = $1;
223
+ my $parm = $2;
224
+ my $val = $3;
225
+ # a single value is just a single scalar
226
+ # multiple values are represented by an array ref
227
+ if (exists($argsinf->{$sec}->{$parm})) {
228
+ if (!ref($argsinf->{$sec}->{$parm})) {
229
+ # convert single scalar to array ref
230
+ my $ary = [$argsinf->{$sec}->{$parm}];
231
+ $argsinf->{$sec}->{$parm} = $ary;
232
+ }
233
+ # just push the new value
234
+ push @{$argsinf->{$sec}->{$parm}}, $val;
235
+ } else {
236
+ # single value
237
+ $argsinf->{$sec}->{$parm} = $val;
238
+ }
239
+ } else { # error
240
+ debug(0, "Error: unknown command line option $arg\n");
241
+ return;
242
+ }
243
+ }
244
+
245
+ # no args read - just return true
246
+ if (!$argsinf || !%{$argsinf}) {
247
+ return 1;
248
+ }
249
+
250
+ # override inf with vals read from args
251
+ while (my ($name, $sec) = each %{$argsinf}) {
252
+ if (ref($sec) eq 'HASH') {
253
+ for my $key (keys %{$sec}) {
254
+ if (defined($sec->{$key})) {
255
+ my $val = $sec->{$key};
256
+ $self->{$name}->{$key} = $val;
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ return 1;
263
+ }
264
+
265
+ #############################################################################
266
+ # Mandatory TRUE return value.
267
+ #
268
+ 1;