|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
FreeIPA Scripts
===============
This repository contains a small collection of scripts written to migrate my
existing LDAP/DNS setup (MacOS Server) to [FreeIPA](https://www.freeipa.org)
and manage my setup afterwards. These scripts provide functionality unavailable
in the FreeIPA command line tools. They use the FreeIPA API as much as possible
as I didn't like the provided alternatives for migration to directly update the
FreeIPA LDAP database. Most of these script / commands are meant to synchronize
between an existing situation and FreeIPA and are safe to run multiple times.
As side-effect, this also makes them suitable to support a gradual migration
over time (where a source system is still in production until final cut-over)
The latest versions, documentation and a bug tracker are available on my
[GitLab instance](https://gitlab.lindenaar.net/scripts/freeipa)
Copyright (c) 2018 Frederik Lindenaar. free for distribution under the GNU
General Public License, see [below](#license)
Contents
========
This repository contains the following scripts:
* [users2freeipa.py](#users2freeipa)
is a migration script to transfer/synchronize LDAP users to/with FreeIPA
* [freeipa-dns.py](#freeipadns)
is a script providing functionality not available in FreeIPA itself to
migrate/synchronize and maintain DNS zones in FreeIPA
|
|
27
28
29
|
* [freeipa-letsencrypt.sh](#freeipaletsencrypt)
is a script to setup and configure Certbot and FreeIPA to request and renew
use publicly verifiable Let's Encrypt certificate(s)
|
|
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
<a name=users2freeipa>users2freeipa.py</a>
---------------------------------------------
This script uses LDAP to obtain users from a MacOS Server (or other LDAP)
server and synchronizes the results with the users registered in FreeIPA.
Since it synchronizes data it is safe to run multiple times and users can be
imported also as stage users initially.
The intent is to migrate user data and to not drag on a legacy setup. For
this reason, the script will create new user and group IDs and not copy homedir
and shell information by default. For the IDs, the legacy information can be
stored in an FreeIPA ID View so it remains available, other items can be copied
over using command line options. Passwords can be copied-over (if available in
a usable format), and the script also supports having FreeIPA generate random
passwords and store these in a file for further processing/sharing with users.
Users can be copied from an existing (generic) LDAP database and a MacOS Server
OpenDirectory-flavor LDAP server. In this case, additional information (e.g.
Apple's generatedUID) will be copied over as well. Please note that this does
require customizing the FreeIPA LDAP schema, which the script will check for
and can install (option ```-U```). As the setup is modular it should be easy
to tweak or add other migrations.
By default all users will be migrated/synchronized, but it is also possible to
limit this to specific user(s) or group(s) or specifically exclude specific
users or groups. An example to copy all users in the group ```workgroup```
except ```admin``` from an Apple MacOS OpenDirectory server:
~~~
./users2freeipa.py -v -O -U -c "Legacy LDAP" -g workgroup -x admin -G \
-P -p passwords.txt ldap://ldap.mydomain.tld
~~~
This will also install the OpenDirectory-specific schema customization, create
groups and copy group memberships, copy usuable passwords and ensure that all
users have a password (storing generated passwords to ```passwords.txt```)
|
|
66
67
68
69
70
71
72
73
|
Please note that migrating existing passwords from LDAP has limitations, see
[this](https://www.freeipa.org/page/NIS_accounts_migration_preserving_Passwords)
page on migrating NIS passwords and [this](https://pagure.io/freeipa/issue/4732)
issue reported with it. Bottom line is that (at this moment) password migration
is flawed and always will require manual action from the user. For this reason
the better alternative to set a random password and ask the user to reset the
password using the FreeIPA portal makes more sense.
|
|
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
Before running a production user migration, it is important to have FreeIPA
setup and configured correctly so that the right defaults are used for new
users. Best is to start with a single user and add that as a stage user (please
note that this will not yet assign userIDs, group memberships and a password
as FreeIPA does not yet support that) and use an ID View to store legacy data.
For all available command-line options, run ```users2freeipa.py -h```
<a name=freeipadns>freeipa-dns.py</a>
----------------------------------------------------------------
This script provides functionality not provided by FreeIPA to migrate and/or
synchronize / maintain DNS data in FreeIPA. Currently the following commands
are implemented:
* axfr - import/synchronize a DNS zone in FreeIPA using a zone-xfer.
for example, to migrate / synchronize fromain ```domain.tld``` from DNS
server ```192.168.1.53``` without checking DNS overlap, issue the command:
|
|
91
|
|
|
92
93
94
|
~~~
./freeipa-dns.py -v axfr -T 172.1.2.53 -n -f none 192.168.1.53 domain.tld
~~~
|
|
95
|
|
|
96
97
|
in addition, this will ensure zone-xfers are allowed from ```172.1.2.53```
and disable forwarding in FreeIPA.
|
|
98
|
|
|
99
100
101
|
* copy - copy a DNS record in FreeIPA within or between zones
for example, to copy ```A``` and ```AAAA``` from host ```wwww.domain.tld```
to the domain ```domain.tld``` itself, issue the command:
|
|
102
|
|
|
103
104
105
|
~~~
./freeipa-dns.py -v copy -l A AAAA wwww.domain.tld -T domain.tld
~~~
|
|
106
|
|
|
107
108
109
|
* move - move a DNS record in FreeIPA from one one to another
for example, to move ```host1.int``` in zone ```domain.tld``` to ```host```
in zone ```int.domain.tld``` issue the command:
|
|
110
|
|
|
111
112
113
|
~~~
./freeipa-dns.py -v move -z domain.tld host.int host.int.domain.tld
~~~
|
|
114
|
|
|
115
116
117
118
|
* serial - update (set) zone serial(s) in FreeIPA, supporting both RFC1912
style serials (YYYYMMDD##) based on current date and setting the serial to
a specific value. To set the serial of a zone to revision 2 of today for
zones ```zone1.mydomain.tld``` and ```zone2.mydomain.tld```, run:
|
|
119
|
|
|
120
121
122
|
~~~~
./freeipa-dns.py -v serial -t 2 zone1.mydomain.tld zone2.mydomain.tld
~~~~
|
|
123
|
|
|
124
125
|
by default this command will set the serial to a larger value (which can be
overridden with the ```-f```/```--force``` flag)
|
|
126
|
|
|
127
128
129
130
|
* generate - generate number-range DNS records/attributes in FreeIPA
This is meant to generate series of hosts or attributes, for example, to
generate hosts ```dhcp-01``` to ```dhcp-10``` in zone ```int.mydomain.tld```
with ip addresses starting from ```192.168.2.100``` issue to command:
|
|
131
|
|
|
132
133
134
135
|
~~~
./freeipa-dns.py -v generate int.mydomain.tld dhcp-%02d -4 192.168.2.100 \
--auto-increment-a -n 5
~~~
|
|
136
|
|
|
137
138
|
it can also be used to generate a farm of web servers in different subnets
with the command:
|
|
139
|
|
|
140
141
142
|
~~~
./freeipa-dns.py -v generate int.mydomain.tld www -4 192.168.%d.80 -n 5
~~~
|
|
143
|
|
|
144
145
146
147
148
|
* reverse-ptr - create/update reverse DNS (PTR) entries in FreeIPA
With this command reverse-zones can be automatically maintained. it scans
the zones in FreeIPA for ```A``` and ```AAAA``` records and creates the
corresponding records in the ```in-addr.arpa``` and ```ip6.arpa``` zones.
The reverse zones must exist, and can also be created with this command by:
|
|
149
|
|
|
150
151
152
|
~~~
./freeipa-dns.py -v reverse-ptr -n -p -c 10. 10.100 192.168 2001:0db8:85a3
~~~
|
|
153
|
|
|
154
155
156
|
which will create the reverse zones for prefixes 10.* 10.100.* 192.168.*
and ipv6 prefix 2001:0db8:85a3. Reverse (PTR) records will automatically be
created in the correct zone with the following command:
|
|
157
|
|
|
158
159
160
|
~~~
./freeipa-dns.py -v reverse-ptr -a
~~~
|
|
161
|
|
|
162
163
164
|
by default, the command will not overwrite existing records, (which can be
overridden with the ```-o```/```--override``` flag). To force a PTR record
to point to a specific host, e.g. ```www.mydomain.tld``` run the command:
|
|
165
|
|
|
166
167
168
169
170
171
172
173
|
~~~
./freeipa-dns.py -v reverse-ptr -o -z mydomain.tld -H www
~~~
for available commands run ```freeipa-dns.py -h``` and to get an overview of
the available options for each commmand run ```freeipa-dns.py <command> -h```
|
|
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
<a name=freeipaletsencrypt>freeipa-letsencrypt.sh</a>
----------------------------------------------------------------
This script will ensure the necessary setup is in place so that Certbot (EFF's
certificate request script for Let's Encrypt) will work with FreeIPA for DNS
challenges and and instructs it to deploy new certificates for FreeIPA's web
interface. Before writing this script I looked at available options, especially
[freeipa-letsencrypt](https://github.com/freeipa/freeipa-letsencrypt) and [antevens'](https://github.com/antevens/letsencrypt-freeipa) implementation but
decided to take a slightly different approach where Certbot does all the work
and the setup script will only ensure that the environment is prepared and that
Certbot is initially instructed correctly. This allows to fully tie-in with how
Certbot handles renews and use the Certbot package's provided method to schedule
these.
The following changes will be made for this:
1. Add Let's Encrypt Root and Intermediate CAs as trusted CAs
2. Create DNS Administrator role in FreeIPA that can edit any DNS Record
3. Create host service: ${SERVICE}
4. Allow letsencrypt host service to manage DNS entries
5. Register with Let's encrypt as: ${EMAIL}
6. Request a Let's Encrypt SSL certificate for: ${CERTNAME}
with DNS Alternative names: ${DNSALTNAMES}
7. install the Let's Encrypt certificate in apache as host SSL certificate,
storing renewal config in: /etc/letsencrypt/renewal/$HOSTNAME.conf
8. configure the Fedora Certbot renew timer so that certbot is run daily to
renew the certificate when needed.
The script is built to auto-configure but many of the defaults can be overridden
by setting one of the following environment variables:
| Variable | Description | Default value |
|-------------|------------------------------------|---------------------------|
| CERTNAME | certificate hostname, | host's canonicalname (*) |
| DNSALTNAMES | certificate DNS names | host's principalnames (*) |
| DOMAIN | Let's Encrypt challenge DNS zone | {DNS name's domain} (**) |
| EMAIL | administrator's e-mail address | hostmaster@{domain} |
| HOSTNAME | FreeIPA server's hostname | `hostname --fqdn` |
| KEYTAB | Let'sEncrypt service's keytab file | /etc/letsencrypt/keytab |
| KRB5CCNAME | Kerberos5 cache to use for tickets | automatically determined |
| REPLY | when 'y' skip user confirmation | "" |
| SERVICE | FreeIPA service for Certbot to use | letsencrypt/canonicalname |
| SUDO | command to become root (if needed) | sudo |
| TMPDIR | Directory for temporary files | /tmp |
(*) obtained from the FreeIPA server record looked up based on ${HOSTNAME}
(**) this allows to enforce the DNS zone, e.g. host.subdomain in mydomain.tld
When things change, the script can simply be run again.
|
|
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
<a name="license">License</a>
-----------------------------
These scripts, documentation & configration examples are free software: you can
redistribute and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This script, documenatation and configuration examples are distributed in the
hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, download it from <http://www.gnu.org/licenses/>.
|