...

Source file src/edge-infra.dev/pkg/edge/datasync/magpie/decrypt.go

Documentation: edge-infra.dev/pkg/edge/datasync/magpie

     1  // Package classification Magpie
     2  //
     3  // Documentation for Edge Decryption API
     4  //
     5  //	Schemes: https
     6  //	BasePath: /
     7  //	Version: 1.0.0
     8  //	Host: edge.ncr.com/crypto/
     9  //
    10  //	Consumes:
    11  //	- text/plain
    12  //
    13  //	Produces:
    14  //	- text/plain
    15  //
    16  // swagger:meta
    17  package magpie
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"hash/crc32"
    24  	"path/filepath"
    25  	"strings"
    26  
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    29  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    30  	"k8s.io/client-go/rest"
    31  	"k8s.io/client-go/tools/clientcmd"
    32  	"k8s.io/client-go/util/homedir"
    33  	"sigs.k8s.io/controller-runtime/pkg/client"
    34  
    35  	"edge-infra.dev/pkg/edge/edgeencrypt"
    36  
    37  	kms "cloud.google.com/go/kms/apiv1"
    38  	"cloud.google.com/go/kms/apiv1/kmspb"
    39  	"github.com/go-logr/logr"
    40  	"google.golang.org/grpc/codes"
    41  	"google.golang.org/grpc/status"
    42  	"google.golang.org/protobuf/types/known/wrapperspb"
    43  )
    44  
    45  // +kubebuilder:rbac:groups="",namespace=magpie,resources=secrets,verbs=get;list;watch
    46  
    47  func Run(log logr.Logger) error {
    48  	cfg, err := NewConfig()
    49  	if err != nil {
    50  		return fmt.Errorf("failed to load config: %w", err)
    51  	}
    52  
    53  	config, err := rest.InClusterConfig()
    54  	if errors.Is(err, rest.ErrNotInCluster) {
    55  		config, err = clientcmd.BuildConfigFromFlags("", filepath.Join(homedir.HomeDir(), ".kube", "config"))
    56  		if err != nil {
    57  			return fmt.Errorf("failed to get local config: %w", err)
    58  		}
    59  	} else if err != nil {
    60  		return fmt.Errorf("failed to get in-cluster config: %w", err)
    61  	}
    62  
    63  	cl, err := client.New(config, client.Options{Scheme: createScheme()})
    64  	if err != nil {
    65  		return fmt.Errorf("failed to create client: %w", err)
    66  	}
    67  
    68  	kmsClient, err := kms.NewKeyManagementClient(context.Background())
    69  	if err != nil {
    70  		return fmt.Errorf("failed to create kms client: %w", err)
    71  	}
    72  	defer kmsClient.Close()
    73  
    74  	crc32c := func(data []byte) uint32 {
    75  		t := crc32.MakeTable(crc32.Castagnoli)
    76  		return crc32.Checksum(data, t)
    77  	}
    78  
    79  	decrypt := func(ctx context.Context, bannerId, channelID, keyVersion string, ciphertext []byte) ([]byte, error) {
    80  		ciphertextCRC32C := crc32c(ciphertext)
    81  		req := &kmspb.AsymmetricDecryptRequest{
    82  			Name:             cfg.KeyPath(bannerId, fmt.Sprintf(edgeencrypt.EncryptionSecret, channelID), keyVersion),
    83  			Ciphertext:       ciphertext,
    84  			CiphertextCrc32C: wrapperspb.Int64(int64(ciphertextCRC32C)),
    85  		}
    86  		res, err := kmsClient.AsymmetricDecrypt(ctx, req)
    87  		if err != nil {
    88  			if status.Code(err) == codes.FailedPrecondition && strings.Contains(err.Error(), "DISABLED") {
    89  				return nil, fmt.Errorf("kms key is disabled: %w", err)
    90  			}
    91  			return nil, fmt.Errorf("kms client failed to decrypt data: %w", err)
    92  		}
    93  		if !res.VerifiedCiphertextCrc32C {
    94  			return nil, fmt.Errorf("AsymmetricDecrypt: request corrupted in-transit")
    95  		}
    96  		if int64(crc32c(res.Plaintext)) != res.PlaintextCrc32C.Value {
    97  			return nil, fmt.Errorf("AsymmetricDecrypt: response corrupted in-transit")
    98  		}
    99  		return res.Plaintext, nil
   100  	}
   101  
   102  	server := NewDecryptionServer(cfg, cl, log, decrypt)
   103  
   104  	return server.Start(fmt.Sprintf(":%s", cfg.Port), fmt.Sprintf(":%s", cfg.MetricPort))
   105  }
   106  
   107  func createScheme() *runtime.Scheme {
   108  	scheme := runtime.NewScheme()
   109  
   110  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
   111  	return scheme
   112  }
   113  

View as plain text