github.com/minio/madmin-go@v1.7.5/inspect.go (about)

     1  //
     2  // MinIO Object Storage (c) 2021 MinIO, Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //      http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package madmin
    18  
    19  import (
    20  	"bufio"
    21  	"context"
    22  	"encoding/base64"
    23  	"errors"
    24  	"fmt"
    25  	"io"
    26  	"net/http"
    27  	"net/url"
    28  )
    29  
    30  // InspectOptions provides options to Inspect.
    31  type InspectOptions struct {
    32  	Volume, File string
    33  	PublicKey    []byte // PublicKey to use for inspected data.
    34  }
    35  
    36  // Inspect makes an admin call to download a raw files from disk.
    37  // If inspect is called with a public key no key will be returned
    38  // and the data is returned encrypted with the public key.
    39  func (adm *AdminClient) Inspect(ctx context.Context, d InspectOptions) (key []byte, c io.ReadCloser, err error) {
    40  	// Add form key/values in the body
    41  	form := make(url.Values)
    42  	form.Set("volume", d.Volume)
    43  	form.Set("file", d.File)
    44  	if d.PublicKey != nil {
    45  		form.Set("public-key", base64.StdEncoding.EncodeToString(d.PublicKey))
    46  	}
    47  
    48  	method := ""
    49  	reqData := requestData{
    50  		relPath: fmt.Sprintf(adminAPIPrefix + "/inspect-data"),
    51  	}
    52  
    53  	// If the public-key is specified, create a POST request and send
    54  	// parameters as multipart-form instead of query values
    55  	if d.PublicKey != nil {
    56  		method = http.MethodPost
    57  		reqData.customHeaders = make(http.Header)
    58  		reqData.customHeaders.Set("Content-Type", "application/x-www-form-urlencoded")
    59  		reqData.content = []byte(form.Encode())
    60  	} else {
    61  		method = http.MethodGet
    62  		reqData.queryValues = form
    63  	}
    64  
    65  	resp, err := adm.executeMethod(ctx, method, reqData)
    66  	if err != nil {
    67  		return nil, nil, err
    68  	}
    69  
    70  	if resp.StatusCode != http.StatusOK {
    71  		closeResponse(resp)
    72  		return nil, nil, httpRespToErrorResponse(resp)
    73  	}
    74  
    75  	bior := bufio.NewReaderSize(resp.Body, 4<<10)
    76  	format, err := bior.ReadByte()
    77  	if err != nil {
    78  		closeResponse(resp)
    79  		return nil, nil, err
    80  	}
    81  
    82  	switch format {
    83  	case 1:
    84  		key = make([]byte, 32)
    85  		// Read key...
    86  		_, err = io.ReadFull(bior, key[:])
    87  		if err != nil {
    88  			closeResponse(resp)
    89  			return nil, nil, err
    90  		}
    91  	case 2:
    92  		if err := bior.UnreadByte(); err != nil {
    93  			return nil, nil, err
    94  		}
    95  	default:
    96  		closeResponse(resp)
    97  		return nil, nil, errors.New("unknown data version")
    98  	}
    99  
   100  	// Return body
   101  	return key, &closeWrapper{Reader: bior, Closer: resp.Body}, nil
   102  }
   103  
   104  type closeWrapper struct {
   105  	io.Reader
   106  	io.Closer
   107  }