freeipa/install/oddjob/com.redhat.idm.trust-fetch-domains
Jan Cholasta 2615103c68 makeaci, makeapi, oddjob: use the default API context
Use the default context rather the server context for code not running
inside the server.

This prevents the affected code from attempting to initialize the session
manager.

https://fedorahosted.org/freeipa/ticket/5988

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
2016-06-30 14:09:24 +02:00

180 lines
6.6 KiB
Python
Executable File

#!/usr/bin/python2
from ipaserver import dcerpc
from ipaserver.install.installutils import is_ipa_configured, ScriptError
from ipapython import config, ipautil
from ipalib import api
from ipapython.dn import DN
from ipalib.config import Env
from ipalib.constants import DEFAULT_CONFIG
from ipapython.ipautil import kinit_keytab
from ipaplatform.constants import constants
import sys
import os
import pwd
import six
import gssapi
if six.PY3:
unicode = str
def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal):
getkeytab_args = ["/usr/sbin/ipa-getkeytab",
"-s", api.env.host,
"-p", oneway_principal,
"-k", oneway_keytab_name,
"-r"]
if os.path.isfile(oneway_keytab_name):
os.unlink(oneway_keytab_name)
ipautil.run(getkeytab_args, env={'KRB5CCNAME': ccache_name, 'LANG': 'C'},
raiseonerr=False)
# Make sure SSSD is able to read the keytab
try:
sssd = pwd.getpwnam(constants.SSSD_USER)
os.chown(oneway_keytab_name, sssd[2], sssd[3])
except KeyError as e:
# If user 'sssd' does not exist, we don't need to chown from root to sssd
# because it means SSSD does not run as sssd user
pass
def parse_options():
usage = "%prog <trusted domain name>\n"
parser = config.IPAOptionParser(usage=usage,
formatter=config.IPAFormatter())
parser.add_option("-d", "--debug", action="store_true", dest="debug",
help="Display debugging information")
options, args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
return safe_options, options, args
if not is_ipa_configured():
# LSB status code 6: program is not configured
raise ScriptError("IPA is not configured " +
"(see man pages of ipa-server-install for help)", 6)
if not os.getegid() == 0:
# LSB status code 4: user had insufficient privilege
raise ScriptError("You must be root to run ipactl.", 4)
safe_options, options, args = parse_options()
if len(args) != 1:
# LSB status code 2: invalid or excess argument(s)
raise ScriptError("You must specify trusted domain name", 2)
trusted_domain = ipautil.fsdecode(args[0]).lower()
env = Env()
env._bootstrap(debug=options.debug, log=None)
env._finalize_core(**dict(DEFAULT_CONFIG))
# Initialize the API with the proper debug level
api.bootstrap(debug=env.debug, log=None)
api.finalize()
# Only import trust plugin after api is initialized or internal imports
# within the plugin will not work
from ipaserver.plugins import trust
# We have to dance with two different credentials caches:
# ccache_name -- for cifs/ipa.master@IPA.REALM to communicate with LDAP
# oneway_ccache_name -- for IPA$@AD.REALM to communicate with AD DCs
#
# ccache_name may not exist, we'll have to initialize it from Samba's keytab
#
# oneway_ccache_name may not exist either but to initialize it, we need
# to check if oneway_keytab_name keytab exists and fetch it first otherwise.
#
# to fetch oneway_keytab_name keytab, we need to initialize ccache_name ccache first
# and retrieve our own NetBIOS domain name and use cifs/ipa.master@IPA.REALM to
# retrieve the keys to oneway_keytab_name.
keytab_name = '/etc/samba/samba.keytab'
principal = str('cifs/' + api.env.host)
oneway_ccache_name = '/var/run/ipa/krb5cc_oddjob_trusts_fetch'
ccache_name = '/var/run/ipa/krb5cc_oddjob_trusts'
# Standard sequence:
# - check if ccache exists
# - if not, initialize it from Samba's keytab
# - check if ccache contains valid TGT
# - if not, initialize it from Samba's keytab
# - refer the correct ccache object for further use
#
have_ccache = False
try:
cred = kinit_keytab(principal, keytab_name, ccache_name)
if cred.lifetime > 0:
have_ccache = True
except gssapi.exceptions.ExpiredCredentialsError:
pass
if not have_ccache:
# delete stale ccache and try again
if os.path.exists(oneway_ccache_name):
os.unlink(ccache_name)
cred = kinit_keytab(principal, keytab_name, ccache_name)
old_ccache = os.environ.get('KRB5CCNAME')
api.Backend.ldap2.connect(ccache_name)
# Retrieve own NetBIOS name and trusted forest's name.
# We use script's input to retrieve the trusted forest's name to sanitize input
# for file-level access as we might need to wipe out keytab in /var/lib/sss/keytabs
own_trust_dn = DN(('cn', api.env.domain),('cn','ad'), ('cn', 'etc'), api.env.basedn)
own_trust_entry = api.Backend.ldap2.get_entry(own_trust_dn, ['ipantflatname'])
own_trust_flatname = own_trust_entry.single_value.get('ipantflatname').upper()
trusted_domain_dn = DN(('cn', trusted_domain.lower()), api.env.container_adtrusts, api.env.basedn)
trusted_domain_entry = api.Backend.ldap2.get_entry(trusted_domain_dn, ['cn'])
trusted_domain = trusted_domain_entry.single_value.get('cn').lower()
# At this point if we didn't find trusted forest name, an exception will be raised
# and script will quit. This is actually intended.
oneway_keytab_name = '/var/lib/sss/keytabs/' + trusted_domain + '.keytab'
oneway_principal = str('%s$@%s' % (own_trust_flatname, trusted_domain.upper()))
# If keytab does not exist, retrieve it
if not os.path.isfile(oneway_keytab_name):
retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal)
try:
have_ccache = False
try:
# The keytab may have stale key material (from older trust-add run)
cred = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
if cred.lifetime > 0:
have_ccache = True
except gssapi.exceptions.ExpiredCredentialsError:
pass
if not have_ccache:
if os.path.exists(oneway_ccache_name):
os.unlink(oneway_ccache_name)
kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
except gssapi.exceptions.GSSError:
# If there was failure on using keytab, assume it is stale and retrieve again
retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal)
if os.path.exists(oneway_ccache_name):
os.unlink(oneway_ccache_name)
kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
# We are done: we have ccache with TDO credentials and can fetch domains
ipa_domain = api.env.domain
os.environ['KRB5CCNAME'] = oneway_ccache_name
domains = dcerpc.fetch_domains(api, ipa_domain, trusted_domain, creds=True)
trust_domain_object = api.Command.trust_show(trusted_domain, raw=True)['result']
trust.add_new_domains_from_trust(api, None, trust_domain_object, domains)
if old_ccache:
os.environ['KRB5CCNAME'] = old_ccache
sys.exit(0)