github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/rkt/image/filefetcher.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  	"os"
    21  	"path/filepath"
    22  
    23  	"github.com/hashicorp/errwrap"
    24  	"github.com/rkt/rkt/pkg/keystore"
    25  	rktflag "github.com/rkt/rkt/rkt/flag"
    26  	"github.com/rkt/rkt/store/imagestore"
    27  )
    28  
    29  // fileFetcher is used to fetch files from a local filesystem
    30  type fileFetcher struct {
    31  	InsecureFlags *rktflag.SecFlags
    32  	S             *imagestore.Store
    33  	Ks            *keystore.Keystore
    34  	Debug         bool
    35  }
    36  
    37  // Hash opens a file, optionally verifies it against passed asc,
    38  // stores it in the store and returns the hash.
    39  func (f *fileFetcher) Hash(aciPath string, a *asc) (string, error) {
    40  	ensureLogger(f.Debug)
    41  	absPath, err := filepath.Abs(aciPath)
    42  	if err != nil {
    43  		return "", errwrap.Wrap(fmt.Errorf("failed to get an absolute path for %q", aciPath), err)
    44  	}
    45  	aciPath = absPath
    46  
    47  	aciFile, err := f.getFile(aciPath, a)
    48  	if err != nil {
    49  		return "", err
    50  	}
    51  	defer aciFile.Close()
    52  
    53  	key, err := f.S.WriteACI(aciFile, imagestore.ACIFetchInfo{
    54  		Latest: false,
    55  	})
    56  	if err != nil {
    57  		return "", err
    58  	}
    59  
    60  	return key, nil
    61  }
    62  
    63  func (f *fileFetcher) getFile(aciPath string, a *asc) (*os.File, error) {
    64  	if f.InsecureFlags.SkipImageCheck() && f.Ks != nil {
    65  		log.Printf("warning: image signature verification has been disabled")
    66  	}
    67  	if f.InsecureFlags.SkipImageCheck() || f.Ks == nil {
    68  		aciFile, err := os.Open(aciPath)
    69  		if err != nil {
    70  			return nil, errwrap.Wrap(errors.New("error opening ACI file"), err)
    71  		}
    72  		return aciFile, nil
    73  	}
    74  	aciFile, err := f.getVerifiedFile(aciPath, a)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	return aciFile, nil
    79  }
    80  
    81  // fetch opens and verifies the ACI.
    82  func (f *fileFetcher) getVerifiedFile(aciPath string, a *asc) (*os.File, error) {
    83  	var aciFile *os.File // closed on error
    84  	var errClose error   // error signaling to close aciFile
    85  
    86  	f.maybeOverrideAsc(aciPath, a)
    87  	ascFile, err := a.Get()
    88  	if err != nil {
    89  		return nil, errwrap.Wrap(errors.New("error opening signature file"), err)
    90  	}
    91  	defer ascFile.Close()
    92  
    93  	aciFile, err = os.Open(aciPath)
    94  	if err != nil {
    95  		return nil, errwrap.Wrap(errors.New("error opening ACI file"), err)
    96  	}
    97  
    98  	defer func() {
    99  		if errClose != nil {
   100  			aciFile.Close()
   101  		}
   102  	}()
   103  
   104  	validator, errClose := newValidator(aciFile)
   105  	if errClose != nil {
   106  		return nil, errClose
   107  	}
   108  
   109  	entity, errClose := validator.ValidateWithSignature(f.Ks, ascFile)
   110  	if errClose != nil {
   111  		return nil, errwrap.Wrap(fmt.Errorf("image %q verification failed", validator.ImageName()), errClose)
   112  	}
   113  	printIdentities(entity)
   114  
   115  	return aciFile, nil
   116  }
   117  
   118  func (f *fileFetcher) maybeOverrideAsc(aciPath string, a *asc) {
   119  	if a.Fetcher != nil {
   120  		return
   121  	}
   122  	a.Location = ascPathFromImgPath(aciPath)
   123  	a.Fetcher = &localAscFetcher{}
   124  }