Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions config/keyprovider-config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,39 @@ type Command struct {
Args []string `json:"args,omitempty"`
}

// GrpcTLS describes the structure of TLS configuration for gRPC connection, it consist of CA certificate,
// client certificate and client key
type GrpcTLS struct {
// RootCAFile defines path to the PEM file with the set of root certificate authorities
// that clients use when verifying server certificates.
// If RootCAs is nil, TLS uses the host's root CA set.
RootCAFile string `json:"root-ca-file,omitempty"`

// CertFile contains the path to the x509 PEM encoded client certificate.
CertFile string `json:"cert-file,omitempty"`
// KeyFile contains the path to the PEM encoded client key.
KeyFile string `json:"key-file,omitempty"`

// ServerName is used to verify the hostname on the returned
// certificates unless InsecureSkipVerify is given. It is also included
// in the client's handshake to support virtual hosting unless it is
// an IP address.
ServerName string `json:"server-name,omitempty"`

// InsecureSkipVerify controls whether a client verifies the
// server's certificate chain and host name.
// If InsecureSkipVerify is true, TLS accepts any certificate
// presented by the server and any host name in that certificate.
// In this mode, TLS is susceptible to man-in-the-middle attacks.
// This should be used only for testing.
InsecureSkipVerify bool `json:"insecure-skip-verify,omitempty"`
}

// KeyProviderAttrs describes the structure of key provider, it defines the way of invocation to key provider
type KeyProviderAttrs struct {
Command *Command `json:"cmd,omitempty"`
Grpc string `json:"grpc,omitempty"`
GrpcTLS *GrpcTLS `json:"grpc-tls,omitempty"`
}

// OcicryptConfig represents the format of an ocicrypt_provider.conf config file
Expand Down
59 changes: 53 additions & 6 deletions keywrap/keyprovider/keyprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ package keyprovider

import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"os"

"github.com/containers/ocicrypt/config"
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
Expand All @@ -29,6 +32,7 @@ import (
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

type keyProviderKeyWrapper struct {
Expand Down Expand Up @@ -118,7 +122,7 @@ func (kw *keyProviderKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []b
}
return protocolOuput.KeyWrapResults.Annotation, nil
} else if kw.attrs.Grpc != "" {
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyWrap)
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, kw.attrs.GrpcTLS, OpKeyWrap)
if err != nil {
return nil, fmt.Errorf("error while retrieving keyprovider protocol grpc output: %w", err)
}
Expand Down Expand Up @@ -154,7 +158,7 @@ func (kw *keyProviderKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString

return protocolOuput.KeyUnwrapResults.OptsData, nil
} else if kw.attrs.Grpc != "" {
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyUnwrap)
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, kw.attrs.GrpcTLS, OpKeyUnwrap)
if err != nil {
// If err is not nil, then ignore it and continue with rest of the given keyproviders
return nil, err
Expand All @@ -165,12 +169,55 @@ func (kw *keyProviderKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
}

func getProviderGRPCOutput(input []byte, connString string, operation KeyProviderKeyWrapProtocolOperation) (*KeyProviderKeyWrapProtocolOutput, error) {
func getProviderGRPCOutput(input []byte, connString string, grpcTls *keyproviderconfig.GrpcTLS, operation KeyProviderKeyWrapProtocolOperation) (*KeyProviderKeyWrapProtocolOutput, error) {
var protocolOuput KeyProviderKeyWrapProtocolOutput
var grpcOutput *keyproviderpb.KeyProviderKeyWrapProtocolOutput
cc, err := grpc.Dial(connString, grpc.WithInsecure())
if err != nil {
return nil, fmt.Errorf("error while dialing rpc server: %w", err)

var cc *grpc.ClientConn
var err error

if grpcTls != nil {
var rootCAs *x509.CertPool
if grpcTls.RootCAFile != "" {
pem, err := os.ReadFile(grpcTls.RootCAFile)
if err != nil {
return nil, fmt.Errorf("failed to load root CA certificates error=%v", err)
}
if !rootCAs.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("no root CA certs parsed from file ")
}
} else {
rootCAs, err = x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("error reading SystemCertPool error=%v", err)
}
}

var clientCerts []tls.Certificate
if grpcTls.CertFile != "" && grpcTls.KeyFile != "" {
cert, err := tls.LoadX509KeyPair(grpcTls.CertFile, grpcTls.KeyFile)
if err != nil {
return nil, fmt.Errorf("failed to load client certificate and key: %v", err)
}
clientCerts = []tls.Certificate{cert}
}

tlsConfig := &tls.Config{
RootCAs: rootCAs,
ServerName: grpcTls.ServerName,
InsecureSkipVerify: grpcTls.InsecureSkipVerify,
Certificates: clientCerts,
}
creds := credentials.NewTLS(tlsConfig)
cc, err = grpc.Dial(connString, grpc.WithTransportCredentials(creds))
if err != nil {
return nil, fmt.Errorf("error while dialing TLS rpc server: %w", err)
}
} else {
cc, err = grpc.Dial(connString, grpc.WithInsecure())
if err != nil {
return nil, fmt.Errorf("error while dialing rpc server: %w", err)
}
}
defer func() {
derr := cc.Close()
Expand Down
9 changes: 8 additions & 1 deletion keywrap/keyprovider/keyprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,15 @@ func TestKeyWrapKeyProviderGRPCSuccess(t *testing.T) {
"path": "/usr/lib/keyprovider-2-unwrapkey",
"args": []
}
},
"keyprovider-4": {
"grpc": "localhost:3990",
"grpc-tls": {
"server-name": "localhost",
"insecure-skip-verify": false,
"root-ca-file": "/etc/ssl/certs/ca-certificates.crt"
}
}

}}
`
tempFile, _ := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
Expand Down
Loading