]>
Commit | Line | Data |
---|---|---|
a6e3ac60 DM |
1 | package PMG::LDAPConfig; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
49a16f65 | 5 | use MIME::Base64; |
a6e3ac60 DM |
6 | use Data::Dumper; |
7 | ||
8 | use PVE::Tools; | |
9 | use PVE::JSONSchema qw(get_standard_option); | |
10 | use PVE::INotify; | |
11 | use PVE::SectionConfig; | |
12 | ||
13 | use base qw(PVE::SectionConfig); | |
14 | ||
7d90f962 DM |
15 | my $inotify_file_id = 'pmg-ldap.conf'; |
16 | my $config_filename = '/etc/pmg/ldap.conf'; | |
17 | ||
a6e3ac60 DM |
18 | my $defaultData = { |
19 | propertyList => { | |
20 | type => { description => "Section type." }, | |
c2ef4490 | 21 | profile => { |
2aeda4ac | 22 | description => "Profile ID.", |
a6e3ac60 DM |
23 | type => 'string', format => 'pve-configid', |
24 | }, | |
2fdba966 DM |
25 | }, |
26 | }; | |
27 | ||
ca0c8b88 | 28 | |
2fdba966 DM |
29 | sub properties { |
30 | return { | |
1c4fa5b1 DM |
31 | disable => { |
32 | description => "Flag to disable/deactivate the entry.", | |
33 | type => 'boolean', | |
34 | optional => 1, | |
35 | }, | |
bfed5777 DM |
36 | comment => { |
37 | description => "Description.", | |
38 | type => 'string', | |
39 | optional => 1, | |
40 | maxLength => 4096, | |
41 | }, | |
a6e3ac60 | 42 | mode => { |
443665c7 | 43 | description => "LDAP protocol mode ('ldap', 'ldaps' or 'ldap+starttls').", |
a6e3ac60 | 44 | type => 'string', |
443665c7 | 45 | enum => ['ldap', 'ldaps', 'ldap+starttls'], |
a6e3ac60 DM |
46 | default => 'ldap', |
47 | }, | |
6ad43a10 | 48 | verify => { |
443665c7 | 49 | description => "Verify server certificate. Only useful with ldaps or ldap+starttls.", |
6ad43a10 DC |
50 | type => 'boolean', |
51 | default => 0, | |
52 | optional => 1, | |
53 | }, | |
54 | cafile => { | |
55 | description => "Path to CA file. Only useful with option 'verify'", | |
56 | type => 'string', | |
57 | optional => 1, | |
58 | }, | |
49a16f65 DM |
59 | server1 => { |
60 | description => "Server address.", | |
61 | type => 'string', format => 'address', | |
bfed5777 | 62 | maxLength => 256, |
49a16f65 DM |
63 | }, |
64 | server2 => { | |
65 | description => "Fallback server address. Userd when the first server is not available.", | |
66 | type => 'string', format => 'address', | |
bfed5777 | 67 | maxLength => 256, |
49a16f65 DM |
68 | }, |
69 | port => { | |
70 | description => "Specify the port to connect to.", | |
71 | type => 'integer', | |
72 | minimum => 1, | |
73 | maximum => 65535, | |
74 | }, | |
75 | binddn => { | |
76 | description => "Bind domain name.", | |
77 | type => 'string', | |
78 | }, | |
79 | bindpw => { | |
80 | description => "Bind password.", | |
81 | type => 'string', | |
82 | }, | |
83 | basedn => { | |
84 | description => "Base domain name.", | |
85 | type => 'string', | |
86 | }, | |
87 | groupbasedn => { | |
88 | description => "Base domain name for groups.", | |
89 | type => 'string', | |
90 | }, | |
91 | filter => { | |
92 | description => "LDAP filter.", | |
93 | type => 'string', | |
94 | }, | |
95 | accountattr => { | |
96 | description => "Account attribute name name.", | |
ca0c8b88 | 97 | type => 'string', format => 'ldap-simple-attr-list', |
23b1d0f8 | 98 | default => 'sAMAccountName, uid', |
49a16f65 DM |
99 | }, |
100 | mailattr => { | |
101 | description => "List of mail attribute names.", | |
ca0c8b88 | 102 | type => 'string', format => 'ldap-simple-attr-list', |
7fc9e381 | 103 | default => "mail, userPrincipalName, proxyAddresses, othermailbox, mailAlternativeAddress", |
49a16f65 | 104 | }, |
b14970ad DC |
105 | groupclass => { |
106 | description => "List of objectclasses for groups.", | |
ca0c8b88 | 107 | type => 'string', format => 'ldap-simple-attr-list', |
b14970ad DC |
108 | default => "group, univentionGroup, ipausergroup", |
109 | }, | |
2fdba966 DM |
110 | }; |
111 | } | |
a6e3ac60 DM |
112 | |
113 | sub options { | |
114 | return { | |
ff4776b6 | 115 | disable => { optional => 1 }, |
bfed5777 | 116 | comment => { optional => 1 }, |
49a16f65 DM |
117 | server1 => { optional => 0 }, |
118 | server2 => { optional => 1 }, | |
119 | port => { optional => 1 }, | |
a6e3ac60 | 120 | mode => { optional => 1 }, |
49a16f65 DM |
121 | binddn => { optional => 1 }, |
122 | bindpw => { optional => 1 }, | |
123 | basedn => { optional => 1 }, | |
124 | groupbasedn => { optional => 1 }, | |
125 | filter => { optional => 1 }, | |
126 | accountattr => { optional => 1 }, | |
127 | mailattr => { optional => 1 }, | |
b14970ad | 128 | groupclass => { optional => 1 }, |
6ad43a10 DC |
129 | verify => { optional => 1 }, |
130 | cafile => { optional => 1 }, | |
a6e3ac60 DM |
131 | }; |
132 | } | |
133 | ||
134 | sub type { | |
135 | return 'ldap'; | |
136 | } | |
137 | ||
138 | sub private { | |
139 | return $defaultData; | |
140 | } | |
141 | ||
05b856e3 DM |
142 | sub parse_section_header { |
143 | my ($class, $line) = @_; | |
144 | ||
145 | if ($line =~ m/^(\S+):\s*(\S+)\s*$/) { | |
c2ef4490 | 146 | my ($type, $profileId) = ($1, $2); |
05b856e3 | 147 | my $errmsg = undef; # set if you want to skip whole section |
c2ef4490 | 148 | eval { PVE::JSONSchema::pve_verify_configid($profileId); }; |
05b856e3 DM |
149 | $errmsg = $@ if $@; |
150 | my $config = {}; # to return additional attributes | |
c2ef4490 | 151 | return ($type, $profileId, $errmsg, $config); |
05b856e3 DM |
152 | } |
153 | return undef; | |
154 | } | |
155 | ||
bfed5777 DM |
156 | sub parse_config { |
157 | my ($class, $filename, $raw) = @_; | |
158 | ||
159 | my $cfg = $class->SUPER::parse_config($filename, $raw); | |
160 | ||
c2ef4490 DM |
161 | foreach my $profile (keys %{$cfg->{ids}}) { |
162 | my $data = $cfg->{ids}->{$profile}; | |
bfed5777 DM |
163 | |
164 | $data->{comment} = PVE::Tools::decode_text($data->{comment}) | |
165 | if defined($data->{comment}); | |
166 | ||
167 | $data->{bindpw} = decode_base64($data->{bindpw}) | |
168 | if defined($data->{bindpw}); | |
169 | } | |
170 | ||
171 | return $cfg; | |
172 | } | |
173 | ||
174 | sub write_config { | |
175 | my ($class, $filename, $cfg) = @_; | |
176 | ||
c2ef4490 DM |
177 | foreach my $profile (keys %{$cfg->{ids}}) { |
178 | my $data = $cfg->{ids}->{$profile}; | |
bfed5777 DM |
179 | |
180 | $data->{comment} = PVE::Tools::encode_text($data->{comment}) | |
181 | if defined($data->{comment}); | |
182 | ||
183 | $data->{bindpw} = encode_base64($data->{bindpw}, '') | |
184 | if defined($data->{bindpw}); | |
185 | } | |
186 | ||
187 | $class->SUPER::write_config($filename, $cfg); | |
188 | } | |
189 | ||
7d90f962 DM |
190 | sub new { |
191 | my ($type) = @_; | |
192 | ||
193 | my $class = ref($type) || $type; | |
194 | ||
195 | my $cfg = PVE::INotify::read_file($inotify_file_id); | |
196 | ||
197 | return bless $cfg, $class; | |
198 | } | |
199 | ||
200 | sub write { | |
201 | my ($self) = @_; | |
202 | ||
203 | PVE::INotify::write_file($inotify_file_id, $self); | |
204 | } | |
205 | ||
e1c64277 DM |
206 | my $lockfile = "/var/lock/pmgldapconfig.lck"; |
207 | ||
208 | sub lock_config { | |
209 | my ($code, $errmsg) = @_; | |
210 | ||
211 | my $p = PVE::Tools::lock_file($lockfile, undef, $code); | |
212 | if (my $err = $@) { | |
213 | $errmsg ? die "$errmsg: $err" : die $err; | |
214 | } | |
215 | } | |
216 | ||
49a16f65 | 217 | |
a6e3ac60 DM |
218 | __PACKAGE__->register(); |
219 | __PACKAGE__->init(); | |
220 | ||
221 | sub read_pmg_ldap_conf { | |
222 | my ($filename, $fh) = @_; | |
223 | ||
181ef3f1 | 224 | my $raw = defined($fh) ? do { local $/ = undef; <$fh> } : ''; |
a6e3ac60 DM |
225 | |
226 | return __PACKAGE__->parse_config($filename, $raw); | |
227 | } | |
228 | ||
229 | sub write_pmg_ldap_conf { | |
230 | my ($filename, $fh, $cfg) = @_; | |
231 | ||
232 | my $raw = __PACKAGE__->write_config($filename, $cfg); | |
233 | ||
bdbc2bc5 DM |
234 | my $gid = getgrnam('www-data'); |
235 | chown(0, $gid, $fh); | |
236 | chmod(0640, $fh); | |
d5121ced | 237 | |
a6e3ac60 DM |
238 | PVE::Tools::safe_print($filename, $fh, $raw); |
239 | } | |
240 | ||
7d90f962 | 241 | PVE::INotify::register_file($inotify_file_id, $config_filename, |
a6e3ac60 | 242 | \&read_pmg_ldap_conf, |
bdbc2bc5 DM |
243 | \&write_pmg_ldap_conf, |
244 | undef, | |
245 | always_call_parser => 1); | |
a6e3ac60 DM |
246 | |
247 | ||
248 | 1; |