Imported Debian patch 4.8.10-2
This commit is contained in:
committed by
Mario Fetka
parent
8bc559c5a1
commit
358acdd85f
2
ipaserver/secrets/handlers/__init__.py
Normal file
2
ipaserver/secrets/handlers/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
"""Export / import handlers
|
||||
"""
|
||||
75
ipaserver/secrets/handlers/common.py
Normal file
75
ipaserver/secrets/handlers/common.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license
|
||||
#
|
||||
"""Common helpers for handlers
|
||||
"""
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
|
||||
def default_json(obj):
|
||||
"""JSON encoder default handler
|
||||
"""
|
||||
if isinstance(obj, (bytes, bytearray)):
|
||||
return base64.b64encode(obj).decode('ascii')
|
||||
raise TypeError(
|
||||
"Object of type {} is not JSON serializable".format(type(obj))
|
||||
)
|
||||
|
||||
|
||||
def json_dump(data, exportfile):
|
||||
"""Dump JSON to file
|
||||
"""
|
||||
json.dump(
|
||||
data,
|
||||
exportfile,
|
||||
default=default_json,
|
||||
separators=(',', ':'),
|
||||
sort_keys=True
|
||||
)
|
||||
|
||||
|
||||
def mkparser(supports_import=True, **kwargs):
|
||||
"""Create default parser for handler with export / import args
|
||||
|
||||
All commands support export to file or stdout. Most commands can also
|
||||
import from a file or stdin. Export and import are mutually exclusive
|
||||
options.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(**kwargs)
|
||||
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument(
|
||||
'--export',
|
||||
help='JSON export file ("-" for stdout)',
|
||||
dest='exportfile',
|
||||
type=argparse.FileType('w')
|
||||
)
|
||||
if supports_import:
|
||||
group.add_argument(
|
||||
'--import',
|
||||
help='JSON import file ("-" for stdin)',
|
||||
dest='importfile',
|
||||
type=argparse.FileType('r')
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def main(parser, export_func, import_func=None, **kwargs):
|
||||
"""Common main function for handlers
|
||||
"""
|
||||
args = parser.parse_args()
|
||||
if args.exportfile is not None:
|
||||
func = export_func
|
||||
else:
|
||||
func = import_func
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
func(args, tmpdir, **kwargs)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
63
ipaserver/secrets/handlers/dmldap.py
Normal file
63
ipaserver/secrets/handlers/dmldap.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license
|
||||
#
|
||||
"""Export / import Directory Manager password hash
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
|
||||
from ipalib import api
|
||||
from ipalib import errors
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython.dn import DN
|
||||
from ipapython.ipaldap import LDAPClient, realm_to_ldapi_uri
|
||||
from . import common
|
||||
|
||||
CN_CONFIG = DN(('cn', 'config'))
|
||||
ROOTPW = 'nsslapd-rootpw'
|
||||
|
||||
|
||||
def export_key(args, tmpdir, conn):
|
||||
entry = conn.get_entry(CN_CONFIG, [ROOTPW])
|
||||
data = {
|
||||
'dmhash': entry.single_value[ROOTPW],
|
||||
}
|
||||
common.json_dump(data, args.exportfile)
|
||||
|
||||
|
||||
def import_key(args, tmpdir, conn):
|
||||
data = json.load(args.importfile)
|
||||
dmhash = data['dmhash'].encode('ascii')
|
||||
entry = conn.get_entry(CN_CONFIG, [ROOTPW])
|
||||
entry.single_value[ROOTPW] = dmhash
|
||||
try:
|
||||
conn.update_entry(entry)
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
parser = common.mkparser(
|
||||
description='ipa-custodia LDAP DM hash handler'
|
||||
)
|
||||
|
||||
if os.getegid() != 0:
|
||||
parser.error("Must be run as root user.\n")
|
||||
|
||||
# create LDAP connection using LDAPI and EXTERNAL bind as root
|
||||
if not api.isdone('bootstrap'):
|
||||
api.bootstrap(confdir=paths.ETC_IPA, log=None)
|
||||
realm = api.env.realm
|
||||
ldap_uri = realm_to_ldapi_uri(realm)
|
||||
conn = LDAPClient(ldap_uri=ldap_uri, no_schema=True)
|
||||
try:
|
||||
conn.external_bind()
|
||||
except Exception as e:
|
||||
parser.error("Failed to connect to {}: {}\n".format(ldap_uri, e))
|
||||
|
||||
with conn:
|
||||
common.main(parser, export_key, import_key, conn=conn)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
122
ipaserver/secrets/handlers/nsscert.py
Normal file
122
ipaserver/secrets/handlers/nsscert.py
Normal file
@@ -0,0 +1,122 @@
|
||||
#
|
||||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license
|
||||
#
|
||||
"""Export / import cert and key from NSS DB as PKCS#12 data
|
||||
"""
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython import ipautil
|
||||
from ipapython.certdb import NSSDatabase
|
||||
from . import common
|
||||
|
||||
|
||||
def export_key(args, tmpdir):
|
||||
"""Export key and certificate from the NSS DB to a PKCS#12 file.
|
||||
|
||||
The PKCS#12 file is encrypted with a password.
|
||||
"""
|
||||
pk12file = os.path.join(tmpdir, 'export.p12')
|
||||
|
||||
password = ipautil.ipa_generate_password()
|
||||
pk12pk12pwfile = os.path.join(tmpdir, 'passwd')
|
||||
with open(pk12pk12pwfile, 'w') as f:
|
||||
f.write(password)
|
||||
|
||||
nssdb = NSSDatabase(args.nssdb_path)
|
||||
nssdb.run_pk12util([
|
||||
"-o", pk12file,
|
||||
"-n", args.nickname,
|
||||
"-k", args.nssdb_pwdfile,
|
||||
"-w", pk12pk12pwfile,
|
||||
])
|
||||
|
||||
with open(pk12file, 'rb') as f:
|
||||
p12data = f.read()
|
||||
|
||||
data = {
|
||||
'export password': password,
|
||||
'pkcs12 data': p12data,
|
||||
}
|
||||
common.json_dump(data, args.exportfile)
|
||||
|
||||
|
||||
def import_key(args, tmpdir):
|
||||
"""Import key and certificate from a PKCS#12 file to a NSS DB.
|
||||
"""
|
||||
data = json.load(args.importfile)
|
||||
password = data['export password']
|
||||
p12data = base64.b64decode(data['pkcs12 data'])
|
||||
|
||||
pk12pwfile = os.path.join(tmpdir, 'passwd')
|
||||
with open(pk12pwfile, 'w') as f:
|
||||
f.write(password)
|
||||
|
||||
pk12file = os.path.join(tmpdir, 'import.p12')
|
||||
with open(pk12file, 'wb') as f:
|
||||
f.write(p12data)
|
||||
|
||||
nssdb = NSSDatabase(args.nssdb_path)
|
||||
nssdb.run_pk12util([
|
||||
"-i", pk12file,
|
||||
"-n", args.nickname,
|
||||
"-k", args.nssdb_pwdfile,
|
||||
"-w", pk12pwfile,
|
||||
])
|
||||
|
||||
|
||||
def default_parser():
|
||||
"""Generic interface
|
||||
"""
|
||||
parser = common.mkparser(
|
||||
description='ipa-custodia NSS cert handler'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nssdb',
|
||||
dest='nssdb_path',
|
||||
help='path to NSS DB',
|
||||
required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--pwdfile',
|
||||
dest='nssdb_pwdfile',
|
||||
help='path to password file for NSS DB',
|
||||
required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nickname',
|
||||
help='nick name of certificate',
|
||||
required=True
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def pki_tomcat_parser():
|
||||
"""Hard-code Dogtag's NSSDB and its password file
|
||||
"""
|
||||
parser = common.mkparser(
|
||||
description='ipa-custodia pki-tomcat NSS cert handler'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nickname',
|
||||
help='nick name of certificate',
|
||||
required=True
|
||||
)
|
||||
parser.set_defaults(
|
||||
nssdb_path=paths.PKI_TOMCAT_ALIAS_DIR,
|
||||
nssdb_pwdfile=paths.PKI_TOMCAT_ALIAS_PWDFILE_TXT,
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def main(parser=None):
|
||||
if parser is None:
|
||||
parser = default_parser()
|
||||
|
||||
common.main(parser, export_key, import_key)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
126
ipaserver/secrets/handlers/nsswrappedcert.py
Normal file
126
ipaserver/secrets/handlers/nsswrappedcert.py
Normal file
@@ -0,0 +1,126 @@
|
||||
#
|
||||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license
|
||||
#
|
||||
"""Export and wrap key from NSS DB
|
||||
"""
|
||||
import os
|
||||
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython import ipautil
|
||||
from ipapython.certdb import NSSDatabase
|
||||
from . import common
|
||||
|
||||
|
||||
def export_key(args, tmpdir):
|
||||
"""Export key and certificate from the NSS DB
|
||||
|
||||
The private key is encrypted using key wrapping.
|
||||
"""
|
||||
wrapped_key_file = os.path.join(tmpdir, 'wrapped_key')
|
||||
certificate_file = os.path.join(tmpdir, 'certificate')
|
||||
|
||||
ipautil.run([
|
||||
paths.PKI,
|
||||
'-d', args.nssdb_path,
|
||||
'-C', args.nssdb_pwdfile,
|
||||
'ca-authority-key-export',
|
||||
'--wrap-nickname', args.wrap_nickname,
|
||||
'--target-nickname', args.nickname,
|
||||
'--algorithm', args.algorithm,
|
||||
'-o', wrapped_key_file
|
||||
])
|
||||
|
||||
nssdb = NSSDatabase(args.nssdb_path)
|
||||
nssdb.run_certutil([
|
||||
'-L',
|
||||
'-n', args.nickname,
|
||||
'-a',
|
||||
'-o', certificate_file,
|
||||
])
|
||||
with open(wrapped_key_file, 'rb') as f:
|
||||
wrapped_key = f.read()
|
||||
with open(certificate_file, 'r') as f:
|
||||
certificate = f.read()
|
||||
|
||||
data = {
|
||||
'wrapped_key': wrapped_key,
|
||||
'certificate': certificate
|
||||
}
|
||||
common.json_dump(data, args.exportfile)
|
||||
|
||||
|
||||
def default_parser():
|
||||
"""Generic interface
|
||||
"""
|
||||
parser = common.mkparser(
|
||||
supports_import=False,
|
||||
description='ipa-custodia NSS wrapped cert handler',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nssdb',
|
||||
dest='nssdb_path',
|
||||
help='path to NSS DB',
|
||||
required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--pwdfile',
|
||||
dest='nssdb_pwdfile',
|
||||
help='path to password file for NSS DB',
|
||||
required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--wrap-nickname',
|
||||
dest='wrap_nickname',
|
||||
help='nick name of wrapping key',
|
||||
required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nickname',
|
||||
dest='nickname',
|
||||
help='nick name of target key',
|
||||
required=True
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def pki_tomcat_parser():
|
||||
"""Hard-code Dogtag's NSS DB, its password file, and CA key for wrapping
|
||||
"""
|
||||
parser = common.mkparser(
|
||||
supports_import=False,
|
||||
description='ipa-custodia pki-tomcat NSS wrapped cert handler',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--nickname',
|
||||
dest='nickname',
|
||||
help='nick name of target key',
|
||||
required=True
|
||||
)
|
||||
|
||||
# Caller must specify a cipher. This gets passed on to
|
||||
# the 'pki ca-authority-key-export' command (part of
|
||||
# Dogtag) via its own --algorithm option.
|
||||
parser.add_argument(
|
||||
'--algorithm',
|
||||
dest='algorithm',
|
||||
help='OID of symmetric wrap algorithm',
|
||||
required=True
|
||||
)
|
||||
|
||||
parser.set_defaults(
|
||||
nssdb_path=paths.PKI_TOMCAT_ALIAS_DIR,
|
||||
nssdb_pwdfile=paths.PKI_TOMCAT_ALIAS_PWDFILE_TXT,
|
||||
wrap_nickname='caSigningCert cert-pki-ca',
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def main(parser=None):
|
||||
if parser is None:
|
||||
parser = default_parser()
|
||||
|
||||
common.main(parser, export_key, None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
118
ipaserver/secrets/handlers/pemfile.py
Normal file
118
ipaserver/secrets/handlers/pemfile.py
Normal file
@@ -0,0 +1,118 @@
|
||||
#
|
||||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license
|
||||
#
|
||||
"""Export / import PEM cert and key file as PKCS#12 data
|
||||
"""
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython import ipautil
|
||||
from . import common
|
||||
|
||||
|
||||
def export_key(args, tmpdir):
|
||||
"""Export cert and private from PEM files as PKCS#12 file.
|
||||
|
||||
The PKCS#12 file is encrypted with a password.
|
||||
"""
|
||||
pk12file = os.path.join(tmpdir, 'export.p12')
|
||||
|
||||
password = ipautil.ipa_generate_password()
|
||||
pk12pwfile = os.path.join(tmpdir, 'passwd')
|
||||
with open(pk12pwfile, 'w') as f:
|
||||
f.write(password)
|
||||
|
||||
# OpenSSL does not support pkcs12 export of a cert without key
|
||||
ipautil.run([
|
||||
paths.OPENSSL, 'pkcs12', '-export',
|
||||
'-in', args.certfile,
|
||||
'-out', pk12file,
|
||||
'-inkey', args.keyfile,
|
||||
'-password', 'file:{pk12pwfile}'.format(pk12pwfile=pk12pwfile),
|
||||
])
|
||||
|
||||
with open(pk12file, 'rb') as f:
|
||||
p12data = f.read()
|
||||
|
||||
data = {
|
||||
'export password': password,
|
||||
'pkcs12 data': p12data,
|
||||
}
|
||||
common.json_dump(data, args.exportfile)
|
||||
|
||||
|
||||
def import_key(args, tmpdir):
|
||||
"""Export key and certificate from a PKCS#12 file to key and cert files.
|
||||
"""
|
||||
data = json.load(args.importfile)
|
||||
password = data['export password']
|
||||
p12data = base64.b64decode(data['pkcs12 data'])
|
||||
|
||||
pk12pwfile = os.path.join(tmpdir, 'passwd')
|
||||
with open(pk12pwfile, 'w') as f:
|
||||
f.write(password)
|
||||
|
||||
pk12file = os.path.join(tmpdir, 'import.p12')
|
||||
with open(pk12file, 'wb') as f:
|
||||
f.write(p12data)
|
||||
|
||||
# get the certificate from the file
|
||||
cmd = [
|
||||
paths.OPENSSL, 'pkcs12',
|
||||
'-in', pk12file,
|
||||
'-clcerts', '-nokeys',
|
||||
'-out', args.certfile,
|
||||
'-password', 'file:{pk12pwfile}'.format(pk12pwfile=pk12pwfile),
|
||||
]
|
||||
ipautil.run(cmd, umask=0o027)
|
||||
|
||||
# get the private key from the file
|
||||
cmd = [
|
||||
paths.OPENSSL, 'pkcs12',
|
||||
'-in', pk12file,
|
||||
'-nocerts', '-nodes',
|
||||
'-out', args.keyfile,
|
||||
'-password', 'file:{pk12pwfile}'.format(pk12pwfile=pk12pwfile),
|
||||
]
|
||||
ipautil.run(cmd, umask=0o027)
|
||||
|
||||
|
||||
def default_parser():
|
||||
parser = common.mkparser(
|
||||
description='ipa-custodia PEM file handler'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--certfile',
|
||||
help='path to PEM encoded cert file',
|
||||
required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'keyfile',
|
||||
help='path to PEM encoded key file',
|
||||
required=True
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def ra_agent_parser():
|
||||
parser = common.mkparser(
|
||||
description='ipa-custodia RA agent cert handler'
|
||||
)
|
||||
parser.set_defaults(
|
||||
certfile=paths.RA_AGENT_PEM,
|
||||
keyfile=paths.RA_AGENT_KEY
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def main(parser=None):
|
||||
if parser is None:
|
||||
parser = default_parser()
|
||||
|
||||
common.main(parser, export_key, import_key)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user