github.com/minio/madmin-go/v2@v2.2.1/inspect.go (about) 1 // 2 // Copyright (c) 2015-2022 MinIO, Inc. 3 // 4 // This file is part of MinIO Object Storage stack 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU Affero General Public License as 8 // published by the Free Software Foundation, either version 3 of the 9 // License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU Affero General Public License for more details. 15 // 16 // You should have received a copy of the GNU Affero General Public License 17 // along with this program. If not, see <http://www.gnu.org/licenses/>. 18 // 19 20 package madmin 21 22 import ( 23 "bufio" 24 "context" 25 "encoding/base64" 26 "errors" 27 "fmt" 28 "io" 29 "net/http" 30 "net/url" 31 ) 32 33 // InspectOptions provides options to Inspect. 34 type InspectOptions struct { 35 Volume, File string 36 PublicKey []byte // PublicKey to use for inspected data. 37 } 38 39 // Inspect makes an admin call to download a raw files from disk. 40 // If inspect is called with a public key no key will be returned 41 // and the data is returned encrypted with the public key. 42 func (adm *AdminClient) Inspect(ctx context.Context, d InspectOptions) (key []byte, c io.ReadCloser, err error) { 43 // Add form key/values in the body 44 form := make(url.Values) 45 form.Set("volume", d.Volume) 46 form.Set("file", d.File) 47 if d.PublicKey != nil { 48 form.Set("public-key", base64.StdEncoding.EncodeToString(d.PublicKey)) 49 } 50 51 method := "" 52 reqData := requestData{ 53 relPath: fmt.Sprintf(adminAPIPrefix + "/inspect-data"), 54 } 55 56 // If the public-key is specified, create a POST request and send 57 // parameters as multipart-form instead of query values 58 if d.PublicKey != nil { 59 method = http.MethodPost 60 reqData.customHeaders = make(http.Header) 61 reqData.customHeaders.Set("Content-Type", "application/x-www-form-urlencoded") 62 reqData.content = []byte(form.Encode()) 63 } else { 64 method = http.MethodGet 65 reqData.queryValues = form 66 } 67 68 resp, err := adm.executeMethod(ctx, method, reqData) 69 if err != nil { 70 return nil, nil, err 71 } 72 73 if resp.StatusCode != http.StatusOK { 74 closeResponse(resp) 75 return nil, nil, httpRespToErrorResponse(resp) 76 } 77 78 bior := bufio.NewReaderSize(resp.Body, 4<<10) 79 format, err := bior.ReadByte() 80 if err != nil { 81 closeResponse(resp) 82 return nil, nil, err 83 } 84 85 switch format { 86 case 1: 87 key = make([]byte, 32) 88 // Read key... 89 _, err = io.ReadFull(bior, key[:]) 90 if err != nil { 91 closeResponse(resp) 92 return nil, nil, err 93 } 94 case 2: 95 if err := bior.UnreadByte(); err != nil { 96 return nil, nil, err 97 } 98 default: 99 closeResponse(resp) 100 return nil, nil, errors.New("unknown data version") 101 } 102 103 // Return body 104 return key, &closeWrapper{Reader: bior, Closer: resp.Body}, nil 105 } 106 107 type closeWrapper struct { 108 io.Reader 109 io.Closer 110 }