Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support cosign rsa keys #416

Merged
merged 2 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ install:
helm install connaisseur helm --atomic --create-namespace --namespace $(NAMESPACE)

dev-install:
helm install --set kubernetes.deployment.replicasCount=1,kubernetes.deployment.imagePullPolicy=Never connaisseur helm --atomic --create-namespace --namespace $(NAMESPACE)
helm install --set kubernetes.deployment.replicasCount=1,kubernetes.deployment.imagePullPolicy=Never,application.logLevel=DEBUG connaisseur helm --atomic --create-namespace --namespace $(NAMESPACE)
phbelitz marked this conversation as resolved.
Show resolved Hide resolved

uninstall:
helm uninstall connaisseur -n $(NAMESPACE)
Expand Down
6 changes: 6 additions & 0 deletions connaisseur/trust_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,17 @@ class ECDSAKey(TrustRootInterface):
def __str__(self) -> str:
return base64.b64encode(self.value.to_der()).decode("utf-8")

def pem(self):
return self.value.to_pem()


class RSAKey(TrustRootInterface):
def __str__(self) -> str:
return base64.b64encode(self.value.save_pkcs1("DER")).decode("utf-8")

def pem(self):
return self.value.save_pkcs1("PEM")


class KMSKey(TrustRootInterface):
pass
Expand Down
12 changes: 8 additions & 4 deletions connaisseur/validators/cosign/cosign_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
WrongKeyError,
)
from connaisseur.image import Image
from connaisseur.trust_root import ECDSAKey, KMSKey, TrustRoot
from connaisseur.trust_root import ECDSAKey, KMSKey, RSAKey, TrustRoot
from connaisseur.util import safe_path_func # nosec
from connaisseur.validators.interface import ValidatorInterface

Expand Down Expand Up @@ -213,7 +213,11 @@ async def __get_cosign_validated_digests(self, image: str, values: dict):
image=str(image),
trust_root=values["name"],
)
elif "Error: no matching signatures:\n\nmain.go:" in stderr:
elif (
"Error: no matching signatures:\n\nmain.go:" in stderr
or "Error: no matching signatures:\ncrypto/rsa: verification error"
in stderr
):
msg = 'No trust data for image "{image}".'
raise NotFoundException(
message=msg,
Expand Down Expand Up @@ -269,13 +273,13 @@ async def __validate_using_trust_root(
# reminder when implementing Keyless validation:
# ["--cert-email", self.value, b""]

if isinstance(trust_root, ECDSAKey):
if isinstance(trust_root, (ECDSAKey, RSAKey)):
return await self.__invoke_cosign(
image,
{
"option_kword": "--key",
"inline_tr": "/dev/stdin",
"trust_root": trust_root.value.to_pem(),
"trust_root": trust_root.pem(),
},
verify_tlog,
)
Expand Down
2 changes: 1 addition & 1 deletion docs/validators/sigstore_cosign.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ kubectl run altsigned --image=docker.io/securesystemsengineering/testimage:co-si
| `name` | - | :heavy_check_mark: | See [basics](../basics.md#validators). |
| `type` | - | :heavy_check_mark: | `cosign`; the validator type must be set to `cosign`. |
| `trustRoots[*].name` | - | :heavy_check_mark: | See [basics](../basics.md#validators). |
| `trustRoots[*].key` | - | :heavy_check_mark: | See [basics](../basics.md#validators). ECDSA public key from `cosign.pub` file or [KMS URI](https://github.com/sigstore/cosign/blob/main/KMS.md). See additional notes [below](#kms-support). |
| `trustRoots[*].key` | - | :heavy_check_mark: | See [basics](../basics.md#validators). ECDSA/RSA public key from `cosign.pub` file or [KMS URI](https://github.com/sigstore/cosign/blob/main/KMS.md). See additional notes [below](#kms-support). |
| `host.rekor` | `rekor.sigstore.dev` | - | Rekor URL to use for validation against the transparency log (default sigstore instance is `rekor.sigstore.dev`). Setting `host` enforces successful transparency log check to pass verification. See additional notes [below](#transparency-log-verification). |
| `auth.` | - | - | Authentication credentials for registries with restricted access (e.g. private registries or ratelimiting). See additional notes [below](#authentication). |
| `auth.secretName` | - | - | Name of a Kubernetes secret in Connaisseur namespace that contains [dockerconfigjson](https://kubernetes.io/docs/concepts/configuration/secret/#docker-config-secrets) for registry authentication. See additional notes [below](#dockerconfigjson). |
Expand Down
7 changes: 7 additions & 0 deletions tests/integration/cases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ test_cases:
txt: Testing signed cosign image with tag and digest...
type: deploy
ref: securesystemsengineering/testimage:co-signed@sha256:c5327b291d702719a26c6cf8cc93f72e7902df46547106a9930feda2c002a4a7
- id: crsa
txt: Testing signed cosign image, signed with RSA key
type: deploy
ref: securesystemsengineering/testimage:rsa-co-signed
namespace: default
expected_msg: pod/pod-crsa-${RAND} created
expected_result: null
multi-cosigned:
- id: mc-u
txt: Testing multi-cosigned image `threshold` => undefined, not reached...
Expand Down
18 changes: 18 additions & 0 deletions tests/integration/update.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ application:
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqxgd/RqCdPnafQmlmX71eICGRBqu
USHEjAv3FZCROHLYts11xR6Peu8ZEvMXOR46L7+z84DRFK6gnTInbIGFmg==
-----END PUBLIC KEY-----
- name: rsa
type: cosign
trustRoots:
- name: default
key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxmEXG8savZ/Q8IJB8dBT
YCKV/ECwkj8zBInilrWSipsKiBwGTugAgKHj7Nvo6pg91DTESpfnryL+UUwAyJ1C
irdUThCZa90vC9SlwYUhC/ftz/dwU8KaiVcWJHCbj4VLLCD7xVKPh65j4x65D8bL
ohbrpZFfboXgG/gJHYhU18q0nmGzuQyGWSxAYcsh8qVcaNa68TvZLqecq/AYvspI
qNIGWekU1BYXoUVt6kBx/fwEKtxESRbgsT1R8ha+q1HTGLMtj71LfWfX9d1bbNeq
2+pXRO8Ut8km2lGEekRNXYb2C+sOX7uA1MSv+gm2JCoVzep69fGTHbqOwf4tm2Qh
AwIDAQAB
-----END PUBLIC KEY-----
policy:
- pattern: "*:*"
validator: dockerhub-basics
Expand Down Expand Up @@ -116,6 +130,10 @@ application:
with:
trustRoot: securesystemsengineering-official
delegations: ["belitzphilipp", "starkteetje"]
- pattern: "docker.io/securesystemsengineering/testimage:rsa-*"
validator: rsa
with:
verifyInTransparencyLog: false
features:
detectionMode: false
automaticChildApproval: true
18 changes: 18 additions & 0 deletions tests/test_trust_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

sample_ecdsa2 = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEi2WD/E/UXF4+yoE5e4cjpJMNgQw\n8PAVALRX+8f8I8B+XneAtnOHDTI8L6wBeFRTzl6G4OmgDyCRYTb5MV3hog==\n-----END PUBLIC KEY-----"

ecdsa_bytes = b"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOXYta5TgdCwXTCnLU09W5T4M4r9f\nQQrqJuADP6U7g5r9ICgPSmZuRHP/1AYUfOQW3baveKsT969EfELKj1lfCA==\n-----END PUBLIC KEY-----\n"
# Due to the sample being PKCS#8 (general public key crypto) encoded and the library exporting PKCS#1 (RSA only) encoded keys
rsa_bytes = b"-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAs5pC7R5OTSTUMJHUniPkrLfmGDAUxZtRlvIE+pGPCD6cUXH22adv\nkK87xwpupjxdVYuKTFnWHUIyFJwjI3vusievezcAr0E/xxyeo49tWog9kFoooK3q\nmXjpETC8OpvNROZ0K3qhlm9PZkGo3gSJ/B4rMU/d+jkCI8eiUPpdVQOczdBoD5nz\nQAF1mfmffWGsbKY+d8/l77Vset0GXExRzUtnglMhREyHNpDeQUg5OEn+kuGLlTzI\nxpIF+MlbzP3+xmNEzH2iafr0ae2g5kX2880priXpxG8GXW2ybZmPvchclnvFu4Zf\nZcM10FpgYJFvR/9iofFeAka9u5z6VZccmQIDAQAB\n-----END RSA PUBLIC KEY-----\n"


def cb(image, key_args):
return key_args[:2]
Expand Down Expand Up @@ -82,3 +86,17 @@ def test_keys(data, class_, exception):
def test_str(key, out):
k = trust_root.TrustRoot(key)
assert str(k) == out


@pytest.mark.parametrize(
"key, out, exception",
[
(sample_ecdsa, ecdsa_bytes, fix.no_exc()),
(sample_rsa, rsa_bytes, fix.no_exc()),
(sample_mail, b"", pytest.raises(AttributeError)),
],
)
def test_pem(key, out, exception):
k = trust_root.TrustRoot(key)
with exception:
assert k.pem() == out
Loading