|
5 | 5 |
|
6 | 6 | import os |
7 | 7 | import sys |
8 | | -from typing import Optional |
| 8 | +import tempfile |
| 9 | +from typing import Optional, BinaryIO |
9 | 10 |
|
10 | 11 | from azext_confcom import oras_proxy, os_util, security_policy |
11 | 12 | from azext_confcom._validators import resolve_stdio |
|
22 | 23 | get_image_name, inject_policy_into_template, inject_policy_into_yaml, |
23 | 24 | pretty_print_func, print_existing_policy_from_arm_template, |
24 | 25 | print_existing_policy_from_yaml, print_func, str_to_sha256) |
| 26 | +from azext_confcom.command.fragment_attach import fragment_attach as _fragment_attach |
| 27 | +from azext_confcom.command.fragment_push import fragment_push as _fragment_push |
25 | 28 | from knack.log import get_logger |
26 | 29 | from pkg_resources import parse_version |
27 | 30 |
|
@@ -255,6 +258,7 @@ def acifragmentgen_confcom( |
255 | 258 | upload_fragment: bool = False, |
256 | 259 | no_print: bool = False, |
257 | 260 | fragments_json: str = "", |
| 261 | + out_signed_fragment: bool = False, |
258 | 262 | ): |
259 | 263 | if container_definitions is None: |
260 | 264 | container_definitions = [] |
@@ -361,24 +365,40 @@ def acifragmentgen_confcom( |
361 | 365 |
|
362 | 366 | fragment_text = policy.generate_fragment(namespace, svn, output_type, omit_id=omit_id) |
363 | 367 |
|
364 | | - if output_type != security_policy.OutputType.DEFAULT and not no_print: |
| 368 | + if output_type != security_policy.OutputType.DEFAULT and not no_print and not out_signed_fragment: |
365 | 369 | print(fragment_text) |
366 | 370 |
|
367 | 371 | # take ".rego" off the end of the filename if it's there, it'll get added back later |
368 | 372 | output_filename = output_filename.replace(".rego", "") |
369 | 373 | filename = f"{output_filename or namespace}.rego" |
| 374 | + |
| 375 | + if out_signed_fragment: |
| 376 | + filename = os.path.join(tempfile.gettempdir(), filename) |
| 377 | + |
370 | 378 | os_util.write_str_to_file(filename, fragment_text) |
371 | 379 |
|
372 | 380 | if key: |
373 | 381 | cose_proxy = CoseSignToolProxy() |
374 | 382 | iss = cose_proxy.create_issuer(chain) |
375 | 383 | out_path = filename + ".cose" |
376 | 384 |
|
| 385 | + if out_signed_fragment: |
| 386 | + out_path = os.path.join(tempfile.gettempdir(), os.path.basename(out_path)) |
| 387 | + |
377 | 388 | cose_proxy.cose_sign(filename, key, chain, feed, iss, algo, out_path) |
378 | | - if upload_fragment and image_target: |
379 | | - oras_proxy.attach_fragment_to_image(image_target, out_path) |
380 | | - elif upload_fragment: |
381 | | - oras_proxy.push_fragment_to_registry(feed, out_path) |
| 389 | + |
| 390 | + # Preserve default behaviour established since version 1.1.0 of attaching |
| 391 | + # the fragment to the first image specified in input |
| 392 | + # (or --image-target if specified) |
| 393 | + if upload_fragment: |
| 394 | + oras_proxy.attach_fragment_to_image( |
| 395 | + image_name=image_target or policy_images[0].containerImage, |
| 396 | + filename=out_path, |
| 397 | + ) |
| 398 | + |
| 399 | + if out_signed_fragment: |
| 400 | + with open(out_path, "rb") as f: |
| 401 | + sys.stdout.buffer.write(f.read()) |
382 | 402 |
|
383 | 403 |
|
384 | 404 | def katapolicygen_confcom( |
@@ -512,3 +532,23 @@ def get_fragment_output_type(outraw): |
512 | 532 | if outraw: |
513 | 533 | output_type = security_policy.OutputType.RAW |
514 | 534 | return output_type |
| 535 | + |
| 536 | + |
| 537 | +def fragment_attach( |
| 538 | + signed_fragment: BinaryIO, |
| 539 | + manifest_tag: str, |
| 540 | +) -> None: |
| 541 | + _fragment_attach( |
| 542 | + signed_fragment=signed_fragment, |
| 543 | + manifest_tag=manifest_tag |
| 544 | + ) |
| 545 | + |
| 546 | + |
| 547 | +def fragment_push( |
| 548 | + signed_fragment: BinaryIO, |
| 549 | + manifest_tag: str, |
| 550 | +) -> None: |
| 551 | + _fragment_push( |
| 552 | + signed_fragment=signed_fragment, |
| 553 | + manifest_tag=manifest_tag |
| 554 | + ) |
0 commit comments