mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Test installation with (fake) userspace FIPS
Based on userspace FIPS mode by Ondrej Moris. Userspace FIPS mode fakes a Kernel in FIPS enforcing mode. User space programs behave like the Kernel was booted in FIPS enforcing mode. Kernel space code still runs in standard mode. Fixes: https://pagure.io/freeipa/issue/8118 Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
@@ -159,6 +159,18 @@ jobs:
|
|||||||
timeout: 3600
|
timeout: 3600
|
||||||
topology: *master_1repl_1client
|
topology: *master_1repl_1client
|
||||||
|
|
||||||
|
fedora-latest/test_fips:
|
||||||
|
requires: [fedora-latest/build]
|
||||||
|
priority: 50
|
||||||
|
job:
|
||||||
|
class: RunPytest
|
||||||
|
args:
|
||||||
|
build_url: '{fedora-latest/build_url}'
|
||||||
|
test_suite: test_integration/test_fips.py
|
||||||
|
template: *ci-master-latest
|
||||||
|
timeout: 3600
|
||||||
|
topology: *master_1repl_1client
|
||||||
|
|
||||||
fedora-latest/test_forced_client_enrolment:
|
fedora-latest/test_forced_client_enrolment:
|
||||||
requires: [fedora-latest/build]
|
requires: [fedora-latest/build]
|
||||||
priority: 50
|
priority: 50
|
||||||
|
|||||||
@@ -159,6 +159,18 @@ jobs:
|
|||||||
timeout: 3600
|
timeout: 3600
|
||||||
topology: *master_1repl_1client
|
topology: *master_1repl_1client
|
||||||
|
|
||||||
|
fedora-previous/test_fips:
|
||||||
|
requires: [fedora-previous/build]
|
||||||
|
priority: 50
|
||||||
|
job:
|
||||||
|
class: RunPytest
|
||||||
|
args:
|
||||||
|
build_url: '{fedora-previous/build_url}'
|
||||||
|
test_suite: test_integration/test_fips.py
|
||||||
|
template: *ci-master-previous
|
||||||
|
timeout: 3600
|
||||||
|
topology: *master_1repl_1client
|
||||||
|
|
||||||
fedora-previous/test_forced_client_enrolment:
|
fedora-previous/test_forced_client_enrolment:
|
||||||
requires: [fedora-previous/build]
|
requires: [fedora-previous/build]
|
||||||
priority: 50
|
priority: 50
|
||||||
|
|||||||
@@ -159,6 +159,18 @@ jobs:
|
|||||||
timeout: 3600
|
timeout: 3600
|
||||||
topology: *master_1repl_1client
|
topology: *master_1repl_1client
|
||||||
|
|
||||||
|
fedora-rawhide/test_fips:
|
||||||
|
requires: [fedora-rawhide/build]
|
||||||
|
priority: 50
|
||||||
|
job:
|
||||||
|
class: RunPytest
|
||||||
|
args:
|
||||||
|
build_url: '{fedora-rawhide/build_url}'
|
||||||
|
test_suite: test_integration/test_fips.py
|
||||||
|
template: *ci-master-frawhide
|
||||||
|
timeout: 3600
|
||||||
|
topology: *master_1repl_1client
|
||||||
|
|
||||||
fedora-rawhide/test_forced_client_enrolment:
|
fedora-rawhide/test_forced_client_enrolment:
|
||||||
requires: [fedora-rawhide/build]
|
requires: [fedora-rawhide/build]
|
||||||
priority: 50
|
priority: 50
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class Config(pytest_multihost.config.Config):
|
|||||||
'dns_forwarder',
|
'dns_forwarder',
|
||||||
'domain_level',
|
'domain_level',
|
||||||
'log_journal_since',
|
'log_journal_since',
|
||||||
|
'fips_mode',
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@@ -67,6 +68,7 @@ class Config(pytest_multihost.config.Config):
|
|||||||
self.log_journal_since = kwargs.get('log_journal_since') or '-1h'
|
self.log_journal_since = kwargs.get('log_journal_since') or '-1h'
|
||||||
if self.domain_level is None:
|
if self.domain_level is None:
|
||||||
self.domain_level = MAX_DOMAIN_LEVEL
|
self.domain_level = MAX_DOMAIN_LEVEL
|
||||||
|
self.fips_mode = kwargs.get('fips_mode', False)
|
||||||
|
|
||||||
def get_domain_class(self):
|
def get_domain_class(self):
|
||||||
return Domain
|
return Domain
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ _setting_infos = (
|
|||||||
_SettingInfo('domain_level', 'DOMAINLVL', MAX_DOMAIN_LEVEL),
|
_SettingInfo('domain_level', 'DOMAINLVL', MAX_DOMAIN_LEVEL),
|
||||||
|
|
||||||
_SettingInfo('log_journal_since', 'LOG_JOURNAL_SINCE', '-1h'),
|
_SettingInfo('log_journal_since', 'LOG_JOURNAL_SINCE', '-1h'),
|
||||||
|
# userspace FIPS mode
|
||||||
|
_SettingInfo('fips_mode', 'IPA_FIPS_MODE', False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
67
ipatests/pytest_ipa/integration/fips.py
Normal file
67
ipatests/pytest_ipa/integration/fips.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2019 FreeIPA Contributors see COPYING for license
|
||||||
|
#
|
||||||
|
"""FIPS testing helpers
|
||||||
|
|
||||||
|
Based on userspace FIPS mode by Ondrej Moris.
|
||||||
|
|
||||||
|
Userspace FIPS mode fakes a Kernel in FIPS enforcing mode. User space
|
||||||
|
programs behave like the Kernel was booted in FIPS enforcing mode. Kernel
|
||||||
|
space code still runs in standard mode.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from ipaplatform.paths import paths
|
||||||
|
|
||||||
|
FIPS_OVERLAY_DIR = "/var/tmp/userspace-fips"
|
||||||
|
FIPS_OVERLAY = os.path.join(FIPS_OVERLAY_DIR, "fips_enabled")
|
||||||
|
SYSTEM_FIPS = "/etc/system-fips"
|
||||||
|
|
||||||
|
|
||||||
|
def is_fips_enabled(host):
|
||||||
|
"""Check if host has """
|
||||||
|
result = host.run_command(
|
||||||
|
["cat", paths.PROC_FIPS_ENABLED], raiseonerr=False
|
||||||
|
)
|
||||||
|
if result.returncode == 1:
|
||||||
|
# FIPS mode not available
|
||||||
|
return None
|
||||||
|
elif result.returncode == 0:
|
||||||
|
return result.stdout_text.strip() == "1"
|
||||||
|
else:
|
||||||
|
raise RuntimeError(result.stderr_text)
|
||||||
|
|
||||||
|
|
||||||
|
def enable_userspace_fips(host):
|
||||||
|
# create /etc/system-fips
|
||||||
|
host.put_file_contents(SYSTEM_FIPS, "# userspace fips\n")
|
||||||
|
# fake Kernel FIPS mode with bind mount
|
||||||
|
host.run_command(["mkdir", "-p", FIPS_OVERLAY_DIR])
|
||||||
|
host.put_file_contents(FIPS_OVERLAY, "1\n")
|
||||||
|
host.run_command(
|
||||||
|
["mount", "--bind", FIPS_OVERLAY, paths.PROC_FIPS_ENABLED]
|
||||||
|
)
|
||||||
|
# set crypto policy to FIPS mode
|
||||||
|
host.run_command(["update-crypto-policies", "--show"])
|
||||||
|
host.run_command(["update-crypto-policies", "--set", "FIPS"])
|
||||||
|
# sanity check
|
||||||
|
assert is_fips_enabled(host)
|
||||||
|
result = host.run_command(
|
||||||
|
["openssl", "md5", "/dev/null"], raiseonerr=False
|
||||||
|
)
|
||||||
|
assert result.returncode == 1
|
||||||
|
assert "EVP_DigestInit_ex:disabled for FIPS" in result.stderr_text
|
||||||
|
|
||||||
|
|
||||||
|
def disable_userspace_fips(host):
|
||||||
|
host.run_command(["rm", "-f", SYSTEM_FIPS])
|
||||||
|
host.run_command(["update-crypto-policies", "--set", "DEFAULT"])
|
||||||
|
result = host.run_command(
|
||||||
|
["umount", paths.PROC_FIPS_ENABLED], raiseonerr=False
|
||||||
|
)
|
||||||
|
host.run_command(["rm", "-rf", FIPS_OVERLAY_DIR])
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise RuntimeError(result.stderr_text)
|
||||||
|
|
||||||
|
# sanity check
|
||||||
|
assert not is_fips_enabled(host)
|
||||||
|
host.run_command(["openssl", "md5", "/dev/null"])
|
||||||
@@ -27,6 +27,10 @@ import pytest_multihost.host
|
|||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
from ipapython import ipaldap
|
from ipapython import ipaldap
|
||||||
|
|
||||||
|
from .fips import (
|
||||||
|
is_fips_enabled, enable_userspace_fips, disable_userspace_fips
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LDAPClientWithoutCertCheck(ipaldap.LDAPClient):
|
class LDAPClientWithoutCertCheck(ipaldap.LDAPClient):
|
||||||
"""Adds an option to disable certificate check for TLS connection
|
"""Adds an option to disable certificate check for TLS connection
|
||||||
@@ -58,6 +62,61 @@ class LDAPClientWithoutCertCheck(ipaldap.LDAPClient):
|
|||||||
class Host(pytest_multihost.host.Host):
|
class Host(pytest_multihost.host.Host):
|
||||||
"""Representation of a remote IPA host"""
|
"""Representation of a remote IPA host"""
|
||||||
|
|
||||||
|
def __init__(self, domain, hostname, role, ip=None,
|
||||||
|
external_hostname=None, username=None, password=None,
|
||||||
|
test_dir=None, host_type=None):
|
||||||
|
super().__init__(
|
||||||
|
domain, hostname, role, ip=ip,
|
||||||
|
external_hostname=external_hostname, username=username,
|
||||||
|
password=password, test_dir=test_dir, host_type=host_type
|
||||||
|
)
|
||||||
|
self._fips_mode = None
|
||||||
|
self._userspace_fips = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_fips_mode(self):
|
||||||
|
"""Check and cache if a system is in FIPS mode
|
||||||
|
"""
|
||||||
|
if self._fips_mode is None:
|
||||||
|
self._fips_mode = is_fips_enabled(self)
|
||||||
|
return self._fips_mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_userspace_fips(self):
|
||||||
|
"""Check if host uses fake userspace FIPS
|
||||||
|
"""
|
||||||
|
return self._userspace_fips
|
||||||
|
|
||||||
|
def enable_userspace_fips(self):
|
||||||
|
"""Enable fake userspace FIPS mode
|
||||||
|
|
||||||
|
The call has no effect if the system is already in FIPS mode.
|
||||||
|
|
||||||
|
:return: True if system was modified, else None
|
||||||
|
"""
|
||||||
|
if not self.is_fips_mode:
|
||||||
|
enable_userspace_fips(self)
|
||||||
|
self._fips_mode = True
|
||||||
|
self._userspace_fips = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def disable_userspace_fips(self):
|
||||||
|
"""Disable fake userspace FIPS mode
|
||||||
|
|
||||||
|
The call has no effect if userspace FIPS mode is not enabled.
|
||||||
|
|
||||||
|
:return: True if system was modified, else None
|
||||||
|
"""
|
||||||
|
if self.is_userspace_fips:
|
||||||
|
disable_userspace_fips(self)
|
||||||
|
self._userspace_fips = False
|
||||||
|
self._fips_mode = False
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _make_host(domain, hostname, role, ip, external_hostname):
|
def _make_host(domain, hostname, role, ip, external_hostname):
|
||||||
# We need to determine the type of the host, this depends on the domain
|
# We need to determine the type of the host, this depends on the domain
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class IntegrationTest:
|
|||||||
required_extra_roles = []
|
required_extra_roles = []
|
||||||
topology = None
|
topology = None
|
||||||
domain_level = None
|
domain_level = None
|
||||||
|
fips_mode = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
@@ -60,12 +61,30 @@ class IntegrationTest:
|
|||||||
def get_domains(cls):
|
def get_domains(cls):
|
||||||
return [cls.domain] + cls.ad_domains
|
return [cls.domain] + cls.ad_domains
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def enable_fips_mode(cls):
|
||||||
|
for host in cls.get_all_hosts():
|
||||||
|
if not host.is_fips_mode:
|
||||||
|
host.enable_userspace_fips()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def disable_fips_mode(cls):
|
||||||
|
for host in cls.get_all_hosts():
|
||||||
|
if host.is_userspace_fips:
|
||||||
|
host.disable_userspace_fips()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def install(cls, mh):
|
def install(cls, mh):
|
||||||
if cls.domain_level is not None:
|
if cls.domain_level is not None:
|
||||||
domain_level = cls.domain_level
|
domain_level = cls.domain_level
|
||||||
else:
|
else:
|
||||||
domain_level = cls.master.config.domain_level
|
domain_level = cls.master.config.domain_level
|
||||||
|
|
||||||
|
if cls.master.config.fips_mode:
|
||||||
|
cls.fips_mode = True
|
||||||
|
if cls.fips_mode:
|
||||||
|
cls.enable_fips_mode()
|
||||||
|
|
||||||
if cls.topology is None:
|
if cls.topology is None:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@@ -83,3 +102,5 @@ class IntegrationTest:
|
|||||||
tasks.uninstall_master(replica)
|
tasks.uninstall_master(replica)
|
||||||
for client in cls.clients:
|
for client in cls.clients:
|
||||||
tasks.uninstall_client(client)
|
tasks.uninstall_client(client)
|
||||||
|
if cls.fips_mode:
|
||||||
|
cls.disable_fips_mode()
|
||||||
|
|||||||
@@ -98,6 +98,16 @@ def dnszone_add_dnssec(host, test_zone):
|
|||||||
return host.run_command(args)
|
return host.run_command(args)
|
||||||
|
|
||||||
|
|
||||||
|
def dnssec_install_master(host):
|
||||||
|
args = [
|
||||||
|
"ipa-dns-install",
|
||||||
|
"--dnssec-master",
|
||||||
|
"--forwarder", host.config.dns_forwarder,
|
||||||
|
"-U",
|
||||||
|
]
|
||||||
|
return host.run_command(args)
|
||||||
|
|
||||||
|
|
||||||
class TestInstallDNSSECLast(IntegrationTest):
|
class TestInstallDNSSECLast(IntegrationTest):
|
||||||
"""Simple DNSSEC test
|
"""Simple DNSSEC test
|
||||||
|
|
||||||
@@ -114,13 +124,7 @@ class TestInstallDNSSECLast(IntegrationTest):
|
|||||||
|
|
||||||
def test_install_dnssec_master(self):
|
def test_install_dnssec_master(self):
|
||||||
"""Both master and replica have DNS installed"""
|
"""Both master and replica have DNS installed"""
|
||||||
args = [
|
dnssec_install_master(self.master)
|
||||||
"ipa-dns-install",
|
|
||||||
"--dnssec-master",
|
|
||||||
"--forwarder", self.master.config.dns_forwarder,
|
|
||||||
"-U",
|
|
||||||
]
|
|
||||||
self.master.run_command(args)
|
|
||||||
|
|
||||||
def test_if_zone_is_signed_master(self):
|
def test_if_zone_is_signed_master(self):
|
||||||
# add zone with enabled DNSSEC signing on master
|
# add zone with enabled DNSSEC signing on master
|
||||||
|
|||||||
127
ipatests/test_integration/test_fips.py
Normal file
127
ipatests/test_integration/test_fips.py
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2019 FreeIPA Contributors see COPYING for license
|
||||||
|
#
|
||||||
|
"""Smoke tests for FreeIPA installation in (fake) userspace FIPS mode
|
||||||
|
"""
|
||||||
|
from ipapython.dn import DN
|
||||||
|
from ipapython.ipautil import ipa_generate_password, realm_to_suffix
|
||||||
|
|
||||||
|
from ipatests.pytest_ipa.integration import tasks
|
||||||
|
from ipatests.pytest_ipa.integration import fips
|
||||||
|
from ipatests.test_integration.base import IntegrationTest
|
||||||
|
|
||||||
|
from .test_dnssec import (
|
||||||
|
test_zone,
|
||||||
|
dnssec_install_master,
|
||||||
|
dnszone_add_dnssec,
|
||||||
|
wait_until_record_is_signed,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestInstallFIPS(IntegrationTest):
|
||||||
|
num_replicas = 1
|
||||||
|
num_clients = 1
|
||||||
|
fips_mode = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def install(cls, mh):
|
||||||
|
super(TestInstallFIPS, cls).install(mh)
|
||||||
|
# sanity check
|
||||||
|
for host in cls.get_all_hosts():
|
||||||
|
assert host.is_fips_mode
|
||||||
|
assert fips.is_fips_enabled(host)
|
||||||
|
# patch named-pkcs11 crypto policy
|
||||||
|
# see RHBZ#1772111
|
||||||
|
for host in [cls.master] + cls.replicas:
|
||||||
|
host.run_command(
|
||||||
|
[
|
||||||
|
"sed",
|
||||||
|
"-i",
|
||||||
|
"-E",
|
||||||
|
"s/RSAMD5;//g",
|
||||||
|
"/etc/crypto-policies/back-ends/bind.config",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
# master with CA, KRA, DNS+DNSSEC
|
||||||
|
tasks.install_master(cls.master, setup_dns=True, setup_kra=True)
|
||||||
|
# replica with CA, KRA, DNS
|
||||||
|
tasks.install_replica(
|
||||||
|
cls.master,
|
||||||
|
cls.replicas[0],
|
||||||
|
setup_dns=True,
|
||||||
|
setup_ca=True,
|
||||||
|
setup_kra=True,
|
||||||
|
)
|
||||||
|
tasks.install_clients([cls.master] + cls.replicas, cls.clients)
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
client = self.clients[0]
|
||||||
|
tasks.kinit_admin(client)
|
||||||
|
client.run_command(["ipa", "ping"])
|
||||||
|
|
||||||
|
def test_dnssec(self):
|
||||||
|
dnssec_install_master(self.master)
|
||||||
|
# DNSSEC zone
|
||||||
|
dnszone_add_dnssec(self.master, test_zone)
|
||||||
|
assert wait_until_record_is_signed(
|
||||||
|
self.master.ip, test_zone, timeout=100
|
||||||
|
), ("Zone %s is not signed (master)" % test_zone)
|
||||||
|
|
||||||
|
# test replica
|
||||||
|
assert wait_until_record_is_signed(
|
||||||
|
self.replicas[0].ip, test_zone, timeout=200
|
||||||
|
), ("DNS zone %s is not signed (replica)" % test_zone)
|
||||||
|
|
||||||
|
def test_vault_basic(self):
|
||||||
|
vault_name = "testvault"
|
||||||
|
vault_password = ipa_generate_password()
|
||||||
|
vault_data = "SSBsb3ZlIENJIHRlc3RzCg=="
|
||||||
|
# create vault
|
||||||
|
self.master.run_command(
|
||||||
|
[
|
||||||
|
"ipa",
|
||||||
|
"vault-add",
|
||||||
|
vault_name,
|
||||||
|
"--password",
|
||||||
|
vault_password,
|
||||||
|
"--type",
|
||||||
|
"symmetric",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# archive secret
|
||||||
|
self.master.run_command(
|
||||||
|
[
|
||||||
|
"ipa",
|
||||||
|
"vault-archive",
|
||||||
|
vault_name,
|
||||||
|
"--password",
|
||||||
|
vault_password,
|
||||||
|
"--data",
|
||||||
|
vault_data,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.master.run_command(
|
||||||
|
[
|
||||||
|
"ipa",
|
||||||
|
"vault-retrieve",
|
||||||
|
vault_name,
|
||||||
|
"--password",
|
||||||
|
vault_password,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_krb_enctypes(self):
|
||||||
|
realm = self.master.domain.realm
|
||||||
|
suffix = realm_to_suffix(realm)
|
||||||
|
dn = DN(("cn", realm), ("cn", "kerberos")) + suffix
|
||||||
|
args = ["krbSupportedEncSaltTypes", "krbDefaultEncSaltTypes"]
|
||||||
|
for host in [self.master] + self.replicas:
|
||||||
|
result = tasks.ldapsearch_dm(host, str(dn), args, scope="base")
|
||||||
|
assert "camellia" not in result.stdout_text
|
||||||
|
assert "aes256-cts" in result.stdout_text
|
||||||
|
assert "aes128-cts" in result.stdout_text
|
||||||
|
# test that update does not add camellia
|
||||||
|
self.master.run_command(["ipa-server-upgrade"])
|
||||||
|
result = tasks.ldapsearch_dm(self.master, str(dn), args, scope="base")
|
||||||
|
assert "camellia" not in result.stdout_text
|
||||||
@@ -43,6 +43,7 @@ DEFAULT_OUTPUT_DICT = {
|
|||||||
"admin_password": "Secret123",
|
"admin_password": "Secret123",
|
||||||
"domain_level": MAX_DOMAIN_LEVEL,
|
"domain_level": MAX_DOMAIN_LEVEL,
|
||||||
"log_journal_since": "-1h",
|
"log_journal_since": "-1h",
|
||||||
|
"fips_mode": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_OUTPUT_ENV = {
|
DEFAULT_OUTPUT_ENV = {
|
||||||
@@ -62,6 +63,7 @@ DEFAULT_OUTPUT_ENV = {
|
|||||||
"IPADEBUG": "",
|
"IPADEBUG": "",
|
||||||
"DOMAINLVL": str(MAX_DOMAIN_LEVEL),
|
"DOMAINLVL": str(MAX_DOMAIN_LEVEL),
|
||||||
"LOG_JOURNAL_SINCE": "-1h",
|
"LOG_JOURNAL_SINCE": "-1h",
|
||||||
|
"IPA_FIPS_MODE": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_INPUT_ENV = {
|
DEFAULT_INPUT_ENV = {
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ ipa_class_members = {
|
|||||||
{'ad_admin_name': dir(str)},
|
{'ad_admin_name': dir(str)},
|
||||||
{'ad_admin_password': dir(str)},
|
{'ad_admin_password': dir(str)},
|
||||||
{'domain_level': dir(str)},
|
{'domain_level': dir(str)},
|
||||||
|
{'fips_mode': dir(bool)},
|
||||||
]},
|
]},
|
||||||
{'domain': [
|
{'domain': [
|
||||||
{'realm': dir(str)},
|
{'realm': dir(str)},
|
||||||
|
|||||||
Reference in New Issue
Block a user