Skip to content

Commit 1d13e88

Browse files
DO NOT MERGE - Review comments, will be squashed
1 parent 2ba18d8 commit 1d13e88

File tree

5 files changed

+31
-24
lines changed

5 files changed

+31
-24
lines changed

pkg/cvo/cvo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ func loadConfigMapVerifierDataFromUpdate(update *payload.Update, clientBuilder v
305305
if err != nil {
306306
return nil, nil, errors.Wrapf(err, "%s is not valid: %v", src, err)
307307
}
308-
verifier, err := verify.NewFromConfigMap(src, data, clientBuilder)
308+
verifier, err := verify.NewFromConfigMapData(src, data, clientBuilder)
309309
if err != nil {
310310
return nil, nil, err
311311
}

pkg/verify/configmap.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import (
1414
// ReleaseAnnotationConfigMapVerifier is an annotation set on a config map in the
1515
// release payload to indicate that this config map controls signing for the payload.
1616
// Only the first config map within the payload should be used, regardless of whether
17-
// it has data. See NewFromConfigMap for more.
17+
// it has data. See NewFromConfigMapData for more.
1818
const ReleaseAnnotationConfigMapVerifier = "release.openshift.io/verification-config-map"
1919

20-
// NewFromConfigMap expects to receive the data field of the first config map in the release
20+
// NewFromConfigMapData expects to receive the data field of the first config map in the release
2121
// image payload with the annotation "release.openshift.io/verification-config-map". Only the
2222
// first payload item in lexographic order will be considered - all others are ignored. The
2323
// verifier returned by this method
@@ -46,7 +46,7 @@ const ReleaseAnnotationConfigMapVerifier = "release.openshift.io/verification-co
4646
// The returned verifier will require that any new release image will only be considered verified
4747
// if each provided public key has signed the release image digest. The signature may be in any
4848
// store and the lookup order is internally defined.
49-
func NewFromConfigMap(src string, data map[string]string, clientBuilder ClientBuilder) (*ReleaseVerifier, error) {
49+
func NewFromConfigMapData(src string, data map[string]string, clientBuilder ClientBuilder) (*ReleaseVerifier, error) {
5050
verifiers := make(map[string]openpgp.EntityList)
5151
var stores []*url.URL
5252
for k, v := range data {

pkg/verify/configmap_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func Test_loadReleaseVerifierFromConfigMap(t *testing.T) {
5656
}
5757
for _, tt := range tests {
5858
t.Run(tt.name, func(t *testing.T) {
59-
got, err := NewFromConfigMap("from_test", tt.data, DefaultClient)
59+
got, err := NewFromConfigMapData("from_test", tt.data, DefaultClient)
6060
if (err != nil) != tt.wantErr {
6161
t.Fatalf("loadReleaseVerifierFromPayload() error = %v, wantErr %v", err, tt.wantErr)
6262
return

pkg/verify/verify.go

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
// in this package uses the container signature format defined at https://github.com/containers/image
2828
// to authenticate that a given release image digest has been signed by a trusted party.
2929
type Interface interface {
30+
// Verify should return nil if the provided release digest has suffient signatures to be considered
31+
// valid. It should return an error in all other cases.
3032
Verify(ctx context.Context, releaseDigest string) error
3133
}
3234

@@ -50,8 +52,30 @@ func (rejectVerifier) Verify(ctx context.Context, releaseDigest string) error {
5052
// Reject fails always fails verification.
5153
var Reject Interface = rejectVerifier{}
5254

55+
// ClientBuilder provides a method for generating an HTTP Client configured
56+
// with cluster proxy settings, if they exist.
57+
type ClientBuilder interface {
58+
// HTTPClient returns a client suitable for retrieving signatures. It is not
59+
// required to be unique per call, but may be called concurrently.
60+
HTTPClient() (*http.Client, error)
61+
}
62+
63+
// DefaultClient uses the default http.Client for accessing signatures.
64+
var DefaultClient = simpleClientBuilder{}
65+
66+
// simpleClientBuilder implements the ClientBuilder interface and may be used for testing.
67+
type simpleClientBuilder struct{}
68+
69+
// HTTPClient from simpleClientBuilder creates an http.Client with no configuration.
70+
func (s simpleClientBuilder) HTTPClient() (*http.Client, error) {
71+
return &http.Client{}, nil
72+
}
73+
74+
// maxSignatureSearch prevents unbounded recursion on malicious signature stores (if
75+
// an attacker was able to take ownership of the store to perform DoS on clusters).
5376
const maxSignatureSearch = 10
5477

78+
// validReleaseDigest is a verification rule to filter clearly invalid digests.
5579
var validReleaseDigest = regexp.MustCompile(`^[a-zA-Z0-9:]+$`)
5680

5781
// ReleaseVerifier implements a signature intersection operation on a provided release
@@ -89,26 +113,9 @@ func (v *ReleaseVerifier) WithStores(stores ...SignatureStore) *ReleaseVerifier
89113
}
90114
}
91115

92-
// ClientBuilder provides a method for generating an HTTP Client configured
93-
// with cluster proxy settings, if they exist.
94-
type ClientBuilder interface {
95-
HTTPClient() (*http.Client, error)
96-
}
97-
98-
// DefaultClient uses the default http.Client for accessing signatures.
99-
var DefaultClient = simpleClientBuilder{}
100-
101-
// simpleClientBuilder implements the ClientBuilder interface and may be used for testing.
102-
type simpleClientBuilder struct{}
103-
104-
// HTTPClient from simpleClientBuilder creates an httpClient with no configuration.
105-
func (s simpleClientBuilder) HTTPClient() (*http.Client, error) {
106-
return &http.Client{}, nil
107-
}
108-
109116
// Verifiers returns a copy of the verifiers in this payload.
110117
func (v *ReleaseVerifier) Verifiers() map[string]openpgp.EntityList {
111-
out := make(map[string]openpgp.EntityList)
118+
out := make(map[string]openpgp.EntityList, len(v.verifiers))
112119
for k, v := range v.verifiers {
113120
out[k] = v
114121
}

pkg/verify/verify_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ func Test_ReleaseVerifier_Signatures(t *testing.T) {
348348
if err := verifier.Verify(context.Background(), signedDigest); err != nil {
349349
t.Fatal(err)
350350
}
351-
if sigs := verifier.Signatures(); len(sigs) != 64 || !reflect.DeepEqual(sigs[signedDigest], [][]byte{expectedSignature}) {
351+
if sigs := verifier.Signatures(); len(sigs) != maxSignatureCacheSize || !reflect.DeepEqual(sigs[signedDigest], [][]byte{expectedSignature}) {
352352
t.Fatalf("%d %#v", len(sigs), sigs)
353353
}
354354
}

0 commit comments

Comments
 (0)