Skip to content
Merged
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
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require (
github.com/crossplane/crossplane-runtime/v2 v2.2.0
github.com/crossplane/function-sdk-go v0.6.0
github.com/google/go-cmp v0.7.0
github.com/pkg/errors v0.9.1
google.golang.org/grpc v1.78.0
google.golang.org/protobuf v1.36.11
k8s.io/api v0.35.2
k8s.io/apimachinery v0.35.2
Expand Down Expand Up @@ -50,7 +52,6 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.5 // indirect
Expand All @@ -73,7 +74,6 @@ require (
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.41.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20 // indirect
google.golang.org/grpc v1.78.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
7 changes: 5 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ type CLI struct {

Network string `help:"Network on which to listen for gRPC connections." default:"tcp"`
Address string `help:"Address at which to listen for gRPC connections." default:":9443"`
TLSCertsDir string `help:"Directory containing server certs (tls.key, tls.crt) and the CA used to verify client certificates (ca.crt)" env:"TLS_SERVER_CERTS_DIR"`
TLSCertsDir string `help:"Directory containing server certs and the CA used to verify client certificates" env:"TLS_SERVER_CERTS_DIR"`
TLSCACertFileName string `help:"Filename of the CA certificate in the TLS certs directory." default:"ca.crt" env:"TLS_CA_CERT_FILENAME"`
TLSCertFileName string `help:"Filename of the server certificate in the TLS certs directory." default:"tls.crt" env:"TLS_CERT_FILENAME"`
TLSKeyFileName string `help:"Filename of the server private key in the TLS certs directory." default:"tls.key" env:"TLS_KEY_FILENAME"`
Insecure bool `help:"Run without mTLS credentials. If you supply this flag --tls-server-certs-dir will be ignored."`
MaxRecvMessageSize int `help:"Maximum size of received messages in MB." default:"4"`
}
Expand All @@ -27,7 +30,7 @@ func (c *CLI) Run() error {

return function.Serve(&Function{log: log},
function.Listen(c.Network, c.Address),
function.MTLSCertificates(c.TLSCertsDir),
mtlsCertificates(c.TLSCertsDir, c.TLSCACertFileName, c.TLSCertFileName, c.TLSKeyFileName),
function.Insecure(c.Insecure),
function.MaxRecvMessageSize(c.MaxRecvMessageSize*1024*1024))
}
Expand Down
52 changes: 52 additions & 0 deletions tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Package main implements a Composition Function.
package main

import (
"crypto/tls"
"crypto/x509"
"os"
"path/filepath"

"github.com/crossplane/function-sdk-go"
"github.com/pkg/errors"
"google.golang.org/grpc/credentials"
)

// mtlsCertificates returns a ServeOption that configures mTLS using certificates
// loaded from the given directory. Unlike the SDK's function.MTLSCertificates,
// this allows configuring the certificate filenames to support emissary-provided
// TLS certs (https://datadoghq.atlassian.net/wiki/spaces/RPC/pages/4745232414).
func mtlsCertificates(dir, caCertFile, certFile, keyFile string) function.ServeOption {
return func(o *function.ServeOptions) error {
if dir == "" {
return nil
}

crt, err := tls.LoadX509KeyPair(
filepath.Join(dir, certFile),
filepath.Join(dir, keyFile),
)
if err != nil {
return errors.Wrap(err, "cannot load X509 keypair")
}

ca, err := os.ReadFile(filepath.Clean(filepath.Join(dir, caCertFile)))
if err != nil {
return errors.Wrap(err, "cannot read CA certificate")
}

pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(ca) {
return errors.New("invalid CA certificate")
}

o.Credentials = credentials.NewTLS(&tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{crt},
ClientCAs: pool,
ClientAuth: tls.RequireAndVerifyClientCert,
})

return nil
}
}