mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
csrgen: Automate full cert request flow
Allows the `ipa cert-request` command to generate its own CSR. It no longer requires a CSR passed on the command line, instead it creates a config (bash script) with `cert-get-requestdata`, then runs it to build a CSR, and submits that CSR. Example usage (NSS database): $ ipa cert-request --principal host/test.example.com --profile-id caIPAserviceCert --database /tmp/certs Example usage (PEM private key file): $ ipa cert-request --principal host/test.example.com --profile-id caIPAserviceCert --private-key /tmp/key.pem https://fedorahosted.org/freeipa/ticket/4899 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
parent
16dac0252e
commit
39a5d9c5aa
@ -19,6 +19,11 @@
|
||||
# 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 subprocess
|
||||
from tempfile import NamedTemporaryFile as NTF
|
||||
|
||||
import six
|
||||
|
||||
from ipaclient.frontend import MethodOverride
|
||||
from ipalib import errors
|
||||
from ipalib import x509
|
||||
@ -27,17 +32,86 @@ from ipalib.parameters import File, Flag, Str
|
||||
from ipalib.plugable import Registry
|
||||
from ipalib.text import _
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register(override=True, no_fail=True)
|
||||
class cert_request(MethodOverride):
|
||||
takes_options = (
|
||||
Str(
|
||||
'database?',
|
||||
label=_('Path to NSS database'),
|
||||
doc=_('Path to NSS database to use for private key'),
|
||||
),
|
||||
Str(
|
||||
'private_key?',
|
||||
label=_('Path to private key file'),
|
||||
doc=_('Path to PEM file containing a private key'),
|
||||
),
|
||||
)
|
||||
|
||||
def get_args(self):
|
||||
for arg in super(cert_request, self).get_args():
|
||||
if arg.name == 'csr':
|
||||
arg = arg.clone_retype(arg.name, File)
|
||||
arg = arg.clone_retype(arg.name, File, required=False)
|
||||
yield arg
|
||||
|
||||
def forward(self, csr=None, **options):
|
||||
database = options.pop('database', None)
|
||||
private_key = options.pop('private_key', None)
|
||||
|
||||
if csr is None:
|
||||
if database:
|
||||
helper = u'certutil'
|
||||
helper_args = ['-d', database]
|
||||
elif private_key:
|
||||
helper = u'openssl'
|
||||
helper_args = [private_key]
|
||||
else:
|
||||
raise errors.InvocationError(
|
||||
message=u"One of 'database' or 'private_key' is required")
|
||||
|
||||
with NTF() as scriptfile, NTF() as csrfile:
|
||||
profile_id = options.get('profile_id')
|
||||
|
||||
self.api.Command.cert_get_requestdata(
|
||||
profile_id=profile_id,
|
||||
principal=options.get('principal'),
|
||||
out=unicode(scriptfile.name),
|
||||
helper=helper)
|
||||
|
||||
helper_cmd = [
|
||||
'bash', '-e', scriptfile.name, csrfile.name] + helper_args
|
||||
|
||||
try:
|
||||
subprocess.check_output(helper_cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise errors.CertificateOperationError(
|
||||
error=(
|
||||
_('Error running "%(cmd)s" to generate CSR:'
|
||||
' %(err)s') %
|
||||
{'cmd': ' '.join(helper_cmd), 'err': e.output}))
|
||||
|
||||
try:
|
||||
csr = unicode(csrfile.read())
|
||||
except IOError as e:
|
||||
raise errors.CertificateOperationError(
|
||||
error=(_('Unable to read generated CSR file: %(err)s')
|
||||
% {'err': e}))
|
||||
if not csr:
|
||||
raise errors.CertificateOperationError(
|
||||
error=(_('Generated CSR was empty')))
|
||||
else:
|
||||
if database is not None or private_key is not None:
|
||||
raise errors.MutuallyExclusiveError(reason=_(
|
||||
"Options 'database' and 'private_key' are not compatible"
|
||||
" with 'csr'"))
|
||||
|
||||
return super(cert_request, self).forward(csr, **options)
|
||||
|
||||
|
||||
@register(override=True, no_fail=True)
|
||||
class cert_show(MethodOverride):
|
||||
|
@ -13,6 +13,7 @@ from ipalib.frontend import Local, Str
|
||||
from ipalib.parameters import Principal
|
||||
from ipalib.plugable import Registry
|
||||
from ipalib.text import _
|
||||
from ipapython import dogtag
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
@ -36,7 +37,7 @@ class cert_get_requestdata(Local):
|
||||
' HTTP/test.example.com)'),
|
||||
),
|
||||
Str(
|
||||
'profile_id',
|
||||
'profile_id?',
|
||||
label=_('Profile ID'),
|
||||
doc=_('CSR Generation Profile to use'),
|
||||
),
|
||||
@ -73,6 +74,8 @@ class cert_get_requestdata(Local):
|
||||
|
||||
principal = options.get('principal')
|
||||
profile_id = options.get('profile_id')
|
||||
if profile_id is None:
|
||||
profile_id = dogtag.DEFAULT_PROFILE
|
||||
helper = options.get('helper')
|
||||
|
||||
if self.api.env.in_server:
|
||||
|
Loading…
Reference in New Issue
Block a user