Skip to content

No easy way to acquire TLS Exported Key Material (EKM) before RPC #9083

@salrashid123

Description

@salrashid123

There doesnt' seem to be an easy to acquire the ExportKeyingMaterial before the RPC is invoked and after the TLS session is established. It looks like the only way to get the EKM and easily invoke the RPC is after the rpc is completed and when the grpc.peeris visible

I know its possible with go and http clients as shown here but what i want to do is use the EKM value for the TLS connection to synthesize a bearer token that is bound to that TLS channel and then invoke the rpc.

The only way i could do that is to dial TLS, get the EKM and then invoke the rpc with that same conn (which is TLS), but set it as if its insecure...that doens't look clean at all

	sconn, err := grpc.Dial(*address, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
		return conn, nil
	}))

Any ideas on how i can improve on this?

thansk


package main

import (
	"crypto/tls"
	"crypto/x509"
	"encoding/hex"
	"flag"
	"fmt"
	"net"

	"os"
	"time"

	echo "github.com/salrashid123/example/echo"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/peer"
)

const ()

var (
	conn *grpc.ClientConn
)

func main() {

	address := flag.String("host", "localhost:50051", "host:port of gRPC server")
	serverName := flag.String("servername", "server.domain.com", "servername")
	tlsCert := flag.String("tlsCert", "../certs/root-ca.crt", "CACert for server")
	flag.Parse()

	var err error

	rootCAs := x509.NewCertPool()
	pem, err := os.ReadFile(*tlsCert)
	if err != nil {
		fmt.Printf("failed to load root CA certificates  error=%v", err)
		os.Exit(1)
	}
	if !rootCAs.AppendCertsFromPEM(pem) {
		fmt.Printf("no root CA certs parsed from file ")
		os.Exit(1)
	}

	tlsCfg := &tls.Config{
		ServerName: *serverName,
		RootCAs:    rootCAs,
	}

	// create connection get its EKM

	conn, err := tls.Dial("tcp", *address, tlsCfg)
	if err != nil {
		fmt.Printf("Error dialing %v\n", err)
		return
	}
	cs := conn.ConnectionState()
	sekm, err := cs.ExportKeyingMaterial("EXPORTER-my_label", []byte("mycontext"), 32)
	if err != nil {
		fmt.Printf("Error getting ekm %v\n", err)
		return
	}
	fmt.Printf("EKM EXPORTER-my_label: %s\n", hex.EncodeToString(sekm))

	// now connect to the actual server and try to get the EKM

	//ce := credentials.NewTLS(tlsCfg)
	sconn, err := grpc.Dial(*address, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
		return conn, nil
	}))
	// sconn, err := grpc.Dial(*address, grpc.WithTransportCredentials(ce), grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
	// 	return conn, nil
	// }))
	//sconn, err := grpc.Dial(*address, grpc.WithTransportCredentials(ce))
	if err != nil {
		fmt.Printf("did not connect: %v", err)
		os.Exit(1)
	}
	defer sconn.Close()

	c := echo.NewEchoServerClient(sconn)
	ctx := context.Background()

	ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
	defer cancel()

	pr := new(peer.Peer)
	r, err := c.SayHello(ctx, &echo.EchoRequest{Name: "unary RPC msg "}, grpc.Peer(pr))
	if err != nil {
		fmt.Printf("could not greet: %v", err)
		os.Exit(1)
	}
	fmt.Println(r.Message)

	// switch info := pr.AuthInfo.(type) {
	// case credentials.TLSInfo:
	// 	authType := info.AuthType()
	// 	sn := info.State.ServerName
	// 	fmt.Printf("AuthType, ServerName %s, %s\n", authType, sn)
	// 	tlsInfo, ok := pr.AuthInfo.(credentials.TLSInfo)
	// 	if !ok {
	// 		fmt.Printf("ERROR:  Could get remote TLS")
	// 		os.Exit(1)
	// 	}
	// 	ekm, err := tlsInfo.State.ExportKeyingMaterial("EXPORTER-my_label", []byte("mycontext"), 32)
	// 	if err != nil {
	// 		fmt.Printf("ERROR:  Could getting EKM %v", err)
	// 		os.Exit(1)
	// 	}
	// 	fmt.Printf("EKM EXPORTER-my_label: %s\n", hex.EncodeToString(ekm))

	// default:
	// 	fmt.Printf("Unknown AuthInfo type %v", info)
	// 	os.Exit(1)
	// }
	// fmt.Println("return")

}

for ref:

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions