Skip to content

Commit e1a7077

Browse files
committed
Added optional signing_key_name to msg signer messages
Signed-off-by: Jindrich Luza <[email protected]>
1 parent 7367c2a commit e1a7077

File tree

11 files changed

+139
-28
lines changed

11 files changed

+139
-28
lines changed

src/pubtools/sign/clients/msg.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ def on_error(self, event: proton.Event, source: Any = None) -> bool:
3030
return False
3131
self.errors.append(
3232
MsgError(
33-
name=event,
34-
description=getattr(source, "condition", None)
35-
or getattr(source, "remote_condition", None),
33+
name=condition.name,
34+
description=condition.description,
3635
source=source,
3736
)
3837
)

src/pubtools/sign/clients/msg_recv_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ def on_message(self, event: proton.Event) -> None:
9898

9999
if self.recv_ids.values() and all(self.recv_ids.values()):
100100
self.timer_task.cancel()
101-
event.receiver.close()
102-
event.connection.close()
101+
if event.receiver:
102+
event.receiver.close()
103+
if event.connection:
104+
event.connection.close()
103105
LOG.info(self._format_log_msg("RECEIVER:All messages received", event=event))
104106

105107
def on_timer_task(self, event: proton.Event) -> None:

src/pubtools/sign/clients/msg_send_client.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def on_connection_opened(self, event: proton.Event) -> None:
5555

5656
@tw.instrument_func()
5757
def on_sendable(self, event: proton.Event) -> None:
58-
if event.sender.credit and self.sent < self.total:
58+
if event.sender and event.sender.credit and self.sent < self.total:
5959
message = self.messages[self.sent]
6060
# Inject trace context to message properties
6161
propagator.inject(carrier=message.headers)
@@ -66,21 +66,23 @@ def on_sendable(self, event: proton.Event) -> None:
6666
f"{json.dumps(message.headers)}",
6767
)
6868
)
69-
event.sender.send(
70-
proton.Message(
71-
properties=message.headers,
72-
address=message.address,
73-
body=json.dumps(message.body),
69+
if event.sender:
70+
event.sender.send(
71+
proton.Message(
72+
properties=message.headers,
73+
address=message.address,
74+
body=json.dumps(message.body),
75+
)
7476
)
75-
)
7677
self.sent += 1
7778

7879
def on_accepted(self, event: proton.Event) -> None:
7980
# LOG.info("Sender accepted")
8081
self.confirmed += 1
8182
if self.confirmed == self.total:
8283
LOG.info("SENDER: closing")
83-
event.connection.close()
84+
if event.connection:
85+
event.connection.close()
8486
self.sender.close()
8587

8688
def on_disconnected(self, event: proton.Event) -> None: # pragma: no cover

src/pubtools/sign/operations/base.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from abc import ABC, abstractmethod
44

5-
from dataclasses import dataclass
5+
from dataclasses import dataclass, field
66
from typing import ClassVar, Dict, Any, Type
77
from typing_extensions import Self
88

@@ -15,6 +15,13 @@ class SignOperation(ABC):
1515

1616
ResultType: ClassVar[OperationResult]
1717
signing_key: str
18+
signing_key_name: str = field(
19+
default="",
20+
metadata={
21+
"description": "Signing key name which should be used for signing",
22+
"sample": "key1",
23+
},
24+
)
1825

1926
@classmethod
2027
def doc_arguments(cls: Type[Self]) -> Dict[str, Any]:

src/pubtools/sign/operations/clearsign.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,35 @@ class ClearSignOperation(SignOperation):
2020
"description": "Signing data",
2121
"required": "true",
2222
"sample": ["input1", "input2"],
23-
}
23+
},
24+
default_factory=list,
2425
)
2526
signing_key: str = field(
2627
metadata={
2728
"type": "str",
2829
"description": "Signing key short id which should be used for signing",
2930
"required": "true",
3031
"sample": "123",
31-
}
32+
},
33+
default="",
3234
)
3335
task_id: str = field(
3436
metadata={
3537
"type": "str",
3638
"description": "Usually pub task id, serves as identifier for in signing request",
3739
"required": "true",
3840
"sample": "1",
39-
}
41+
},
42+
default="",
4043
)
4144
repo: str = field(
4245
metadata={
4346
"type": "str",
4447
"description": "Repository name",
4548
"required": "true",
4649
"sample": "repo",
47-
}
50+
},
51+
default="",
4852
)
4953
requester: str = field(
5054
metadata={"description": "Requester of the signing operation"}, default=""

src/pubtools/sign/operations/containersign.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,21 @@ class ContainerSignOperation(SignOperation):
1414
"""ContainersSignOperation model class."""
1515

1616
ResultType: ClassVar[OperationResult]
17-
digests: List[str] = field(metadata={"description": "List of digest to sign"})
18-
references: List[str] = field(metadata={"description": "List of references to sign"})
17+
digests: List[str] = field(
18+
metadata={"description": "List of digest to sign"}, default_factory=list
19+
)
20+
references: List[str] = field(
21+
metadata={"description": "List of references to sign"}, default_factory=list
22+
)
1923
signing_key: str = field(
20-
metadata={"description": "Signing key short id which should be used for signing"}
24+
metadata={"description": "Signing key short id which should be used for signing"},
25+
default="",
2126
)
2227
task_id: str = field(
23-
metadata={"description": "Usually pub task id, serves as identifier for in signing request"}
28+
metadata={
29+
"description": "Usually pub task id, serves as identifier for in signing request"
30+
},
31+
default="",
2432
)
2533
identity_references: List[str] = field(
2634
metadata={"description": "List of references to sign"}, default_factory=list
@@ -34,6 +42,7 @@ def to_dict(self) -> dict[str, Any]:
3442
return dict(
3543
digests=self.digests,
3644
references=self.references,
45+
signing_key_name=self.signing_key_name,
3746
signing_key=self.signing_key,
3847
task_id=self.task_id,
3948
requester=self.requester,

src/pubtools/sign/signers/msgsigner.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737

3838
LOG = logging.getLogger("pubtools.sign.signers.msgsigner")
39+
LOG.setLevel(logging.INFO)
3940

4041

4142
class SignRequestType(str, enum.Enum):
@@ -169,6 +170,7 @@ def _construct_signing_message(
169170
claim: str,
170171
signing_key: str,
171172
repo: str,
173+
signing_key_name: str = "",
172174
extra_attrs: Optional[Dict[str, Any]] = None,
173175
sig_type: str = SignRequestType.CONTAINER,
174176
) -> dict[str, Any]:
@@ -182,6 +184,8 @@ def _construct_signing_message(
182184
"requested_by": self.creator,
183185
"repo": repo,
184186
}
187+
if signing_key_name:
188+
message["sig_keyname"] = signing_key_name
185189
message.update(_extra_attrs)
186190
return message
187191

@@ -217,6 +221,7 @@ def _create_msg_message(
217221
data,
218222
signing_key,
219223
repo,
224+
signing_key_name=operation.signing_key_name,
220225
extra_attrs=extra_attrs,
221226
sig_type=sig_type.value,
222227
),
@@ -625,6 +630,7 @@ def msg_clear_sign(
625630

626631
def msg_container_sign(
627632
signing_key: str = "",
633+
signing_key_name: str = "",
628634
task_id: str = "",
629635
config_file: str = "",
630636
digest: list[str] = [],
@@ -642,6 +648,7 @@ def msg_container_sign(
642648
digests=digest,
643649
references=reference,
644650
signing_key=signing_key,
651+
signing_key_name=signing_key_name,
645652
task_id=task_id,
646653
requester=requester,
647654
)
@@ -727,6 +734,11 @@ def msg_clear_sign_main(
727734
required=True,
728735
help="8 characters key fingerprint of key which should be used for signing",
729736
)
737+
@click.option(
738+
"--signing-key-name",
739+
required=False,
740+
help="signing key name",
741+
)
730742
@click.option("--task-id", required=True, help="Task id identifier (usually pub task-id)")
731743
@click.option("--config-file", default=CONFIG_PATHS[0], help="path to the config file")
732744
@click.option(
@@ -759,6 +771,7 @@ def msg_clear_sign_main(
759771
)
760772
def msg_container_sign_main(
761773
signing_key: str = "",
774+
signing_key_name: str = "",
762775
task_id: str = "",
763776
config_file: str = "",
764777
digest: List[str] = [],
@@ -775,6 +788,7 @@ def msg_container_sign_main(
775788

776789
ret = msg_container_sign(
777790
signing_key=signing_key,
791+
signing_key_name=signing_key_name,
778792
task_id=task_id,
779793
config_file=config_file,
780794
digest=digest,

tests/test_msg_handle.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@ def test_msg_handler_errors():
1414
msgsc = _MsgClient(errors)
1515
msgsc.on_link_error(mock_error)
1616
assert errors == [
17-
MsgError(name=mock_error, description=mock_error.link.condition, source=mock_error.link)
17+
MsgError(
18+
name=mock_error.link.condition.name,
19+
description=mock_error.link.condition.description,
20+
source=mock_error.link,
21+
)
1822
]
1923

2024
errors = []
2125
msgsc = _MsgClient(errors)
2226
msgsc.on_session_error(mock_error)
2327
assert errors == [
2428
MsgError(
25-
name=mock_error, description=mock_error.session.condition, source=mock_error.session
29+
name=mock_error.session.condition.name,
30+
description=mock_error.session.condition.description,
31+
source=mock_error.session,
2632
)
2733
]
2834

@@ -31,8 +37,8 @@ def test_msg_handler_errors():
3137
msgsc.on_connection_error(mock_error)
3238
assert errors == [
3339
MsgError(
34-
name=mock_error,
35-
description=mock_error.connection.condition,
40+
name=mock_error.connection.condition.name,
41+
description=mock_error.connection.condition.description,
3642
source=mock_error.connection,
3743
)
3844
]

tests/test_msg_send_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ def test_non_ingored_error(
123123
msgsc.on_transport_error(mock_error)
124124
assert errors == [
125125
MsgError(
126-
name=mock_error, description=mock_error.transport.condition, source=mock_error.transport
126+
name="amqp:simulated-error",
127+
description="",
128+
source=mock_error.transport,
127129
)
128130
]

tests/test_msg_signer.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,34 @@ def test_msg_container_sign(f_msg_signer, f_config_msg_signer_ok):
5353
assert result.exit_code == 0, result.output
5454

5555

56+
def test_msg_container_sign_keyname(f_msg_signer, f_config_msg_signer_ok):
57+
f_msg_signer.return_value.sign.return_value.signer_results.to_dict.return_value = {
58+
"status": "ok"
59+
}
60+
f_msg_signer.return_value.sign.return_value.operation_result.results = []
61+
f_msg_signer.return_value.sign.return_value.operation_result.signing_key = ""
62+
f_msg_signer.return_value.sign.return_value.operation.to_dict.return_value = {}
63+
result = CliRunner().invoke(
64+
msg_container_sign_main,
65+
[
66+
"--signing-key",
67+
"test-signing-key",
68+
"--signing-key-name",
69+
"test-signing-key-name",
70+
"--digest",
71+
"some-digest",
72+
"--reference",
73+
"some-reference",
74+
"--task-id",
75+
"1",
76+
"--config-file",
77+
f_config_msg_signer_ok,
78+
],
79+
)
80+
print(result.stdout)
81+
assert result.exit_code == 0, result.output
82+
83+
5684
def test_msg_container_sign_requester(f_msg_signer, f_config_msg_signer_ok):
5785
f_msg_signer.return_value.sign.return_value.signer_results.to_dict.return_value = {
5886
"status": "ok"
@@ -408,9 +436,35 @@ def test__construct_signing_message(f_config_msg_signer_ok):
408436
with patch("uuid.uuid4", return_value="1234-5678-abcd-efgh"):
409437
with patch("pubtools.sign.signers.msgsigner.isodate_now") as patched_date:
410438
patched_date.return_value = "created-date-Z"
411-
ret = signer._construct_signing_message("some-claim", "some-signing-key", "repo", {})
439+
ret = signer._construct_signing_message(
440+
"some-claim", "some-signing-key", "repo", extra_attrs={}, signing_key_name=""
441+
)
442+
assert ret == {
443+
"sig_key_id": "ning-key",
444+
"claim_file": "some-claim",
445+
"request_id": "1234-5678-abcd-efgh",
446+
"created": "created-date-Z",
447+
"requested_by": "pubtools-sign-test",
448+
"repo": "repo",
449+
}
450+
451+
452+
def test__construct_signing_message_signing_key_name(f_config_msg_signer_ok):
453+
signer = MsgSigner()
454+
signer.load_config(load_config(f_config_msg_signer_ok))
455+
with patch("uuid.uuid4", return_value="1234-5678-abcd-efgh"):
456+
with patch("pubtools.sign.signers.msgsigner.isodate_now") as patched_date:
457+
patched_date.return_value = "created-date-Z"
458+
ret = signer._construct_signing_message(
459+
"some-claim",
460+
"some-signing-key",
461+
"repo",
462+
extra_attrs={},
463+
signing_key_name="test-signing-key-name",
464+
)
412465
assert ret == {
413466
"sig_key_id": "ning-key",
467+
"sig_keyname": "test-signing-key-name",
414468
"claim_file": "some-claim",
415469
"request_id": "1234-5678-abcd-efgh",
416470
"created": "created-date-Z",
@@ -595,6 +649,7 @@ def test_clear_sign_aliases(patched_uuid, f_config_msg_signer_aliases):
595649
"repo",
596650
extra_attrs={"pub_task_id": "1"},
597651
sig_type="clearsign_signature",
652+
signing_key_name="",
598653
)
599654

600655
assert res == SigningResults(
@@ -755,6 +810,7 @@ def test_container_sign_alias(patched_uuid, f_config_msg_signer_aliases, f_clien
755810
"abcde1245",
756811
"namespace/repo",
757812
extra_attrs={"pub_task_id": "1", "manifest_digest": "sha256:abcdefg"},
813+
signing_key_name="",
758814
sig_type="container_signature",
759815
)
760816

0 commit comments

Comments
 (0)