mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-26 08:51:50 -06:00
ed74b89878
dogtag updated its cipher list, disabling a lot of ciphers, which causes an overlap problem with a RHEL 6.x IPA master. This update script adds the two available ciphers to the nss.conf so that creating a CA replica is possible. Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
198 lines
6.2 KiB
Python
Executable File
198 lines
6.2 KiB
Python
Executable File
#!/usr/bin/python2
|
|
|
|
"""Copy the IPA schema to the CA directory server instance
|
|
|
|
You need to run this script to prepare a 2.2 or 3.0 IPA master for
|
|
installation of a 3.1 replica.
|
|
|
|
Once a 3.1 replica is in the domain, every older CA master will emit schema
|
|
replication errors until this script is run on it.
|
|
|
|
"""
|
|
|
|
# DO NOT TOUCH THIS CODE, IT MUST BE COMPATIBLE WITH RHEL6
|
|
# disable pylint because current codebase didn't match RHEL6 code
|
|
# pylint: disable=all
|
|
|
|
import os
|
|
import sys
|
|
import pwd
|
|
import shutil
|
|
|
|
from hashlib import sha1
|
|
|
|
from ipapython import ipautil
|
|
from ipapython.ipa_log_manager import root_logger, standard_logging_setup
|
|
from ipaserver.install.dsinstance import schema_dirname
|
|
from ipalib import api
|
|
|
|
# oh dear, this is an old IPA (3.0+)
|
|
from ipaserver.install.dsinstance import DS_USER
|
|
from ipaserver.install.cainstance import PKI_USER
|
|
from ipapython import services
|
|
|
|
# for mod_nss
|
|
from ipaserver.install.httpinstance import NSS_CONF
|
|
from ipaserver.install.httpinstance import HTTPInstance
|
|
from ipaserver.install import installutils
|
|
from ipapython import sysrestore
|
|
|
|
SERVERID = "PKI-IPA"
|
|
SCHEMA_FILENAMES = (
|
|
"60kerberos.ldif",
|
|
"60samba.ldif",
|
|
"60ipaconfig.ldif",
|
|
"60basev2.ldif",
|
|
"60basev3.ldif",
|
|
"60ipadns.ldif",
|
|
"61kerberos-ipav3.ldif",
|
|
"65ipacertstore.ldif",
|
|
"65ipasudo.ldif",
|
|
"70ipaotp.ldif",
|
|
"05rfc2247.ldif",
|
|
)
|
|
|
|
|
|
def _sha1_file(filename):
|
|
with open(filename, 'rb') as f:
|
|
return sha1(f.read()).hexdigest()
|
|
|
|
|
|
def add_ca_schema():
|
|
"""Copy IPA schema files into the CA DS instance
|
|
"""
|
|
pki_pent = pwd.getpwnam(PKI_USER)
|
|
ds_pent = pwd.getpwnam(DS_USER)
|
|
for schema_fname in SCHEMA_FILENAMES:
|
|
source_fname = os.path.join(ipautil.SHARE_DIR, schema_fname)
|
|
target_fname = os.path.join(schema_dirname(SERVERID), schema_fname)
|
|
if not os.path.exists(source_fname):
|
|
root_logger.debug('File does not exist: %s', source_fname)
|
|
continue
|
|
if os.path.exists(target_fname):
|
|
target_sha1 = _sha1_file(target_fname)
|
|
source_sha1 = _sha1_file(source_fname)
|
|
if target_sha1 != source_sha1:
|
|
target_size = os.stat(target_fname).st_size
|
|
source_size = os.stat(source_fname).st_size
|
|
root_logger.info('Target file %s exists but the content is '
|
|
'different', target_fname)
|
|
root_logger.info('\tTarget file: sha1: %s, size: %s B',
|
|
target_sha1, target_size)
|
|
root_logger.info('\tSource file: sha1: %s, size: %s B',
|
|
source_sha1, source_size)
|
|
if not ipautil.user_input("Do you want replace %s file?" %
|
|
target_fname, True):
|
|
continue
|
|
|
|
else:
|
|
root_logger.info(
|
|
'Target exists, not overwriting: %s', target_fname)
|
|
continue
|
|
try:
|
|
shutil.copyfile(source_fname, target_fname)
|
|
except IOError as e:
|
|
root_logger.warning('Could not install %s: %s', target_fname, e)
|
|
else:
|
|
root_logger.info('Installed %s', target_fname)
|
|
os.chmod(target_fname, 0o440) # read access for dirsrv user/group
|
|
os.chown(target_fname, pki_pent.pw_uid, ds_pent.pw_gid)
|
|
|
|
|
|
def restart_pki_ds():
|
|
"""Restart the CA DS instance to pick up schema changes
|
|
"""
|
|
root_logger.info('Restarting CA DS')
|
|
services.service('dirsrv').restart(SERVERID)
|
|
|
|
|
|
# The ipa-3-0 set_directive() has very loose comparision of directive
|
|
# which would cause multiple NSSCipherSuite to be added so provide
|
|
# a custom function for it.
|
|
def set_directive(filename, directive, value, quotes=True, separator=' '):
|
|
"""Set a name/value pair directive in a configuration file.
|
|
|
|
A value of None means to drop the directive.
|
|
|
|
This has only been tested with nss.conf
|
|
"""
|
|
valueset = False
|
|
st = os.stat(filename)
|
|
fd = open(filename)
|
|
newfile = []
|
|
for line in fd:
|
|
if line.lstrip().startswith(directive):
|
|
valueset = True
|
|
if value is not None:
|
|
if quotes:
|
|
newfile.append('%s%s"%s"\n' %
|
|
(directive, separator, value))
|
|
else:
|
|
newfile.append('%s%s%s\n' % (directive, separator, value))
|
|
else:
|
|
newfile.append(line)
|
|
fd.close()
|
|
if not valueset:
|
|
if value is not None:
|
|
if quotes:
|
|
newfile.append('%s%s"%s"\n' % (directive, separator, value))
|
|
else:
|
|
newfile.append('%s%s%s\n' % (directive, separator, value))
|
|
|
|
fd = open(filename, "w")
|
|
fd.write("".join(newfile))
|
|
fd.close()
|
|
os.chown(filename, st.st_uid, st.st_gid) # reset perms
|
|
|
|
|
|
def update_mod_nss_cipher_suite():
|
|
add_ciphers = ['ecdhe_rsa_aes_128_sha', 'ecdhe_rsa_aes_256_sha']
|
|
ciphers = installutils.get_directive(NSS_CONF, 'NSSCipherSuite')
|
|
|
|
# Run through once to see if any of the new ciphers are there but
|
|
# disabled. If they are then enable them.
|
|
lciphers = ciphers.split(',')
|
|
new_ciphers = []
|
|
for cipher in lciphers:
|
|
for add in add_ciphers:
|
|
if cipher.endswith(add):
|
|
if cipher.startswith('-'):
|
|
cipher = '+%s' % add
|
|
new_ciphers.append(cipher)
|
|
|
|
# Run through again and add remaining ciphers as enabled.
|
|
for add in add_ciphers:
|
|
if add not in ciphers:
|
|
new_ciphers.append('+%s' % add)
|
|
|
|
ciphers = ','.join(new_ciphers)
|
|
set_directive(NSS_CONF, 'NSSCipherSuite', ciphers, False)
|
|
root_logger.info('Updated Apache cipher list')
|
|
|
|
|
|
def restart_http():
|
|
root_logger.info('Restarting HTTP')
|
|
fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
|
|
http = HTTPInstance(fstore)
|
|
http.restart()
|
|
|
|
|
|
def main():
|
|
if os.getegid() != 0:
|
|
sys.exit("Must be root to run this script")
|
|
standard_logging_setup(verbose=True)
|
|
|
|
# In 3.0, restarting needs access to api.env
|
|
api.bootstrap_with_global_options(context='server')
|
|
|
|
add_ca_schema()
|
|
restart_pki_ds()
|
|
update_mod_nss_cipher_suite()
|
|
restart_http()
|
|
|
|
root_logger.info('Schema updated successfully')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|