@@ -121,10 +121,8 @@ func (di *DefaultPromoterImplementation) SignImages(
121121 // used at all and images would be signed with a wrong identity.
122122 di .signer = sign .New (signOpts )
123123
124- // We only sign the first image of each edge. If there are more
125- // than one destination registries for an image, we copy the
126- // signature to avoid varying valid signatures in each registry.
127- sortedEdges := map [image.Digest ][]reg.PromotionEdge {}
124+ // We only sign the first normalized image of each edge.
125+ sortedEdges := map [string ][]reg.PromotionEdge {}
128126 for edge := range edges {
129127 // Skip signing the signature, sbom and attestation layers
130128 if strings .HasSuffix (string (edge .DstImageTag .Tag ), ".sig" ) ||
@@ -133,18 +131,19 @@ func (di *DefaultPromoterImplementation) SignImages(
133131 continue
134132 }
135133
136- if _ , ok := sortedEdges [edge .Digest ]; ! ok {
137- sortedEdges [edge .Digest ] = []reg.PromotionEdge {}
134+ identity := targetIdentity (& edge )
135+ if _ , ok := sortedEdges [identity ]; ! ok {
136+ sortedEdges [identity ] = []reg.PromotionEdge {}
138137 }
139- sortedEdges [edge . Digest ] = append (sortedEdges [edge . Digest ], edge )
138+ sortedEdges [identity ] = append (sortedEdges [identity ], edge )
140139 }
141140
142141 t := throttler .New (opts .MaxSignatureOps , len (sortedEdges ))
143142 // Sign the required edges
144143 for d := range sortedEdges {
145144 d := d
146- go func (digest image. Digest ) {
147- t .Done (di .signAndReplicate (signOpts , sortedEdges [digest ]))
145+ go func (identity string ) {
146+ t .Done (di .signAndReplicate (signOpts , identity , sortedEdges [identity ]))
148147 }(d )
149148 if t .Throttle () > 0 {
150149 break
@@ -154,16 +153,17 @@ func (di *DefaultPromoterImplementation) SignImages(
154153 return t .Err ()
155154}
156155
157- func (di * DefaultPromoterImplementation ) signAndReplicate (signOpts * sign.Options , edges []reg.PromotionEdge ) error {
156+ func (di * DefaultPromoterImplementation ) signAndReplicate (signOpts * sign.Options , identity string , edges []reg.PromotionEdge ) error {
158157 // Build the reference we will use
159- edge := & edges [0 ]
160- imageRef := edge .DstReference ()
158+ firstEdge := & edges [0 ]
159+ imageRef := firstEdge .DstReference ()
161160
162161 // Make a shallow copy so we can safely modify the options per go routine
163162 signOptsCopy := * signOpts
164163
165164 // Update the production container identity (".critical.identity.docker-reference")
166- signOptsCopy .SignContainerIdentity = targetIdentity (edge )
165+ signOptsCopy .SignContainerIdentity = identity
166+ logrus .Infof ("Using new production registry reference for %s: %v" , imageRef , identity )
167167
168168 // Add an annotation recording the kpromo version to ensure we
169169 // get a 2nd signature, otherwise cosign will not resign a signed image:
@@ -174,7 +174,7 @@ func (di *DefaultPromoterImplementation) signAndReplicate(signOpts *sign.Options
174174 logrus .Infof ("Signing image %s" , imageRef )
175175
176176 // Carry over existing signatures from the staging repo
177- if err := di .copyAttachedObjects (& edges [ 0 ] ); err != nil {
177+ if err := di .copyAttachedObjects (firstEdge ); err != nil {
178178 return fmt .Errorf ("copying staging signatures: %w" , err )
179179 }
180180
@@ -193,7 +193,7 @@ func (di *DefaultPromoterImplementation) signAndReplicate(signOpts *sign.Options
193193 }
194194
195195 if err := di .replicateSignatures (
196- & edges [ 0 ] , edges [1 :],
196+ firstEdge , edges [1 :],
197197 ); err != nil {
198198 return fmt .Errorf ("replicating signatures: %w" , err )
199199 }
@@ -221,7 +221,6 @@ func targetIdentity(edge *reg.PromotionEdge) string {
221221
222222 idx := strings .Index (identity , productionRepositoryPath ) + len (productionRepositoryPath )
223223 newRef := consts .ProdRegistry + identity [idx :]
224- logrus .Infof ("Using new production registry reference for image signature: %v" , newRef )
225224
226225 return newRef
227226}
0 commit comments