Commit 3470ed2dcf8c31dc3103a271e828522a36a85b61
1 parent
63e71697
Added 3 additional scripts (refer to README.md for what they do)
- freeipa-samba-user.sh - freeipa-service-ntlm.sh - freeipa-service-password.sh
Showing
4 changed files
with
373 additions
and
4 deletions
README.md
... | ... | @@ -10,11 +10,17 @@ between an existing situation and FreeIPA and are safe to run multiple times. |
10 | 10 | As side-effect, this also makes them suitable to support a gradual migration |
11 | 11 | over time (where a source system is still in production until final cut-over) |
12 | 12 | |
13 | +Please note that these scripts are intended to run on the FreeIPA server and | |
14 | +require a valid (admin) kerberos ticket, which can be obtained with: | |
15 | +``` | |
16 | +kinit admin | |
17 | +``` | |
18 | + | |
13 | 19 | The latest versions, documentation and a bug tracker are available on my |
14 | 20 | [GitLab instance](https://gitlab.lindenaar.net/scripts/freeipa) |
15 | 21 | |
16 | -Copyright (c) 2018 Frederik Lindenaar. free for distribution under the GNU | |
17 | -General Public License, see [below](#license) | |
22 | +Copyright (c) 2018 - 2019 Frederik Lindenaar. free for distribution under the | |
23 | +GNU General Public License, see [below](#license) | |
18 | 24 | |
19 | 25 | Contents |
20 | 26 | ======== |
... | ... | @@ -30,6 +36,12 @@ This repository contains the following scripts: |
30 | 36 | around for bind-dyndb-ldap plugin not supporting bind's ```notify-source``` |
31 | 37 | * [users2freeipa.py](#users2freeipa) |
32 | 38 | is a migration script to transfer/synchronize LDAP users to/with FreeIPA |
39 | + * [freeipa-service-password.sh](#freeipaservicepassword) | |
40 | + is a script to create a service account and (re)set it's password | |
41 | + * [freeipa-service-ntlm.sh](#freeipaservicentlm) | |
42 | + is a script to grant a service account access to NTLM password attributes | |
43 | + * [freeipa-samba-user.sh](freeipasambauser) | |
44 | + is a script to extend users to a sambaSAMAccount for Samba compatibility | |
33 | 45 | |
34 | 46 | |
35 | 47 | <a name=freeipadns>freeipa-dns.py</a> |
... | ... | @@ -133,7 +145,8 @@ This script will ensure the necessary setup is in place so that Certbot (EFF's |
133 | 145 | certificate request script for Let's Encrypt) will work with FreeIPA for DNS |
134 | 146 | challenges and and instructs it to deploy new certificates for FreeIPA's web |
135 | 147 | interface. Before writing this script I looked at available options, especially |
136 | -[freeipa-letsencrypt](https://github.com/freeipa/freeipa-letsencrypt) and [antevens'](https://github.com/antevens/letsencrypt-freeipa) implementation but | |
148 | +[freeipa-letsencrypt](https://github.com/freeipa/freeipa-letsencrypt) and | |
149 | +[antevens'](https://github.com/antevens/letsencrypt-freeipa) implementation but | |
137 | 150 | decided to take a slightly different approach where Certbot does all the work |
138 | 151 | and the setup script will only ensure that the environment is prepared and that |
139 | 152 | Certbot is initially instructed correctly. This allows to fully tie-in with how |
... | ... | @@ -160,7 +173,7 @@ by setting one of the following environment variables: |
160 | 173 | |-------------|------------------------------------|---------------------------| |
161 | 174 | | CERTNAME | certificate hostname, | host's canonicalname (1) | |
162 | 175 | | DNSALTNAMES | certificate DNS names | host's principalnames (1) | |
163 | -| DOMAIN | Let's Encrypt challenge DNS zone | {DNS name's domain} (2) | | |
176 | +| DOMAIN | Let's Encrypt challenge DNS zone | {DNS name's domain} (2) | | |
164 | 177 | | EMAIL | administrator's e-mail address | hostmaster@{domain} | |
165 | 178 | | HOSTNAME | FreeIPA server's hostname | `hostname --fqdn` | |
166 | 179 | | KEYTAB | Let'sEncrypt service's keytab file | /etc/letsencrypt/keytab | |
... | ... | @@ -250,6 +263,123 @@ as FreeIPA does not yet support that) and use an ID View to store legacy data. |
250 | 263 | For all available command-line options, run ```users2freeipa.py -h``` |
251 | 264 | |
252 | 265 | |
266 | +<a name=freeipaservicepassword>freeipa-service-password.sh</a> | |
267 | +-------------------------------------------------------------- | |
268 | +This script sets up a service under a host (creating both if needed) so that it | |
269 | +can use an LDAP simple bind for authentication. Although it is straightforward | |
270 | +to setup a host and service account in FreeIPA using the web interface, this | |
271 | +will not allow it to perform an LDAP simple bind (without requiring Kerberos). | |
272 | +For this, a direct change to the LDAP database is required to extend the service | |
273 | +principal object and make it an ```simpleSecurityObject``` with a password. This | |
274 | +script accepts a hostname and one or more services and should be run like: | |
275 | +~~~ | |
276 | +./freeipa-service-password.sh <hostname> <service> [<service>] | |
277 | +~~~ | |
278 | + | |
279 | +As it always sets the password this script can be used for initial setup as well | |
280 | +as a reset of a service password. It performs the following actions: | |
281 | + * Creates the host in FreeIPA (if it does not exists) | |
282 | + When creating a new host it scans its SSH key and stores this in FreeIPA | |
283 | + * Creates each service under the host in FreeIPA (if it does not exists) | |
284 | + * (Re)sets each service’s LDAP password to a long generated random password | |
285 | + | |
286 | +When done it prints the services bind DN and generated password for later use. | |
287 | + | |
288 | + | |
289 | +<a name=freeipaservicentlm>freeipa-service-ntlm.sh</a> | |
290 | +------------------------------------------------------ | |
291 | +This script grants a service under a host access to the LDAP attributes required | |
292 | +to perform NLTM authentication. It sets up the necessary privilege, permission | |
293 | +and a role to grant the rights (if necessary) and then assigns the role to the | |
294 | +service on the host as specified on the command line. for this to work, Active | |
295 | +Directory domain trust support must have been enabled with the command: | |
296 | +~~~ | |
297 | +sudo ipa-adtrust-install --add-sid | |
298 | +~~~ | |
299 | +(the ```--addsid``` parameter is required to convert existing users). | |
300 | + | |
301 | +Please note that for the necessary attributes to become available, users *must* | |
302 | +change their password after enabling Active Directoy domain support as FreeIPA | |
303 | +only maintains the necessary attributes after the user object has been modified. | |
304 | + | |
305 | +Running this command will make the ```ipNTHash``` attribute available with the | |
306 | +necessary hash to perform NTLM authentication. Depending on whether the client | |
307 | +implementation supports mapping the attribute it is sufficient to configure it | |
308 | +to use this attribute or require to migrate users to the Samba schema with | |
309 | +[freeipa-samba-user.sh](freeipasambauser). To use the script execute: | |
310 | +~~~ | |
311 | +./freeipa-service-ntlm.sh <hostname> <service> [<service>] | |
312 | +~~~ | |
313 | +The specified service principals must already exist (they can be created using | |
314 | +[freeipa-service-password.sh](#freeipaservicepassword) or manually). | |
315 | + | |
316 | +The script is built to auto-configure though some settings can be overridden by | |
317 | +setting one of the following environment variables: | |
318 | + | |
319 | +| Variable | Description | Default value | | |
320 | +|-----------|-------------------------|----------------------------------------| | |
321 | +| HOST | Service host hostname | 1st command line parameter | | |
322 | +| HOSTNAME | FreeIPA server hostname | `hostname --fqdn` | | |
323 | +| PERM_NAME | Name of permission | Read Samba NTLM RC4 Password Hash attribute | | |
324 | +| PRIV_NAME | Name of privilege | Samba (NTLM) RC4 Password Hash Access | | |
325 | +| ROLE_NAME | Name of role | Samba/NTLM Authenticator | | |
326 | + | |
327 | +The description of the privilege / role creates can be changed through: | |
328 | +| Variable | Default value | | |
329 | +|----------------|-------------------------------------------------------------| | |
330 | +|PRIV_DESCRIPTION|Perform Samba NTLM authentication using the RC4 password Hash| | |
331 | +|ROLE_DESCRIPTION|Perform Samba (NTLM) Authentication using the RC4 Password hash| | |
332 | + | |
333 | + | |
334 | +<a name=freeipasambauser>freeipa-samba-user.sh</a> | |
335 | +-------------------------------------------------- | |
336 | +This script adds the ```sambaSAMAccount``` objectclass to specified users so | |
337 | +that they can with Samba / NTLM. For everything to work, the Samba server must | |
338 | +login with a service account that has a simple password (setup with | |
339 | +[freeipa-service-password.sh](#freeipaservicepassword)) with access to the NTLM | |
340 | +password attributes (setup with [freeipa-service-ntlm.sh](#freeipaservicentlm)). | |
341 | +This script was written to support integration with Synology DSM (see also this | |
342 | +[blog post](https://frederik.lindenaar.nl/2019/07/14/integrating-synology-ds-with-freeipa.html)) | |
343 | +but should also work for other Samba servers (please raise an issue in case it | |
344 | +doesn't work). I found that FreeIPA will maintain and expose required attributes | |
345 | +for NTLM authentication (```sambaNTPassword``` and ```sambaPwdLastSet```) when | |
346 | +Active Directory domain trust support has been enabled with the command: | |
347 | +~~~ | |
348 | +sudo ipa-adtrust-install --add-sid | |
349 | +~~~ | |
350 | +(the ```--addsid``` parameter is required to convert existing users). | |
351 | + | |
352 | +To use the script to migrate all users (except admin) run (the backslash is | |
353 | +needed to avoid shell expansion of * as parameter): | |
354 | +~~~ | |
355 | +./freeipa-service-password.sh \* | |
356 | +~~~ | |
357 | + | |
358 | +Besides a single * the script also accepts the login of one or more users to | |
359 | +migrate as parameter. To explicitly migrate admin - excluded with * - run: | |
360 | +~~~ | |
361 | +./freeipa-samba-user.sh admin | |
362 | +~~~ | |
363 | + | |
364 | +The script will only migrate users that are not yet a ```sambaSAMAccount``` so | |
365 | +it can be run safely multiple times or at set intervals from cron (additional | |
366 | +work is required to make that work though as it will need a valid Kerberos | |
367 | +ticket from a keytab file for that). | |
368 | + | |
369 | +Please note that for the necessary attributes to become available, users *must* | |
370 | +change their password after being converted ```sambaSAMAccount``` as FreeIPA | |
371 | +only maintains the necessary attributes after the user object has been modified. | |
372 | + | |
373 | +The script is built to auto-configure though some settings can be overridden by | |
374 | +setting one of the following environment variables: | |
375 | + | |
376 | +| Variable | Description | Default value | | |
377 | +|-------------|------------------------------------|---------------------------| | |
378 | +| HOST | Service host hostname | 1st command line parameter| | |
379 | +| HOSTNAME | FreeIPA server's hostname | `hostname --fqdn` | | |
380 | +| SAMBADOMAIN | Samba (Windows) domain name | FreeIPA Kerberos realm | | |
381 | + | |
382 | + | |
253 | 383 | <a name="license">License</a> |
254 | 384 | ----------------------------- |
255 | 385 | These scripts, documentation & configration examples are free software: you can |
... | ... |
freeipa-samba-user.sh
0 → 100755
1 | +#!/bin/bash -e | |
2 | +# | |
3 | +# freeipa-samba-user.sh - extend existing user(s) with sambaSAMAccount | |
4 | +# | |
5 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
6 | +# https://gitlab.lindenaar.net/scripts/freeipa | |
7 | +# | |
8 | +# Copyright (c) 2019 Frederik Lindenaar | |
9 | +# | |
10 | +# This script is free software: you can redistribute and/or modify it under the | |
11 | +# terms of version 3 of the GNU General Public License as published by the Free | |
12 | +# Software Foundation, or (at your option) any later version of the license. | |
13 | +# | |
14 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
15 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
16 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
17 | +# | |
18 | +# You should have received a copy of the GNU General Public License along with | |
19 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
20 | + | |
21 | +die() { echo $* >&2; exit 1; } | |
22 | + | |
23 | +# Exit if hostname not provided | |
24 | +if [ $# -lt 1 ]; then | |
25 | + die "Usage: `basename $0` <user> [<user> ...]" | |
26 | +fi | |
27 | + | |
28 | +# Sanity checks, ensure we have a valid Kerberos ticket and run on FreeIPA server | |
29 | +if ! klist -s; then | |
30 | + die "no valid Kerberos ticket, please login to FreeIPA using kinit first" | |
31 | +elif ! ipa server-show ${HOSTNAME:=$(hostname --fqdn)} > /dev/null; then | |
32 | + die "this script should be run on an active IPA server" | |
33 | +fi | |
34 | + | |
35 | +# Generate the LDAP User filter, !admin if parameter is * else a list of users | |
36 | +if [ $# == 1 -a "$1" == "*" ]; then | |
37 | + USERFILTER='(!(uid=admin))' | |
38 | +else | |
39 | + USERS="$*" | |
40 | + USERFILTER="(|(uid=${USERS// /)(uid=}))" | |
41 | +fi | |
42 | + | |
43 | +# Lookup the Samba Domain - equal to the Kerberos REALM by default | |
44 | +: ${SAMBADOMAIN:=$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d@ -f2)} | |
45 | + | |
46 | +# Lookup the users not yet converted and process each of them | |
47 | +declare -A params=( ) | |
48 | +ldapsearch -QLLL "(&${USERFILTER}(objectClass=ipantuserattrs)(!(objectClass=sambaSamAccount)))" dn uid ipaNTSecurityIdentifier | while read key value; do | |
49 | + # If we're at an empty line it's the end of the record, perform the change | |
50 | + if [ -z "$key" ]; then | |
51 | + if ldapmodify -Q > /dev/null 2>&1 <<EOLDIF; then | |
52 | +dn: ${params[dn]} | |
53 | +changetype: modify | |
54 | +add: objectClass | |
55 | +objectClass: sambaSamAccount | |
56 | +- | |
57 | +add: sambaSID | |
58 | +sambaSID: ${params[ipaNTSecurityIdentifier]} | |
59 | +- | |
60 | +add: sambaAcctFlags | |
61 | +sambaAcctFlags: [U ] | |
62 | +- | |
63 | +add: sambaDomainName | |
64 | +sambaDomainName: ${SAMBADOMAIN} | |
65 | +EOLDIF | |
66 | + echo "successfully updated user ${params[uid]}" | |
67 | + else | |
68 | + die "failed to update user ${params[uid]}, aborting!" | |
69 | + fi | |
70 | + declare -A params=( ) | |
71 | + else # we got another attibute, store it for later processing | |
72 | + params[${key/:/}]="$value" | |
73 | + fi | |
74 | +done | |
75 | + | |
... | ... |
freeipa-service-ntlm.sh
0 → 100755
1 | +#!/bin/bash -e | |
2 | +# | |
3 | +# freeipa-service-ntlm.sh - grant host service access to NTLM Password Hash | |
4 | +# | |
5 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
6 | +# https://gitlab.lindenaar.net/scripts/freeipa | |
7 | +# | |
8 | +# Copyright (c) 2019 Frederik Lindenaar | |
9 | +# | |
10 | +# This script is free software: you can redistribute and/or modify it under the | |
11 | +# terms of version 3 of the GNU General Public License as published by the Free | |
12 | +# Software Foundation, or (at your option) any later version of the license. | |
13 | +# | |
14 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
15 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
16 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
17 | +# | |
18 | +# You should have received a copy of the GNU General Public License along with | |
19 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
20 | + | |
21 | +die() { echo $* >&2; exit 1; } | |
22 | + | |
23 | +# Exit if hostname not provided | |
24 | +if [ $# -lt 2 ]; then | |
25 | + die "Usage: `basename $0` <hostname> <service> [<service> ...]" | |
26 | +fi | |
27 | + | |
28 | +# Sanity checks, ensure we have a valid Kerberos ticket and run on FreeIPA server | |
29 | +if ! klist -s; then | |
30 | + die "no valid Kerberos ticket, please login to FreeIPA using kinit first" | |
31 | +elif ! ipa server-show ${HOSTNAME:=$(hostname --fqdn)} > /dev/null; then | |
32 | + die "this script should be run on an active IPA server" | |
33 | +fi | |
34 | + | |
35 | +# Set parameters | |
36 | +: ${HOST:=$1} | |
37 | +shift | |
38 | +: ${ROLE_NAME:=Samba/NTLM Authenticator} | |
39 | +: ${ROLE_DESCRIPTION:=Perform Samba (NTLM) Authentication using the RC4 Password hash} | |
40 | +: ${PRIV_NAME:=Samba (NTLM) RC4 Password Hash Access} | |
41 | +: ${PRIV_DESCRIPTION:=Perform Samba NTLM authentication using the RC4 password Hash} | |
42 | +: ${PERM_NAME:=Read Samba NTLM RC4 Password Hash attribute} | |
43 | + | |
44 | + | |
45 | +if ! ipa host-show "$HOST" > /dev/null 2>&1; then | |
46 | + die "host $HOST does not exist, aborting!" | |
47 | +fi | |
48 | + | |
49 | + | |
50 | +if ipa role-add "$ROLE_NAME" --desc="$ROLE_DESCRIPTION" > /dev/null 2>&1; then | |
51 | + echo created role $ROLE_NAME | |
52 | + if ipa privilege-add "$PRIV_NAME" --desc="$PRIV_DESCRIPTION" > /dev/null 2>&1; then | |
53 | + echo created privilege $PRIV_NAME | |
54 | + if ipa permission-add "$PERM_NAME" --attrs=sambaNTPassword --attrs=sambaPwdLastSet --attrs=sambaSID --attrs=sambaAcctFlags --attrs=sambaDomainName --type=user --right=read --right=compare > /dev/null 2>&1; then | |
55 | + echo created permission $PERM_NAME | |
56 | + else | |
57 | + echo permission $PERM_NAME exists | |
58 | + fi | |
59 | + if ! ipa privilege-add-permission "$PRIV_NAME" --permissions="$PERM_NAME" > /dev/null 2>&1; then | |
60 | + die "adding permission to privileges failed, aborting!" | |
61 | + fi | |
62 | + else | |
63 | + echo privilege $PRIV_NAME exists | |
64 | + fi | |
65 | + if ! ipa role-add-privilege "$ROLE_NAME" --privileges="$PRIV_NAME" > /dev/null 2>&1; then | |
66 | + die "adding privilege to role failed, aborting!" | |
67 | + fi | |
68 | +fi | |
69 | + | |
70 | + | |
71 | +for service in $* | |
72 | +do | |
73 | + if ipa service-show "$service/$HOST" > /dev/null 2>&1; then | |
74 | + if ipa role-add-member "$ROLE_NAME" --services="$service/$HOST" > /dev/null 2>&1; then | |
75 | + echo granted service $service/$HOST the role $ROLE_NAME | |
76 | + else | |
77 | + echo service $service/$HOST already had role $ROLE_NAME | |
78 | + fi | |
79 | + else | |
80 | + echo "service $service/$HOST does not exist, skipping" | |
81 | + fi | |
82 | +done | |
83 | + | |
... | ... |
freeipa-service-password.sh
0 → 100755
1 | +#!/bin/bash -e | |
2 | +# | |
3 | +# freeipa-service-password.sh - add/set host service login password | |
4 | +# | |
5 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
6 | +# https://gitlab.lindenaar.net/scripts/freeipa | |
7 | +# | |
8 | +# Copyright (c) 2019 Frederik Lindenaar | |
9 | +# | |
10 | +# This script is free software: you can redistribute and/or modify it under the | |
11 | +# terms of version 3 of the GNU General Public License as published by the Free | |
12 | +# Software Foundation, or (at your option) any later version of the license. | |
13 | +# | |
14 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
15 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
16 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
17 | +# | |
18 | +# You should have received a copy of the GNU General Public License along with | |
19 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
20 | + | |
21 | +die() { echo $* >&2; exit 1; } | |
22 | + | |
23 | +# Exit if hostname not provided | |
24 | +if [ $# -lt 2 ]; then | |
25 | + die "Usage: `basename $0` <hostname> <service> [<service> ...]" | |
26 | +fi | |
27 | + | |
28 | +# Sanity checks, ensure we have a valid Kerberos ticket and run on FreeIPA server | |
29 | +if ! klist -s; then | |
30 | + die "no valid Kerberos ticket, please login to FreeIPA using kinit first" | |
31 | +elif ! ipa server-show ${HOSTNAME:=$(hostname --fqdn)} > /dev/null; then | |
32 | + die "this script should be run on an active IPA server" | |
33 | +fi | |
34 | + | |
35 | +# Set parameters from command line | |
36 | +: ${HOST:=$1} | |
37 | +shift | |
38 | + | |
39 | +if ! ipa host-show "$HOST" > /dev/null 2>&1; then | |
40 | + echo Fetching information for $HOST | |
41 | + SSHKEYS=($(ssh-keyscan $HOST 2>/dev/null | cut -f2- -d\ | sed "s/\(.*\)/--sshpubkey='\1'/")) | |
42 | + echo Creating host $HOST | |
43 | + eval ipa host-add "$HOST" ${SSHKEYS[@]} | |
44 | + eval ipa host-add-principal "$HOST" $HOSTALIASES | |
45 | +else | |
46 | + echo host $HOST exists | |
47 | +fi | |
48 | + | |
49 | + | |
50 | +for service in $* | |
51 | +do | |
52 | + if ipa service-add "$service/$HOST" > /dev/null 2>&1; then | |
53 | + echo Created service $service/$HOST | |
54 | + else | |
55 | + echo service $service/$HOST exists | |
56 | + fi | |
57 | + service_binddn=$(ipa service-show "$service/$HOST" --raw --all | fgrep " dn: " | cut -f2 -d: | tr -d \ ) | |
58 | + echo Service Bind DN: $service_binddn | |
59 | + service_bindpw=$(pwmake 128) | |
60 | + if ipa service-show "$service/$HOST" --all --raw | fgrep "objectClass:" | fgrep -q "simpleSecurityObject" > /dev/null 2>&1; then | |
61 | + echo resetting password to generated password: $service_bindpw | |
62 | + ldapmodify -Q > /dev/null 2>&1 <<EOLDIF | |
63 | +dn: $service_binddn | |
64 | +changetype: modify | |
65 | +replace: userPassword | |
66 | +userPassword: $service_bindpw | |
67 | +EOLDIF | |
68 | + else | |
69 | + echo Enabled login with generated password: $service_bindpw | |
70 | + ldapmodify -Q > /dev/null 2>&1 <<EOLDIF | |
71 | +dn: $service_binddn | |
72 | +changetype: modify | |
73 | +add: objectClass | |
74 | +objectClass: simpleSecurityObject | |
75 | +- | |
76 | +add: userPassword | |
77 | +userPassword: $service_bindpw | |
78 | +EOLDIF | |
79 | + fi | |
80 | +done | |
81 | + | |
... | ... |