github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/oracleobjectstorage/byok.go (about)

     1  //go:build !plan9 && !solaris && !js
     2  
     3  package oracleobjectstorage
     4  
     5  import (
     6  	"crypto/sha256"
     7  	"encoding/base64"
     8  	"errors"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/oracle/oci-go-sdk/v65/common"
    14  	"github.com/oracle/oci-go-sdk/v65/objectstorage"
    15  )
    16  
    17  const (
    18  	sseDefaultAlgorithm = "AES256"
    19  )
    20  
    21  func getSha256(p []byte) []byte {
    22  	h := sha256.New()
    23  	h.Write(p)
    24  	return h.Sum(nil)
    25  }
    26  
    27  func validateSSECustomerKeyOptions(opt *Options) error {
    28  	if opt.SSEKMSKeyID != "" && (opt.SSECustomerKeyFile != "" || opt.SSECustomerKey != "") {
    29  		return errors.New("oos: can't use vault sse_kms_key_id and local sse_customer_key at the same time")
    30  	}
    31  	if opt.SSECustomerKey != "" && opt.SSECustomerKeyFile != "" {
    32  		return errors.New("oos: can't use sse_customer_key and sse_customer_key_file at the same time")
    33  	}
    34  	if opt.SSEKMSKeyID != "" {
    35  		return nil
    36  	}
    37  	err := populateSSECustomerKeys(opt)
    38  	if err != nil {
    39  		return err
    40  	}
    41  	return nil
    42  }
    43  
    44  func populateSSECustomerKeys(opt *Options) error {
    45  	if opt.SSECustomerKeyFile != "" {
    46  		// Reads the base64-encoded AES key data from the specified file and computes its SHA256 checksum
    47  		data, err := os.ReadFile(expandPath(opt.SSECustomerKeyFile))
    48  		if err != nil {
    49  			return fmt.Errorf("oos: error reading sse_customer_key_file: %v", err)
    50  		}
    51  		opt.SSECustomerKey = strings.TrimSpace(string(data))
    52  	}
    53  	if opt.SSECustomerKey != "" {
    54  		decoded, err := base64.StdEncoding.DecodeString(opt.SSECustomerKey)
    55  		if err != nil {
    56  			return fmt.Errorf("oos: Could not decode sse_customer_key_file: %w", err)
    57  		}
    58  		sha256Checksum := base64.StdEncoding.EncodeToString(getSha256(decoded))
    59  		if opt.SSECustomerKeySha256 == "" {
    60  			opt.SSECustomerKeySha256 = sha256Checksum
    61  		} else {
    62  			if opt.SSECustomerKeySha256 != sha256Checksum {
    63  				return fmt.Errorf("the computed SHA256 checksum "+
    64  					"(%v) of the key doesn't match the config entry sse_customer_key_sha256=(%v)",
    65  					sha256Checksum, opt.SSECustomerKeySha256)
    66  			}
    67  		}
    68  		if opt.SSECustomerAlgorithm == "" {
    69  			opt.SSECustomerAlgorithm = sseDefaultAlgorithm
    70  		}
    71  	}
    72  	return nil
    73  }
    74  
    75  // https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/usingyourencryptionkeys.htm
    76  func useBYOKPutObject(fs *Fs, request *objectstorage.PutObjectRequest) {
    77  	if fs.opt.SSEKMSKeyID != "" {
    78  		request.OpcSseKmsKeyId = common.String(fs.opt.SSEKMSKeyID)
    79  	}
    80  	if fs.opt.SSECustomerAlgorithm != "" {
    81  		request.OpcSseCustomerAlgorithm = common.String(fs.opt.SSECustomerAlgorithm)
    82  	}
    83  	if fs.opt.SSECustomerKey != "" {
    84  		request.OpcSseCustomerKey = common.String(fs.opt.SSECustomerKey)
    85  	}
    86  	if fs.opt.SSECustomerKeySha256 != "" {
    87  		request.OpcSseCustomerKeySha256 = common.String(fs.opt.SSECustomerKeySha256)
    88  	}
    89  }
    90  
    91  func useBYOKHeadObject(fs *Fs, request *objectstorage.HeadObjectRequest) {
    92  	if fs.opt.SSECustomerAlgorithm != "" {
    93  		request.OpcSseCustomerAlgorithm = common.String(fs.opt.SSECustomerAlgorithm)
    94  	}
    95  	if fs.opt.SSECustomerKey != "" {
    96  		request.OpcSseCustomerKey = common.String(fs.opt.SSECustomerKey)
    97  	}
    98  	if fs.opt.SSECustomerKeySha256 != "" {
    99  		request.OpcSseCustomerKeySha256 = common.String(fs.opt.SSECustomerKeySha256)
   100  	}
   101  }
   102  
   103  func useBYOKGetObject(fs *Fs, request *objectstorage.GetObjectRequest) {
   104  	if fs.opt.SSECustomerAlgorithm != "" {
   105  		request.OpcSseCustomerAlgorithm = common.String(fs.opt.SSECustomerAlgorithm)
   106  	}
   107  	if fs.opt.SSECustomerKey != "" {
   108  		request.OpcSseCustomerKey = common.String(fs.opt.SSECustomerKey)
   109  	}
   110  	if fs.opt.SSECustomerKeySha256 != "" {
   111  		request.OpcSseCustomerKeySha256 = common.String(fs.opt.SSECustomerKeySha256)
   112  	}
   113  }
   114  
   115  func useBYOKCopyObject(fs *Fs, request *objectstorage.CopyObjectRequest) {
   116  	if fs.opt.SSEKMSKeyID != "" {
   117  		request.OpcSseKmsKeyId = common.String(fs.opt.SSEKMSKeyID)
   118  	}
   119  	if fs.opt.SSECustomerAlgorithm != "" {
   120  		request.OpcSseCustomerAlgorithm = common.String(fs.opt.SSECustomerAlgorithm)
   121  	}
   122  	if fs.opt.SSECustomerKey != "" {
   123  		request.OpcSseCustomerKey = common.String(fs.opt.SSECustomerKey)
   124  	}
   125  	if fs.opt.SSECustomerKeySha256 != "" {
   126  		request.OpcSseCustomerKeySha256 = common.String(fs.opt.SSECustomerKeySha256)
   127  	}
   128  }