Skip to content

Commit 53c99a2

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "osc-included image signing (using openstacksdk)"
2 parents 62302ad + 1981eb2 commit 53c99a2

4 files changed

Lines changed: 71 additions & 2 deletions

File tree

lower-constraints.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ msgpack-python==0.4.0
5050
munch==2.1.0
5151
netaddr==0.7.18
5252
netifaces==0.10.4
53-
openstacksdk==0.11.2
53+
openstacksdk==0.17.0
5454
os-client-config==1.28.0
5555
os-service-types==1.2.0
5656
os-testr==1.0.0

openstackclient/image/v2/image.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
"""Image V2 Action Implementations"""
1717

1818
import argparse
19+
from base64 import b64encode
1920
import logging
2021

2122
from glanceclient.common import utils as gc_utils
23+
from openstack.image import image_signer
2224
from osc_lib.cli import parseractions
2325
from osc_lib.command import command
2426
from osc_lib import exceptions
@@ -183,6 +185,22 @@ def get_parser(self, prog_name):
183185
help=_("Force image creation if volume is in use "
184186
"(only meaningful with --volume)"),
185187
)
188+
parser.add_argument(
189+
'--sign-key-path',
190+
metavar="<sign-key-path>",
191+
default=[],
192+
help=_("Sign the image using the specified private key. "
193+
"Only use in combination with --sign-cert-id")
194+
)
195+
parser.add_argument(
196+
'--sign-cert-id',
197+
metavar="<sign-cert-id>",
198+
default=[],
199+
help=_("The specified certificate UUID is a reference to "
200+
"the certificate in the key manager that corresponds "
201+
"to the public key and is used for signature validation. "
202+
"Only use in combination with --sign-key-path")
203+
)
186204
protected_group = parser.add_mutually_exclusive_group()
187205
protected_group.add_argument(
188206
"--protected",
@@ -335,6 +353,46 @@ def take_action(self, parsed_args):
335353
parsed_args.project_domain,
336354
).id
337355

356+
# sign an image using a given local private key file
357+
if parsed_args.sign_key_path or parsed_args.sign_cert_id:
358+
if not parsed_args.file:
359+
msg = (_("signing an image requires the --file option, "
360+
"passing files via stdin when signing is not "
361+
"supported."))
362+
raise exceptions.CommandError(msg)
363+
if (len(parsed_args.sign_key_path) < 1 or
364+
len(parsed_args.sign_cert_id) < 1):
365+
msg = (_("'sign-key-path' and 'sign-cert-id' must both be "
366+
"specified when attempting to sign an image."))
367+
raise exceptions.CommandError(msg)
368+
else:
369+
sign_key_path = parsed_args.sign_key_path
370+
sign_cert_id = parsed_args.sign_cert_id
371+
signer = image_signer.ImageSigner()
372+
try:
373+
pw = utils.get_password(
374+
self.app.stdin,
375+
prompt=("Please enter private key password, leave "
376+
"empty if none: "),
377+
confirm=False)
378+
if not pw or len(pw) < 1:
379+
pw = None
380+
signer.load_private_key(
381+
sign_key_path,
382+
password=pw)
383+
except Exception:
384+
msg = (_("Error during sign operation: private key could "
385+
"not be loaded."))
386+
raise exceptions.CommandError(msg)
387+
388+
signature = signer.generate_signature(fp)
389+
signature_b64 = b64encode(signature)
390+
kwargs['img_signature'] = signature_b64
391+
kwargs['img_signature_certificate_uuid'] = sign_cert_id
392+
kwargs['img_signature_hash_method'] = signer.hash_method
393+
if signer.padding_method:
394+
kwargs['img_signature_key_type'] = signer.padding_method
395+
338396
# If a volume is specified.
339397
if parsed_args.volume:
340398
volume_client = self.app.client_manager.volume
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
features:
3+
- |
4+
Add options ``--sign-key-path`` and ``--sign-cert-id`` to the ``image create``
5+
command. Tthe image must be present on disk, therefore the ``file`` option
6+
is required:
7+
8+
``image create --file <filename> --sign-key-path <key-path> --sign-cert-id <secret-id>``.
9+
10+
A prompt for a password ensures, that the private key can be protected too.
11+
[Bug `2002128 <https://storyboard.openstack.org/#!/story/2002128>`_]

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ six>=1.10.0 # MIT
77
Babel!=2.4.0,>=2.3.4 # BSD
88
cliff!=2.9.0,>=2.8.0 # Apache-2.0
99
keystoneauth1>=3.4.0 # Apache-2.0
10-
openstacksdk>=0.11.2 # Apache-2.0
10+
openstacksdk>=0.17.0 # Apache-2.0
1111
osc-lib>=1.10.0 # Apache-2.0
1212
oslo.i18n>=3.15.3 # Apache-2.0
1313
oslo.utils>=3.33.0 # Apache-2.0

0 commit comments

Comments
 (0)