gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/types/asset.go (about) 1 // Copyright (c) 2017 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package types 7 8 import ( 9 "crypto/sha512" 10 "encoding/hex" 11 "fmt" 12 "io/ioutil" 13 "path/filepath" 14 15 "github.com/kata-containers/runtime/virtcontainers/pkg/annotations" 16 ) 17 18 // AssetType describe a type of assets. 19 type AssetType string 20 21 // Annotations returns the path and hash annotations for a given Asset type. 22 func (t AssetType) Annotations() (string, string, error) { 23 switch t { 24 case KernelAsset: 25 return annotations.KernelPath, annotations.KernelHash, nil 26 case ImageAsset: 27 return annotations.ImagePath, annotations.ImageHash, nil 28 case InitrdAsset: 29 return annotations.InitrdPath, annotations.InitrdHash, nil 30 case HypervisorAsset: 31 return annotations.HypervisorPath, annotations.HypervisorHash, nil 32 case JailerAsset: 33 return annotations.JailerPath, annotations.JailerHash, nil 34 case FirmwareAsset: 35 return annotations.FirmwarePath, annotations.FirmwareHash, nil 36 } 37 38 return "", "", fmt.Errorf("Wrong asset type %s", t) 39 } 40 41 const ( 42 // KernelAsset is a kernel asset. 43 KernelAsset AssetType = "kernel" 44 45 // ImageAsset is an image asset. 46 ImageAsset AssetType = "image" 47 48 // InitrdAsset is an intird asset. 49 InitrdAsset AssetType = "initrd" 50 51 // HypervisorAsset is an hypervisor asset. 52 HypervisorAsset AssetType = "hypervisor" 53 54 // HypervisorCtlAsset is an hypervisor control asset. 55 HypervisorCtlAsset AssetType = "hypervisorctl" 56 // JailerAsset is an jailer asset. 57 JailerAsset AssetType = "jailer" 58 59 // FirmwareAsset is a firmware asset. 60 FirmwareAsset AssetType = "firmware" 61 ) 62 63 // Asset represents a virtcontainers asset. 64 type Asset struct { 65 path string 66 computedHash string 67 kind AssetType 68 } 69 70 // Path returns an asset path. 71 func (a Asset) Path() string { 72 return a.path 73 } 74 75 // Type returns an asset type. 76 func (a Asset) Type() AssetType { 77 return a.kind 78 } 79 80 // Valid checks if an asset is valid or not. 81 func (a *Asset) Valid() bool { 82 if !filepath.IsAbs(a.path) { 83 return false 84 } 85 86 switch a.kind { 87 case KernelAsset: 88 return true 89 case ImageAsset: 90 return true 91 case InitrdAsset: 92 return true 93 case HypervisorAsset: 94 return true 95 case JailerAsset: 96 return true 97 case FirmwareAsset: 98 return true 99 } 100 101 return false 102 } 103 104 // Hash returns the hex encoded string for the asset hash 105 func (a *Asset) Hash(hashType string) (string, error) { 106 var hashEncodedLen int 107 var hash string 108 109 // We read the actual asset content 110 bytes, err := ioutil.ReadFile(a.path) 111 if err != nil { 112 return "", err 113 } 114 115 if len(bytes) == 0 { 116 return "", fmt.Errorf("Empty asset file at %s", a.path) 117 } 118 119 // Build the asset hash and convert it to a string. 120 // We only support SHA512 for now. 121 switch hashType { 122 case annotations.SHA512: 123 hashComputed := sha512.Sum512(bytes) 124 hashEncodedLen = hex.EncodedLen(len(hashComputed)) 125 hashEncoded := make([]byte, hashEncodedLen) 126 hex.Encode(hashEncoded, hashComputed[:]) 127 hash = string(hashEncoded[:]) 128 default: 129 return "", fmt.Errorf("Invalid hash type %s", hashType) 130 } 131 132 a.computedHash = hash 133 134 return hash, nil 135 } 136 137 // NewAsset returns a new asset from a slice of annotations. 138 func NewAsset(anno map[string]string, t AssetType) (*Asset, error) { 139 pathAnnotation, hashAnnotation, err := t.Annotations() 140 if err != nil { 141 return nil, err 142 } 143 144 if pathAnnotation == "" || hashAnnotation == "" { 145 return nil, fmt.Errorf("Missing annotation paths for %s", t) 146 } 147 148 path, ok := anno[pathAnnotation] 149 if !ok || path == "" { 150 return nil, nil 151 } 152 153 if !filepath.IsAbs(path) { 154 return nil, fmt.Errorf("%s is not an absolute path", path) 155 } 156 157 a := &Asset{path: path, kind: t} 158 159 hash, ok := anno[hashAnnotation] 160 if !ok || hash == "" { 161 return a, nil 162 } 163 164 // We have a hash annotation, we need to verify the asset against it. 165 hashType, ok := anno[annotations.AssetHashType] 166 if !ok { 167 hashType = annotations.SHA512 168 } 169 170 hashComputed, err := a.Hash(hashType) 171 if err != nil { 172 return a, err 173 } 174 175 // If our computed asset hash does not match the passed annotation, we must exit. 176 if hashComputed != hash { 177 return nil, fmt.Errorf("Invalid hash for %s: computed %s, expecting %s]", a.path, hashComputed, hash) 178 } 179 180 return a, nil 181 }