Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42d0bb0805 | ||
|
|
024b410710 | ||
|
|
96ea6f94c8 | ||
|
|
20c03a3e89 | ||
|
|
bb24703a18 | ||
|
|
67a9d537e3 | ||
|
|
f2fc367fb0 | ||
|
|
e8c410ae5f | ||
|
|
6ae52a2fb4 | ||
|
|
f33a0e8e71 | ||
|
|
7a5a10b6bf | ||
|
|
3b38efe758 | ||
|
|
cf84a22228 |
No files matched your search
+1
-1
@@ -21,7 +21,7 @@
|
||||
########################################################
|
||||
define(IPA_VERSION_MAJOR, 4)
|
||||
define(IPA_VERSION_MINOR, 12)
|
||||
define(IPA_VERSION_RELEASE, 2)
|
||||
define(IPA_VERSION_RELEASE, 5)
|
||||
|
||||
########################################################
|
||||
# For 'pre' releases the version will be #
|
||||
|
||||
@@ -530,26 +530,43 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
|
||||
|
||||
/* get adtrust options using default refresh interval */
|
||||
ret = ipadb_reinit_mspac(ipactx, false, &stmsg);
|
||||
if (ret && stmsg)
|
||||
krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (ret == LDAP_SERVER_DOWN) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
return EIO;
|
||||
|
||||
/* Replace LDAP error code by POSIX error code. */
|
||||
ret = ret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static krb5_principal ipadb_create_local_tgs(krb5_context kcontext,
|
||||
|
||||
@@ -431,6 +431,14 @@ 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,
|
||||
@@ -475,3 +483,4 @@ 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);
|
||||
@@ -767,3 +767,21 @@ 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);
|
||||
}
|
||||
@@ -195,7 +195,7 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||
*lifetime_out = 0;
|
||||
*renew_lifetime_out = 0;
|
||||
|
||||
return 0;
|
||||
return ipadb_enforce_pac(context, ticket, status);
|
||||
}
|
||||
|
||||
krb5_error_code kdcpolicy_ipakdb_initvt(krb5_context context,
|
||||
|
||||
@@ -3346,3 +3346,90 @@ 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;
|
||||
}
|
||||
@@ -188,25 +188,6 @@ 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)
|
||||
@@ -1986,7 +1967,7 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
|
||||
return kerr;
|
||||
|
||||
/* If TGS principal, some virtual attributes may be added */
|
||||
if (is_tgs_princ(kcontext, (*entry)->princ)) {
|
||||
if (ipadb_is_tgs_princ(kcontext, (*entry)->princ)) {
|
||||
kerr = cmp_local_tgs_princ(kcontext, ipactx->realm, (*entry)->princ,
|
||||
&is_local_tgs_princ);
|
||||
if (kerr)
|
||||
|
||||
+14
-10
@@ -31,6 +31,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -93,6 +94,7 @@ 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) {
|
||||
@@ -102,15 +104,18 @@ static void oauth2_on_child_writable(verto_ctx *vctx, verto_ev *ev)
|
||||
}
|
||||
|
||||
if (child_ctx->oauth2_state == OAUTH2_GET_DEVICE_CODE) {
|
||||
/* no input needed */
|
||||
verto_del(ev);
|
||||
return;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
@@ -429,8 +434,7 @@ 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";
|
||||
args[args_idx++] = (*item)->idp.ipaidpClientSecret;
|
||||
args[args_idx++] = "--client-secret-stdin";
|
||||
}
|
||||
|
||||
if ((*item)->idp.ipaidpScope) {
|
||||
|
||||
+5
-4
@@ -1670,10 +1670,11 @@ fi
|
||||
%dir %{_sysconfdir}/ipa/html
|
||||
%config(noreplace) %{_sysconfdir}/ipa/html/ssbrowser.html
|
||||
%config(noreplace) %{_sysconfdir}/ipa/html/unauthorized.html
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-rewrite.conf
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa.conf
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-kdc-proxy.conf
|
||||
%ghost %attr(0640,root,root) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-pki-proxy.conf
|
||||
%dir %{_sysconfdir}/ipa/http
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipa/httpd/ipa-rewrite.conf
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipa/httpd/ipa.conf
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipa/httpd/ipa-kdc-proxy.conf
|
||||
%ghost %attr(0640,root,root) %config(noreplace) %{_sysconfdir}/ipa/httpd/ipa-pki-proxy.conf
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipa/kdcproxy/ipa-kdc-proxy.conf
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{_usr}/share/ipa/html/ca.crt
|
||||
%ghost %attr(0640,root,named) %config(noreplace) %{_sysconfdir}/named/ipa-ext.conf
|
||||
|
||||
@@ -15,6 +15,7 @@ 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
|
||||
@@ -52,11 +53,13 @@ def parse_options():
|
||||
"--password",
|
||||
action="store",
|
||||
dest="password",
|
||||
help="Display debugging information",
|
||||
help="Password for Active Directory administrator",
|
||||
sensitive=True
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
@@ -100,6 +100,7 @@ dist_app_DATA = \
|
||||
ipa-kdc-proxy.conf.template \
|
||||
ipa-pki-proxy.conf.template \
|
||||
ipa-rewrite.conf.template \
|
||||
ipa-vhost.conf.template \
|
||||
ipaca_default.ini \
|
||||
ipaca_customize.ini \
|
||||
ipaca_softhsm2.ini \
|
||||
|
||||
@@ -239,6 +239,7 @@ objectClass: ipasshuser
|
||||
uid: admin
|
||||
krbPrincipalName: admin@$REALM
|
||||
krbPrincipalName: root@$REALM
|
||||
krbCanonicalName: admin@$REALM
|
||||
cn: Administrator
|
||||
sn: Administrator
|
||||
uidNumber: $IDSTART
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# VERSION 32 - DO NOT REMOVE THIS LINE
|
||||
#
|
||||
# This file may be overwritten on upgrades.
|
||||
#
|
||||
|
||||
# FIXME: WSGISocketPrefix is a server-scope directive. The mod_wsgi package
|
||||
# should really be fixed by adding this its /etc/httpd/conf.d/wsgi.conf:
|
||||
WSGISocketPrefix $WSGI_PREFIX_DIR
|
||||
|
||||
# Configure mod_wsgi handler for /ipa
|
||||
WSGIDaemonProcess ipa processes=$WSGI_PROCESSES threads=1 maximum-requests=500 \
|
||||
user=ipaapi group=ipaapi display-name=%{GROUP} socket-timeout=2147483647 \
|
||||
lang=C.UTF-8 locale=C.UTF-8
|
||||
|
||||
<VirtualHost *:80>
|
||||
ServerName $FQDN
|
||||
ServerAlias ipa-ca.$DOMAIN
|
||||
|
||||
# Logging
|
||||
CustomLog /var/log/httpd/ipa-access.log combined
|
||||
ErrorLog /var/log/httpd/ipa-error.log
|
||||
|
||||
IncludeOptional $HTTPD_IPA_PKI_PROXY_CONF
|
||||
Include $HTTPD_IPA_REWRITE_CONF
|
||||
Include $HTTPD_IPA_CONF
|
||||
</VirtualHost>
|
||||
|
||||
# the below section is only need if you have above 3 lines and want SSL
|
||||
<VirtualHost *:443>
|
||||
ServerName $FQDN
|
||||
ServerAlias ipa-ca.$DOMAIN
|
||||
|
||||
# Logging
|
||||
CustomLog /var/log/httpd/ipa-access.log combined
|
||||
ErrorLog /var/log/httpd/ipa-error.log
|
||||
|
||||
# SSL
|
||||
SSLEngine on
|
||||
SSLCertificateFile $HTTPD_CERT_FILE
|
||||
SSLCertificateKeyFile $HTTPD_KEY_FILE
|
||||
SSLCACertificateFile $IPA_CA_CRT
|
||||
SSLVerifyDepth $MOD_SSL_VERIFY_DEPTH
|
||||
|
||||
# FreeIPA
|
||||
IncludeOptional $HTTPD_IPA_KDCPROXY_CONF_SYMLINK
|
||||
IncludeOptional $HTTPD_IPA_PKI_PROXY_CONF
|
||||
Include $HTTPD_IPA_REWRITE_CONF
|
||||
Include $HTTPD_IPA_CONF
|
||||
</VirtualHost>
|
||||
@@ -35,19 +35,11 @@ AddOutputFilterByType DEFLATE text/html text/plain text/xml \
|
||||
application/javascript application/json text/css \
|
||||
application/x-font-ttf
|
||||
|
||||
# FIXME: WSGISocketPrefix is a server-scope directive. The mod_wsgi package
|
||||
# should really be fixed by adding this its /etc/httpd/conf.d/wsgi.conf:
|
||||
WSGISocketPrefix $WSGI_PREFIX_DIR
|
||||
|
||||
# Configure mod_wsgi handler for /ipa
|
||||
WSGIDaemonProcess ipa processes=$WSGI_PROCESSES threads=1 maximum-requests=500 \
|
||||
user=ipaapi group=ipaapi display-name=%{GROUP} socket-timeout=2147483647 \
|
||||
lang=C.UTF-8 locale=C.UTF-8
|
||||
WSGIScriptAlias /ipa /usr/share/ipa/wsgi.py process-group=ipa \
|
||||
application-group=%{GLOBAL}
|
||||
WSGIScriptReloading Off
|
||||
|
||||
|
||||
# Turn off mod_msgi handler for errors, config, crl:
|
||||
<Location "/ipa/errors">
|
||||
SetHandler None
|
||||
|
||||
@@ -1,34 +1,16 @@
|
||||
dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
|
||||
dn: cn=kerberos name uniqueness,cn=plugins,cn=config
|
||||
changetype: add
|
||||
objectClass: top
|
||||
objectClass: nsSlapdPlugin
|
||||
objectClass: extensibleObject
|
||||
cn: krbPrincipalName uniqueness
|
||||
cn: kerberos name uniqueness
|
||||
nsslapd-pluginPath: libattr-unique-plugin
|
||||
nsslapd-pluginInitfunc: NSUniqueAttr_Init
|
||||
nsslapd-pluginType: preoperation
|
||||
nsslapd-pluginEnabled: on
|
||||
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
|
||||
uniqueness-attribute-name: krbPrincipalName:CaseIgnoreMatch:
|
||||
uniqueness-attribute-name: krbPrincipalAlias:CaseIgnoreMatch:
|
||||
uniqueness-attribute-name: krbCanonicalName:CaseIgnoreMatch:
|
||||
nsslapd-plugin-depends-on-type: database
|
||||
nsslapd-pluginId: NSUniqueAttr
|
||||
nsslapd-pluginVersion: 1.1.0
|
||||
|
||||
@@ -29,19 +29,17 @@ 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
|
||||
from ipapython.admintool import ScriptError, admin_cleanup_global_argv
|
||||
from ipapython import version
|
||||
from ipapython import ipautil
|
||||
from ipalib import api, errors, krb_utils
|
||||
from ipapython.config import IPAOptionParser
|
||||
from ipapython.config import IPAOptionParser, SUPPRESS_HELP
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython.ipa_log_manager import standard_logging_setup
|
||||
|
||||
@@ -95,6 +93,7 @@ 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
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ 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__))
|
||||
|
||||
@@ -132,6 +133,7 @@ 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")
|
||||
|
||||
@@ -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,7 +46,8 @@ 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 = OptionParser(usage=usage, formatter=config.IPAFormatter())
|
||||
parser = config.IPAOptionParser(usage=usage,
|
||||
formatter=config.IPAFormatter())
|
||||
|
||||
parser.add_option("-d", "--debug", action="store_true", dest="debug",
|
||||
help="Display debugging information about the update(s)")
|
||||
@@ -55,6 +56,7 @@ def parse_options():
|
||||
|
||||
config.add_standard_options(parser)
|
||||
options, args = parser.parse_args()
|
||||
admin_cleanup_global_argv(parser, options, sys.argv)
|
||||
|
||||
return options, args
|
||||
|
||||
|
||||
@@ -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
|
||||
from ipapython.admintool import ScriptError
|
||||
from ipapython import ipautil, ipaldap, version, config
|
||||
from ipapython.admintool import admin_cleanup_global_argv, ScriptError
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(os.path.basename(__file__))
|
||||
@@ -54,11 +54,10 @@ commands = {
|
||||
|
||||
|
||||
def parse_options():
|
||||
from optparse import OptionParser # pylint: disable=deprecated-module
|
||||
|
||||
parser = OptionParser(version=version.VERSION)
|
||||
parser = config.IPAOptionParser(version=version.VERSION)
|
||||
parser.add_option("-H", "--host", dest="host", help="starting host")
|
||||
parser.add_option("-p", "--password", dest="dirman_passwd", help="Directory Manager password")
|
||||
parser.add_option("-p", "--password", dest="dirman_passwd", sensitive=True,
|
||||
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,
|
||||
@@ -66,6 +65,7 @@ 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
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ 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
|
||||
@@ -32,6 +31,7 @@ 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,7 +39,8 @@ logger = logging.getLogger(os.path.basename(__file__))
|
||||
def parse_options():
|
||||
usage = "%prog [options] <status|enable|disable>\n"
|
||||
usage += "%prog [options]\n"
|
||||
parser = OptionParser(usage=usage, formatter=config.IPAFormatter())
|
||||
parser = config.IPAOptionParser(usage=usage,
|
||||
formatter=config.IPAFormatter())
|
||||
|
||||
parser.add_option("-d", "--debug", action="store_true", dest="debug",
|
||||
help="Display debugging information about the update(s)")
|
||||
@@ -50,9 +51,10 @@ def parse_options():
|
||||
action="store_true",
|
||||
help="List available Managed Entries")
|
||||
parser.add_option("-p", "--password", dest="dirman_password",
|
||||
help="Directory Manager password")
|
||||
sensitive=True, help="Directory Manager password")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
admin_cleanup_global_argv(parser, options, sys.argv)
|
||||
|
||||
return options, args
|
||||
|
||||
|
||||
@@ -23,15 +23,15 @@ from __future__ import print_function
|
||||
import logging
|
||||
|
||||
from ipapython import ipachangeconf
|
||||
from ipapython.config import IPAOptionParser
|
||||
from ipapython.config import (IPAOptionParser, OptionGroup,
|
||||
OptionValueError)
|
||||
from ipapython.admintool import admin_cleanup_global_argv
|
||||
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,6 +189,7 @@ 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!")
|
||||
|
||||
@@ -43,6 +43,7 @@ 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
|
||||
@@ -84,7 +85,8 @@ 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", help="Directory Manager password")
|
||||
parser.add_option("-p", "--password", dest="dirman_passwd", sensitive=True,
|
||||
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,
|
||||
@@ -95,7 +97,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,
|
||||
parser.add_option("--bindpw", dest="bindpw", default=None, sensitive=True,
|
||||
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")
|
||||
@@ -103,13 +105,15 @@ 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,
|
||||
parser.add_option("--passsync", dest="passsync",
|
||||
default=None, sensitive=True,
|
||||
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
|
||||
|
||||
|
||||
@@ -80,13 +80,32 @@ add:uniqueness-subtree-entries-oc: posixAccount
|
||||
|
||||
# krbPrincipalName uniqueness scopes Active/Delete containers
|
||||
dn: 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
|
||||
deleteentry: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
|
||||
|
||||
# krbCanonicalName uniqueness scopes Active/Delete containers
|
||||
dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
|
||||
add:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
|
||||
add:uniqueness-across-all-subtrees: on
|
||||
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
|
||||
|
||||
# ipaUniqueID uniqueness scopes Active/Delete containers
|
||||
dn: cn=ipaUniqueID uniqueness,cn=plugins,cn=config
|
||||
|
||||
@@ -27,6 +27,7 @@ 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
|
||||
|
||||
@@ -34,7 +34,6 @@ 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 (
|
||||
@@ -52,6 +51,7 @@ 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 = OptionParser(usage=usage)
|
||||
parser = IPAOptionParser(usage=usage)
|
||||
parser.add_option("--server", dest="server", help="FQDN of IPA server")
|
||||
parser.add_option(
|
||||
"--location",
|
||||
|
||||
@@ -9,7 +9,6 @@ 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
|
||||
@@ -31,6 +30,7 @@ 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 = OptionParser(usage=usage)
|
||||
parser = IPAOptionParser(usage=usage)
|
||||
parser.add_option(
|
||||
"--server",
|
||||
dest="server",
|
||||
|
||||
+12
-9
@@ -30,7 +30,6 @@ import textwrap
|
||||
import sys
|
||||
import getpass
|
||||
import code
|
||||
import optparse # pylint: disable=deprecated-module
|
||||
import os
|
||||
import pprint
|
||||
import fcntl
|
||||
@@ -71,6 +70,8 @@ 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
|
||||
|
||||
@@ -1121,7 +1122,8 @@ class Collector:
|
||||
def __todict__(self):
|
||||
return dict(self.__options)
|
||||
|
||||
class CLIOptionParserFormatter(optparse.IndentedHelpFormatter):
|
||||
|
||||
class CLIOptionParserFormatter(IPAFormatter):
|
||||
def format_argument(self, name, help_string):
|
||||
result = []
|
||||
opt_width = self.help_position - self.current_indent - 2
|
||||
@@ -1141,7 +1143,8 @@ class CLIOptionParserFormatter(optparse.IndentedHelpFormatter):
|
||||
result.append("\n")
|
||||
return "".join(result)
|
||||
|
||||
class CLIOptionParser(optparse.OptionParser):
|
||||
|
||||
class CLIOptionParser(IPAOptionParser):
|
||||
"""
|
||||
This OptionParser subclass adds an ability to print positional
|
||||
arguments in CLI help. Custom formatter is used to format the argument
|
||||
@@ -1151,13 +1154,13 @@ class CLIOptionParser(optparse.OptionParser):
|
||||
self._arguments = []
|
||||
if 'formatter' not in kwargs:
|
||||
kwargs['formatter'] = CLIOptionParserFormatter()
|
||||
optparse.OptionParser.__init__(self, *args, **kwargs)
|
||||
IPAOptionParser.__init__(self, *args, **kwargs)
|
||||
|
||||
def format_option_help(self, formatter=None):
|
||||
"""
|
||||
Prepend argument help to standard OptionParser's option help
|
||||
"""
|
||||
option_help = optparse.OptionParser.format_option_help(self, formatter)
|
||||
option_help = IPAOptionParser.format_option_help(self, formatter)
|
||||
|
||||
if isinstance(formatter, CLIOptionParserFormatter):
|
||||
heading = unicode(_("Positional arguments"))
|
||||
@@ -1272,7 +1275,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 = optparse.OptionGroup(parser, group_name)
|
||||
option_group = OptionGroup(parser, group_name)
|
||||
parser.add_option_group(option_group)
|
||||
option_groups[group_name] = option_group
|
||||
return option_group
|
||||
@@ -1298,7 +1301,7 @@ class cli(backend.Executioner):
|
||||
option_names = ['--%s' % cli_name]
|
||||
if option.cli_short_name:
|
||||
option_names.append('-%s' % option.cli_short_name)
|
||||
opt = optparse.make_option(*option_names, **kw)
|
||||
opt = make_option(*option_names, **kw)
|
||||
if option.option_group is None:
|
||||
parser.add_option(opt)
|
||||
else:
|
||||
@@ -1312,7 +1315,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(optparse.make_option(name, **new_kw))
|
||||
group.add_option(make_option(name, **new_kw))
|
||||
|
||||
for arg in cmd.args():
|
||||
name = self.__get_arg_name(arg, format_name=False)
|
||||
@@ -1442,7 +1445,7 @@ class cli(backend.Executioner):
|
||||
)
|
||||
|
||||
|
||||
class IPAHelpFormatter(optparse.IndentedHelpFormatter):
|
||||
class IPAHelpFormatter(IPAFormatter):
|
||||
"""Formatter suitable for printing IPA command help
|
||||
|
||||
The default help formatter reflows text to fit the terminal, but it
|
||||
|
||||
+4
-4
@@ -33,7 +33,6 @@ import sys
|
||||
import threading
|
||||
import os
|
||||
from os import path
|
||||
import optparse # pylint: disable=deprecated-module
|
||||
import textwrap
|
||||
import collections
|
||||
import importlib
|
||||
@@ -47,6 +46,7 @@ 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 optparse.OptionParser instance.
|
||||
Add global options to an IPAOptionParser 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 = optparse.OptionParser(
|
||||
parser = IPAOptionParser(
|
||||
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(optparse.IndentedHelpFormatter):
|
||||
class IPAHelpFormatter(IPAFormatter):
|
||||
def format_epilog(self, epilog):
|
||||
text_width = self.width - self.current_indent
|
||||
indent = " " * self.current_indent
|
||||
|
||||
@@ -45,11 +45,13 @@ class BasePathNamespace:
|
||||
GSSAPI_SESSION_KEY = "/etc/httpd/alias/ipasession.key"
|
||||
OLD_KRA_AGENT_PEM = "/etc/httpd/alias/kra-agent.pem"
|
||||
HTTPD_CONF_D_DIR = "/etc/httpd/conf.d/"
|
||||
HTTPD_IPA_DIR = "/etc/ipa/httpd"
|
||||
HTTPD_IPA_KDCPROXY_CONF = "/etc/ipa/kdcproxy/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/httpd/conf.d/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/httpd/conf.d/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/httpd/conf.d/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/httpd/conf.d/ipa.conf"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/ipa/httpd/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/ipa/httpd/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/ipa/httpd/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/ipa/httpd/ipa.conf"
|
||||
HTTPD_IPA_SITE_CONF = "/etc/httpd/conf.d/ipa-vhost.conf"
|
||||
HTTPD_NSS_CONF = "/etc/httpd/conf.d/nss.conf"
|
||||
HTTPD_SSL_CONF = "/etc/httpd/conf.d/ssl.conf"
|
||||
HTTPD_SSL_SITE_CONF = "/etc/httpd/conf.d/ssl.conf"
|
||||
|
||||
@@ -20,10 +20,12 @@ class DebianPathNamespace(BasePathNamespace):
|
||||
ETC_HTTPD_DIR = "/etc/apache2"
|
||||
HTTPD_ALIAS_DIR = "/etc/apache2/ipa"
|
||||
HTTPD_CONF_D_DIR = "/etc/apache2/conf-enabled/"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/apache2/conf-enabled/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/apache2/conf-enabled/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/apache2/conf-available/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/apache2/conf-enabled/ipa.conf"
|
||||
HTTPD_IPA_DIR = "/etc/ipa/httpd/"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/ipa/httpd/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/ipa/httpd/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/ipa/httpd/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/ipa/httpd/ipa.conf"
|
||||
HTTPD_IPA_SITE_CONF = "/etc/apache2/sites-available/ipa.conf"
|
||||
HTTPD_NSS_CONF = "/etc/apache2/mods-available/nss.conf"
|
||||
HTTPD_SSL_CONF = "/etc/apache2/mods-available/ssl.conf"
|
||||
HTTPD_SSL_SITE_CONF = "/etc/apache2/sites-available/default-ssl.conf"
|
||||
|
||||
@@ -17,10 +17,12 @@ class SusePathNamespace(BasePathNamespace):
|
||||
HTTPD_ALIAS_DIR = "/etc/apache2/ipa"
|
||||
GSSAPI_SESSION_KEY = "/etc/apache2/ipa/ipasession.key"
|
||||
HTTPD_CONF_D_DIR = "/etc/apache2/conf.d/"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/apache2/conf.d/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/apache2/conf.d/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/apache2/conf.d/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/apache2/conf.d/ipa.conf"
|
||||
HTTPD_IPA_DIR = "/etc/ipa/httpd/"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/ipa/httpd/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/ipa/httpd/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/ipa/httpd/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/ipa/httpd/ipa.conf"
|
||||
HTTPD_IPA_SITE_CONF = "/etc/apache2/conf.d/ipa-vhost.conf"
|
||||
HTTPD_NSS_CONF = "/etc/apache2/conf.d/nss.conf"
|
||||
HTTPD_SSL_CONF = "/etc/apache2/conf.d/ssl.conf"
|
||||
HTTPD_SSL_SITE_CONF = "/etc/apache2/conf.d/ssl.conf"
|
||||
|
||||
+41
-2
@@ -26,7 +26,6 @@ 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
|
||||
@@ -40,6 +39,45 @@ 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
|
||||
"""
|
||||
@@ -113,7 +151,7 @@ class AdminTool:
|
||||
:param parser: The parser to add options to
|
||||
:param debug_option: Add a --debug option as an alias to --verbose
|
||||
"""
|
||||
group = OptionGroup(parser, "Logging and output options")
|
||||
group = config.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:
|
||||
@@ -149,6 +187,7 @@ 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)
|
||||
|
||||
+11
-7
@@ -18,9 +18,9 @@
|
||||
#
|
||||
from __future__ import absolute_import
|
||||
|
||||
# pylint: disable=deprecated-module
|
||||
from optparse import (
|
||||
Option, Values, OptionParser, IndentedHelpFormatter, OptionValueError)
|
||||
# pylint: disable=deprecated-module, disable=unused-import
|
||||
from optparse import (Option, Values, OptionGroup, OptionParser, SUPPRESS_HELP,
|
||||
IndentedHelpFormatter, OptionValueError, make_option)
|
||||
# pylint: enable=deprecated-module
|
||||
from copy import copy
|
||||
from configparser import ConfigParser as SafeConfigParser
|
||||
@@ -113,10 +113,14 @@ class IPAOptionParser(OptionParser):
|
||||
description=None,
|
||||
formatter=None,
|
||||
add_help_option=True,
|
||||
prog=None):
|
||||
OptionParser.__init__(self, usage, option_list, option_class,
|
||||
version, conflict_handler, description,
|
||||
formatter, add_help_option, prog)
|
||||
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)
|
||||
|
||||
def get_safe_opts(self, opts):
|
||||
"""
|
||||
|
||||
@@ -9,12 +9,11 @@ Command line support.
|
||||
import collections
|
||||
import enum
|
||||
import logging
|
||||
import optparse # pylint: disable=deprecated-module
|
||||
import signal
|
||||
|
||||
import six
|
||||
|
||||
from ipapython import admintool
|
||||
from ipapython import admintool, config
|
||||
from ipapython.ipa_log_manager import standard_logging_setup
|
||||
from ipapython.ipautil import (CheckedIPAddress, CheckedIPAddressLoopback,
|
||||
private_ccache)
|
||||
@@ -158,7 +157,7 @@ class ConfigureTool(admintool.AdminTool):
|
||||
try:
|
||||
opt_group = groups[group_cls]
|
||||
except KeyError:
|
||||
opt_group = groups[group_cls] = optparse.OptionGroup(
|
||||
opt_group = groups[group_cls] = config.OptionGroup(
|
||||
parser, "{0} options".format(group_cls.description))
|
||||
parser.add_option_group(opt_group)
|
||||
|
||||
@@ -232,7 +231,7 @@ class ConfigureTool(admintool.AdminTool):
|
||||
if not hidden:
|
||||
help = knob_cls.description
|
||||
else:
|
||||
help = optparse.SUPPRESS_HELP
|
||||
help = config.SUPPRESS_HELP
|
||||
|
||||
opt_group.add_option(
|
||||
*opt_strs,
|
||||
@@ -256,7 +255,7 @@ class ConfigureTool(admintool.AdminTool):
|
||||
|
||||
# fake option parser to parse positional arguments
|
||||
# (because optparse does not support positional argument parsing)
|
||||
fake_option_parser = optparse.OptionParser()
|
||||
fake_option_parser = config.IPAOptionParser()
|
||||
self.add_options(fake_option_parser, True)
|
||||
|
||||
fake_option_map = {option.dest: option
|
||||
|
||||
@@ -110,6 +110,14 @@ class HTTPInstance(service.Service):
|
||||
IPA_CCACHES=paths.IPA_CCACHES,
|
||||
WSGI_PREFIX_DIR=paths.WSGI_PREFIX_DIR,
|
||||
WSGI_PROCESSES=constants.WSGI_PROCESSES,
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK=paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK,
|
||||
HTTPD_IPA_PKI_PROXY_CONF=paths.HTTPD_IPA_PKI_PROXY_CONF,
|
||||
HTTPD_IPA_REWRITE_CONF=paths.HTTPD_IPA_REWRITE_CONF,
|
||||
HTTPD_IPA_CONF=paths.HTTPD_IPA_CONF,
|
||||
HTTPD_CERT_FILE=paths.HTTPD_CERT_FILE,
|
||||
HTTPD_KEY_FILE=paths.HTTPD_KEY_FILE,
|
||||
IPA_CA_CRT=paths.IPA_CA_CRT,
|
||||
MOD_SSL_VERIFY_DEPTH=MOD_SSL_VERIFY_DEPTH,
|
||||
)
|
||||
self.ca_file = ca_file
|
||||
if ca_is_configured is not None:
|
||||
@@ -127,7 +135,6 @@ class HTTPInstance(service.Service):
|
||||
self.step("configuring mod_ssl log directory",
|
||||
self.set_mod_ssl_logdir)
|
||||
self.step("disabling mod_ssl OCSP", self.disable_mod_ssl_ocsp)
|
||||
self.step("adding URL rewriting rules", self.__add_include)
|
||||
self.step("configuring httpd", self.__configure_http)
|
||||
self.step("setting up httpd keytab", self.request_service_keytab)
|
||||
self.step("configuring Gssproxy", self.configure_gssproxy)
|
||||
@@ -196,6 +203,14 @@ class HTTPInstance(service.Service):
|
||||
# https://pagure.io/freeipa/issue/7662
|
||||
tasks.restore_context(session_dir)
|
||||
|
||||
# create /etc/httpd/ipa
|
||||
if not os.path.isdir(paths.HTTPD_IPA_DIR):
|
||||
os.makedirs(paths.HTTPD_IPA_DIR)
|
||||
# Must be world-readable / executable
|
||||
os.chmod(paths.HTTPD_IPA_DIR, 0o755)
|
||||
# Restore SELinux context of /etc/httpd/ipa
|
||||
tasks.restore_context(paths.HTTPD_IPA_DIR)
|
||||
|
||||
target_fname = paths.HTTPD_IPA_CONF
|
||||
http_txt = ipautil.template_file(
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
@@ -207,6 +222,17 @@ class HTTPInstance(service.Service):
|
||||
http_fd.close()
|
||||
os.chmod(target_fname, 0o644)
|
||||
|
||||
target_fname = paths.HTTPD_IPA_SITE_CONF
|
||||
http_txt = ipautil.template_file(
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
"ipa-vhost.conf.template"),
|
||||
self.sub_dict)
|
||||
self.fstore.backup_file(paths.HTTPD_IPA_SITE_CONF)
|
||||
http_fd = open(target_fname, "w")
|
||||
http_fd.write(http_txt)
|
||||
http_fd.close()
|
||||
os.chmod(target_fname, 0o644)
|
||||
|
||||
target_fname = paths.HTTPD_IPA_REWRITE_CONF
|
||||
http_txt = ipautil.template_file(
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
@@ -284,17 +310,6 @@ class HTTPInstance(service.Service):
|
||||
aug.set(ocsp_comment, '{} {}'.format(OCSP_DIRECTIVE, ocsp_state))
|
||||
aug.save()
|
||||
|
||||
def __add_include(self):
|
||||
"""This should run after __set_mod_nss_port so is already backed up"""
|
||||
if installutils.update_file(paths.HTTPD_SSL_SITE_CONF,
|
||||
'</VirtualHost>',
|
||||
'Include {path}\n'
|
||||
'</VirtualHost>'.format(
|
||||
path=paths.HTTPD_IPA_REWRITE_CONF)
|
||||
) != 0:
|
||||
self.print_msg("Adding Include conf.d/ipa-rewrite to "
|
||||
"%s failed." % paths.HTTPD_SSL_SITE_CONF)
|
||||
|
||||
def configure_certmonger_renewal_guard(self):
|
||||
certmonger = services.knownservices.certmonger
|
||||
certmonger_stopped = not certmonger.is_running()
|
||||
@@ -552,13 +567,14 @@ class HTTPInstance(service.Service):
|
||||
paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host),
|
||||
paths.HTTPD_IPA_REWRITE_CONF,
|
||||
paths.HTTPD_IPA_CONF,
|
||||
paths.HTTPD_IPA_SITE_CONF,
|
||||
paths.HTTPD_IPA_PKI_PROXY_CONF,
|
||||
paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK,
|
||||
paths.HTTPD_IPA_KDCPROXY_CONF,
|
||||
paths.GSSPROXY_CONF,
|
||||
paths.GSSAPI_SESSION_KEY,
|
||||
paths.HTTPD_PASSWORD_CONF,
|
||||
paths.SYSTEMD_SYSTEM_HTTPD_IPA_CONF,
|
||||
paths.SYSTEMD_SYSTEM_HTTPD_IPA_CONF
|
||||
]
|
||||
# NSS DB backups
|
||||
remove_files.extend(
|
||||
@@ -677,7 +693,6 @@ class HTTPInstance(service.Service):
|
||||
self.configure_mod_ssl_certs()
|
||||
self.set_mod_ssl_protocol()
|
||||
self.set_mod_ssl_logdir()
|
||||
self.__add_include()
|
||||
|
||||
self.cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
|
||||
|
||||
|
||||
@@ -7,14 +7,12 @@ 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
|
||||
from ipapython import cookie, dogtag, config
|
||||
from ipapython.ipautil import run
|
||||
from ipapython.certdb import NSSDatabase, EXTERNAL_CA_TRUST_FLAGS
|
||||
from ipaserver.install import cainstance
|
||||
@@ -143,7 +141,7 @@ class IPAACMEManage(AdminTool):
|
||||
@classmethod
|
||||
def add_options(cls, parser):
|
||||
|
||||
group = OptionGroup(parser, 'Pruning')
|
||||
group = config.OptionGroup(parser, 'Pruning')
|
||||
group.add_option(
|
||||
"--enable", dest="enable", action="store_true",
|
||||
default=False, help="Enable certificate pruning")
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import logging
|
||||
import optparse # pylint: disable=deprecated-module
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
@@ -32,7 +31,7 @@ import six
|
||||
from ipaplatform.paths import paths
|
||||
from ipaplatform import services
|
||||
from ipalib import api, errors
|
||||
from ipapython import version
|
||||
from ipapython import version, config
|
||||
from ipapython.ipautil import run, write_tmp_file
|
||||
from ipapython import admintool, certdb
|
||||
from ipapython.dn import DN
|
||||
@@ -155,6 +154,7 @@ class Backup(admintool.AdminTool):
|
||||
paths.HTTPD_CERT_FILE,
|
||||
paths.HTTPD_KEY_FILE,
|
||||
paths.HTTPD_IPA_CONF,
|
||||
paths.HTTPD_IPA_SITE_CONF,
|
||||
paths.SSHD_CONFIG,
|
||||
paths.SSHD_IPA_CONFIG,
|
||||
paths.SSH_CONFIG,
|
||||
@@ -245,7 +245,7 @@ class Backup(admintool.AdminTool):
|
||||
|
||||
parser.add_option(
|
||||
"--gpg-keyring", dest="gpg_keyring",
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
help=config.SUPPRESS_HELP)
|
||||
parser.add_option(
|
||||
"--gpg", dest="gpg", action="store_true",
|
||||
default=False, help="Encrypt the backup")
|
||||
|
||||
@@ -22,14 +22,13 @@ 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
|
||||
from ipapython import admintool, ipautil, config
|
||||
from ipapython.certdb import (EMPTY_TRUST_FLAGS,
|
||||
EXTERNAL_CA_TRUST_FLAGS,
|
||||
TrustFlags,
|
||||
@@ -61,7 +60,7 @@ class CACertManage(admintool.AdminTool):
|
||||
"-p", "--password", dest='password',
|
||||
help="Directory Manager password")
|
||||
|
||||
renew_group = OptionGroup(parser, "Renew options")
|
||||
renew_group = config.OptionGroup(parser, "Renew options")
|
||||
renew_group.add_option(
|
||||
"--self-signed", dest='self_signed',
|
||||
action='store_true',
|
||||
@@ -89,7 +88,7 @@ class CACertManage(admintool.AdminTool):
|
||||
"certificate chain")
|
||||
parser.add_option_group(renew_group)
|
||||
|
||||
install_group = OptionGroup(parser, "Install options")
|
||||
install_group = config.OptionGroup(parser, "Install options")
|
||||
install_group.add_option(
|
||||
"-n", "--nickname", dest='nickname',
|
||||
help="Nickname for the certificate")
|
||||
@@ -98,7 +97,7 @@ class CACertManage(admintool.AdminTool):
|
||||
help="Trust flags for the certificate in certutil format")
|
||||
parser.add_option_group(install_group)
|
||||
|
||||
delete_group = OptionGroup(parser, "Delete options")
|
||||
delete_group = config.OptionGroup(parser, "Delete options")
|
||||
delete_group.add_option(
|
||||
"-f", "--force", action='store_true',
|
||||
help="Force removing the CA even if chain validation fails")
|
||||
|
||||
@@ -22,13 +22,12 @@ 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
|
||||
from ipapython import admintool, config
|
||||
from ipaserver.install import service
|
||||
from ipaserver.install import cainstance
|
||||
from ipaserver.install import custodiainstance
|
||||
@@ -73,7 +72,7 @@ class KRAInstall(admintool.AdminTool):
|
||||
parser.add_option(
|
||||
"--uninstall",
|
||||
dest="uninstall", action="store_true", default=False,
|
||||
help=SUPPRESS_HELP)
|
||||
help=config.SUPPRESS_HELP)
|
||||
|
||||
parser.add_option(
|
||||
"--pki-config-override", dest="pki_config_override",
|
||||
|
||||
@@ -28,6 +28,7 @@ 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,
|
||||
@@ -284,6 +285,18 @@ 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
|
||||
#
|
||||
@@ -344,7 +357,8 @@ 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)
|
||||
default=None, sensitive=True,
|
||||
action=SensitiveStoreAction)
|
||||
parser.add_argument('-j', '--bind-pw-file',
|
||||
help='A text file containing the clear text '
|
||||
'password for the Bind DN', default=None)
|
||||
@@ -2023,6 +2037,7 @@ 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:
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import logging
|
||||
import optparse # pylint: disable=deprecated-module
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
@@ -34,7 +33,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
|
||||
from ipapython import version, ipautil, config
|
||||
from ipapython.ipautil import run, user_input
|
||||
from ipapython import admintool, certdb
|
||||
from ipapython.dn import DN
|
||||
@@ -186,11 +185,11 @@ class Restore(admintool.AdminTool):
|
||||
super(Restore, cls).add_options(parser, debug_option=True)
|
||||
|
||||
parser.add_option(
|
||||
"-p", "--password", dest="password",
|
||||
"-p", "--password", dest="password", sensitive=True,
|
||||
help="Directory Manager password")
|
||||
parser.add_option(
|
||||
"--gpg-keyring", dest="gpg_keyring",
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
help=config.SUPPRESS_HELP)
|
||||
parser.add_option(
|
||||
"--data", dest="data_only", action="store_true",
|
||||
default=False, help="Restore only the data")
|
||||
|
||||
@@ -22,12 +22,11 @@ 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
|
||||
from ipapython import admintool, dogtag, config
|
||||
from ipapython.certdb import NSSDatabase, get_ca_nickname
|
||||
from ipapython.dn import DN
|
||||
from ipapython import ipaldap
|
||||
@@ -65,15 +64,15 @@ class ServerCertInstall(admintool.AdminTool):
|
||||
help="The password of the PKCS#12 file")
|
||||
parser.add_option(
|
||||
"--dirsrv_pin", "--http_pin",
|
||||
dest="pin",
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
dest="pin", sensitive=True,
|
||||
help=config.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",
|
||||
dest="dirman_password", sensitive=True,
|
||||
help="Directory Manager password")
|
||||
|
||||
def validate_options(self):
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#
|
||||
# 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, []
|
||||
@@ -20,7 +20,7 @@ from augeas import Augeas
|
||||
from pkg_resources import parse_version
|
||||
|
||||
from ipalib import api, x509
|
||||
from ipalib.constants import RENEWAL_CA_NAME, RA_AGENT_PROFILE, IPA_CA_RECORD
|
||||
from ipalib.constants import RENEWAL_CA_NAME, RA_AGENT_PROFILE, IPA_CA_RECORD, MOD_SSL_VERIFY_DEPTH
|
||||
from ipalib.install import certmonger
|
||||
from ipalib import sysrestore
|
||||
from ipalib.facts import is_ipa_configured
|
||||
@@ -1708,6 +1708,14 @@ def upgrade_configuration():
|
||||
IPA_CUSTODIA_SOCKET=paths.IPA_CUSTODIA_SOCKET,
|
||||
KDCPROXY_CONFIG=paths.KDCPROXY_CONFIG,
|
||||
DOMAIN=api.env.domain,
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK=paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK,
|
||||
HTTPD_IPA_PKI_PROXY_CONF=paths.HTTPD_IPA_PKI_PROXY_CONF,
|
||||
HTTPD_IPA_REWRITE_CONF=paths.HTTPD_IPA_REWRITE_CONF,
|
||||
HTTPD_IPA_CONF=paths.HTTPD_IPA_CONF,
|
||||
HTTPD_CERT_FILE=paths.HTTPD_CERT_FILE,
|
||||
HTTPD_KEY_FILE=paths.HTTPD_KEY_FILE,
|
||||
IPA_CA_CRT=paths.IPA_CA_CRT,
|
||||
MOD_SSL_VERIFY_DEPTH=MOD_SSL_VERIFY_DEPTH,
|
||||
)
|
||||
|
||||
subject_base = find_subject_base()
|
||||
@@ -1744,6 +1752,9 @@ def upgrade_configuration():
|
||||
upgrade_file(sub_dict, paths.HTTPD_IPA_CONF,
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
"ipa.conf.template"))
|
||||
upgrade_file(sub_dict, paths.HTTPD_IPA_SITE_CONF,
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
"ipa-vhost.conf.template"))
|
||||
upgrade_file(sub_dict, paths.HTTPD_IPA_REWRITE_CONF,
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
"ipa-rewrite.conf.template"))
|
||||
|
||||
+4
-4
@@ -22,7 +22,6 @@ 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
|
||||
@@ -30,6 +29,7 @@ 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 = optparse.OptionParser(usage=usage)
|
||||
parser = config.IPAOptionParser(usage=usage)
|
||||
|
||||
mode_group = optparse.OptionGroup(parser, 'Operational Mode',
|
||||
mode_group = config.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 = optparse.OptionGroup(parser, 'Run Time Parameters',
|
||||
param_group = config.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,6 +1883,80 @@ 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
|
||||
|
||||
+2
-3
@@ -38,6 +38,7 @@ 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'
|
||||
|
||||
@@ -84,9 +85,7 @@ OUTPUT_IGNORED_ATTRIBUTES = (
|
||||
)
|
||||
|
||||
def parse_options():
|
||||
from optparse import OptionParser # pylint: disable=deprecated-module
|
||||
|
||||
parser = OptionParser()
|
||||
parser = config.IPAOptionParser()
|
||||
parser.add_option("--validate", dest="validate", action="store_true",
|
||||
default=False, help="Validate the API vs the stored API")
|
||||
|
||||
|
||||
Reference in new issue
Block a user