mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-23 07:33:27 -06:00
Add client certificate update tool ipa-certupdate.
Part of https://fedorahosted.org/freeipa/ticket/3259 Part of https://fedorahosted.org/freeipa/ticket/3520 Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
parent
2b7a7c356c
commit
60e19b585c
@ -741,6 +741,7 @@ fi
|
|||||||
%doc COPYING README Contributors.txt
|
%doc COPYING README Contributors.txt
|
||||||
%{_sbindir}/ipa-client-install
|
%{_sbindir}/ipa-client-install
|
||||||
%{_sbindir}/ipa-client-automount
|
%{_sbindir}/ipa-client-automount
|
||||||
|
%{_sbindir}/ipa-certupdate
|
||||||
%{_sbindir}/ipa-getkeytab
|
%{_sbindir}/ipa-getkeytab
|
||||||
%{_sbindir}/ipa-rmkeytab
|
%{_sbindir}/ipa-rmkeytab
|
||||||
%{_sbindir}/ipa-join
|
%{_sbindir}/ipa-join
|
||||||
@ -753,6 +754,7 @@ fi
|
|||||||
%{_mandir}/man1/ipa-rmkeytab.1.gz
|
%{_mandir}/man1/ipa-rmkeytab.1.gz
|
||||||
%{_mandir}/man1/ipa-client-install.1.gz
|
%{_mandir}/man1/ipa-client-install.1.gz
|
||||||
%{_mandir}/man1/ipa-client-automount.1.gz
|
%{_mandir}/man1/ipa-client-automount.1.gz
|
||||||
|
%{_mandir}/man1/ipa-certupdate.1.gz
|
||||||
%{_mandir}/man1/ipa-join.1.gz
|
%{_mandir}/man1/ipa-join.1.gz
|
||||||
%{_mandir}/man5/default.conf.5.gz
|
%{_mandir}/man5/default.conf.5.gz
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ NULL =
|
|||||||
sbin_SCRIPTS = \
|
sbin_SCRIPTS = \
|
||||||
ipa-client-install \
|
ipa-client-install \
|
||||||
ipa-client-automount \
|
ipa-client-automount \
|
||||||
|
ipa-certupdate \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
23
ipa-client/ipa-install/ipa-certupdate
Executable file
23
ipa-client/ipa-install/ipa-certupdate
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#! /usr/bin/python2 -E
|
||||||
|
# Authors: Jan Cholasta <jcholast@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from ipaclient.ipa_certupdate import CertUpdate
|
||||||
|
|
||||||
|
CertUpdate.run_cli()
|
@ -6,6 +6,7 @@ app_PYTHON = \
|
|||||||
ipachangeconf.py \
|
ipachangeconf.py \
|
||||||
ipadiscovery.py \
|
ipadiscovery.py \
|
||||||
ntpconf.py \
|
ntpconf.py \
|
||||||
|
ipa_certupdate.py \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
171
ipa-client/ipaclient/ipa_certupdate.py
Normal file
171
ipa-client/ipaclient/ipa_certupdate.py
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
# Authors: Jan Cholasta <jcholast@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from ipapython import (admintool, ipautil, ipaldap, sysrestore, dogtag,
|
||||||
|
certmonger)
|
||||||
|
from ipaplatform import services
|
||||||
|
from ipaplatform.paths import paths
|
||||||
|
from ipaplatform.tasks import tasks
|
||||||
|
from ipalib import api, x509, certstore
|
||||||
|
|
||||||
|
|
||||||
|
class CertUpdate(admintool.AdminTool):
|
||||||
|
command_name = 'ipa-certupdate'
|
||||||
|
|
||||||
|
usage = "%prog [options]"
|
||||||
|
|
||||||
|
description = ("Update local IPA certificate databases with certificates "
|
||||||
|
"from the server.")
|
||||||
|
|
||||||
|
def validate_options(self):
|
||||||
|
super(CertUpdate, self).validate_options(needs_root=True)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
api.bootstrap(context='cli_installer')
|
||||||
|
api.finalize()
|
||||||
|
|
||||||
|
try:
|
||||||
|
server = api.env.server
|
||||||
|
except AttributeError:
|
||||||
|
server = api.env.host
|
||||||
|
ldap = ipaldap.IPAdmin(server)
|
||||||
|
|
||||||
|
tmpdir = tempfile.mkdtemp(prefix="tmp-")
|
||||||
|
try:
|
||||||
|
principal = str('host/%s@%s' % (api.env.host, api.env.realm))
|
||||||
|
ipautil.kinit_hostprincipal(paths.KRB5_KEYTAB, tmpdir, principal)
|
||||||
|
|
||||||
|
ldap.do_sasl_gssapi_bind()
|
||||||
|
|
||||||
|
certs = certstore.get_ca_certs(ldap, api.env.basedn,
|
||||||
|
api.env.realm, api.env.enable_ra)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
server_fstore = sysrestore.FileStore(paths.SYSRESTORE)
|
||||||
|
if server_fstore.has_files():
|
||||||
|
self.update_server(certs)
|
||||||
|
|
||||||
|
self.update_client(certs)
|
||||||
|
|
||||||
|
def update_client(self, certs):
|
||||||
|
self.update_file(paths.IPA_CA_CRT, certs)
|
||||||
|
|
||||||
|
self.update_db(paths.NSS_DB_DIR, certs)
|
||||||
|
|
||||||
|
new_nicknames = set(c[1] for c in certs)
|
||||||
|
old_nicknames = set()
|
||||||
|
if ipautil.file_exists(paths.NSSDB_IPA_TXT):
|
||||||
|
try:
|
||||||
|
list_file = open(paths.NSSDB_IPA_TXT, 'r')
|
||||||
|
except IOError, e:
|
||||||
|
self.log.error("failed to open %s: %s", paths.NSSDB_IPA_TXT, e)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
lines = list_file.readlines()
|
||||||
|
except IOError, e:
|
||||||
|
self.log.error(
|
||||||
|
"failed to read %s: %s", paths.NSSDB_IPA_TXT, e)
|
||||||
|
else:
|
||||||
|
for line in lines:
|
||||||
|
nickname = line.strip()
|
||||||
|
if nickname:
|
||||||
|
old_nicknames.add(nickname)
|
||||||
|
list_file.close()
|
||||||
|
if new_nicknames != old_nicknames:
|
||||||
|
try:
|
||||||
|
list_file = open(paths.NSSDB_IPA_TXT, 'w')
|
||||||
|
except IOError, e:
|
||||||
|
self.log.error("failed to open %s: %s", paths.NSSDB_IPA_TXT, e)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for nickname in new_nicknames:
|
||||||
|
list_file.write(nickname + '\n')
|
||||||
|
except IOError, e:
|
||||||
|
self.log.error(
|
||||||
|
"failed to write %s: %s", paths.NSSDB_IPA_TXT, e)
|
||||||
|
list_file.close()
|
||||||
|
|
||||||
|
tasks.remove_ca_certs_from_systemwide_ca_store()
|
||||||
|
tasks.insert_ca_certs_into_systemwide_ca_store(certs)
|
||||||
|
|
||||||
|
def update_server(self, certs):
|
||||||
|
instance = '-'.join(api.env.realm.split('.'))
|
||||||
|
self.update_db(
|
||||||
|
paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % instance, certs)
|
||||||
|
if services.knownservices.dirsrv.is_running():
|
||||||
|
services.knownservices.dirsrv.restart(instance)
|
||||||
|
|
||||||
|
self.update_db(paths.HTTPD_ALIAS_DIR, certs)
|
||||||
|
if services.knownservices.httpd.is_running():
|
||||||
|
services.knownservices.httpd.restart()
|
||||||
|
|
||||||
|
dogtag_constants = dogtag.configured_constants()
|
||||||
|
nickname = 'caSigningCert cert-pki-ca'
|
||||||
|
criteria = (
|
||||||
|
('cert_storage_location', dogtag_constants.ALIAS_DIR,
|
||||||
|
certmonger.NPATH),
|
||||||
|
('cert_nickname', nickname, None),
|
||||||
|
)
|
||||||
|
request_id = certmonger.get_request_id(criteria)
|
||||||
|
if request_id is not None:
|
||||||
|
timeout = api.env.startup_timeout + 60
|
||||||
|
|
||||||
|
self.log.debug("resubmitting certmonger request '%s'", request_id)
|
||||||
|
certmonger.resubmit_request(request_id, profile='ipaRetrieval')
|
||||||
|
try:
|
||||||
|
state = certmonger.wait_for_request(request_id, timeout)
|
||||||
|
except RuntimeError:
|
||||||
|
raise admintool.ScriptError(
|
||||||
|
"Resubmitting certmonger request '%s' timed out, "
|
||||||
|
"please check the request manually" % request_id)
|
||||||
|
if state != 'MONITORING':
|
||||||
|
raise admintool.ScriptError(
|
||||||
|
"Error resubmitting certmonger request '%s', "
|
||||||
|
"please check the request manually" % request_id)
|
||||||
|
|
||||||
|
self.log.debug("modifying certmonger request '%s'", request_id)
|
||||||
|
certmonger.modify(request_id, profile='ipaCACertRenewal')
|
||||||
|
|
||||||
|
self.update_file(paths.CA_CRT, certs)
|
||||||
|
|
||||||
|
def update_file(self, filename, certs, mode=0444):
|
||||||
|
certs = (c[0] for c in certs if c[2] is not False)
|
||||||
|
try:
|
||||||
|
x509.write_certificate_list(certs, filename)
|
||||||
|
except Exception, e:
|
||||||
|
self.log.error("failed to update %s: %s", filename, e)
|
||||||
|
|
||||||
|
def update_db(self, path, certs):
|
||||||
|
for cert, nickname, trusted, eku in certs:
|
||||||
|
trust_flags = certstore.key_policy_to_trust_flags(
|
||||||
|
trusted, True, eku)
|
||||||
|
try:
|
||||||
|
ipautil.run([paths.CERTUTIL, '-A',
|
||||||
|
'-d', path,
|
||||||
|
'-n', nickname,
|
||||||
|
'-t', trust_flags],
|
||||||
|
stdin=cert)
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
self.log.error(
|
||||||
|
"failed to update %s in %s: %s", nickname, path, e)
|
@ -9,6 +9,7 @@ man1_MANS = \
|
|||||||
ipa-rmkeytab.1 \
|
ipa-rmkeytab.1 \
|
||||||
ipa-client-install.1 \
|
ipa-client-install.1 \
|
||||||
ipa-client-automount.1 \
|
ipa-client-automount.1 \
|
||||||
|
ipa-certupdate.1 \
|
||||||
ipa-join.1
|
ipa-join.1
|
||||||
|
|
||||||
man5_MANS = \
|
man5_MANS = \
|
||||||
|
39
ipa-client/man/ipa-certupdate.1
Normal file
39
ipa-client/man/ipa-certupdate.1
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
.\" A man page for ipa-certupdate
|
||||||
|
.\" Copyright (C) 2014 Red Hat, Inc.
|
||||||
|
.\"
|
||||||
|
.\" This program is free software; you can redistribute it and/or modify
|
||||||
|
.\" it under the terms of the GNU General Public License as published by
|
||||||
|
.\" the Free Software Foundation, either version 3 of the License, or
|
||||||
|
.\" (at your option) any later version.
|
||||||
|
.\"
|
||||||
|
.\" This program is distributed in the hope that it will be useful, but
|
||||||
|
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
.\" General Public License for more details.
|
||||||
|
.\"
|
||||||
|
.\" You should have received a copy of the GNU General Public License
|
||||||
|
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.\"
|
||||||
|
.\" Author: Jan Cholasta <jcholast@redhat.com>
|
||||||
|
.\"
|
||||||
|
.TH "ipa-certupdate" "1" "Jul 2 2014" "FreeIPA" "FreeIPA Manual Pages"
|
||||||
|
.SH "NAME"
|
||||||
|
ipa\-certupdate \- Update local IPA certificate databases with certificates from the server
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
\fBipa\-certupdate\fR [\fIOPTIONS\fR...]
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
\fBipa\-certupdate\fR can be used to update local IPA certificate databases with certificates from the server.
|
||||||
|
.SH "OPTIONS"
|
||||||
|
.TP
|
||||||
|
\fB\-v\fR, \fB\-\-verbose\fR
|
||||||
|
Print debugging information.
|
||||||
|
.TP
|
||||||
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
|
Output only errors.
|
||||||
|
.TP
|
||||||
|
\fB\-\-log\-file\fR=\fIFILE\fR
|
||||||
|
Log to the given file.
|
||||||
|
.SH "EXIT STATUS"
|
||||||
|
0 if the command was successful
|
||||||
|
|
||||||
|
1 if an error occurred
|
Loading…
Reference in New Issue
Block a user