Commit 63e71697e235b494630e073cdde40b4692adabc6
1 parent
02d0b225
fixed issue in freeipa-letsencrypt.sh with setting variable defaults
added set-dns-source.sh updated README.md accordingly
Showing
3 changed files
with
152 additions
and
68 deletions
README.md
@@ -19,73 +19,29 @@ General Public License, see [below](#license) | @@ -19,73 +19,29 @@ General Public License, see [below](#license) | ||
19 | Contents | 19 | Contents |
20 | ======== | 20 | ======== |
21 | This repository contains the following scripts: | 21 | This repository contains the following scripts: |
22 | - * [users2freeipa.py](#users2freeipa) | ||
23 | - is a migration script to transfer/synchronize LDAP users to/with FreeIPA | ||
24 | * [freeipa-dns.py](#freeipadns) | 22 | * [freeipa-dns.py](#freeipadns) |
25 | is a script providing functionality not available in FreeIPA itself to | 23 | is a script providing functionality not available in FreeIPA itself to |
26 | migrate/synchronize and maintain DNS zones in FreeIPA | 24 | migrate/synchronize and maintain DNS zones in FreeIPA |
27 | * [freeipa-letsencrypt.sh](#freeipaletsencrypt) | 25 | * [freeipa-letsencrypt.sh](#freeipaletsencrypt) |
28 | is a script to setup and configure Certbot and FreeIPA to request and renew | 26 | is a script to setup and configure Certbot and FreeIPA to request and renew |
29 | use publicly verifiable Let's Encrypt certificate(s) | 27 | use publicly verifiable Let's Encrypt certificate(s) |
30 | - | ||
31 | - | ||
32 | -<a name=users2freeipa>users2freeipa.py</a> | ||
33 | ---------------------------------------------- | ||
34 | -This script uses LDAP to obtain users from a MacOS Server (or other LDAP) | ||
35 | -server and synchronizes the results with the users registered in FreeIPA. | ||
36 | -Since it synchronizes data it is safe to run multiple times and users can be | ||
37 | -imported also as stage users initially. | ||
38 | - | ||
39 | -The intent is to migrate user data and to not drag on a legacy setup. For | ||
40 | -this reason, the script will create new user and group IDs and not copy homedir | ||
41 | -and shell information by default. For the IDs, the legacy information can be | ||
42 | -stored in an FreeIPA ID View so it remains available, other items can be copied | ||
43 | -over using command line options. Passwords can be copied-over (if available in | ||
44 | -a usable format), and the script also supports having FreeIPA generate random | ||
45 | -passwords and store these in a file for further processing/sharing with users. | ||
46 | - | ||
47 | -Users can be copied from an existing (generic) LDAP database and a MacOS Server | ||
48 | -OpenDirectory-flavor LDAP server. In this case, additional information (e.g. | ||
49 | -Apple's generatedUID) will be copied over as well. Please note that this does | ||
50 | -require customizing the FreeIPA LDAP schema, which the script will check for | ||
51 | -and can install (option ```-U```). As the setup is modular it should be easy | ||
52 | -to tweak or add other migrations. | ||
53 | - | ||
54 | -By default all users will be migrated/synchronized, but it is also possible to | ||
55 | -limit this to specific user(s) or group(s) or specifically exclude specific | ||
56 | -users or groups. An example to copy all users in the group ```workgroup``` | ||
57 | -except ```admin``` from an Apple MacOS OpenDirectory server: | ||
58 | -~~~ | ||
59 | -./users2freeipa.py -v -O -U -c "Legacy LDAP" -g workgroup -x admin -G \ | ||
60 | - -P -p passwords.txt ldap://ldap.mydomain.tld | ||
61 | -~~~ | ||
62 | -This will also install the OpenDirectory-specific schema customization, create | ||
63 | -groups and copy group memberships, copy usuable passwords and ensure that all | ||
64 | -users have a password (storing generated passwords to ```passwords.txt```) | ||
65 | - | ||
66 | -Please note that migrating existing passwords from LDAP has limitations, see | ||
67 | -[this](https://www.freeipa.org/page/NIS_accounts_migration_preserving_Passwords) | ||
68 | -page on migrating NIS passwords and [this](https://pagure.io/freeipa/issue/4732) | ||
69 | -issue reported with it. Bottom line is that (at this moment) password migration | ||
70 | -is flawed and always will require manual action from the user. For this reason | ||
71 | -the better alternative to set a random password and ask the user to reset the | ||
72 | -password using the FreeIPA portal makes more sense. | ||
73 | - | ||
74 | -Before running a production user migration, it is important to have FreeIPA | ||
75 | -setup and configured correctly so that the right defaults are used for new | ||
76 | -users. Best is to start with a single user and add that as a stage user (please | ||
77 | -note that this will not yet assign userIDs, group memberships and a password | ||
78 | -as FreeIPA does not yet support that) and use an ID View to store legacy data. | ||
79 | - | ||
80 | -For all available command-line options, run ```users2freeipa.py -h``` | 28 | + * [set-dns-source.sh](#setdnssource) |
29 | + enforce the source address of outgoing DNS messages using firewalld as work | ||
30 | + around for bind-dyndb-ldap plugin not supporting bind's ```notify-source``` | ||
31 | + * [users2freeipa.py](#users2freeipa) | ||
32 | + is a migration script to transfer/synchronize LDAP users to/with FreeIPA | ||
81 | 33 | ||
82 | 34 | ||
83 | <a name=freeipadns>freeipa-dns.py</a> | 35 | <a name=freeipadns>freeipa-dns.py</a> |
84 | ----------------------------------------------------------------- | 36 | +------------------------------------- |
85 | This script provides functionality not provided by FreeIPA to migrate and/or | 37 | This script provides functionality not provided by FreeIPA to migrate and/or |
86 | synchronize / maintain DNS data in FreeIPA. Currently the following commands | 38 | synchronize / maintain DNS data in FreeIPA. Currently the following commands |
87 | are implemented: | 39 | are implemented: |
88 | - * axfr - import/synchronize a DNS zone in FreeIPA using a zone-xfer. | 40 | + * axfr - synchronize DNS zone(s) using a zone-xfer. Contrary to the suggested |
41 | + [migration approach](https://docs.pagure.org/bind-dyndb-ldap/Migration.html) | ||
42 | + this uses the FreeIPA API to migrate or synchronize DNS zones with FreeIPA | ||
43 | + so it can also be used for running things in parallel or gradual migrations. | ||
44 | + | ||
89 | for example, to migrate / synchronize fromain ```domain.tld``` from DNS | 45 | for example, to migrate / synchronize fromain ```domain.tld``` from DNS |
90 | server ```192.168.1.53``` without checking DNS overlap, issue the command: | 46 | server ```192.168.1.53``` without checking DNS overlap, issue the command: |
91 | 47 | ||
@@ -172,7 +128,7 @@ the available options for each commmand run ```freeipa-dns.py <command> -h``` | @@ -172,7 +128,7 @@ the available options for each commmand run ```freeipa-dns.py <command> -h``` | ||
172 | 128 | ||
173 | 129 | ||
174 | <a name=freeipaletsencrypt>freeipa-letsencrypt.sh</a> | 130 | <a name=freeipaletsencrypt>freeipa-letsencrypt.sh</a> |
175 | ----------------------------------------------------------------- | 131 | +----------------------------------------------------- |
176 | This script will ensure the necessary setup is in place so that Certbot (EFF's | 132 | This script will ensure the necessary setup is in place so that Certbot (EFF's |
177 | certificate request script for Let's Encrypt) will work with FreeIPA for DNS | 133 | certificate request script for Let's Encrypt) will work with FreeIPA for DNS |
178 | challenges and and instructs it to deploy new certificates for FreeIPA's web | 134 | challenges and and instructs it to deploy new certificates for FreeIPA's web |
@@ -202,9 +158,9 @@ by setting one of the following environment variables: | @@ -202,9 +158,9 @@ by setting one of the following environment variables: | ||
202 | 158 | ||
203 | | Variable | Description | Default value | | 159 | | Variable | Description | Default value | |
204 | |-------------|------------------------------------|---------------------------| | 160 | |-------------|------------------------------------|---------------------------| |
205 | -| CERTNAME | certificate hostname, | host's canonicalname (*) | | ||
206 | -| DNSALTNAMES | certificate DNS names | host's principalnames (*) | | ||
207 | -| DOMAIN | Let's Encrypt challenge DNS zone | {DNS name's domain} (**) | | 161 | +| CERTNAME | certificate hostname, | host's canonicalname (1) | |
162 | +| DNSALTNAMES | certificate DNS names | host's principalnames (1) | | ||
163 | +| DOMAIN | Let's Encrypt challenge DNS zone | {DNS name's domain} (2) | | ||
208 | | EMAIL | administrator's e-mail address | hostmaster@{domain} | | 164 | | EMAIL | administrator's e-mail address | hostmaster@{domain} | |
209 | | HOSTNAME | FreeIPA server's hostname | `hostname --fqdn` | | 165 | | HOSTNAME | FreeIPA server's hostname | `hostname --fqdn` | |
210 | | KEYTAB | Let'sEncrypt service's keytab file | /etc/letsencrypt/keytab | | 166 | | KEYTAB | Let'sEncrypt service's keytab file | /etc/letsencrypt/keytab | |
@@ -214,11 +170,86 @@ by setting one of the following environment variables: | @@ -214,11 +170,86 @@ by setting one of the following environment variables: | ||
214 | | SUDO | command to become root (if needed) | sudo | | 170 | | SUDO | command to become root (if needed) | sudo | |
215 | | TMPDIR | Directory for temporary files | /tmp | | 171 | | TMPDIR | Directory for temporary files | /tmp | |
216 | 172 | ||
217 | -(*) obtained from the FreeIPA server record looked up based on ${HOSTNAME} | ||
218 | -(**) this allows to enforce the DNS zone, e.g. host.subdomain in mydomain.tld | 173 | +(1) obtained from the FreeIPA server record looked up based on ${HOSTNAME} |
174 | +(2) this allows to enforce the DNS zone, e.g. host.subdomain in mydomain.tld | ||
219 | 175 | ||
220 | When things change, the script can simply be run again. | 176 | When things change, the script can simply be run again. |
221 | 177 | ||
178 | + | ||
179 | +<a name=setdnssource>set-dns-source.sh</a> | ||
180 | +------------------------------------------ | ||
181 | +FreeIPA's bind-dyndb-ldap plugin does not support bind's ```notify-source``` | ||
182 | +settings and simply uses the main address when sending DNS notifications. This | ||
183 | +breaks multi-homed setups and, in case of IPv6, even causes bind to send NOTIFY | ||
184 | +messages from the temporary IPv6 address, causing slave servers to reject them. | ||
185 | +This script will setup Source NAT in firewalld to enforce the IPv4/IPv6 address | ||
186 | +of outgoing DNS packets to ensure that DNS NOTIFYs messages will use the correct | ||
187 | +source IPv4/IPv6 address. The IPv4/IPv6 address(es) to enforce should either be | ||
188 | +provided in the environment or changed at the top of the script. In case an IPv4 | ||
189 | +address is provided, the script can figure out itself which device to use when | ||
190 | +running it, if not this should be provided as well. To install run: | ||
191 | +~~~ | ||
192 | +sudo IPV4ADDR=192.168.0.100 IPV6ADDR=none ./set-dns-source.sh install | ||
193 | +~~~ | ||
194 | +to remove installed rules, run with the same parameters and parameter 'remove': | ||
195 | +~~~ | ||
196 | +sudo IPV4ADDR=192.168.0.100 IPV6ADDR=none ./set-dns-source.sh remove | ||
197 | +~~~ | ||
198 | +and to see custom rules run: ```sudo firewall-cmd --direct --get-all-rules``` | ||
199 | + | ||
200 | + | ||
201 | + | ||
202 | +<a name=users2freeipa>users2freeipa.py</a> | ||
203 | +------------------------------------------ | ||
204 | +This script uses LDAP to obtain users from a MacOS Server (or other LDAP) | ||
205 | +server and synchronizes the results with the users registered in FreeIPA. | ||
206 | +Since it synchronizes data it is safe to run multiple times and users can be | ||
207 | +imported also as stage users initially. | ||
208 | + | ||
209 | +The intent is to migrate user data and to not drag on a legacy setup. For | ||
210 | +this reason, the script will create new user and group IDs and not copy homedir | ||
211 | +and shell information by default. For the IDs, the legacy information can be | ||
212 | +stored in an FreeIPA ID View so it remains available, other items can be copied | ||
213 | +over using command line options. Passwords can be copied-over (if available in | ||
214 | +a usable format), and the script also supports having FreeIPA generate random | ||
215 | +passwords and store these in a file for further processing/sharing with users. | ||
216 | + | ||
217 | +Users can be copied from an existing (generic) LDAP database and a MacOS Server | ||
218 | +OpenDirectory-flavor LDAP server. In this case, additional information (e.g. | ||
219 | +Apple's generatedUID) will be copied over as well. Please note that this does | ||
220 | +require customizing the FreeIPA LDAP schema, which the script will check for | ||
221 | +and can install (option ```-U```). As the setup is modular it should be easy | ||
222 | +to tweak or add other migrations. | ||
223 | + | ||
224 | +By default all users will be migrated/synchronized, but it is also possible to | ||
225 | +limit this to specific user(s) or group(s) or specifically exclude specific | ||
226 | +users or groups. An example to copy all users in the group ```workgroup``` | ||
227 | +except ```admin``` from an Apple MacOS OpenDirectory server: | ||
228 | +~~~ | ||
229 | +./users2freeipa.py -v -O -U -c "Legacy LDAP" -g workgroup -x admin -G \ | ||
230 | + -P -p passwords.txt ldap://ldap.mydomain.tld | ||
231 | +~~~ | ||
232 | +This will also install the OpenDirectory-specific schema customization, create | ||
233 | +groups and copy group memberships, copy usuable passwords and ensure that all | ||
234 | +users have a password (storing generated passwords to ```passwords.txt```) | ||
235 | + | ||
236 | +Please note that migrating existing passwords from LDAP has limitations, see | ||
237 | +[this](https://www.freeipa.org/page/NIS_accounts_migration_preserving_Passwords) | ||
238 | +page on migrating NIS passwords and [this](https://pagure.io/freeipa/issue/4732) | ||
239 | +issue reported with it. Bottom line is that (at this moment) password migration | ||
240 | +is flawed and always will require manual action from the user. For this reason | ||
241 | +the better alternative to set a random password and ask the user to reset the | ||
242 | +password using the FreeIPA portal makes more sense. | ||
243 | + | ||
244 | +Before running a production user migration, it is important to have FreeIPA | ||
245 | +setup and configured correctly so that the right defaults are used for new | ||
246 | +users. Best is to start with a single user and add that as a stage user (please | ||
247 | +note that this will not yet assign userIDs, group memberships and a password | ||
248 | +as FreeIPA does not yet support that) and use an ID View to store legacy data. | ||
249 | + | ||
250 | +For all available command-line options, run ```users2freeipa.py -h``` | ||
251 | + | ||
252 | + | ||
222 | <a name="license">License</a> | 253 | <a name="license">License</a> |
223 | ----------------------------- | 254 | ----------------------------- |
224 | These scripts, documentation & configration examples are free software: you can | 255 | These scripts, documentation & configration examples are free software: you can |
freeipa-letsencrypt.sh
@@ -36,7 +36,13 @@ else | @@ -36,7 +36,13 @@ else | ||
36 | fi | 36 | fi |
37 | 37 | ||
38 | # Set KRB5CCNAME to ensure the current ticket cache will be used | 38 | # Set KRB5CCNAME to ensure the current ticket cache will be used |
39 | -KRB5CCNAME=${KRB5CCNAME:-$(klist -l | head -3 | tail -1 | cut -d\ -f2-)} | 39 | +: ${KRB5CCNAME:=$(klist -l | head -3 | tail -1 | cut -d\ -f2-)} |
40 | + | ||
41 | +# Set parameters | ||
42 | +: ${CERTNAME:=$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2 | cut -d@ -f1)} | ||
43 | +: ${DNSALTNAMES:=$(ipa host-show $HOSTNAME --raw | fgrep "krbprincipalname: host/" | cut -d/ -f2 | cut -d@ -f1 | paste -sd,)} | ||
44 | +: ${EMAIL:=hostmaster@${HOSTNAME#*.}} | ||
45 | +: ${SERVICE:=letsencrypt/$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2)} | ||
40 | 46 | ||
41 | # Ensure the user consents with changing his system. | 47 | # Ensure the user consents with changing his system. |
42 | if tty > /dev/null; then | 48 | if tty > /dev/null; then |
@@ -46,12 +52,11 @@ use a Let's Encrypt certificate and will automatically renew that when needed. | @@ -46,12 +52,11 @@ use a Let's Encrypt certificate and will automatically renew that when needed. | ||
46 | The following changes will be made for this: | 52 | The following changes will be made for this: |
47 | 1. Add Let's Encrypt Root and Intermediate CAs as trusted CAs | 53 | 1. Add Let's Encrypt Root and Intermediate CAs as trusted CAs |
48 | 2. Create DNS Administrator role in FreeIPA that can edit any DNS Record | 54 | 2. Create DNS Administrator role in FreeIPA that can edit any DNS Record |
49 | - 3. Create host service: ${SERVICE:=letsencrypt/$( | ||
50 | -ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2)} | 55 | + 3. Create host service: $SERVICE |
51 | 4. Allow letsencrypt host service to manage DNS entries | 56 | 4. Allow letsencrypt host service to manage DNS entries |
52 | - 5. Register with Let's encrypt as: ${EMAIL:=hostmaster@${HOSTNAME#*.}} | ||
53 | - 6. Request a Let's Encrypt SSL certificate for: ${CERTNAME:=$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2 | cut -d@ -f1)} | ||
54 | - with DNS Alternative names: ${DNSALTNAMES:=$(ipa host-show $HOSTNAME --raw | fgrep "krbprincipalname: host/" | cut -d/ -f2 | cut -d@ -f1 | paste -sd,)} | 57 | + 5. Register with Let's encrypt as: $EMAIL |
58 | + 6. Request a Let's Encrypt SSL certificate for: $CERTNAME | ||
59 | + with DNS Alternative names: $DNSALTNAMES | ||
55 | 7. install the Let's Encrypt certificate in apache as host SSL certificate, | 60 | 7. install the Let's Encrypt certificate in apache as host SSL certificate, |
56 | storing renewal config in: /etc/letsencrypt/renewal/$HOSTNAME.conf | 61 | storing renewal config in: /etc/letsencrypt/renewal/$HOSTNAME.conf |
57 | 8. configure the Fedora Certbot renew timer so that certbot is run daily to | 62 | 8. configure the Fedora Certbot renew timer so that certbot is run daily to |
@@ -121,7 +126,7 @@ $SUDO systemctl enable --now certbot-renew.timer | @@ -121,7 +126,7 @@ $SUDO systemctl enable --now certbot-renew.timer | ||
121 | 126 | ||
122 | cat << EOT | 127 | cat << EOT |
123 | 128 | ||
124 | -FreeIPA was successfully setup to use a Let\'s Encrypt certificate for its web | 129 | +FreeIPA was successfully setup to use a Let's Encrypt certificate for its web |
125 | interface. This certificate will be renewed automatically when needed. | 130 | interface. This certificate will be renewed automatically when needed. |
126 | 131 | ||
127 | EOT | 132 | EOT |
set-dns-source.sh
0 → 100755
1 | +#!/bin/bash -e | ||
2 | +# | ||
3 | +# set-dns-source.sh - Setup Source NAT in firewalld for outgoing DNS traffic | ||
4 | +# | ||
5 | +# Version 1.0, latest version, documentation and bugtracker available at: | ||
6 | +# https://gitlab.lindenaar.net/scripts/freeipa | ||
7 | +# | ||
8 | +# Copyright (c) 2018 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 | +case $1 in | ||
22 | + install) CMD=add | ||
23 | + ;; | ||
24 | + remove) CMD=remove | ||
25 | + ;; | ||
26 | + *) echo "usage: $0 <install | remove>" | ||
27 | + exit 1 | ||
28 | +esac | ||
29 | + | ||
30 | +IPV4ADDR=${IPV4ADDR:?Please provide an IPv4 address or set to 'none'} | ||
31 | +IPV6ADDR=${IPV6ADDR:?Please provide an IPv6 address or set to 'none'} | ||
32 | + | ||
33 | +DEV=${DEV:=$( /usr/sbin/ip route | fgrep ${IPV4ADDR:?No IPv4 address provided, please set device manually} | cut -d\ -f3 )} | ||
34 | +: ${DEV:?No route found for $IPV4ADDR, please check config or set device manually} | ||
35 | + | ||
36 | +# inspired by https://blog.sebastien.raveau.name/2009/04/per-process-routing.html | ||
37 | +# and https://unix.stackexchange.com/questions/389756/how-to-use-snat-with-firewalld-vs-masq | ||
38 | + | ||
39 | +for PROTO in ipv4 ipv6; do | ||
40 | + [ "$PROTO" == ipv6 ] && ADDR="$IPV6ADDR" || ADDR="$IPV4ADDR" | ||
41 | + if [ -n "$ADDR" -a "$ADDR" != none ]; then | ||
42 | + for MODE in "" --permanent; do | ||
43 | + firewall-cmd $MODE --direct --$CMD-rule $PROTO mangle OUTPUT 0 -m owner --uid-owner named -j MARK --set-mark 53 | ||
44 | + firewall-cmd $MODE --direct --$CMD-rule $PROTO nat POSTROUTING 0 -o $DEV -m mark --mark 53 -j SNAT --to-source $ADDR | ||
45 | + done | ||
46 | + fi | ||
47 | +done | ||
48 | + |