2 Commits
Author SHA1 Message Date
zpericic cbc33f21ef ipaserver: Move /etc/httpd/ipa to /etc/ipa/httpd 2025-01-29 22:57:39 +01:00
zpericic b146dbb946 ipaserver: Use apache VirtualHost for IPA UI 2025-01-29 22:57:32 +01:00
38 changed files with 151 additions and 488 deletions

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@
########################################################
define(IPA_VERSION_MAJOR, 4)
define(IPA_VERSION_MINOR, 12)
define(IPA_VERSION_RELEASE, 5)
define(IPA_VERSION_RELEASE, 2)
########################################################
# For 'pre' releases the version will be #
+7 -24
View File
@@ -530,43 +530,26 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
/* get adtrust options using default refresh interval */
ret = ipadb_reinit_mspac(ipactx, false, &stmsg);
if (ret) {
if (stmsg) {
krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
}
/* Initialization of the MS-PAC generator is an optional dependency.
* Fail only if the connection was lost. */
if (!ipactx->lcontext) {
goto done;
}
}
if (ret && stmsg)
krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
ret = 0;
done:
ldap_msgfree(res);
/* LDAP context should never be null on success, but keep this test out of
* security to make sure we do not return an invalid context. */
if (ret == 0 && !ipactx->lcontext) {
krb5_klog_syslog(LOG_WARNING, "Internal malfunction: LDAP connection "
"process resulted in an invalid context "
"(please report this incident)");
ret = LDAP_SERVER_DOWN;
}
if (ret) {
/* Cleanup LDAP context if connection failed. */
if (ipactx->lcontext) {
ldap_unbind_ext_s(ipactx->lcontext, NULL, NULL);
ipactx->lcontext = NULL;
}
/* Replace LDAP error code by POSIX error code. */
ret = ret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO;
if (ret == LDAP_SERVER_DOWN) {
return ETIMEDOUT;
}
return EIO;
}
return ret;
return 0;
}
static krb5_principal ipadb_create_local_tgs(krb5_context kcontext,
-9
View File
@@ -431,14 +431,6 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
const char *test_realm, size_t size,
char **trusted_realm);
/* Check the ticket provided in a TGS-REQ. In some situations, the ticket is
* expected to contain a PAC. If it is not the case, or if the function is
* enable to decode an authorization-data element, it fails.
* Any failure should result in the TGS-REQ to be rejected. */
krb5_error_code ipadb_enforce_pac(krb5_context kcontext,
const krb5_ticket *ticket,
const char **status);
/* DELEGATION CHECKS */
krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
@@ -483,4 +475,3 @@ int ipadb_string_to_sid(const char *str, struct dom_sid *sid);
void alloc_sid(struct dom_sid **sid);
void free_sid(struct dom_sid **sid);
bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check);
bool ipadb_is_tgs_princ(krb5_context kcontext, krb5_const_principal princ);
-18
View File
@@ -767,21 +767,3 @@ krb5_error_code ipadb_multibase_search(struct ipadb_context *ipactx,
return ipadb_simple_ldap_to_kerr(ret);
}
bool
ipadb_is_tgs_princ(krb5_context kcontext, krb5_const_principal princ)
{
krb5_data *primary;
size_t l_tgs_name;
if (2 != krb5_princ_size(kcontext, princ))
return false;
primary = krb5_princ_component(kcontext, princ, 0);
l_tgs_name = strlen(KRB5_TGS_NAME);
if (l_tgs_name != primary->length)
return false;
return 0 == memcmp(primary->data, KRB5_TGS_NAME, l_tgs_name);
}
+1 -1
View File
@@ -195,7 +195,7 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
*lifetime_out = 0;
*renew_lifetime_out = 0;
return ipadb_enforce_pac(context, ticket, status);
return 0;
}
krb5_error_code kdcpolicy_ipakdb_initvt(krb5_context context,
-87
View File
@@ -3346,90 +3346,3 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
return KRB5_KDB_NOENTRY;
}
static krb5_error_code
check_for_pac(krb5_context kcontext, krb5_authdata **authdata, bool *pac_present)
{
krb5_error_code kerr = ENOENT;
size_t i, j;
krb5_authdata **ifrel = NULL;
for (i = 0; authdata && authdata[i]; ++i) {
if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
continue;
}
kerr = krb5_decode_authdata_container(kcontext,
KRB5_AUTHDATA_IF_RELEVANT,
authdata[i], &ifrel);
if (kerr) {
goto end;
}
for (j = 0; ifrel[j]; ++j) {
if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
break;
}
}
if (ifrel[j]) {
break;
}
krb5_free_authdata(kcontext, ifrel);
ifrel = NULL;
}
*pac_present = ifrel;
kerr = 0;
end:
krb5_free_authdata(kcontext, ifrel);
return kerr;
}
krb5_error_code
ipadb_enforce_pac(krb5_context kcontext, const krb5_ticket *ticket,
const char **status)
{
struct ipadb_context *ipactx;
bool pac_present;
krb5_error_code kerr;
/* Filter TGTs only */
if (!ipadb_is_tgs_princ(kcontext, ticket->server)) {
kerr = 0;
goto end;
}
/* Get IPA context */
ipactx = ipadb_get_context(kcontext);
if (!ipactx) {
kerr = KRB5_KDB_DBNOTINITED;
goto end;
}
/* If local TGT but PAC generator not initialized, skip PAC enforcement */
if (krb5_realm_compare(kcontext, ipactx->local_tgs, ticket->server) &&
!ipactx->mspac)
{
krb5_klog_syslog(LOG_WARNING, "MS-PAC not available. This makes "
"FreeIPA vulnerable to privilege escalation exploit "
"(CVE-2025-7493). Please generate SIDs to enable PAC "
"support.");
kerr = 0;
goto end;
}
/* Search for the PAC, fail if it cannot be found */
kerr = check_for_pac(kcontext, ticket->enc_part2->authorization_data,
&pac_present);
if (kerr) {
*status = "PAC_ENFORCEMENT_CANNOT_DECODE_TGT_AUTHDATA";
} else if (!pac_present) {
kerr = ENOENT;
*status = "PAC_ENFORCEMENT_TGT_WITHOUT_PAC";
}
end:
return kerr;
}
+20 -1
View File
@@ -188,6 +188,25 @@ done:
return ret;
}
static bool
is_tgs_princ(krb5_context kcontext, krb5_const_principal princ)
{
krb5_data *primary;
size_t l_tgs_name;
if (2 != krb5_princ_size(kcontext, princ))
return false;
primary = krb5_princ_component(kcontext, princ, 0);
l_tgs_name = strlen(KRB5_TGS_NAME);
if (l_tgs_name != primary->length)
return false;
return 0 == memcmp(primary->data, KRB5_TGS_NAME, l_tgs_name);
}
static krb5_error_code
cmp_local_tgs_princ(krb5_context kcontext, const char *local_realm,
krb5_const_principal princ, bool *result)
@@ -1967,7 +1986,7 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
return kerr;
/* If TGS principal, some virtual attributes may be added */
if (ipadb_is_tgs_princ(kcontext, (*entry)->princ)) {
if (is_tgs_princ(kcontext, (*entry)->princ)) {
kerr = cmp_local_tgs_princ(kcontext, ipactx->realm, (*entry)->princ,
&is_local_tgs_princ);
if (kerr)
+10 -14
View File
@@ -31,7 +31,6 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/random.h>
#include <sys/uio.h>
#include "internal.h"
@@ -94,7 +93,6 @@ static void oauth2_on_child_writable(verto_ctx *vctx, verto_ev *ev)
(void)vctx; /* Unused */
ssize_t io;
struct child_ctx *child_ctx;
struct iovec iov[3];
child_ctx = verto_get_private(ev);
if (child_ctx == NULL) {
@@ -104,18 +102,15 @@ static void oauth2_on_child_writable(verto_ctx *vctx, verto_ev *ev)
}
if (child_ctx->oauth2_state == OAUTH2_GET_DEVICE_CODE) {
io = write(verto_get_fd(ev), child_ctx->item->idp.ipaidpClientSecret,
strlen(child_ctx->item->idp.ipaidpClientSecret));
} else {
iov[0].iov_base = child_ctx->item->idp.ipaidpClientSecret;
iov[0].iov_len = strlen(child_ctx->item->idp.ipaidpClientSecret);
iov[1].iov_base = "\n";
iov[1].iov_len = 1;
iov[2].iov_base = child_ctx->saved_item->oauth2.device_code_reply;
iov[2].iov_len = strlen(child_ctx->saved_item->oauth2.device_code_reply);
io = writev(verto_get_fd(ev), iov, 3);
/* no input needed */
verto_del(ev);
return;
}
io = write(verto_get_fd(ev),
child_ctx->saved_item->oauth2.device_code_reply,
strlen(child_ctx->saved_item->oauth2.device_code_reply));
otpd_queue_item_free(child_ctx->saved_item);
if (io < 0) {
@@ -434,7 +429,8 @@ int oauth2(struct otpd_queue_item **item, enum oauth2_state oauth2_state)
args[args_idx++] = (*item)->idp.ipaidpClientID;
if ((*item)->idp.ipaidpClientSecret) {
args[args_idx++] = "--client-secret-stdin";
args[args_idx++] = "--client-secret";
args[args_idx++] = (*item)->idp.ipaidpClientSecret;
}
if ((*item)->idp.ipaidpScope) {
@@ -15,7 +15,6 @@ import six
import gssapi
from ipalib.install.kinit import kinit_keytab, kinit_password
from ipapython.admintool import admin_cleanup_global_argv
if six.PY3:
unicode = str
@@ -53,13 +52,11 @@ def parse_options():
"--password",
action="store",
dest="password",
help="Password for Active Directory administrator",
sensitive=True
help="Display debugging information",
)
options, args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
admin_cleanup_global_argv(parser, options, sys.argv)
# We only use first argument of the passed args but as D-BUS interface
# in oddjobd cannot expose optional, we fill in empty slots from IPA side
-1
View File
@@ -239,7 +239,6 @@ objectClass: ipasshuser
uid: admin
krbPrincipalName: admin@$REALM
krbPrincipalName: root@$REALM
krbCanonicalName: admin@$REALM
cn: Administrator
sn: Administrator
uidNumber: $IDSTART
+23 -5
View File
@@ -1,16 +1,34 @@
dn: cn=kerberos name uniqueness,cn=plugins,cn=config
dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
changetype: add
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
cn: kerberos name uniqueness
cn: krbPrincipalName uniqueness
nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
uniqueness-attribute-name: krbPrincipalName:CaseIgnoreMatch:
uniqueness-attribute-name: krbPrincipalAlias:CaseIgnoreMatch:
uniqueness-attribute-name: krbCanonicalName:CaseIgnoreMatch:
uniqueness-attribute-name: krbPrincipalName
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
nsslapd-pluginVendor: Fedora Project
nsslapd-pluginDescription: Enforce unique attribute values
uniqueness-subtrees: $SUFFIX
uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
uniqueness-across-all-subtrees: on
dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
changetype: add
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
cn: krbCanonicalName uniqueness
nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
uniqueness-attribute-name: krbCanonicalName
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
+4 -3
View File
@@ -29,17 +29,19 @@ import sys
import six
from optparse import SUPPRESS_HELP # pylint: disable=deprecated-module
from ipalib.install import sysrestore
from ipaserver.install import adtrust, service
from ipaserver.install.installutils import (
read_password,
check_server_configuration,
run_script)
from ipapython.admintool import ScriptError, admin_cleanup_global_argv
from ipapython.admintool import ScriptError
from ipapython import version
from ipapython import ipautil
from ipalib import api, errors, krb_utils
from ipapython.config import IPAOptionParser, SUPPRESS_HELP
from ipapython.config import IPAOptionParser
from ipaplatform.paths import paths
from ipapython.ipa_log_manager import standard_logging_setup
@@ -93,7 +95,6 @@ def parse_options():
options, _args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
admin_cleanup_global_argv(parser, options, sys.argv)
return safe_options, options
-2
View File
@@ -42,7 +42,6 @@ from ipalib.constants import DOMAIN_LEVEL_1
from ipapython.config import IPAOptionParser
from ipapython.ipa_log_manager import standard_logging_setup
from ipaplatform.paths import paths
from ipapython.admintool import admin_cleanup_global_argv
logger = logging.getLogger(os.path.basename(__file__))
@@ -133,7 +132,6 @@ def parse_options():
options, args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
admin_cleanup_global_argv(parser, options, sys.argv)
if args:
parser.error("Too many arguments provided")
+2 -4
View File
@@ -24,13 +24,13 @@ from __future__ import print_function
import sys
from ipaplatform.paths import paths
try:
from optparse import OptionParser # pylint: disable=deprecated-module
from ipapython import ipautil, config
from ipaserver.install import installutils
from ipaserver.install.ldapupdate import LDAPUpdate
from ipalib import api, errors
from ipapython.ipa_log_manager import standard_logging_setup
from ipapython.dn import DN
from ipapython.admintool import admin_cleanup_global_argv
except ImportError as e:
print("""\
There was a problem importing one of the required Python modules. The
@@ -46,8 +46,7 @@ nis_config_dn = DN(('cn', 'NIS Server'), ('cn', 'plugins'), ('cn', 'config'))
def parse_options():
usage = "%prog [options] <enable|disable|status>\n"
usage += "%prog [options]\n"
parser = config.IPAOptionParser(usage=usage,
formatter=config.IPAFormatter())
parser = OptionParser(usage=usage, formatter=config.IPAFormatter())
parser.add_option("-d", "--debug", action="store_true", dest="debug",
help="Display debugging information about the update(s)")
@@ -56,7 +55,6 @@ def parse_options():
config.add_standard_options(parser)
options, args = parser.parse_args()
admin_cleanup_global_argv(parser, options, sys.argv)
return options, args
+6 -6
View File
@@ -32,8 +32,8 @@ from ipaserver.install import (replication, installutils, bindinstance,
from ipalib import api, errors
from ipalib.constants import FQDN
from ipalib.util import has_managed_topology, print_replication_status
from ipapython import ipautil, ipaldap, version, config
from ipapython.admintool import admin_cleanup_global_argv, ScriptError
from ipapython import ipautil, ipaldap, version
from ipapython.admintool import ScriptError
from ipapython.dn import DN
logger = logging.getLogger(os.path.basename(__file__))
@@ -54,10 +54,11 @@ commands = {
def parse_options():
parser = config.IPAOptionParser(version=version.VERSION)
from optparse import OptionParser # pylint: disable=deprecated-module
parser = OptionParser(version=version.VERSION)
parser.add_option("-H", "--host", dest="host", help="starting host")
parser.add_option("-p", "--password", dest="dirman_passwd", sensitive=True,
help="Directory Manager password")
parser.add_option("-p", "--password", dest="dirman_passwd", help="Directory Manager password")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False,
help="provide additional information")
parser.add_option("-f", "--force", dest="force", action="store_true", default=False,
@@ -65,7 +66,6 @@ def parse_options():
parser.add_option("--from", dest="fromhost", help="Host to get data from")
options, args = parser.parse_args()
admin_cleanup_global_argv(parser, options, sys.argv)
valid_syntax = False
+3 -5
View File
@@ -24,6 +24,7 @@ import logging
import os
import re
import sys
from optparse import OptionParser # pylint: disable=deprecated-module
from ipaplatform.paths import paths
from ipapython import config
@@ -31,7 +32,6 @@ from ipaserver.install import installutils
from ipalib import api, errors
from ipapython.ipa_log_manager import standard_logging_setup
from ipapython.dn import DN
from ipapython.admintool import admin_cleanup_global_argv
logger = logging.getLogger(os.path.basename(__file__))
@@ -39,8 +39,7 @@ logger = logging.getLogger(os.path.basename(__file__))
def parse_options():
usage = "%prog [options] <status|enable|disable>\n"
usage += "%prog [options]\n"
parser = config.IPAOptionParser(usage=usage,
formatter=config.IPAFormatter())
parser = OptionParser(usage=usage, formatter=config.IPAFormatter())
parser.add_option("-d", "--debug", action="store_true", dest="debug",
help="Display debugging information about the update(s)")
@@ -51,10 +50,9 @@ def parse_options():
action="store_true",
help="List available Managed Entries")
parser.add_option("-p", "--password", dest="dirman_password",
sensitive=True, help="Directory Manager password")
help="Directory Manager password")
options, args = parser.parse_args()
admin_cleanup_global_argv(parser, options, sys.argv)
return options, args
+3 -4
View File
@@ -23,15 +23,15 @@ from __future__ import print_function
import logging
from ipapython import ipachangeconf
from ipapython.config import (IPAOptionParser, OptionGroup,
OptionValueError)
from ipapython.admintool import admin_cleanup_global_argv
from ipapython.config import IPAOptionParser
from ipapython.dn import DN
from ipapython import version
from ipapython import ipautil, certdb
from ipalib import api, errors, x509
from ipalib.constants import FQDN
from ipaserver.install import installutils
# pylint: disable=deprecated-module
from optparse import OptionGroup, OptionValueError
# pylint: enable=deprecated-module
from ipapython.ipa_log_manager import standard_logging_setup
import copy
@@ -189,7 +189,6 @@ def parse_options():
options, _args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
admin_cleanup_global_argv(parser, options, sys.argv)
if options.master and options.replica:
parser.error("on-master and on-replica options are mutually exclusive!")
+3 -7
View File
@@ -43,7 +43,6 @@ from ipalib.util import (
print_replication_status,
verify_host_resolvable,
)
from ipapython.admintool import admin_cleanup_global_argv
from ipapython.ipa_log_manager import standard_logging_setup
from ipapython.dn import DN
from ipapython.config import IPAOptionParser
@@ -85,8 +84,7 @@ class NoRUVsFound(Exception):
def parse_options():
parser = IPAOptionParser(version=version.VERSION)
parser.add_option("-H", "--host", dest="host", help="starting host")
parser.add_option("-p", "--password", dest="dirman_passwd", sensitive=True,
help="Directory Manager password")
parser.add_option("-p", "--password", dest="dirman_passwd", help="Directory Manager password")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False,
help="provide additional information")
parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False,
@@ -97,7 +95,7 @@ def parse_options():
help="DANGER: clean up references to a ghost master")
parser.add_option("--binddn", dest="binddn", default=None, type="dn",
help="Bind DN to use with remote server")
parser.add_option("--bindpw", dest="bindpw", default=None, sensitive=True,
parser.add_option("--bindpw", dest="bindpw", default=None,
help="Password for Bind DN to use with remote server")
parser.add_option("--winsync", dest="winsync", action="store_true", default=False,
help="This is a Windows Sync Agreement")
@@ -105,15 +103,13 @@ def parse_options():
help="Full path and filename of CA certificate to use with TLS/SSL to the remote server")
parser.add_option("--win-subtree", dest="win_subtree", default=None,
help="DN of Windows subtree containing the users you want to sync (default cn=Users,<domain suffix)")
parser.add_option("--passsync", dest="passsync",
default=None, sensitive=True,
parser.add_option("--passsync", dest="passsync", default=None,
help="Password for the IPA system user used by the Windows PassSync plugin to synchronize passwords")
parser.add_option("--from", dest="fromhost", help="Host to get data from")
parser.add_option("--no-lookup", dest="nolookup", action="store_true", default=False,
help="do not perform DNS lookup checks")
options, args = parser.parse_args()
admin_cleanup_global_argv(parser, options, sys.argv)
valid_syntax = False
+4 -23
View File
@@ -80,32 +80,13 @@ add:uniqueness-subtree-entries-oc: posixAccount
# krbPrincipalName uniqueness scopes Active/Delete containers
dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
deleteentry: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
add:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
add:uniqueness-across-all-subtrees: on
# krbCanonicalName uniqueness scopes Active/Delete containers
dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
deleteentry: dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
dn: cn=kerberos name uniqueness,cn=plugins,cn=config
default:objectClass: top
default:objectClass: nsSlapdPlugin
default:objectClass: extensibleObject
default:cn: kerberos name uniqueness
default:nsslapd-pluginPath: libattr-unique-plugin
default:nsslapd-pluginInitfunc: NSUniqueAttr_Init
default:nsslapd-pluginType: preoperation
default:nsslapd-pluginEnabled: on
default:uniqueness-attribute-name: krbPrincipalName:CaseIgnoreMatch:
default:uniqueness-attribute-name: krbPrincipalAlias:CaseIgnoreMatch:
default:uniqueness-attribute-name: krbCanonicalName:CaseIgnoreMatch:
default:nsslapd-plugin-depends-on-type: database
default:nsslapd-pluginId: NSUniqueAttr
default:nsslapd-pluginVersion: 1.1.0
default:nsslapd-pluginVendor: Fedora Project
default:nsslapd-pluginDescription: Enforce unique attribute values
default:uniqueness-subtrees: $SUFFIX
default:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
default:uniqueness-across-all-subtrees: on
add:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
add:uniqueness-across-all-subtrees: on
# ipaUniqueID uniqueness scopes Active/Delete containers
dn: cn=ipaUniqueID uniqueness,cn=plugins,cn=config
@@ -27,7 +27,6 @@ plugin: update_mapping_Guests_to_nobody
plugin: fix_kra_people_entry
plugin: update_pwpolicy
plugin: update_pwpolicy_grace
plugin: add_admin_krbcanonicalname
# last
# DNS version 1
+2 -2
View File
@@ -34,6 +34,7 @@ import SSSDConfig
from six.moves.urllib.parse import urlsplit
from optparse import OptionParser # pylint: disable=deprecated-module
from ipapython import ipachangeconf
from ipaclient import discovery
from ipaclient.install.client import (
@@ -51,7 +52,6 @@ from ipaplatform.tasks import tasks
from ipaplatform import services
from ipaplatform.paths import paths
from ipapython.admintool import ScriptError
from ipapython.config import IPAOptionParser
logger = logging.getLogger(os.path.basename(__file__))
@@ -59,7 +59,7 @@ logger = logging.getLogger(os.path.basename(__file__))
def parse_options():
usage = "%prog [options]\n"
parser = IPAOptionParser(usage=usage)
parser = OptionParser(usage=usage)
parser.add_option("--server", dest="server", help="FQDN of IPA server")
parser.add_option(
"--location",
+2 -2
View File
@@ -9,6 +9,7 @@ import logging
import os
import gssapi
from urllib.parse import urlsplit
from optparse import OptionParser # pylint: disable=deprecated-module
from contextlib import contextmanager
from ipaclient import discovery
@@ -30,7 +31,6 @@ from ipaplatform.constants import constants
from ipaplatform import services
from ipapython.admintool import ScriptError
from samba import generate_random_password
from ipapython.config import IPAOptionParser
logger = logging.getLogger(os.path.basename(__file__))
logger.setLevel(logging.DEBUG)
@@ -68,7 +68,7 @@ def use_api_as_principal(principal, keytab):
def parse_options():
usage = "%prog [options]\n"
parser = IPAOptionParser(usage=usage)
parser = OptionParser(usage=usage)
parser.add_option(
"--server",
dest="server",
+9 -12
View File
@@ -30,6 +30,7 @@ import textwrap
import sys
import getpass
import code
import optparse # pylint: disable=deprecated-module
import os
import pprint
import fcntl
@@ -70,8 +71,6 @@ from ipalib.text import _
from ipalib import api
from ipapython.dnsutil import DNSName
from ipapython.admintool import ScriptError
from ipapython.config import (IPAOptionParser, IPAFormatter,
OptionGroup, make_option)
import datetime
@@ -1122,8 +1121,7 @@ class Collector:
def __todict__(self):
return dict(self.__options)
class CLIOptionParserFormatter(IPAFormatter):
class CLIOptionParserFormatter(optparse.IndentedHelpFormatter):
def format_argument(self, name, help_string):
result = []
opt_width = self.help_position - self.current_indent - 2
@@ -1143,8 +1141,7 @@ class CLIOptionParserFormatter(IPAFormatter):
result.append("\n")
return "".join(result)
class CLIOptionParser(IPAOptionParser):
class CLIOptionParser(optparse.OptionParser):
"""
This OptionParser subclass adds an ability to print positional
arguments in CLI help. Custom formatter is used to format the argument
@@ -1154,13 +1151,13 @@ class CLIOptionParser(IPAOptionParser):
self._arguments = []
if 'formatter' not in kwargs:
kwargs['formatter'] = CLIOptionParserFormatter()
IPAOptionParser.__init__(self, *args, **kwargs)
optparse.OptionParser.__init__(self, *args, **kwargs)
def format_option_help(self, formatter=None):
"""
Prepend argument help to standard OptionParser's option help
"""
option_help = IPAOptionParser.format_option_help(self, formatter)
option_help = optparse.OptionParser.format_option_help(self, formatter)
if isinstance(formatter, CLIOptionParserFormatter):
heading = unicode(_("Positional arguments"))
@@ -1275,7 +1272,7 @@ class cli(backend.Executioner):
"""Get or create an option group for the given name"""
option_group = option_groups.get(group_name)
if option_group is None:
option_group = OptionGroup(parser, group_name)
option_group = optparse.OptionGroup(parser, group_name)
parser.add_option_group(option_group)
option_groups[group_name] = option_group
return option_group
@@ -1301,7 +1298,7 @@ class cli(backend.Executioner):
option_names = ['--%s' % cli_name]
if option.cli_short_name:
option_names.append('-%s' % option.cli_short_name)
opt = make_option(*option_names, **kw)
opt = optparse.make_option(*option_names, **kw)
if option.option_group is None:
parser.add_option(opt)
else:
@@ -1315,7 +1312,7 @@ class cli(backend.Executioner):
group = _get_option_group(unicode(_('Deprecated options')))
for alias in option.deprecated_cli_aliases:
name = '--%s' % alias
group.add_option(make_option(name, **new_kw))
group.add_option(optparse.make_option(name, **new_kw))
for arg in cmd.args():
name = self.__get_arg_name(arg, format_name=False)
@@ -1445,7 +1442,7 @@ class cli(backend.Executioner):
)
class IPAHelpFormatter(IPAFormatter):
class IPAHelpFormatter(optparse.IndentedHelpFormatter):
"""Formatter suitable for printing IPA command help
The default help formatter reflows text to fit the terminal, but it
+4 -4
View File
@@ -33,6 +33,7 @@ import sys
import threading
import os
from os import path
import optparse # pylint: disable=deprecated-module
import textwrap
import collections
import importlib
@@ -46,7 +47,6 @@ from ipalib.util import classproperty
from ipalib.base import ReadOnly, lock, islocked
from ipalib.constants import DEFAULT_CONFIG
from ipapython import ipa_log_manager, ipautil
from ipapython.config import IPAOptionParser, IPAFormatter
from ipapython.ipa_log_manager import (
LOGGING_FORMAT_FILE,
LOGGING_FORMAT_STDERR)
@@ -526,7 +526,7 @@ class API(ReadOnly):
def build_global_parser(self, parser=None, context=None):
"""
Add global options to an IPAOptionParser instance.
Add global options to an optparse.OptionParser instance.
"""
def config_file_callback(option, opt, value, parser):
if not os.path.isfile(value):
@@ -536,7 +536,7 @@ class API(ReadOnly):
parser.values.conf = value
if parser is None:
parser = IPAOptionParser(
parser = optparse.OptionParser(
add_help_option=False,
formatter=IPAHelpFormatter(),
usage='%prog [global-options] COMMAND [command-options]',
@@ -821,7 +821,7 @@ class API(ReadOnly):
return self.__next[plugin]
class IPAHelpFormatter(IPAFormatter):
class IPAHelpFormatter(optparse.IndentedHelpFormatter):
def format_epilog(self, epilog):
text_width = self.width - self.current_indent
indent = " " * self.current_indent
+2 -41
View File
@@ -26,6 +26,7 @@ import logging
import sys
import os
import traceback
from optparse import OptionGroup # pylint: disable=deprecated-module
from ipaplatform.osinfo import osinfo
from ipapython import version
@@ -39,45 +40,6 @@ SERVER_NOT_CONFIGURED = 2
logger = logging.getLogger(__name__)
def admin_cleanup_global_argv(option_parser, options, argv):
"""Takes option parser and generated options and scrubs sensitive arguments
from the global program arguments. Note that this only works for GNU GLIBC
as Python has no generic way to get access to the original argv values to
modify them in place.
The code assumes Python behavior, e.g. there are two additional args in the
list (/path/to/python -I ...) than what's passed as 'argv' here.
"""
import ctypes
import ctypes.util
try:
_c = ctypes.CDLL(ctypes.util.find_library("c"))
if _c._name is None:
return
_argv = ctypes.POINTER(ctypes.c_voidp).in_dll(_c, "_dl_argv")
# since we run as 'python -I <executable> ...', add two args
_argc = len(argv) + 2
all_options = []
if '_get_all_options' in dir(option_parser):
# OptParse parser
all_options = option_parser._get_all_options()
elif '_actions' in dir(option_parser):
# ArgParse parser
all_options = option_parser._actions
for opt in all_options:
if getattr(opt, 'sensitive', False):
v = getattr(options, opt.dest)
for i in range(0, _argc):
vi = ctypes.cast(_argv[i],
ctypes.c_char_p
).value.decode('utf-8')
if vi == v:
ctypes.memset(_argv[i], ord('X'), len(v))
except Exception:
pass
class ScriptError(Exception):
"""An exception that records an error message and a return value
"""
@@ -151,7 +113,7 @@ class AdminTool:
:param parser: The parser to add options to
:param debug_option: Add a --debug option as an alias to --verbose
"""
group = config.OptionGroup(parser, "Logging and output options")
group = OptionGroup(parser, "Logging and output options")
group.add_option("-v", "--verbose", dest="verbose", default=False,
action="store_true", help="print debugging information")
if debug_option:
@@ -187,7 +149,6 @@ class AdminTool:
cls._option_parsers[cls] = cls.option_parser
options, args = cls.option_parser.parse_args(argv[1:])
admin_cleanup_global_argv(cls.option_parser, options, argv)
command_class = cls.get_command_class(options, args)
command = command_class(options, args)
+7 -11
View File
@@ -18,9 +18,9 @@
#
from __future__ import absolute_import
# pylint: disable=deprecated-module, disable=unused-import
from optparse import (Option, Values, OptionGroup, OptionParser, SUPPRESS_HELP,
IndentedHelpFormatter, OptionValueError, make_option)
# pylint: disable=deprecated-module
from optparse import (
Option, Values, OptionParser, IndentedHelpFormatter, OptionValueError)
# pylint: enable=deprecated-module
from copy import copy
from configparser import ConfigParser as SafeConfigParser
@@ -113,14 +113,10 @@ class IPAOptionParser(OptionParser):
description=None,
formatter=None,
add_help_option=True,
prog=None,
epilog=None):
OptionParser.__init__(self, usage=usage, option_list=option_list,
option_class=option_class, version=version,
conflict_handler=conflict_handler,
description=description, formatter=formatter,
add_help_option=add_help_option, prog=prog,
epilog=epilog)
prog=None):
OptionParser.__init__(self, usage, option_list, option_class,
version, conflict_handler, description,
formatter, add_help_option, prog)
def get_safe_opts(self, opts):
"""
+5 -4
View File
@@ -9,11 +9,12 @@ Command line support.
import collections
import enum
import logging
import optparse # pylint: disable=deprecated-module
import signal
import six
from ipapython import admintool, config
from ipapython import admintool
from ipapython.ipa_log_manager import standard_logging_setup
from ipapython.ipautil import (CheckedIPAddress, CheckedIPAddressLoopback,
private_ccache)
@@ -157,7 +158,7 @@ class ConfigureTool(admintool.AdminTool):
try:
opt_group = groups[group_cls]
except KeyError:
opt_group = groups[group_cls] = config.OptionGroup(
opt_group = groups[group_cls] = optparse.OptionGroup(
parser, "{0} options".format(group_cls.description))
parser.add_option_group(opt_group)
@@ -231,7 +232,7 @@ class ConfigureTool(admintool.AdminTool):
if not hidden:
help = knob_cls.description
else:
help = config.SUPPRESS_HELP
help = optparse.SUPPRESS_HELP
opt_group.add_option(
*opt_strs,
@@ -255,7 +256,7 @@ class ConfigureTool(admintool.AdminTool):
# fake option parser to parse positional arguments
# (because optparse does not support positional argument parsing)
fake_option_parser = config.IPAOptionParser()
fake_option_parser = optparse.OptionParser()
self.add_options(fake_option_parser, True)
fake_option_map = {option.dest: option
+4 -2
View File
@@ -7,12 +7,14 @@ import enum
import pki.util
import logging
from optparse import OptionGroup # pylint: disable=deprecated-module
from ipalib import api, errors, x509
from ipalib import _
from ipalib.facts import is_ipa_configured
from ipaplatform.paths import paths
from ipapython.admintool import AdminTool
from ipapython import cookie, dogtag, config
from ipapython import cookie, dogtag
from ipapython.ipautil import run
from ipapython.certdb import NSSDatabase, EXTERNAL_CA_TRUST_FLAGS
from ipaserver.install import cainstance
@@ -141,7 +143,7 @@ class IPAACMEManage(AdminTool):
@classmethod
def add_options(cls, parser):
group = config.OptionGroup(parser, 'Pruning')
group = OptionGroup(parser, 'Pruning')
group.add_option(
"--enable", dest="enable", action="store_true",
default=False, help="Enable certificate pruning")
+3 -2
View File
@@ -20,6 +20,7 @@
from __future__ import absolute_import, print_function
import logging
import optparse # pylint: disable=deprecated-module
import os
import shutil
import sys
@@ -31,7 +32,7 @@ import six
from ipaplatform.paths import paths
from ipaplatform import services
from ipalib import api, errors
from ipapython import version, config
from ipapython import version
from ipapython.ipautil import run, write_tmp_file
from ipapython import admintool, certdb
from ipapython.dn import DN
@@ -245,7 +246,7 @@ class Backup(admintool.AdminTool):
parser.add_option(
"--gpg-keyring", dest="gpg_keyring",
help=config.SUPPRESS_HELP)
help=optparse.SUPPRESS_HELP)
parser.add_option(
"--gpg", dest="gpg", action="store_true",
default=False, help="Encrypt the backup")
+5 -4
View File
@@ -22,13 +22,14 @@ from __future__ import print_function, absolute_import
import datetime
import logging
import os
from optparse import OptionGroup # pylint: disable=deprecated-module
import gssapi
from ipalib.constants import (
RENEWAL_CA_NAME, RENEWAL_REUSE_CA_NAME, RENEWAL_SELFSIGNED_CA_NAME,
IPA_CA_CN)
from ipalib.install import certmonger, certstore
from ipapython import admintool, ipautil, config
from ipapython import admintool, ipautil
from ipapython.certdb import (EMPTY_TRUST_FLAGS,
EXTERNAL_CA_TRUST_FLAGS,
TrustFlags,
@@ -60,7 +61,7 @@ class CACertManage(admintool.AdminTool):
"-p", "--password", dest='password',
help="Directory Manager password")
renew_group = config.OptionGroup(parser, "Renew options")
renew_group = OptionGroup(parser, "Renew options")
renew_group.add_option(
"--self-signed", dest='self_signed',
action='store_true',
@@ -88,7 +89,7 @@ class CACertManage(admintool.AdminTool):
"certificate chain")
parser.add_option_group(renew_group)
install_group = config.OptionGroup(parser, "Install options")
install_group = OptionGroup(parser, "Install options")
install_group.add_option(
"-n", "--nickname", dest='nickname',
help="Nickname for the certificate")
@@ -97,7 +98,7 @@ class CACertManage(admintool.AdminTool):
help="Trust flags for the certificate in certutil format")
parser.add_option_group(install_group)
delete_group = config.OptionGroup(parser, "Delete options")
delete_group = OptionGroup(parser, "Delete options")
delete_group.add_option(
"-f", "--force", action='store_true',
help="Force removing the CA even if chain validation fails")
+3 -2
View File
@@ -22,12 +22,13 @@ from __future__ import print_function, absolute_import
import logging
import sys
import tempfile
from optparse import SUPPRESS_HELP # pylint: disable=deprecated-module
from textwrap import dedent
from ipalib import api
from ipalib.constants import DOMAIN_LEVEL_1
from ipaplatform.paths import paths
from ipapython import admintool, config
from ipapython import admintool
from ipaserver.install import service
from ipaserver.install import cainstance
from ipaserver.install import custodiainstance
@@ -72,7 +73,7 @@ class KRAInstall(admintool.AdminTool):
parser.add_option(
"--uninstall",
dest="uninstall", action="store_true", default=False,
help=config.SUPPRESS_HELP)
help=SUPPRESS_HELP)
parser.add_option(
"--pki-config-override", dest="pki_config_override",
+1 -16
View File
@@ -28,7 +28,6 @@ from ipaplatform.paths import paths
from ipapython.dn import DN
from ipapython.ipaldap import LDAPClient, LDAPEntry, realm_to_ldapi_uri
from ipapython.ipa_log_manager import standard_logging_setup
from ipapython.admintool import admin_cleanup_global_argv
from ipaserver.install.ipa_migrate_constants import (
DS_CONFIG, DB_OBJECTS, DS_INDEXES, BIND_DN, LOG_FILE_NAME,
STRIP_OP_ATTRS, STRIP_ATTRS, STRIP_OC, PROD_ATTRS,
@@ -285,18 +284,6 @@ class LDIFParser(ldif.LDIFParser):
self.mc.process_db_entry(entry_dn=dn, entry_attrs=entry_attrs)
class SensitiveStoreAction(argparse._StoreAction):
def __init__(self, *, sensitive, **options):
super(SensitiveStoreAction, self).__init__(**options)
self.sensitive = sensitive
def _get_kwargs(self):
names = super(SensitiveStoreAction, self)._get_kwargs()
sensitive_name = 'sensitive'
names.extend((sensitive_name, getattr(self, sensitive_name)))
return names
#
# Migrate IPA to IPA Class
#
@@ -357,8 +344,7 @@ class IPAMigrate():
help='Password for the Bind DN. If a password '
'is not provided then the user will be '
'prompted to enter it',
default=None, sensitive=True,
action=SensitiveStoreAction)
default=None)
parser.add_argument('-j', '--bind-pw-file',
help='A text file containing the clear text '
'password for the Bind DN', default=None)
@@ -2037,7 +2023,6 @@ class IPAMigrate():
parser = argparse.ArgumentParser(description=desc, allow_abbrev=True)
self.add_options(parser)
self.validate_options()
admin_cleanup_global_argv(parser, self.args, sys.argv)
# Check for dryrun mode
if self.args.dryrun or self.args.dryrun_record is not None:
+4 -3
View File
@@ -20,6 +20,7 @@
from __future__ import absolute_import, print_function
import logging
import optparse # pylint: disable=deprecated-module
import os
import shutil
import sys
@@ -33,7 +34,7 @@ import six
from ipaclient.install.client import update_ipa_nssdb
from ipalib import api, errors
from ipalib.constants import FQDN
from ipapython import version, ipautil, config
from ipapython import version, ipautil
from ipapython.ipautil import run, user_input
from ipapython import admintool, certdb
from ipapython.dn import DN
@@ -185,11 +186,11 @@ class Restore(admintool.AdminTool):
super(Restore, cls).add_options(parser, debug_option=True)
parser.add_option(
"-p", "--password", dest="password", sensitive=True,
"-p", "--password", dest="password",
help="Directory Manager password")
parser.add_option(
"--gpg-keyring", dest="gpg_keyring",
help=config.SUPPRESS_HELP)
help=optparse.SUPPRESS_HELP)
parser.add_option(
"--data", dest="data_only", action="store_true",
default=False, help="Restore only the data")
+5 -4
View File
@@ -22,11 +22,12 @@ from __future__ import print_function, absolute_import
import os
import os.path
import tempfile
import optparse # pylint: disable=deprecated-module
from ipalib import x509
from ipalib.install import certmonger
from ipaplatform.paths import paths
from ipapython import admintool, dogtag, config
from ipapython import admintool, dogtag
from ipapython.certdb import NSSDatabase, get_ca_nickname
from ipapython.dn import DN
from ipapython import ipaldap
@@ -64,15 +65,15 @@ class ServerCertInstall(admintool.AdminTool):
help="The password of the PKCS#12 file")
parser.add_option(
"--dirsrv_pin", "--http_pin",
dest="pin", sensitive=True,
help=config.SUPPRESS_HELP)
dest="pin",
help=optparse.SUPPRESS_HELP)
parser.add_option(
"--cert-name",
dest="cert_name", metavar="NAME",
help="Name of the certificate to install")
parser.add_option(
"-p", "--dirman-password",
dest="dirman_password", sensitive=True,
dest="dirman_password",
help="Directory Manager password")
def validate_options(self):
@@ -1,79 +0,0 @@
#
# Copyright (C) 2025 FreeIPA Contributors see COPYING for license
#
from __future__ import absolute_import
import logging
from ipalib import errors
from ipalib import Registry
from ipalib import Updater
from ipapython.dn import DN
logger = logging.getLogger(__name__)
register = Registry()
@register()
class add_admin_krbcanonicalname(Updater):
"""
Ensures that only the admin user has the krbCanonicalName of
admin@$REALM.
"""
def execute(self, **options):
ldap = self.api.Backend.ldap2
search_filter = (
"(krbcanonicalname=admin@{})".format(self.api.env.realm))
try:
(entries, _truncated) = ldap.find_entries(
filter=search_filter, base_dn=self.api.env.basedn,
time_limit=0, size_limit=0)
except errors.EmptyResult:
logger.debug("add_admin_krbcanonicalname: No user set with "
"admin krbcanonicalname")
entries = []
# fall through
except errors.ExecutionError as e:
logger.error("add_admin_krbcanonicalname: Can not get list "
"of krbcanonicalname: %s", e)
return False, []
admin_set = False
# admin should be only user with admin@ as krbcanonicalname
# It has a uniquness setting so there can be only one, we
# just didn't automatically set it for admin.
for entry in entries:
if entry.single_value.get('uid') != 'admin':
logger.critical(
"add_admin_krbcanonicalname: "
"entry %s has a krbcanonicalname of admin. Removing.",
entry.dn)
del entry['krbcanonicalname']
ldap.update_entry(entry)
else:
admin_set = True
if not admin_set:
dn = DN(
('uid', 'admin'),
self.api.env.container_user,
self.api.env.basedn)
entry = ldap.get_entry(dn)
entry['krbcanonicalname'] = 'admin@%s' % self.api.env.realm
try:
ldap.update_entry(entry)
except errors.DuplicateEntry:
logger.critical(
"add_admin_krbcanonicalname: "
"Failed to set krbcanonicalname on admin. It is set "
"on another entry.")
except errors.ExecutionError as e:
logger.critical(
"add_admin_krbcanonicalname: "
"Failed to set krbcanonicalname on admin: %s", e)
return False, []
+4 -4
View File
@@ -22,6 +22,7 @@ from __future__ import print_function
# WARNING: Do not import ipa modules, this is also used as a
# stand-alone script (invoked from po Makefile).
import optparse # pylint: disable=deprecated-module
import sys
import gettext
import re
@@ -29,7 +30,6 @@ import os
import traceback
import polib
from collections import namedtuple
from ipapython import config
import six
@@ -722,9 +722,9 @@ usage ='''
def main():
global verbose, print_traceback, pedantic, show_strings
parser = config.IPAOptionParser(usage=usage)
parser = optparse.OptionParser(usage=usage)
mode_group = config.OptionGroup(parser, 'Operational Mode',
mode_group = optparse.OptionGroup(parser, 'Operational Mode',
'You must select one these modes to run in')
mode_group.add_option('-g', '--test-gettext', action='store_const', const='test_gettext', dest='mode',
@@ -748,7 +748,7 @@ def main():
parser.add_option('--traceback', action='store_true', dest='print_traceback', default=False,
help='print the traceback when an exception occurs')
param_group = config.OptionGroup(parser, 'Run Time Parameters',
param_group = optparse.OptionGroup(parser, 'Run Time Parameters',
'These may be used to modify the run time defaults')
param_group.add_option('--test-lang', action='store', dest='test_lang', default='test',
@@ -1883,80 +1883,6 @@ class TestIPACommandWithoutReplica(IntegrationTest):
assert old_err_msg not in dirsrv_error_log
assert re.search(new_err_msg, dirsrv_error_log)
def test_unique_krbcanonicalname(self):
"""Verify that the uniqueness for krbcanonicalname is working"""
master = self.master
base_dn = str(master.domain.basedn)
hostname = master.hostname
realm = master.domain.realm
principal = f'test/{hostname}@{realm}'
entry_ldif_template = textwrap.dedent("""
dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn}
changetype: add
ipakrbprincipalalias: test/{hostname}@{realm}
krbprincipalname: {principal}
objectclass: ipakrbprincipal
objectclass: ipaobject
objectclass: ipaservice
objectclass: krbprincipal
objectclass: krbprincipalaux
objectclass: top
krbcanonicalname: {user}@{realm}
managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn}
""")
entry_ldif = entry_ldif_template.format(
base_dn=base_dn,
hostname=hostname,
principal=principal,
realm=realm,
user='admin')
tasks.kdestroy_all(master)
master.run_command(
['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}'])
args = [
'ldapmodify',
'-Y',
'GSSAPI'
]
result = master.run_command(args, stdin_text=entry_ldif,
raiseonerr=False)
assert "entry with the same attribute value" in result.stderr_text
# Now try with root@realm instead of admin@realm
entry_ldif = entry_ldif_template.format(
base_dn=base_dn,
hostname=hostname,
principal=principal,
realm=realm,
user='root')
args = [
'ldapmodify',
'-Y',
'GSSAPI'
]
result = master.run_command(args, stdin_text=entry_ldif,
raiseonerr=False)
assert "entry with the same attribute value" in result.stderr_text
tasks.kdestroy_all(master)
def test_no_request_pac(self):
# Try to use a TGT obtained without PAC
# Should fail as the presence of the PAC when processing TGTs
# provided by TGS-REQ is now enforced.
hostname = self.master.hostname
realm = self.master.domain.realm
self.master.run_command([
'kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}',
'--no-request-pac'
])
result = self.master.run_command(
['kvno', f'ldap/{hostname}@{realm}'],
raiseonerr=False
)
assert result.returncode == 1
assert "PAC_ENFORCEMENT_TGT_WITHOUT_PAC" in result.stderr_text
class TestIPAautomount(IntegrationTest):
@classmethod
+3 -2
View File
@@ -38,7 +38,6 @@ from ipalib.parameters import Param
from ipalib.output import Output
from ipalib.text import Gettext, NGettext, ConcatenatedLazyText
from ipalib.capabilities import capabilities
from ipapython import config
API_FILE='API.txt'
@@ -85,7 +84,9 @@ OUTPUT_IGNORED_ATTRIBUTES = (
)
def parse_options():
parser = config.IPAOptionParser()
from optparse import OptionParser # pylint: disable=deprecated-module
parser = OptionParser()
parser.add_option("--validate", dest="validate", action="store_true",
default=False, help="Validate the API vs the stored API")