diff --git a/src/backend/BSConSign.pm b/src/backend/BSConSign.pm index cb3b7eeac11..edf447317cf 100644 --- a/src/backend/BSConSign.pm +++ b/src/backend/BSConSign.pm @@ -31,6 +31,8 @@ use Digest::SHA (); use MIME::Base64 (); use IO::Compress::RawDeflate; +our $mt_cosign = 'application/vnd.dev.cosign.simplesigning.v1+json'; + sub canonical_json { return JSON::XS->new->utf8->canonical->encode($_[0]); } @@ -83,7 +85,7 @@ sub sig2openshift { } sub createcosign { - my ($signfunc, $digest, $reference, $creator, $timestamp) = @_; + my ($signfunc, $digest, $reference, $creator, $timestamp, $annotations) = @_; my $payload = createpayload('cosign container image signature', $digest, $reference, $creator, $timestamp); my $payload_digest = 'sha256:'.Digest::SHA::sha256_hex($payload); # signfunc must return the openssl rsa signature @@ -98,12 +100,12 @@ sub createcosign { }; my $config_json = canonical_json($config); my $payload_layer = { - 'annotations' => { 'dev.cosignproject.cosign/signature' => $sig }, + 'annotations' => { 'dev.cosignproject.cosign/signature' => $sig, %{$annotations || {}} }, 'digest' => $payload_digest, - 'mediaType' => 'application/vnd.dev.cosign.simplesigning.v1+json', + 'mediaType' => $mt_cosign, 'size' => length($payload), }; - return ($config_json, $payload_layer, $payload); + return ($config_json, $payload_layer, $payload, $sig); } 1; diff --git a/src/backend/BSPublisher/Registry.pm b/src/backend/BSPublisher/Registry.pm index ea6238726e6..7469b83d516 100644 --- a/src/backend/BSPublisher/Registry.pm +++ b/src/backend/BSPublisher/Registry.pm @@ -141,14 +141,14 @@ sub push_blob { return $blobid; } -sub push_blob_string { - my ($repodir, $blobdata) = @_; - my $blob_id = 'sha256:'.Digest::SHA::sha256_hex($blobdata); +sub push_blob_content { + my ($repodir, $content) = @_; + my $blob_id = 'sha256:'.Digest::SHA::sha256_hex($content); my $dir = "$repodir/:blobs"; return $blob_id if -e "$dir/$blob_id"; mkdir_p($dir) unless -d $dir; unlink("$dir/.$blob_id.$$"); - writestr("$dir/.$blob_id.$$", "$dir/$blob_id", $blobdata); + writestr("$dir/.$blob_id.$$", "$dir/$blob_id", $content); return $blob_id; } @@ -432,7 +432,7 @@ sub update_sigs { } sub update_cosign { - my ($prp, $repo, $gun, $imagedigests, $pubkey, $signargs, $oci, $knownmanifests, $knownblobs) = @_; + my ($prp, $repo, $gun, $digests_to_cosign, $pubkey, $signargs, $knownmanifests, $knownblobs) = @_; my $creator = 'OBS'; my ($projid, $repoid) = split('/', $prp, 2); @@ -443,14 +443,15 @@ sub update_cosign { my $signfunc = sub { BSUtil::xsystem($_[0], @signcmd, '-O', '-h', 'sha256') }; my $repodir = "$registrydir/$repo"; my $oldsigs = BSUtil::retrieve("$repodir/:cosign", 1) || {}; - return if !%$oldsigs && !%$imagedigests; + return if !%$oldsigs && !%$digests_to_cosign; my $gpgpubkey = BSPGP::unarmor($pubkey); my $pubkey_fp = BSPGP::pk2fingerprint($gpgpubkey); if (($oldsigs->{'pubkey'} || '') ne $pubkey_fp || ($oldsigs->{'gun'} || '') ne $gun || ($oldsigs->{'creator'} || '') ne ($creator || '')) { $oldsigs = {}; # fingerprint/gun/creator mismatch, do not use old signatures } my $sigs = { 'pubkey' => $pubkey_fp, 'gun' => $gun, 'creator' => $creator, 'digests' => {} }; - for my $digest (sort keys %$imagedigests) { + for my $digest (sort keys %$digests_to_cosign) { + my $oci = $digests_to_cosign->{$digest}; my $old = ($oldsigs->{'digests'} || {})->{$digest}; if ($old) { $sigs->{'digests'}->{$digest} = $old; @@ -458,12 +459,12 @@ sub update_cosign { } print "creating cosign signature for $gun $digest\n"; my ($config, $payload_layer, $payload) = BSConSign::createcosign($signfunc, $digest, $gun, $creator); - my $config_blobid = push_blob_string($repodir, $config); + my $config_blobid = push_blob_content($repodir, $config); $knownblobs->{$config_blobid} = 1; - my $payload_blobid = push_blob_string($repodir, $payload); + my $payload_blobid = push_blob_content($repodir, $payload); $knownblobs->{$payload_blobid} = 1; die unless $payload_blobid eq $payload_layer->{'digest'}; - my $config_data = { + my $config_data = { 'mediaType' => $oci ? $BSContar::mt_oci_config : $BSContar::mt_docker_config, 'size' => length($config), 'digest' => $config_blobid, @@ -511,6 +512,7 @@ sub push_containers { my %knownmanifests; my %knowntags; my %knownimagedigests; + my %digests_to_cosign; my %info; @@ -627,6 +629,7 @@ sub push_containers { my $mani_json = BSContar::create_dist_manifest($mani); my $mani_id = push_manifest($repodir, $mani_json); $knownmanifests{$mani_id} = 1; + $digests_to_cosign{$mani_id} = $oci; my $multimani = { 'mediaType' => $mediaType, @@ -680,6 +683,7 @@ sub push_containers { $mani_size = length($mani_json); $knownmanifests{$mani_id} = 1; $taginfo->{'distmanifesttype'} = 'list'; + $digests_to_cosign{$mani_id} = $oci; } else { $mani_id = $multimanifests[0]->{'digest'}; $mani_size = $multimanifests[0]->{'size'}; @@ -692,9 +696,9 @@ sub push_containers { $info{$tag} = $taginfo; } - # write signatures file - if ($gun && %knownimagedigests) { - update_cosign($prp, $repo, $gun, \%knownimagedigests, $pubkey, $signargs, 0, \%knownmanifests, \%knownblobs); + # write signatures file (need to do this early as it adds manifests/blobs) + if ($gun && %digests_to_cosign) { + update_cosign($prp, $repo, $gun, \%digests_to_cosign, $pubkey, $signargs, \%knownmanifests, \%knownblobs); } elsif (-e "$repodir/:cosign") { unlink("$repodir/:cosign"); }