forked from freeipa-pr-ci2/freeipa
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move Custodia secrets handler to scripts
Implement the import and export handlers for Custodia keys as external scripts. It's a prerequisite to drop DAC override permission and proper SELinux rules for ipa-custodia. Except for DMLDAP, handlers no longer run as root but as handler specific users with reduced privileges. The Dogtag-related handlers run as pkiuser, which also help with HSM support. The export and import handles are designed to be executed by sudo, too. In the future, ipa-custodia could be executed as an unprivileged process that runs the minimal helper scripts with higher privileges. Fixes: https://pagure.io/freeipa/issue/6888 Signed-off-by: Christian Heimes <[email protected]> Reviewed-By: Alexander Bokovoy <[email protected]>
- Loading branch information
Showing
18 changed files
with
642 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ NULL = | |
|
||
SUBDIRS = \ | ||
certmonger \ | ||
custodia \ | ||
html \ | ||
migration \ | ||
share \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
NULL = | ||
|
||
appdir = $(libexecdir)/ipa/custodia/ | ||
nodist_app_SCRIPTS = \ | ||
ipa-custodia-dmldap \ | ||
ipa-custodia-pki-tomcat \ | ||
ipa-custodia-pki-tomcat-wrapped \ | ||
ipa-custodia-ra-agent \ | ||
$(NULL) | ||
|
||
dist_noinst_DATA = \ | ||
ipa-custodia-dmldap.in \ | ||
ipa-custodia-pki-tomcat.in \ | ||
ipa-custodia-pki-tomcat-wrapped.in \ | ||
ipa-custodia-ra-agent.in \ | ||
$(NULL) | ||
|
||
PYTHON_SHEBANG = $(nodist_app_SCRIPTS) | ||
|
||
CLEANFILES = $(PYTHON_SHEBANG) | ||
|
||
include $(top_srcdir)/Makefile.pythonscripts.am |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@PYTHONSHEBANG@ | ||
# | ||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license | ||
# | ||
|
||
from ipaserver.secrets.handlers.dmldap import main | ||
|
||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@PYTHONSHEBANG@ | ||
# | ||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license | ||
# | ||
|
||
from ipaserver.secrets.handlers.nsswrappedcert import main, pki_tomcat_parser | ||
|
||
main(pki_tomcat_parser()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@PYTHONSHEBANG@ | ||
# | ||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license | ||
# | ||
|
||
from ipaserver.secrets.handlers.nsscert import main, pki_tomcat_parser | ||
|
||
main(pki_tomcat_parser()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@PYTHONSHEBANG@ | ||
# | ||
# Copyright (C) 2019 IPA Project Contributors, see COPYING for license | ||
# | ||
|
||
from ipaserver.secrets.handlers.pemfile import main, ra_agent_parser | ||
|
||
main(ra_agent_parser()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
"""Export / import handlers | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ipapython.dn import DN | ||
from ipapython.ipaldap import LDAPClient | ||
from ipaserver.install.installutils import 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() | ||
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |
Oops, something went wrong.