mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-28 22:33:05 +00:00
Compare commits
45 Commits
validate_e
...
v1.15.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fc1b043c1 | ||
|
|
bdf1efde80 | ||
|
|
513d5ee46b | ||
|
|
cd440a2049 | ||
|
|
e2317f304c | ||
|
|
7a23c668fc | ||
|
|
91d818b334 | ||
|
|
902d8b7238 | ||
|
|
d553f9a0b1 | ||
|
|
9cfe835b03 | ||
|
|
30c405cb36 | ||
|
|
7275bbf6a3 | ||
|
|
6df89ad7db | ||
|
|
c5fa54f2cf | ||
|
|
8e3102270d | ||
|
|
89cfb5f4c4 | ||
|
|
5fb22581bb | ||
|
|
6976ef57eb | ||
|
|
0d9b164358 | ||
|
|
8b03e4d007 | ||
|
|
ef73a85320 | ||
|
|
5b3a4729f0 | ||
|
|
7245339934 | ||
|
|
638422e113 | ||
|
|
432376524c | ||
|
|
86701caf8b | ||
|
|
d1857c18ac | ||
|
|
edbdd3af79 | ||
|
|
2d3da2d72c | ||
|
|
329c16f742 | ||
|
|
66c0be06d0 | ||
|
|
f04c90f4db | ||
|
|
dfa4bcb68f | ||
|
|
b1328ba7d5 | ||
|
|
fe58f3a8ba | ||
|
|
4dc6192640 | ||
|
|
e9435410b2 | ||
|
|
de6a0429a0 | ||
|
|
40d85f83e4 | ||
|
|
678927f35c | ||
|
|
f0e6d0c89f | ||
|
|
c095c24950 | ||
|
|
34dc75802c | ||
|
|
feb33e4e3a | ||
|
|
3c50a8121f |
@@ -26,7 +26,7 @@ repos:
|
||||
- id: yamllint
|
||||
files: \.(yaml|yml)$
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 7.0.0
|
||||
rev: 7.2.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/pycqa/pylint
|
||||
|
||||
@@ -68,23 +68,6 @@ Example playbook to ensure a local domain idrange is present:
|
||||
name: local_domain_id_range
|
||||
base_id: 150000
|
||||
range_size: 200000
|
||||
```
|
||||
|
||||
Example playbook to ensure a local domain idrange is present, with RID and secondary RID base values:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idrange.
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure local idrange is present
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: local_domain_id_range
|
||||
base_id: 150000000
|
||||
range_size: 200000
|
||||
rid_base: 1000000
|
||||
secondary_rid_base: 200000000
|
||||
```
|
||||
@@ -172,8 +155,8 @@ Variable | Description | Required
|
||||
`name` \| `cn` | The list of idrange name strings. | yes
|
||||
`base_id` \| `ipabaseid` | First Posix ID of the range. (int) | yes, if `state: present`
|
||||
`range_size` \| `ipaidrangesize` | Number of IDs in the range. (int) | yes, if `state: present`
|
||||
`rid_base` \| `ipabaserid` | First RID of the corresponding RID range. (int) | no
|
||||
`secondary_rid_base` \| `ipasecondarybaserid` | First RID of the secondary RID range. (int) | no
|
||||
`rid_base` \| `ipabaserid` | First RID of the corresponding RID range. (int) | yes, if `idrange_type: ipa-local` and `state: present` |
|
||||
`secondary_rid_base` \| `ipasecondarybaserid` | First RID of the secondary RID range. (int) | yes, if `idrange_type: ipa-local` and `state: present` |
|
||||
`dom_sid` \| `ipanttrusteddomainsid` | Domain SID of the trusted domain. | no
|
||||
`idrange_type` \| `iparangetype` | ID range type, one of `ipa-ad-trust`, `ipa-ad-trust-posix`, `ipa-local`. Only valid if idrange does not exist. | no
|
||||
`dom_name` \| `ipanttrusteddomainname` | Name of the trusted domain. Can only be used when `ipaapi_context: server`. | no
|
||||
|
||||
@@ -3,7 +3,7 @@ trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
variables:
|
||||
ansible_version: "-core >=2.16,<2.17"
|
||||
|
||||
@@ -10,7 +10,7 @@ schedules:
|
||||
trigger: none
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
variables:
|
||||
# We need to have two sets, as c8s is not supported by all ansible versions
|
||||
|
||||
@@ -3,7 +3,7 @@ trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
variables:
|
||||
distros: "fedora-latest,c10s,c9s,c8s,fedora-rawhide"
|
||||
|
||||
@@ -119,13 +119,6 @@ then
|
||||
deployed=true
|
||||
fi
|
||||
echo
|
||||
|
||||
if $deployed; then
|
||||
log info "= Enabling services ="
|
||||
container_exec "${name}" systemctl enable fixnet
|
||||
container_exec "${name}" systemctl enable fixipaip
|
||||
echo
|
||||
fi
|
||||
|
||||
container_stop "${name}"
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -4,13 +4,20 @@
|
||||
SCRIPTDIR="$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")"
|
||||
TOPDIR="$(readlink -f "${SCRIPTDIR}/../..")"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. "${SCRIPTDIR}/shdefaults"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. "${TOPDIR}/utils/shfun"
|
||||
|
||||
container_create() {
|
||||
local name=${1}
|
||||
local image=${2}
|
||||
shift 2
|
||||
declare -a extra_opts=()
|
||||
declare -a extra_opts
|
||||
readarray -t extra_opts < \
|
||||
<(sed -e "s/-/--cap-drop=/g" -e "s/+/--cap-add=/g" \
|
||||
<<< "$(printf '%s\n' "${CAP_DEFAULTS[@]}")")
|
||||
for opt in "$@"
|
||||
do
|
||||
[ -z "${opt}" ] && continue
|
||||
@@ -19,6 +26,7 @@ container_create() {
|
||||
cpus=*) extra_opts+=("--${opt}") ;;
|
||||
memory=*) extra_opts+=("--${opt}") ;;
|
||||
capabilities=*) extra_opts+=("--cap-add=${opt##*=}") ;;
|
||||
volume=*) extra_opts+=("--volume=${opt##*=}") ;;
|
||||
*) log error "container_create: Invalid option: ${opt}" ;;
|
||||
esac
|
||||
done
|
||||
@@ -47,6 +55,19 @@ container_start() {
|
||||
|
||||
log info "= Starting ${name} ="
|
||||
podman start "${name}"
|
||||
# Add host entry to /etc/hosts
|
||||
ip=$(podman inspect "${name}" --format "{{.NetworkSettings.IPAddress}}")
|
||||
hostname=$(podman inspect "${name}" --format "{{.Config.Hostname}}")
|
||||
if [ -n "${ip}" ] && [ -n "${hostname}" ]; then
|
||||
cmd=$(cat <<EOF
|
||||
sed -i -E "/\s+${hostname}(\s|$)/d" /etc/hosts
|
||||
echo -e "$ip\t${hostname} ${hostname%%.*}" >> /etc/hosts
|
||||
EOF
|
||||
)
|
||||
podman exec "${name}" bash -c "$cmd"
|
||||
fi
|
||||
# Ensure /etc/shadow is readable
|
||||
podman exec "${name}" bash -c "chmod u+r /etc/shadow"
|
||||
echo
|
||||
}
|
||||
|
||||
@@ -195,3 +216,15 @@ container_fetch() {
|
||||
podman cp "${name}:${source}" "${destination}"
|
||||
echo
|
||||
}
|
||||
|
||||
container_tee() {
|
||||
local name=${1}
|
||||
local destination=${2}
|
||||
tmpfile=$(mktemp /tmp/container-temp.XXXXXX)
|
||||
|
||||
log info "= Creating ${name}:${destination} from stdin ="
|
||||
cat - > "${tmpfile}"
|
||||
podman cp "${tmpfile}" "${name}:${destination}"
|
||||
rm "${tmpfile}"
|
||||
echo
|
||||
}
|
||||
|
||||
9
infra/image/shdefaults
Normal file
9
infra/image/shdefaults
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -eu
|
||||
# This file is meant to be source'd by other scripts
|
||||
|
||||
# Set default capabilities options for freeipa containers.
|
||||
# Use +CAP to add the capability and -CAP to drop the capability.
|
||||
CAP_DEFAULTS=(
|
||||
"+DAC_READ_SEARCH" # Required for SSSD
|
||||
"+SYS_PTRACE" # Required for debugging
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
[Unit]
|
||||
Description=Fix IPA server IP in IPA Server
|
||||
After=ipa.service
|
||||
PartOf=ipa.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
@@ -9,4 +10,4 @@ StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=ipa.service
|
||||
|
||||
@@ -50,9 +50,9 @@ if [ -z "${FORWARDER}" ] || [ "${FORWARDER}" == "127.0.0.1" ]; then
|
||||
fi
|
||||
|
||||
echo "Fix IPA:"
|
||||
echo " HOSTNAME: '${HOSTNAME}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo " PTR: '${PTR}'"
|
||||
echo " HOSTNAME: '${HOSTNAME}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo " PTR: '${PTR}'"
|
||||
echo " FORWARDER: '${FORWARDER}'"
|
||||
|
||||
ZONES=$(ipa -e in_server=true dnszone-find --name-from-ip="${HOSTNAME}." \
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
[Unit]
|
||||
Description=Fix server IP in IPA Server
|
||||
Wants=network.target
|
||||
After=network.target
|
||||
Before=ipa.service
|
||||
Description=Fix /etc/hosts and with local DNS also /etc/resolv.conf
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
@@ -11,4 +8,4 @@ StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=ipa.service
|
||||
WantedBy=container-ipa.target
|
||||
|
||||
@@ -39,26 +39,35 @@ if [ -z "${IP}" ] || ! valid_ipv4 "${IP}" ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOMAIN=${HOSTNAME#*.}
|
||||
|
||||
echo "Fix NET:"
|
||||
echo " HOSTNAME: '${HOSTNAME}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo " DOMAIN: '${DOMAIN}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo
|
||||
|
||||
if grep -qE "^[^(#\s*)][0-9\.]+\s$HOSTNAME(\s|$)" /etc/hosts
|
||||
then
|
||||
sed -i.bak -e "s/.*${HOSTNAME}/${IP}\t${HOSTNAME}/" /etc/hosts
|
||||
else
|
||||
echo -e "$IP\t${HOSTNAME} ${HOSTNAME%%.*}" >> /etc/hosts
|
||||
fi
|
||||
# /etc/hosts
|
||||
|
||||
cp -a /etc/resolv.conf /etc/resolv.conf.fixnet
|
||||
cat > /etc/resolv.conf <<EOF
|
||||
search ${HOSTNAME#*.}
|
||||
nameserver 127.0.0.1
|
||||
EOF
|
||||
sed -i -E "/\s+${HOSTNAME}(\s|$)/d" /etc/hosts
|
||||
echo -e "$IP\t${HOSTNAME} ${HOSTNAME%%.*}" >> /etc/hosts
|
||||
|
||||
echo "/etc/hosts:"
|
||||
cat "/etc/hosts"
|
||||
|
||||
# /etc/resolv.conf
|
||||
|
||||
# If bind is not installed, exit
|
||||
[ -f "/etc/named.conf" ] || exit 0
|
||||
# If dyndb is not enabled for bind, exit
|
||||
grep -q '^dyndb "ipa"' "/etc/named.conf" || exit 0
|
||||
|
||||
cp -a /etc/resolv.conf /etc/resolv.conf.fixnet
|
||||
cat > /etc/resolv.conf <<EOF
|
||||
search ${DOMAIN}
|
||||
nameserver 127.0.0.1
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo "/etc/resolv.conf:"
|
||||
cat "/etc/resolv.conf"
|
||||
|
||||
@@ -281,6 +281,14 @@ def main():
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
# set required fields
|
||||
required = ["base_id", "range_size"]
|
||||
requires_baserid = (
|
||||
ansible_module.ipa_command_param_exists("config_mod", "enable_sid")
|
||||
and idrange_type in [None, "ipa-local"]
|
||||
)
|
||||
if requires_baserid:
|
||||
required.extend(["rid_base", "secondary_rid_base"])
|
||||
|
||||
commands = []
|
||||
for name in names:
|
||||
@@ -321,6 +329,18 @@ def main():
|
||||
del args["iparangetype"]
|
||||
commands.append([name, "idrange_mod", args])
|
||||
else:
|
||||
# Check if required parameters were given
|
||||
missing_params = [
|
||||
pname for pname in required
|
||||
if ansible_module.params_get(pname) is None
|
||||
]
|
||||
if missing_params:
|
||||
ansible_module.fail_json(
|
||||
msg=(
|
||||
"Missing required parameters: %s"
|
||||
% (", ".join(missing_params))
|
||||
)
|
||||
)
|
||||
commands.append([name, "idrange_add", args])
|
||||
|
||||
elif state == "absent":
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-r requirements-tests.txt
|
||||
ipdb==0.13.4
|
||||
pre-commit==2.20.0
|
||||
flake8==7.0.0
|
||||
flake8
|
||||
flake8-bugbear
|
||||
pylint>=3.2
|
||||
wrapt==1.14.1
|
||||
|
||||
@@ -202,6 +202,8 @@ Variable | Description | Required
|
||||
`ipaclient_request_cert` | The bool value defines if the certificate for the machine wil be requested. The certificate will be stored in /etc/ipa/nssdb under the nickname "Local IPA host". . `ipaclient_request_cert` defaults to `no`. The option is deprecated and will be removed in a future release. | no
|
||||
`ipaclient_keytab` | The string value contains the path on the node of a backup host keytab from a previous enrollment. | no
|
||||
`ipaclient_automount_location` | Automount location | no
|
||||
`ipaclient_dns_over_tls` | Configure DNS over TLS. Requires FreeIPA version 4.12.5 or later. (bool, default: false) | no
|
||||
`ipaclient_no_dnssec_validation` | Disable DNSSEC validation for DNS over TLS. This turns off DNSSEC validation for unbound. Ignored if `ipaserver_dns_over_tls` is not enabled. (bool, default: false) | no
|
||||
|
||||
|
||||
Server Variables
|
||||
|
||||
@@ -26,6 +26,8 @@ ipasssd_enable_dns_updates: no
|
||||
ipasssd_no_krb5_offline_passwords: no
|
||||
ipasssd_preserve_sssd: no
|
||||
ipaclient_request_cert: no
|
||||
ipaclient_dns_over_tls: no
|
||||
ipaclient_no_dnssec_validation: no
|
||||
|
||||
### packages ###
|
||||
ipaclient_install_packages: yes
|
||||
|
||||
@@ -86,6 +86,16 @@ options:
|
||||
type: bool
|
||||
required: no
|
||||
default: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
no_dnssec_validation:
|
||||
description: Disable DNSSEC validation for DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
enable_dns_updates:
|
||||
description: |
|
||||
Configures the machine to attempt dns updates when the ip address
|
||||
@@ -212,7 +222,9 @@ def main():
|
||||
mkhomedir=dict(required=False, type='bool'),
|
||||
on_master=dict(required=False, type='bool'),
|
||||
dnsok=dict(required=False, type='bool', default=False),
|
||||
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
enable_dns_updates=dict(required=False, type='bool'),
|
||||
all_ip_addresses=dict(required=False, type='bool', default=False),
|
||||
ip_addresses=dict(required=False, type='list', elements='str',
|
||||
@@ -249,6 +261,8 @@ def main():
|
||||
options.mkhomedir = module.params.get('mkhomedir')
|
||||
options.on_master = module.params.get('on_master')
|
||||
dnsok = module.params.get('dnsok')
|
||||
options.dns_over_tls = module.params.get('dns_over_tls')
|
||||
options.no_dnssec_validation = module.params.get('no_dnssec_validation')
|
||||
|
||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
|
||||
@@ -256,6 +270,7 @@ def main():
|
||||
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
|
||||
|
||||
options.dns_updates = module.params.get('enable_dns_updates')
|
||||
options.dns_over_tls = module.params.get('dns_over_tls')
|
||||
options.all_ip_addresses = module.params.get('all_ip_addresses')
|
||||
options.ip_addresses = ansible_module_get_parsed_ip_addresses(module)
|
||||
options.request_cert = module.params.get('request_cert')
|
||||
@@ -279,6 +294,7 @@ def main():
|
||||
options.no_sssd = False
|
||||
options.sssd = not options.no_sssd
|
||||
options.no_ac = False
|
||||
options.dns_over_tls = module.params.get('dns_over_tls')
|
||||
nosssd_files = module.params.get('nosssd_files')
|
||||
selinux_works = module.params.get('selinux_works')
|
||||
krb_name = module.params.get('krb_name')
|
||||
@@ -339,17 +355,19 @@ def main():
|
||||
ca_subject)
|
||||
ca_certs_trust = [(c, n,
|
||||
certstore.key_policy_to_trust_flags(t, True, u))
|
||||
for (c, n, t, u) in ca_certs]
|
||||
for (c, n, t, u) in [x[0:4] for x in ca_certs]]
|
||||
|
||||
if hasattr(paths, "KDC_CA_BUNDLE_PEM"):
|
||||
x509.write_certificate_list(
|
||||
[c for c, n, t, u in ca_certs if t is not False],
|
||||
[c for c, n, t, u in [x[0:4] for x in ca_certs]
|
||||
if t is not False],
|
||||
paths.KDC_CA_BUNDLE_PEM,
|
||||
# mode=0o644
|
||||
)
|
||||
if hasattr(paths, "CA_BUNDLE_PEM"):
|
||||
x509.write_certificate_list(
|
||||
[c for c, n, t, u in ca_certs if t is not False],
|
||||
[c for c, n, t, u in [x[0:4] for x in ca_certs]
|
||||
if t is not False],
|
||||
paths.CA_BUNDLE_PEM,
|
||||
# mode=0o644
|
||||
)
|
||||
@@ -370,13 +388,22 @@ def main():
|
||||
tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs)
|
||||
|
||||
if not options.on_master:
|
||||
client_dns(cli_server[0], hostname, options)
|
||||
argspec_client_dns = getargspec(client_dns)
|
||||
if "statestore" in argspec_client_dns.args:
|
||||
client_dns(cli_server[0], hostname, options, statestore)
|
||||
else:
|
||||
client_dns(cli_server[0], hostname, options)
|
||||
|
||||
if hasattr(paths, "SSH_CONFIG_DIR"):
|
||||
ssh_config_dir = paths.SSH_CONFIG_DIR
|
||||
else:
|
||||
ssh_config_dir = services.knownservices.sshd.get_config_dir()
|
||||
update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp)
|
||||
argspec_update_ssh_keys = getargspec(update_ssh_keys)
|
||||
# Hotfix for https://github.com/freeipa/freeipa/pull/7343
|
||||
if "options" in argspec_update_ssh_keys.args:
|
||||
update_ssh_keys(hostname, ssh_config_dir, options, cli_server[0])
|
||||
else:
|
||||
update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp)
|
||||
|
||||
try:
|
||||
os.remove(CCACHE_FILE)
|
||||
|
||||
@@ -91,6 +91,11 @@ options:
|
||||
changes
|
||||
type: bool
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
preserve_sssd:
|
||||
description: Preserve old SSSD configuration if possible
|
||||
type: bool
|
||||
@@ -140,6 +145,7 @@ def main():
|
||||
fixed_primary=dict(required=False, type='bool'),
|
||||
permit=dict(required=False, type='bool'),
|
||||
enable_dns_updates=dict(required=False, type='bool'),
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
preserve_sssd=dict(required=False, type='bool'),
|
||||
no_krb5_offline_passwords=dict(required=False, type='bool'),
|
||||
),
|
||||
@@ -169,11 +175,13 @@ def main():
|
||||
options.primary = module.params.get('fixed_primary')
|
||||
options.permit = module.params.get('permit')
|
||||
options.dns_updates = module.params.get('enable_dns_updates')
|
||||
options.dns_over_tls = module.params.get('dns_over_tls')
|
||||
options.preserve_sssd = module.params.get('preserve_sssd')
|
||||
|
||||
options.no_krb5_offline_passwords = module.params.get(
|
||||
'no_krb5_offline_passwords')
|
||||
options.krb5_offline_passwords = not options.no_krb5_offline_passwords
|
||||
options.dns_over_tls = False
|
||||
|
||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||
client_domain = hostname[hostname.find(".") + 1:]
|
||||
|
||||
@@ -124,6 +124,16 @@ options:
|
||||
type: bool
|
||||
required: no
|
||||
default: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
no_dnssec_validation:
|
||||
description: Disable DNSSEC validation for DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
enable_dns_updates:
|
||||
description:
|
||||
Configures the machine to attempt dns updates when the ip address
|
||||
@@ -248,7 +258,8 @@ from ansible.module_utils.ansible_ipa_client import (
|
||||
CLIENT_INSTALL_ERROR, tasks, check_ldap_conf, timeconf, constants,
|
||||
validate_hostname, nssldap_exists, gssapi, remove_file,
|
||||
check_ip_addresses, ipadiscovery, print_port_conf_info,
|
||||
IPA_PYTHON_VERSION, getargspec
|
||||
IPA_PYTHON_VERSION, getargspec, services,
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION
|
||||
)
|
||||
|
||||
|
||||
@@ -328,6 +339,9 @@ def main():
|
||||
default=None),
|
||||
all_ip_addresses=dict(required=False, type='bool', default=False),
|
||||
on_master=dict(required=False, type='bool', default=False),
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
# sssd
|
||||
enable_dns_updates=dict(required=False, type='bool',
|
||||
default=False),
|
||||
@@ -356,6 +370,8 @@ def main():
|
||||
options.ip_addresses = module.params.get('ip_addresses')
|
||||
options.all_ip_addresses = module.params.get('all_ip_addresses')
|
||||
options.on_master = module.params.get('on_master')
|
||||
options.dns_over_tls = module.params.get('dns_over_tls')
|
||||
options.no_dnssec_validation = module.params.get('no_dnssec_validation')
|
||||
options.enable_dns_updates = module.params.get('enable_dns_updates')
|
||||
|
||||
# Get domain from first server if domain is not set, but if there are
|
||||
@@ -365,6 +381,16 @@ def main():
|
||||
options.domain_name = options.servers[0][
|
||||
options.servers[0].find(".") + 1:]
|
||||
|
||||
if options.dns_over_tls \
|
||||
and not services.knownservices["unbound"].is_installed():
|
||||
module.fail_json(
|
||||
msg="To enable DNS over TLS, package ipa-client-encrypted-dns "
|
||||
"must be installed.")
|
||||
if options.dns_over_tls and not CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION:
|
||||
module.fail_json(
|
||||
msg="Important patches for DNS over TLS are missing in your IPA "
|
||||
"version.")
|
||||
|
||||
try:
|
||||
self = options
|
||||
|
||||
|
||||
@@ -231,8 +231,6 @@ try:
|
||||
cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
|
||||
filename, client_domain, client_hostname, force=False,
|
||||
configure_sssd=True):
|
||||
# pylint: disable=global-variable-not-assigned
|
||||
global options
|
||||
options.force = force
|
||||
options.sssd = configure_sssd
|
||||
return ipa_client_install.configure_krb5_conf(
|
||||
@@ -312,6 +310,15 @@ try:
|
||||
except ImportError:
|
||||
configure_selinux_for_client = None
|
||||
|
||||
try:
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = False
|
||||
from ipaclient.install.client import ClientInstallInterface
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
if hasattr(ClientInstallInterface, "no_dnssec_validation"):
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = True
|
||||
|
||||
logger = logging.getLogger("ipa-client-install")
|
||||
root_logger = logger
|
||||
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
---
|
||||
# tasks file for ipaclient
|
||||
|
||||
- name: Install - Ensure that IPA client packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipaclient_packages }}"
|
||||
state: present
|
||||
- name: Install - Package installation
|
||||
when: ipaclient_install_packages | bool
|
||||
block:
|
||||
|
||||
- name: Install - Set packages for installation
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ ipaclient_packages }}"
|
||||
|
||||
- name: Install - Set packages for installlation, add DOT
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipaclient_packages_dot }}"
|
||||
when: ipaclient_dns_over_tls | bool
|
||||
|
||||
- name: Install - Ensure that packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ _ipapackages }}"
|
||||
state: present
|
||||
|
||||
- name: Install - Set ipaclient_servers
|
||||
ansible.builtin.set_fact:
|
||||
@@ -38,7 +50,7 @@
|
||||
msg: "ipaclient_domain or ipaserver_domain is required for ipaclient_configure_dns_resolver"
|
||||
when: ipaserver_domain is not defined and ipaclient_domain is not defined
|
||||
|
||||
- name: Install - Fail on missing ipaclient_servers
|
||||
- name: Install - Fail on missing ipaclient_dns_servers
|
||||
ansible.builtin.fail:
|
||||
msg: "ipaclient_dns_servers is required for ipaclient_configure_dns_resolver"
|
||||
when: ipaclient_dns_servers is not defined
|
||||
@@ -69,9 +81,10 @@
|
||||
ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}"
|
||||
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
|
||||
on_master: "{{ ipaclient_on_master }}"
|
||||
dns_over_tls: "{{ ipaclient_dns_over_tls }}"
|
||||
no_dnssec_validation: "{{ ipaclient_no_dnssec_validation }}"
|
||||
### sssd ###
|
||||
enable_dns_updates: "{{ ipassd_enable_dns_updates
|
||||
| default(ipasssd_enable_dns_updates) }}"
|
||||
enable_dns_updates: "{{ ipasssd_enable_dns_updates }}"
|
||||
register: result_ipaclient_test
|
||||
|
||||
- name: Install - Client deployment
|
||||
@@ -321,16 +334,12 @@
|
||||
no_sshd: "{{ ipaclient_no_sshd }}"
|
||||
no_sudo: "{{ ipaclient_no_sudo }}"
|
||||
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
|
||||
fixed_primary: "{{ ipassd_fixed_primary
|
||||
| default(ipasssd_fixed_primary) }}"
|
||||
permit: "{{ ipassd_permit | default(ipasssd_permit) }}"
|
||||
enable_dns_updates: "{{ ipassd_enable_dns_updates
|
||||
| default(ipasssd_enable_dns_updates) }}"
|
||||
preserve_sssd: "{{ ipassd_preserve_sssd
|
||||
| default(ipasssd_preserve_sssd) }}"
|
||||
no_krb5_offline_passwords:
|
||||
"{{ ipassd_no_krb5_offline_passwords
|
||||
| default(ipasssd_no_krb5_offline_passwords) }}"
|
||||
fixed_primary: "{{ ipasssd_fixed_primary }}"
|
||||
permit: "{{ ipasssd_permit }}"
|
||||
enable_dns_updates: "{{ ipasssd_enable_dns_updates }}"
|
||||
dns_over_tls: "{{ ipaclient_dns_over_tls }}"
|
||||
preserve_sssd: "{{ ipasssd_preserve_sssd }}"
|
||||
no_krb5_offline_passwords: "{{ ipasssd_no_krb5_offline_passwords }}"
|
||||
|
||||
- name: Install - IPA API calls for remaining enrollment parts
|
||||
ipaclient_api:
|
||||
@@ -365,23 +374,20 @@
|
||||
ca_enabled: "{{ result_ipaclient_api.ca_enabled }}"
|
||||
on_master: "{{ ipaclient_on_master }}"
|
||||
dnsok: "{{ result_ipaclient_test.dnsok }}"
|
||||
enable_dns_updates: "{{ ipassd_enable_dns_updates
|
||||
| default(ipasssd_enable_dns_updates) }}"
|
||||
enable_dns_updates: "{{ ipasssd_enable_dns_updates }}"
|
||||
dns_over_tls: "{{ ipaclient_dns_over_tls }}"
|
||||
no_dnssec_validation: "{{ ipaclient_no_dnssec_validation }}"
|
||||
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
|
||||
ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}"
|
||||
request_cert: "{{ ipaclient_request_cert }}"
|
||||
preserve_sssd: "{{ ipassd_preserve_sssd
|
||||
| default(ipasssd_preserve_sssd) }}"
|
||||
preserve_sssd: "{{ ipasssd_preserve_sssd }}"
|
||||
no_ssh: "{{ ipaclient_no_ssh }}"
|
||||
no_sshd: "{{ ipaclient_no_sshd }}"
|
||||
no_sudo: "{{ ipaclient_no_sudo }}"
|
||||
subid: "{{ ipaclient_subid }}"
|
||||
fixed_primary: "{{ ipassd_fixed_primary
|
||||
| default(ipasssd_fixed_primary) }}"
|
||||
permit: "{{ ipassd_permit | default(ipasssd_permit) }}"
|
||||
no_krb5_offline_passwords:
|
||||
"{{ ipassd_no_krb5_offline_passwords
|
||||
| default(ipasssd_no_krb5_offline_passwords) }}"
|
||||
fixed_primary: "{{ ipasssd_fixed_primary }}"
|
||||
permit: "{{ ipasssd_permit }}"
|
||||
no_krb5_offline_passwords: "{{ ipasssd_no_krb5_offline_passwords }}"
|
||||
no_dns_sshfp: "{{ ipaclient_no_dns_sshfp }}"
|
||||
nosssd_files: "{{ result_ipaclient_test.nosssd_files }}"
|
||||
selinux_works: "{{ result_ipaclient_test.selinux_works }}"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
# vars/Debian.yml
|
||||
ipaclient_packages: [ "freeipa-client" ]
|
||||
ipaclient_packages_dot: [ ]
|
||||
# Debian Buster must use python2 as Python interpreter due
|
||||
# to the way freeipa-client package is defined.
|
||||
# You must install package python2.7 before executing this role.
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# vars/Debian.yml
|
||||
---
|
||||
ipaclient_packages: [ "freeipa-client" ]
|
||||
ipaclient_packages_dot: [ ]
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# vars/RedHat-7
|
||||
---
|
||||
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
|
||||
ipaclient_packages_dot: [ ]
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# vars/RedHat-8.yml
|
||||
---
|
||||
ipaclient_packages: [ "@idm:DL1/client" ]
|
||||
ipaclient_packages_dot: [ ]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# vars/Ubuntu-18.04.yml
|
||||
---
|
||||
ipaclient_packages: [ "freeipa-client" ]
|
||||
ipaclient_packages_dot: [ ]
|
||||
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
|
||||
# to the way python-ipalib package is defined.
|
||||
# Package python2.7 must be installed before executing this role.
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# vars/default.yml
|
||||
---
|
||||
ipaclient_packages: [ "ipa-client", "python3-libselinux" ]
|
||||
ipaclient_packages_dot: [ "ipa-client-encrypted-dns" ]
|
||||
|
||||
@@ -270,6 +270,11 @@ Variable | Description | Required
|
||||
`ipareplica_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
|
||||
`ipareplica_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first,only) | no
|
||||
`ipareplica_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
|
||||
`ipareplica_dot_forwarders` | List of DNS over TLS forwarders. Required if `ipareplica_dns_over_tls` is enabled. (list of strings) | no
|
||||
`ipareplica_dns_over_tls` \| `ipaclient_dns_over_tls` | Configure DNS over TLS. Requires FreeIPA version 4.12.5 or later. (bool, default: false) | no
|
||||
`ipareplica_dns_over_tls_cert` | Certificate to use for DNS over TLS. If empty, a new certificate will be requested from IPA CA. (string) | no
|
||||
`ipareplica_dns_over_tls_key` | Key for certificate specified in `ipareplica_dns_over_tls_cert`. (string) | no
|
||||
`ipareplica_dns_policy` | Encrypted DNS policy. Only usable if `ipareplica_dns_over_tls` is enabled. (choice: relaxed, enforced, default: relaxed) | no
|
||||
|
||||
AD trust Variables
|
||||
------------------
|
||||
|
||||
@@ -224,6 +224,32 @@ options:
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dot_forwarders:
|
||||
description: List of DNS over TLS forwarders
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dns_over_tls_cert:
|
||||
description:
|
||||
Certificate to use for DNS over TLS. If empty, a new
|
||||
certificate will be requested from IPA CA
|
||||
type: str
|
||||
required: no
|
||||
dns_over_tls_key:
|
||||
description: Key for certificate specified in dns_over_tls_cert
|
||||
type: str
|
||||
required: no
|
||||
dns_policy:
|
||||
description: Encrypted DNS policy
|
||||
type: str
|
||||
choices: ['relaxed', 'enforced']
|
||||
default: 'relaxed'
|
||||
enable_compat:
|
||||
description: Enable support for trusted domains for old clients
|
||||
type: bool
|
||||
@@ -354,6 +380,15 @@ def main():
|
||||
choices=['first', 'only'], default=None),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dot_forwarders=dict(required=False, type='list', elements='str',
|
||||
default=[]),
|
||||
dns_over_tls=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dns_over_tls_cert=dict(required=False, type='str'),
|
||||
dns_over_tls_key=dict(required=False, type='str'),
|
||||
dns_policy=dict(required=False, type='str',
|
||||
choices=['relaxed', 'enforced'],
|
||||
default='relaxed'),
|
||||
# ad trust
|
||||
enable_compat=dict(required=False, type='bool', default=False),
|
||||
netbios_name=dict(required=False, type='str'),
|
||||
@@ -430,6 +465,11 @@ def main():
|
||||
options.forward_policy = ansible_module.params.get('forward_policy')
|
||||
options.no_dnssec_validation = ansible_module.params.get(
|
||||
'no_dnssec_validation')
|
||||
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
|
||||
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
|
||||
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
|
||||
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
|
||||
options.dns_policy = ansible_module.params.get('dns_policy')
|
||||
# ad trust
|
||||
options.enable_compat = ansible_module.params.get('enable_compat')
|
||||
options.netbios_name = ansible_module.params.get('netbios_name')
|
||||
|
||||
@@ -72,6 +72,32 @@ options:
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dot_forwarders:
|
||||
description: List of DNS over TLS forwarders
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dns_over_tls_cert:
|
||||
description:
|
||||
Certificate to use for DNS over TLS. If empty, a new
|
||||
certificate will be requested from IPA CA
|
||||
type: str
|
||||
required: no
|
||||
dns_over_tls_key:
|
||||
description: Key for certificate specified in dns_over_tls_cert
|
||||
type: str
|
||||
required: no
|
||||
dns_policy:
|
||||
description: Encrypted DNS policy
|
||||
type: str
|
||||
choices: ['relaxed', 'enforced']
|
||||
default: 'relaxed'
|
||||
dns_ip_addresses:
|
||||
description: The dns ip_addresses setting
|
||||
type: list
|
||||
@@ -117,6 +143,9 @@ from ansible.module_utils.ansible_ipa_replica import (
|
||||
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, dns,
|
||||
ansible_module_get_parsed_ip_addresses
|
||||
)
|
||||
# pylint: disable=unused-import
|
||||
from ansible.module_utils.ansible_ipa_replica import bindinstance # noqa: F401
|
||||
# pylint: enable=unused-import
|
||||
|
||||
|
||||
def main():
|
||||
@@ -135,6 +164,14 @@ def main():
|
||||
choices=['first', 'only'], default=None),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dot_forwarders=dict(required=False, type='list', elements='str',
|
||||
default=[]),
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
dns_over_tls_cert=dict(required=False, type='str'),
|
||||
dns_over_tls_key=dict(required=False, type='str'),
|
||||
dns_policy=dict(required=False, type='str',
|
||||
choices=['relaxed', 'enforced'],
|
||||
default='relaxed'),
|
||||
# additional
|
||||
dns_ip_addresses=dict(required=True, type='list', elements='str'),
|
||||
dns_reverse_zones=dict(required=True, type='list', elements='str'),
|
||||
@@ -167,6 +204,11 @@ def main():
|
||||
options.forward_policy = ansible_module.params.get('forward_policy')
|
||||
options.no_dnssec_validation = ansible_module.params.get(
|
||||
'no_dnssec_validation')
|
||||
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
|
||||
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
|
||||
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
|
||||
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
|
||||
options.dns_policy = ansible_module.params.get('dns_policy')
|
||||
# additional
|
||||
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
|
||||
ansible_module, 'dns_ip_addresses')
|
||||
|
||||
@@ -181,6 +181,32 @@ options:
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dot_forwarders:
|
||||
description: List of DNS over TLS forwarders
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dns_over_tls_cert:
|
||||
description:
|
||||
Certificate to use for DNS over TLS. If empty, a new
|
||||
certificate will be requested from IPA CA
|
||||
type: str
|
||||
required: no
|
||||
dns_over_tls_key:
|
||||
description: Key for certificate specified in dns_over_tls_cert
|
||||
type: str
|
||||
required: no
|
||||
dns_policy:
|
||||
description: Encrypted DNS policy
|
||||
type: str
|
||||
choices: ['relaxed', 'enforced']
|
||||
default: 'relaxed'
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
'''
|
||||
@@ -199,7 +225,8 @@ from ansible.module_utils.ansible_ipa_replica import (
|
||||
paths, sysrestore, ansible_module_get_parsed_ip_addresses, service,
|
||||
redirect_stdout, create_ipa_conf, ipautil,
|
||||
x509, validate_domain_name, common_check,
|
||||
IPA_PYTHON_VERSION, getargspec, adtrustinstance, install_ca_cert
|
||||
IPA_PYTHON_VERSION, getargspec, adtrustinstance, install_ca_cert,
|
||||
services, CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION
|
||||
)
|
||||
|
||||
|
||||
@@ -250,6 +277,14 @@ def main():
|
||||
choices=['first', 'only'], default=None),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dot_forwarders=dict(required=False, type='list', elements='str',
|
||||
default=[]),
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
dns_over_tls_cert=dict(required=False, type='str'),
|
||||
dns_over_tls_key=dict(required=False, type='str'),
|
||||
dns_policy=dict(required=False, type='str',
|
||||
choices=['relaxed', 'enforced'],
|
||||
default='relaxed'),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -298,6 +333,11 @@ def main():
|
||||
options.forward_policy = ansible_module.params.get('forward_policy')
|
||||
options.no_dnssec_validation = ansible_module.params.get(
|
||||
'no_dnssec_validation')
|
||||
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
|
||||
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
|
||||
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
|
||||
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
|
||||
options.dns_policy = ansible_module.params.get('dns_policy')
|
||||
|
||||
##########################################################################
|
||||
# replica init ###########################################################
|
||||
@@ -419,6 +459,14 @@ def main():
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --no-dnssec-validation option "
|
||||
"without the --setup-dns option")
|
||||
if installer.dns_over_tls_cert:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dns-over-tls-cert option "
|
||||
"without the --setup-dns option")
|
||||
if installer.dns_over_tls_key:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dns-over-tls-key option "
|
||||
"without the --setup-dns option")
|
||||
elif installer.forwarders and installer.no_forwarders:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --forwarder option together with "
|
||||
@@ -435,6 +483,31 @@ def main():
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --auto-reverse option together with "
|
||||
"--no-reverse")
|
||||
elif installer.dot_forwarders and not installer.dns_over_tls:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dot-forwarder option "
|
||||
"without the --dns-over-tls option")
|
||||
elif (installer.dns_over_tls
|
||||
and not services.knownservices["unbound"].is_installed()):
|
||||
ansible_module.fail_json(
|
||||
msg="To enable DNS over TLS, package ipa-server-encrypted-dns "
|
||||
"must be installed.")
|
||||
elif installer.dns_policy == "enforced" and not installer.dns_over_tls:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dns-policy option "
|
||||
"without the --dns-over-tls option")
|
||||
elif installer.dns_over_tls_cert and not installer.dns_over_tls:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dns-over-tls-cert option "
|
||||
"without the --dns-over-tls option")
|
||||
elif installer.dns_over_tls_key and not installer.dns_over_tls:
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dns-over-tls-key option "
|
||||
"without the --dns-over-tls option")
|
||||
elif bool(installer.dns_over_tls_key) != bool(installer.dns_over_tls_cert):
|
||||
ansible_module.fail_json(
|
||||
msg="You cannot specify a --dns-over-tls-key option "
|
||||
"without the --dns-over-tls-cert option and vice versa")
|
||||
|
||||
# replica installers
|
||||
if installer.servers and not installer.domain_name:
|
||||
@@ -449,6 +522,10 @@ def main():
|
||||
ansible_module.fail_json(
|
||||
msg="You must specify at least one of --forwarder, "
|
||||
"--auto-forwarders, or --no-forwarders options")
|
||||
if installer.dns_over_tls and not installer.dot_forwarders:
|
||||
ansible_module.fail_json(
|
||||
msg="You must specify --dot-forwarder "
|
||||
"when enabling DNS over TLS")
|
||||
|
||||
if installer.dirsrv_config_file is not None and \
|
||||
not os.path.exists(installer.dirsrv_config_file):
|
||||
@@ -486,6 +563,11 @@ def main():
|
||||
if installer.domain_name is not None:
|
||||
validate_domain_name(installer.domain_name)
|
||||
|
||||
if installer.dns_over_tls and not CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION:
|
||||
ansible_module.fail_json(
|
||||
msg="Important patches for DNS over TLS are missing in your "
|
||||
"IPA version.")
|
||||
|
||||
##########################################################################
|
||||
# replica promote_check excerpts #########################################
|
||||
##########################################################################
|
||||
|
||||
@@ -80,6 +80,13 @@ except ImportError:
|
||||
try:
|
||||
from contextlib import contextmanager as contextlib_contextmanager
|
||||
from ipapython.version import NUM_VERSION, VERSION
|
||||
try:
|
||||
from ipapython.version import parse_version
|
||||
except ImportError:
|
||||
# In IPA we either need pkg_resources or packaging Version
|
||||
# class to compare versions with check_remote_version, so
|
||||
# we let an exception to be raised if neither is available.
|
||||
from pkg_resources import parse_version
|
||||
|
||||
if NUM_VERSION < 30201:
|
||||
# See ipapython/version.py
|
||||
@@ -99,8 +106,6 @@ try:
|
||||
import dns.resolver as dnsresolver
|
||||
import dns.reversename as dnsreversename
|
||||
|
||||
from pkg_resources import parse_version
|
||||
|
||||
from ipaclient.install.ipachangeconf import IPAChangeConf
|
||||
from ipalib.install import certstore, sysrestore
|
||||
from ipapython.ipautil import ipa_generate_password
|
||||
@@ -182,6 +187,14 @@ try:
|
||||
from ipaserver.install import ntpinstance
|
||||
time_service = "ntpd" # pylint: disable=invalid-name
|
||||
|
||||
try:
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = False
|
||||
from ipaclient.install.client import ClientInstallInterface
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
if hasattr(ClientInstallInterface, "no_dnssec_validation"):
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = True
|
||||
else:
|
||||
# IPA version < 4.6
|
||||
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
|
||||
@@ -208,11 +221,13 @@ def setup_logging():
|
||||
|
||||
@contextlib_contextmanager
|
||||
def redirect_stdout(stream):
|
||||
old_stdout = sys.stdout
|
||||
|
||||
sys.stdout = stream
|
||||
try:
|
||||
yield stream
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stdout = old_stdout
|
||||
|
||||
|
||||
class AnsibleModuleLog():
|
||||
@@ -331,6 +346,7 @@ options.add_agents = False
|
||||
# ServerReplicaInstall
|
||||
options.subject_base = None
|
||||
options.ca_subject = None
|
||||
|
||||
# pylint: enable=attribute-defined-outside-init
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +1,43 @@
|
||||
---
|
||||
# tasks file for ipareplica
|
||||
|
||||
- name: Package installation
|
||||
- name: Install - Set ipareplica__dns_over_lts
|
||||
ansible.builtin.set_fact:
|
||||
ipareplica__dns_over_tls: "{{ ipareplica_dns_over_tls | default(ipaclient_dns_over_tls) | default(False) }}"
|
||||
|
||||
- name: Install - Package installation
|
||||
when: ipareplica_install_packages | bool
|
||||
block:
|
||||
|
||||
- name: Install - Ensure IPA replica packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipareplica_packages }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installation
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ ipareplica_packages }}"
|
||||
|
||||
- name: Install - Ensure IPA replica packages for dns are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipareplica_packages_dns }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installlation, add DNS
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipareplica_packages_dns }}"
|
||||
when: ipareplica_setup_dns | bool
|
||||
|
||||
- name: Install - Ensure IPA replica packages for adtrust are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipareplica_packages_adtrust }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installlation, add DOT
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipareplica_packages_dot }}"
|
||||
when: ipareplica__dns_over_tls | bool
|
||||
|
||||
- name: Install - Set packages for installlation, add adtrust
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipareplica_packages_adtrust }}"
|
||||
when: ipareplica_setup_adtrust | bool
|
||||
|
||||
- name: Install - Ensure that firewall packages installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipareplica_packages_firewalld }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installlation, add firewalld
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipareplica_packages_firewalld }}"
|
||||
when: ipareplica_setup_firewalld | bool
|
||||
|
||||
- name: Install - Ensure that packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ _ipapackages }}"
|
||||
state: present
|
||||
|
||||
- name: Firewall configuration
|
||||
when: ipareplica_setup_firewalld | bool
|
||||
block:
|
||||
@@ -104,6 +114,11 @@
|
||||
auto_forwarders: "{{ ipareplica_auto_forwarders }}"
|
||||
forward_policy: "{{ ipareplica_forward_policy | default(omit) }}"
|
||||
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
|
||||
dot_forwarders: "{{ ipareplica_dot_forwarders | default([]) }}"
|
||||
dns_over_tls: "{{ ipareplica__dns_over_tls }}"
|
||||
dns_over_tls_cert: "{{ ipareplica_dns_over_tls_cert | default(omit) }}"
|
||||
dns_over_tls_key: "{{ ipareplica_dns_over_tls_key | default(omit) }}"
|
||||
dns_policy: "{{ ipareplica_dns_policy | default(omit) }}"
|
||||
register: result_ipareplica_test
|
||||
|
||||
- name: Install - Deploy replica
|
||||
@@ -127,6 +142,8 @@
|
||||
ipaclient_hostname: "{{ result_ipareplica_test.hostname }}"
|
||||
ipaclient_ip_addresses: "{{ ipareplica_ip_addresses | default(omit) }}"
|
||||
ipaclient_install_packages: "{{ ipareplica_install_packages }}"
|
||||
ipaclient_dns_over_tls: "{{ ipareplica__dns_over_tls }}"
|
||||
ipaclient_no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
|
||||
when: not result_ipareplica_test.client_enrolled
|
||||
|
||||
- name: Install - Configure firewalld
|
||||
@@ -140,6 +157,8 @@
|
||||
{{ "--add-service=freeipa-trust" if result_ipareplica_test.setup_adtrust
|
||||
else "" }}
|
||||
{{ "--add-service=dns" if ipareplica_setup_dns | bool else "" }}
|
||||
{{ "--add-service=dns-over-tls" if ipareplica__dns_over_tls | bool
|
||||
else "" }}
|
||||
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
|
||||
when: ipareplica_setup_firewalld | bool
|
||||
|
||||
@@ -153,6 +172,8 @@
|
||||
{{ "--add-service=freeipa-trust" if result_ipareplica_test.setup_adtrust
|
||||
else "" }}
|
||||
{{ "--add-service=dns" if ipareplica_setup_dns | bool else "" }}
|
||||
{{ "--add-service=dns-over-tls" if ipareplica__dns_over_tls | bool
|
||||
else "" }}
|
||||
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
|
||||
when: ipareplica_setup_firewalld | bool
|
||||
|
||||
@@ -201,6 +222,11 @@
|
||||
auto_forwarders: "{{ ipareplica_auto_forwarders }}"
|
||||
forward_policy: "{{ ipareplica_forward_policy | default(omit) }}"
|
||||
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
|
||||
dot_forwarders: "{{ ipareplica_dot_forwarders | default([]) }}"
|
||||
dns_over_tls: "{{ ipareplica__dns_over_tls }}"
|
||||
dns_over_tls_cert: "{{ ipareplica_dns_over_tls_cert | default(omit) }}"
|
||||
dns_over_tls_key: "{{ ipareplica_dns_over_tls_key | default(omit) }}"
|
||||
dns_policy: "{{ ipareplica_dns_policy | default(omit) }}"
|
||||
### ad trust ###
|
||||
enable_compat: "{{ ipareplica_enable_compat }}"
|
||||
netbios_name: "{{ ipareplica_netbios_name | default(omit) }}"
|
||||
@@ -717,6 +743,11 @@
|
||||
result_ipareplica_prepare.forward_policy is
|
||||
not none else omit }}"
|
||||
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
|
||||
dot_forwarders: "{{ ipareplica_dot_forwarders | default([]) }}"
|
||||
dns_over_tls: "{{ ipareplica__dns_over_tls }}"
|
||||
dns_over_tls_cert: "{{ ipareplica_dns_over_tls_cert | default(omit) }}"
|
||||
dns_over_tls_key: "{{ ipareplica_dns_over_tls_key | default(omit) }}"
|
||||
dns_policy: "{{ ipareplica_dns_policy | default(omit) }}"
|
||||
### additional ###
|
||||
dns_ip_addresses: "{{ result_ipareplica_prepare.dns_ip_addresses }}"
|
||||
dns_reverse_zones: "{{ result_ipareplica_prepare.dns_reverse_zones }}"
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipareplica_packages: [ "freeipa-server", "python3-libselinux" ]
|
||||
ipareplica_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipareplica_packages_dot: [ "freeipa-server-encrypted-dns" ]
|
||||
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipareplica_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
|
||||
ipareplica_packages_dns: [ "ipa-server-dns" ]
|
||||
ipareplica_packages_dot: [ ]
|
||||
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
|
||||
ipareplica_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipareplica_packages: [ "@idm:DL1/server" ]
|
||||
ipareplica_packages_dns: [ "@idm:DL1/dns" ]
|
||||
ipareplica_packages_dot: [ ]
|
||||
ipareplica_packages_adtrust: [ "@idm:DL1/adtrust" ]
|
||||
ipareplica_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
---
|
||||
ipareplica_packages: [ "freeipa-server" ]
|
||||
ipareplica_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipareplica_packages_dot: [ ]
|
||||
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipareplica_packages_firewalld: [ "firewalld" ]
|
||||
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipareplica_packages: [ "freeipa-server" ]
|
||||
ipareplica_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipareplica_packages_dot: [ ]
|
||||
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipareplica_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# defaults file for ipareplica
|
||||
# vars/default.yml
|
||||
---
|
||||
ipareplica_packages: [ "freeipa-server", "python3-libselinux" ]
|
||||
ipareplica_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipareplica_packages: [ "ipa-server", "python3-libselinux" ]
|
||||
ipareplica_packages_dns: [ "ipa-server-dns" ]
|
||||
ipareplica_packages_dot: [ "ipa-server-encrypted-dns" ]
|
||||
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
|
||||
ipareplica_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -343,6 +343,12 @@ Variable | Description | Required
|
||||
`ipaserver_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
|
||||
`ipaserver_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first, only) | no
|
||||
`ipaserver_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
|
||||
`ipaserver_dot_forwarders` | List of DNS over TLS forwarders. Required if `ipaserver_dns_over_tls` is enabled. (list of strings) | no
|
||||
`ipaserver_dns_over_tls` \| `ipaclient_dns_over_tls` | Configure DNS over TLS. Requires FreeIPA version 4.12.5 or later. (bool, default: false) | no
|
||||
`ipaserver_dns_over_tls_cert` | Certificate to use for DNS over TLS. If empty, a new certificate will be requested from IPA CA. (string) | no
|
||||
`ipaserver_dns_over_tls_key` | Key for certificate specified in `ipaserver_dns_over_tls_cert`. (string) | no
|
||||
`ipaserver_dns_policy` | Encrypted DNS policy. Only usable if `ipaserver_dns_over_tls` is enabled. (choice: relaxed, enforced, default: relaxed) | no
|
||||
|
||||
|
||||
AD trust Variables
|
||||
------------------
|
||||
|
||||
@@ -174,6 +174,32 @@ options:
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dot_forwarders:
|
||||
description: List of DNS over TLS forwarders
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dns_over_tls_cert:
|
||||
description:
|
||||
Certificate to use for DNS over TLS. If empty, a new
|
||||
certificate will be requested from IPA CA
|
||||
type: str
|
||||
required: no
|
||||
dns_over_tls_key:
|
||||
description: Key for certificate specified in dns_over_tls_cert
|
||||
type: str
|
||||
required: no
|
||||
dns_policy:
|
||||
description: Encrypted DNS policy
|
||||
type: str
|
||||
choices: ['relaxed', 'enforced']
|
||||
default: 'relaxed'
|
||||
enable_compat:
|
||||
description: Enable support for trusted domains for old clients
|
||||
type: bool
|
||||
@@ -280,6 +306,15 @@ def main():
|
||||
choices=['first', 'only'], default=None),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dot_forwarders=dict(required=False, type='list', elements='str',
|
||||
default=[]),
|
||||
dns_over_tls=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dns_over_tls_cert=dict(required=False, type='str'),
|
||||
dns_over_tls_key=dict(required=False, type='str'),
|
||||
dns_policy=dict(required=False, type='str',
|
||||
choices=['relaxed', 'enforced'],
|
||||
default='relaxed'),
|
||||
# ad trust
|
||||
enable_compat=dict(required=False, type='bool', default=False),
|
||||
netbios_name=dict(required=False, type='str'),
|
||||
@@ -360,6 +395,11 @@ def main():
|
||||
options.forward_policy = ansible_module.params.get('forward_policy')
|
||||
options.no_dnssec_validation = ansible_module.params.get(
|
||||
'no_dnssec_validation')
|
||||
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
|
||||
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
|
||||
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
|
||||
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
|
||||
options.dns_policy = ansible_module.params.get('dns_policy')
|
||||
# ad trust
|
||||
options.enable_compat = ansible_module.params.get('enable_compat')
|
||||
options.netbios_name = ansible_module.params.get('netbios_name')
|
||||
|
||||
@@ -83,6 +83,32 @@ options:
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dot_forwarders:
|
||||
description: List of DNS over TLS forwarders
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dns_over_tls_cert:
|
||||
description:
|
||||
Certificate to use for DNS over TLS. If empty, a new
|
||||
certificate will be requested from IPA CA
|
||||
type: str
|
||||
required: no
|
||||
dns_over_tls_key:
|
||||
description: Key for certificate specified in dns_over_tls_cert
|
||||
type: str
|
||||
required: no
|
||||
dns_policy:
|
||||
description: Encrypted DNS policy
|
||||
type: str
|
||||
choices: ['relaxed', 'enforced']
|
||||
default: 'relaxed'
|
||||
dns_ip_addresses:
|
||||
description: The dns ip_addresses setting
|
||||
type: list
|
||||
@@ -107,9 +133,13 @@ from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.ansible_ipa_server import (
|
||||
check_imports, AnsibleModuleLog, setup_logging, options, paths, dns,
|
||||
ansible_module_get_parsed_ip_addresses, sysrestore, api_Backend_ldap2,
|
||||
redirect_stdout, bindinstance
|
||||
redirect_stdout
|
||||
)
|
||||
|
||||
# pylint: disable=unused-import
|
||||
from ansible.module_utils.ansible_ipa_server import bindinstance # noqa: F401
|
||||
# pylint: enable=unused-import
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = AnsibleModule(
|
||||
@@ -130,6 +160,14 @@ def main():
|
||||
default='first'),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dot_forwarders=dict(required=False, type='list', elements='str',
|
||||
default=[]),
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
dns_over_tls_cert=dict(required=False, type='str'),
|
||||
dns_over_tls_key=dict(required=False, type='str'),
|
||||
dns_policy=dict(required=False, type='str',
|
||||
choices=['relaxed', 'enforced'],
|
||||
default='relaxed'),
|
||||
# additional
|
||||
dns_ip_addresses=dict(required=True, type='list', elements='str'),
|
||||
dns_reverse_zones=dict(required=True, type='list', elements='str'),
|
||||
@@ -158,6 +196,11 @@ def main():
|
||||
options.forward_policy = ansible_module.params.get('forward_policy')
|
||||
options.no_dnssec_validation = ansible_module.params.get(
|
||||
'no_dnssec_validation')
|
||||
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
|
||||
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
|
||||
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
|
||||
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
|
||||
options.dns_policy = ansible_module.params.get('dns_policy')
|
||||
# additional
|
||||
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
|
||||
ansible_module, 'dns_ip_addresses')
|
||||
@@ -165,25 +208,16 @@ def main():
|
||||
|
||||
# init ##################################################################
|
||||
|
||||
fstore = sysrestore.FileStore(paths.SYSRESTORE)
|
||||
# pylint: disable=unused-variable
|
||||
fstore = sysrestore.FileStore(paths.SYSRESTORE) # noqa: F841
|
||||
# pylint: enable=unused-variable
|
||||
|
||||
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
|
||||
|
||||
# setup dns #############################################################
|
||||
|
||||
with redirect_stdout(ansible_log):
|
||||
if options.setup_dns:
|
||||
dns.install(False, False, options)
|
||||
else:
|
||||
# Create a BIND instance
|
||||
bind = bindinstance.BindInstance(fstore)
|
||||
bind.set_output(ansible_log)
|
||||
bind.setup(options.host_name, options.ip_addresses,
|
||||
options.realm_name,
|
||||
options.domain_name, (), 'first', (),
|
||||
zonemgr=options.zonemgr,
|
||||
no_dnssec_validation=options.no_dnssec_validation)
|
||||
bind.create_file_with_system_records()
|
||||
dns.install(False, False, options)
|
||||
|
||||
# done ##################################################################
|
||||
|
||||
|
||||
@@ -265,6 +265,32 @@ options:
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dot_forwarders:
|
||||
description: List of DNS over TLS forwarders
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
required: no
|
||||
dns_over_tls:
|
||||
description: Configure DNS over TLS
|
||||
type: bool
|
||||
default: no
|
||||
required: no
|
||||
dns_over_tls_cert:
|
||||
description:
|
||||
Certificate to use for DNS over TLS. If empty, a new
|
||||
certificate will be requested from IPA CA
|
||||
type: str
|
||||
required: no
|
||||
dns_over_tls_key:
|
||||
description: Key for certificate specified in dns_over_tls_cert
|
||||
type: str
|
||||
required: no
|
||||
dns_policy:
|
||||
description: Encrypted DNS policy
|
||||
type: str
|
||||
choices: ['relaxed', 'enforced']
|
||||
default: 'relaxed'
|
||||
enable_compat:
|
||||
description: Enable support for trusted domains for old clients
|
||||
type: bool
|
||||
@@ -312,7 +338,8 @@ from ansible.module_utils.ansible_ipa_server import (
|
||||
check_dirsrv, ScriptError, get_fqdn, verify_fqdn, BadHostError,
|
||||
validate_domain_name, load_pkcs12, IPA_PYTHON_VERSION,
|
||||
encode_certificate, check_available_memory, getargspec, adtrustinstance,
|
||||
get_min_idstart, SerialNumber
|
||||
get_min_idstart, SerialNumber, services, service,
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION
|
||||
)
|
||||
from ansible.module_utils import six
|
||||
|
||||
@@ -396,6 +423,14 @@ def main():
|
||||
choices=['first', 'only'], default=None),
|
||||
no_dnssec_validation=dict(required=False, type='bool',
|
||||
default=False),
|
||||
dot_forwarders=dict(required=False, type='list', elements='str',
|
||||
default=[]),
|
||||
dns_over_tls=dict(required=False, type='bool', default=False),
|
||||
dns_over_tls_cert=dict(required=False, type='str'),
|
||||
dns_over_tls_key=dict(required=False, type='str'),
|
||||
dns_policy=dict(required=False, type='str',
|
||||
choices=['relaxed', 'enforced'],
|
||||
default='relaxed'),
|
||||
# ad trust
|
||||
enable_compat=dict(required=False, type='bool', default=False),
|
||||
netbios_name=dict(required=False, type='str'),
|
||||
@@ -482,6 +517,11 @@ def main():
|
||||
options.forward_policy = ansible_module.params.get('forward_policy')
|
||||
options.no_dnssec_validation = ansible_module.params.get(
|
||||
'no_dnssec_validation')
|
||||
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
|
||||
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
|
||||
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
|
||||
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
|
||||
options.dns_policy = ansible_module.params.get('dns_policy')
|
||||
# ad trust
|
||||
options.enable_compat = ansible_module.params.get('enable_compat')
|
||||
options.netbios_name = ansible_module.params.get('netbios_name')
|
||||
@@ -603,6 +643,14 @@ def main():
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --no-dnssec-validation option "
|
||||
"without the --setup-dns option")
|
||||
if self.dns_over_tls_cert:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dns-over-tls-cert option "
|
||||
"without the --setup-dns option")
|
||||
if self.dns_over_tls_key:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dns-over-tls-key option "
|
||||
"without the --setup-dns option")
|
||||
elif self.forwarders and self.no_forwarders:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --forwarder option together with "
|
||||
@@ -619,7 +667,31 @@ def main():
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --auto-reverse option together with "
|
||||
"--no-reverse")
|
||||
|
||||
elif self.dot_forwarders and not self.dns_over_tls:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dot-forwarder option "
|
||||
"without the --dns-over-tls option")
|
||||
elif (self.dns_over_tls
|
||||
and not services.knownservices["unbound"].is_installed()):
|
||||
raise RuntimeError(
|
||||
"To enable DNS over TLS, package ipa-server-encrypted-dns "
|
||||
"must be installed.")
|
||||
elif self.dns_policy == "enforced" and not self.dns_over_tls:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dns-policy option "
|
||||
"without the --dns-over-tls option")
|
||||
elif self.dns_over_tls_cert and not self.dns_over_tls:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dns-over-tls-cert option "
|
||||
"without the --dns-over-tls option")
|
||||
elif self.dns_over_tls_key and not self.dns_over_tls:
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dns-over-tls-key option "
|
||||
"without the --dns-over-tls option")
|
||||
elif bool(self.dns_over_tls_key) != bool(self.dns_over_tls_cert):
|
||||
raise RuntimeError(
|
||||
"You cannot specify a --dns-over-tls-key option "
|
||||
"without the --dns-over-tls-cert option and vice versa")
|
||||
if not self.setup_adtrust:
|
||||
if self.add_agents:
|
||||
raise RuntimeError(
|
||||
@@ -677,6 +749,10 @@ def main():
|
||||
raise RuntimeError(
|
||||
"You must specify at least one of --forwarder, "
|
||||
"--auto-forwarders, or --no-forwarders options")
|
||||
if self.dns_over_tls and not self.dot_forwarders:
|
||||
raise RuntimeError(
|
||||
"You must specify --dot-forwarder "
|
||||
"when enabling DNS over TLS")
|
||||
|
||||
any_ignore_option_true = any(
|
||||
[self.ignore_topology_disconnect, self.ignore_last_of_role])
|
||||
@@ -719,6 +795,19 @@ def main():
|
||||
|
||||
# #######################################################################
|
||||
|
||||
if options.dns_over_tls and not CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION:
|
||||
ansible_module.fail_json(
|
||||
msg="Important patches for DNS over TLS are missing in your "
|
||||
"IPA version.")
|
||||
|
||||
client_dns_over_tls = self.dns_over_tls
|
||||
if self.dns_over_tls and not self.setup_dns:
|
||||
service.print_msg("Warning: --dns-over-tls option "
|
||||
"specified without --setup-dns, ignoring")
|
||||
client_dns_over_tls = False
|
||||
|
||||
# #######################################################################
|
||||
|
||||
# If any of the key file options are selected, all are required.
|
||||
cert_file_req = (options.dirsrv_cert_files, options.http_cert_files)
|
||||
cert_file_opt = (options.pkinit_cert_files,)
|
||||
@@ -1208,6 +1297,7 @@ def main():
|
||||
domainlevel=options.domainlevel,
|
||||
sid_generation_always=sid_generation_always,
|
||||
random_serial_numbers=options._random_serial_numbers,
|
||||
client_dns_over_tls=client_dns_over_tls
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -216,6 +216,14 @@ try:
|
||||
except ImportError:
|
||||
SerialNumber = None
|
||||
|
||||
try:
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = False
|
||||
from ipaclient.install.client import ClientInstallInterface
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
if hasattr(ClientInstallInterface, "no_dnssec_validation"):
|
||||
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = True
|
||||
else:
|
||||
# IPA version < 4.5
|
||||
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
|
||||
@@ -241,11 +249,13 @@ def setup_logging():
|
||||
|
||||
@contextlib_contextmanager
|
||||
def redirect_stdout(stream):
|
||||
old_stdout = sys.stdout
|
||||
|
||||
sys.stdout = stream
|
||||
try:
|
||||
yield stream
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stdout = old_stdout
|
||||
|
||||
|
||||
class AnsibleModuleLog():
|
||||
|
||||
@@ -1,32 +1,42 @@
|
||||
---
|
||||
# tasks file for ipaserver
|
||||
|
||||
- name: Install - Set ipaserver__dns_over_lts
|
||||
ansible.builtin.set_fact:
|
||||
ipaserver__dns_over_tls: "{{ ipaserver_dns_over_tls | default(ipaclient_dns_over_tls) | default(False) }}"
|
||||
|
||||
- name: Install - Package installation
|
||||
when: ipaserver_install_packages | bool
|
||||
block:
|
||||
- name: Install - Ensure that IPA server packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipaserver_packages }}"
|
||||
state: present
|
||||
|
||||
- name: Install - Ensure that IPA server packages for dns are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipaserver_packages_dns }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installation
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ ipaserver_packages }}"
|
||||
|
||||
- name: Install - Set packages for installlation, add DNS
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipaserver_packages_dns }}"
|
||||
when: ipaserver_setup_dns | bool
|
||||
|
||||
- name: Install - Ensure that IPA server packages for adtrust are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipaserver_packages_adtrust }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installlation, add DOT
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipaserver_packages_dot }}"
|
||||
when: ipaserver__dns_over_tls | bool
|
||||
|
||||
- name: Install - Set packages for installlation, add adtrust
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipaserver_packages_adtrust }}"
|
||||
when: ipaserver_setup_adtrust | bool
|
||||
|
||||
- name: Install - Ensure that firewall packages installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipaserver_packages_firewalld }}"
|
||||
state: present
|
||||
- name: Install - Set packages for installlation, add firewalld
|
||||
ansible.builtin.set_fact:
|
||||
_ipapackages: "{{ _ipapackages + ipaserver_packages_firewalld }}"
|
||||
when: ipaserver_setup_firewalld | bool
|
||||
|
||||
- name: Install - Ensure that packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ _ipapackages }}"
|
||||
state: present
|
||||
|
||||
- name: Install - Firewall configuration
|
||||
when: ipaserver_setup_firewalld | bool
|
||||
@@ -121,6 +131,11 @@
|
||||
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
|
||||
forward_policy: "{{ ipaserver_forward_policy | default(omit) }}"
|
||||
no_dnssec_validation: "{{ ipaserver_no_dnssec_validation }}"
|
||||
dot_forwarders: "{{ ipaserver_dot_forwarders | default([]) }}"
|
||||
dns_over_tls: "{{ ipaserver__dns_over_tls }}"
|
||||
dns_over_tls_cert: "{{ ipaserver_dns_over_tls_cert | default(omit) }}"
|
||||
dns_over_tls_key: "{{ ipaserver_dns_over_tls_key | default(omit) }}"
|
||||
dns_policy: "{{ ipaserver_dns_policy | default(omit) }}"
|
||||
### ad trust ###
|
||||
enable_compat: "{{ ipaserver_enable_compat }}"
|
||||
netbios_name: "{{ ipaserver_netbios_name | default(omit) }}"
|
||||
@@ -192,6 +207,11 @@
|
||||
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
|
||||
forward_policy: "{{ ipaserver_forward_policy | default(omit) }}"
|
||||
no_dnssec_validation: "{{ ipaserver_no_dnssec_validation }}"
|
||||
dot_forwarders: "{{ ipaserver_dot_forwarders | default([]) }}"
|
||||
dns_over_tls: "{{ ipaserver__dns_over_tls }}"
|
||||
dns_over_tls_cert: "{{ ipaserver_dns_over_tls_cert | default(omit) }}"
|
||||
dns_over_tls_key: "{{ ipaserver_dns_over_tls_key | default(omit) }}"
|
||||
dns_policy: "{{ ipaserver_dns_policy | default(omit) }}"
|
||||
### ad trust ###
|
||||
enable_compat: "{{ ipaserver_enable_compat }}"
|
||||
netbios_name: "{{ ipaserver_netbios_name | default(omit) }}"
|
||||
@@ -381,6 +401,11 @@
|
||||
forward_policy: "{{ result_ipaserver_prepare.forward_policy }}"
|
||||
zonemgr: "{{ ipaserver_zonemgr | default(omit) }}"
|
||||
no_dnssec_validation: "{{ result_ipaserver_prepare.no_dnssec_validation }}"
|
||||
dot_forwarders: "{{ ipaserver_dot_forwarders | default([]) }}"
|
||||
dns_over_tls: "{{ ipaserver__dns_over_tls }}"
|
||||
dns_over_tls_cert: "{{ ipaserver_dns_over_tls_cert | default(omit) }}"
|
||||
dns_over_tls_key: "{{ ipaserver_dns_over_tls_key | default(omit) }}"
|
||||
dns_policy: "{{ ipaserver_dns_policy | default(omit) }}"
|
||||
### additional ###
|
||||
dns_ip_addresses: "{{ result_ipaserver_prepare.dns_ip_addresses }}"
|
||||
dns_reverse_zones: "{{ result_ipaserver_prepare.dns_reverse_zones }}"
|
||||
@@ -432,6 +457,7 @@
|
||||
ipaclient_no_ntp:
|
||||
"{{ 'true' if result_ipaserver_test.ipa_python_version >= 40690
|
||||
else 'false' }}"
|
||||
ipaclient_dns_over_tls: "{{ result_ipaserver_test.client_dns_over_tls }}"
|
||||
ipaclient_install_packages: no
|
||||
|
||||
- name: Install - Enable IPA
|
||||
@@ -452,6 +478,8 @@
|
||||
{{ "--add-service=freeipa-trust" if ipaserver_setup_adtrust | bool
|
||||
else "" }}
|
||||
{{ "--add-service=dns" if ipaserver_setup_dns | bool else "" }}
|
||||
{{ "--add-service=dns-over-tls" if ipaserver__dns_over_tls | bool
|
||||
else "" }}
|
||||
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
|
||||
when: ipaserver_setup_firewalld | bool
|
||||
|
||||
@@ -465,6 +493,8 @@
|
||||
{{ "--add-service=freeipa-trust" if ipaserver_setup_adtrust | bool
|
||||
else "" }}
|
||||
{{ "--add-service=dns" if ipaserver_setup_dns | bool else "" }}
|
||||
{{ "--add-service=dns-over-tls" if ipaserver__dns_over_tls | bool
|
||||
else "" }}
|
||||
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
|
||||
when: ipaserver_setup_firewalld | bool
|
||||
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipaserver_packages: [ "freeipa-server", "python3-libselinux" ]
|
||||
ipaserver_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipaserver_packages_dot: [ "freeipa-server-encrypted-dns" ]
|
||||
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
|
||||
ipaserver_packages_dns: [ "ipa-server-dns" ]
|
||||
ipaserver_packages_dot: [ ]
|
||||
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
|
||||
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipaserver_packages: [ "@idm:DL1/server" ]
|
||||
ipaserver_packages_dns: [ "@idm:DL1/dns" ]
|
||||
ipaserver_packages_dot: [ ]
|
||||
ipaserver_packages_adtrust: [ "@idm:DL1/adtrust" ]
|
||||
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
---
|
||||
ipaserver_packages: [ "freeipa-server" ]
|
||||
ipaserver_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipaserver_packages_dot: [ ]
|
||||
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipaserver_packages: [ "freeipa-server" ]
|
||||
ipaserver_packages_dns: [ "freeipa-server-dns" ]
|
||||
ipaserver_packages_dot: [ ]
|
||||
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
---
|
||||
ipaserver_packages: [ "ipa-server", "python3-libselinux" ]
|
||||
ipaserver_packages_dns: [ "ipa-server-dns" ]
|
||||
ipaserver_packages_dot: [ "ipa-server-encrypted-dns" ]
|
||||
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||
|
||||
@@ -36,6 +36,50 @@
|
||||
# Test local idrange, only if ipa-adtrust-install was not executed.
|
||||
- name: Test local idrange
|
||||
block:
|
||||
- name: Can't add idrange without base_id
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: local_id_range
|
||||
range_size: 200000
|
||||
rid_base: 1000000
|
||||
secondary_rid_base: 200000000
|
||||
register: result
|
||||
failed_when: "not (result.failed and 'Missing required parameters: base_id' in result.msg)"
|
||||
|
||||
- name: Can't add idrange without range_size
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: local_id_range
|
||||
base_id: 150000000
|
||||
rid_base: 1000000
|
||||
secondary_rid_base: 200000000
|
||||
register: result
|
||||
failed_when: "not (result.failed and 'Missing required parameters: range_size' in result.msg)"
|
||||
|
||||
- name: Can't add idrange without rid_base
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: local_id_range
|
||||
base_id: 150000000
|
||||
range_size: 200000
|
||||
secondary_rid_base: 200000000
|
||||
register: result
|
||||
failed_when: "not (result.failed and 'Missing required parameters: rid_base' in result.msg)"
|
||||
|
||||
- name: Can't add idrange without secondary_rid_base
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: local_id_range
|
||||
base_id: 150000000
|
||||
range_size: 200000
|
||||
rid_base: 1000000
|
||||
register: result
|
||||
failed_when: "not (result.failed and 'Missing required parameters: secondary_rid_base' in result.msg)"
|
||||
|
||||
- name: Ensure idrange with minimal attributes is present
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -43,6 +87,8 @@
|
||||
name: local_id_range
|
||||
base_id: 150000000
|
||||
range_size: 200000
|
||||
rid_base: 1000000
|
||||
secondary_rid_base: 200000000
|
||||
register: result
|
||||
failed_when:
|
||||
not (result.failed or result.changed) or (result.failed and 'ipa-adtrust-install has already been run' not in result.msg)
|
||||
@@ -54,6 +100,8 @@
|
||||
name: local_id_range
|
||||
base_id: 150000000
|
||||
range_size: 200000
|
||||
rid_base: 1000000
|
||||
secondary_rid_base: 200000000
|
||||
register: result
|
||||
failed_when:
|
||||
result.changed or (result.failed and 'ipa-adtrust-install has already been run' not in result.msg)
|
||||
@@ -118,6 +166,7 @@
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: local_id_range
|
||||
state: absent
|
||||
|
||||
- name: Execute idrange tests if trust test environment is supported
|
||||
when: trust_test_is_supported | default(false)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
- "{{ host2_fqdn }}"
|
||||
- "{{ nohost_fqdn }}"
|
||||
- svc.ihavenodns.info
|
||||
update_dns: no
|
||||
update_dns: true
|
||||
state: absent
|
||||
|
||||
- name: Ensure testing users are absent.
|
||||
|
||||
@@ -79,6 +79,20 @@ shift
|
||||
prepare_container "${scenario}" "${IMAGE_TAG}"
|
||||
start_container "${scenario}"
|
||||
|
||||
log info "Wait till systemd-journald is running"
|
||||
max=20
|
||||
wait=2
|
||||
count=0
|
||||
while ! podman exec "${scenario}" ps -x | grep -q "systemd-journald"
|
||||
do
|
||||
if [ $count -ge $max ]; then
|
||||
die "Timeout: systemd-journald is not starting up"
|
||||
fi
|
||||
count=$((count+1))
|
||||
log none "Waiting ${wait} seconds .."
|
||||
sleep ${wait}
|
||||
done
|
||||
|
||||
# wait for FreeIPA services to be available (usually ~45 seconds)
|
||||
log info "Wait for container to be initialized."
|
||||
wait=15
|
||||
|
||||
Reference in New Issue
Block a user