github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/rkt/image/validator.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package image 16 17 import ( 18 "errors" 19 "fmt" 20 "io" 21 22 "github.com/hashicorp/errwrap" 23 "github.com/rkt/rkt/pkg/keystore" 24 25 "github.com/appc/spec/aci" 26 "github.com/appc/spec/schema" 27 "github.com/appc/spec/schema/types" 28 "golang.org/x/crypto/openpgp" 29 pgperrors "golang.org/x/crypto/openpgp/errors" 30 ) 31 32 // validator is a general image checker 33 type validator struct { 34 image io.ReadSeeker 35 manifest *schema.ImageManifest 36 } 37 38 // newValidator returns a validator instance if passed image is indeed 39 // an ACI. 40 func newValidator(image io.ReadSeeker) (*validator, error) { 41 manifest, err := aci.ManifestFromImage(image) 42 if err != nil { 43 return nil, err 44 } 45 v := &validator{ 46 image: image, 47 manifest: manifest, 48 } 49 return v, nil 50 } 51 52 // ImageName returns image name as it is in the image manifest. 53 func (v *validator) ImageName() string { 54 return v.manifest.Name.String() 55 } 56 57 // ValidateName checks if desired image name is actually the same as 58 // the one in the image manifest. 59 func (v *validator) ValidateName(imageName string) error { 60 name := v.ImageName() 61 if name != imageName { 62 return fmt.Errorf("error when reading the app name: %q expected but %q found", 63 imageName, name) 64 } 65 return nil 66 } 67 68 // ValidateLabels checks if desired image labels are actually the same as 69 // the ones in the image manifest. 70 func (v *validator) ValidateLabels(labels map[types.ACIdentifier]string) error { 71 for n, rv := range labels { 72 if av, ok := v.manifest.GetLabel(n.String()); ok { 73 if rv != av { 74 return fmt.Errorf("requested value for label %q: %q differs from fetched aci label value: %q", n, rv, av) 75 } 76 } else { 77 return fmt.Errorf("requested label %q not provided by the image manifest", n) 78 } 79 } 80 return nil 81 } 82 83 // ValidateWithSignature verifies the image against a given signature 84 // file. 85 func (v *validator) ValidateWithSignature(ks *keystore.Keystore, sig io.ReadSeeker) (*openpgp.Entity, error) { 86 if ks == nil { 87 return nil, nil 88 } 89 if _, err := v.image.Seek(0, 0); err != nil { 90 return nil, errwrap.Wrap(errors.New("error seeking ACI file"), err) 91 } 92 if _, err := sig.Seek(0, 0); err != nil { 93 return nil, errwrap.Wrap(errors.New("error seeking signature file"), err) 94 } 95 entity, err := ks.CheckSignature(v.ImageName(), v.image, sig) 96 if err == pgperrors.ErrUnknownIssuer { 97 log.Print("If you expected the signing key to change, try running:") 98 log.Print(" rkt trust --prefix <image>") 99 } 100 if err != nil { 101 return nil, err 102 } 103 return entity, nil 104 }