Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

Fix SPIFFE url handling #225

Merged
merged 5 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
3 changes: 3 additions & 0 deletions .changelog/225.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
fix SPIFFE handling for Vault connect certificates
```
22 changes: 0 additions & 22 deletions internal/consul/certmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"net/url"
"os"
"path"
"sync"
Expand Down Expand Up @@ -116,7 +114,6 @@ type CertManager struct {
privateKey []byte
tlsCertificate *tls.Certificate
rootCertificatePool *x509.CertPool
spiffeURL *url.URL

// watches
rootWatch *watch.Plan
Expand Down Expand Up @@ -164,18 +161,6 @@ func (c *CertManager) handleRootWatch(blockParam watch.BlockingParamVal, raw int
for _, root := range v.Roots {
roots.AppendCertsFromPEM([]byte(root.RootCertPEM))
if root.Active {
block, _ := pem.Decode([]byte(root.RootCertPEM))
caCert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
c.logger.Error("failed to parse root certificate")
return
}
for _, uri := range caCert.URIs {
if uri.Scheme == "spiffe" {
c.spiffeURL = uri
break
}
}
c.ca = []byte(root.RootCertPEM)
}
}
Expand Down Expand Up @@ -340,13 +325,6 @@ func (c *CertManager) RootPool() *x509.CertPool {
return c.rootCertificatePool
}

func (c *CertManager) SPIFFE() *url.URL {
c.lock.RLock()
defer c.lock.RUnlock()

return c.spiffeURL
}

// Certificate returns the current leaf cert
func (c *CertManager) Certificate() []byte {
c.lock.RLock()
Expand Down
12 changes: 4 additions & 8 deletions internal/envoy/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package envoy
import (
"context"
"errors"
"net/url"
"strings"

"google.golang.org/grpc"
Expand Down Expand Up @@ -65,26 +64,23 @@ type GatewaySecretRegistry interface {
// the request is rejected.
func SPIFFEStreamMiddleware(logger hclog.Logger, fetcher CertificateFetcher, registry GatewaySecretRegistry) grpc.StreamServerInterceptor {
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
if info, ok := verifySPIFFE(ss.Context(), logger, fetcher.SPIFFE(), registry); ok {
if info, ok := verifySPIFFE(ss.Context(), logger, registry); ok {
return handler(srv, wrapStream(ss, info))
}
return status.Errorf(codes.Unauthenticated, "unable to authenticate request")
}
}

func verifySPIFFE(ctx context.Context, logger hclog.Logger, spiffeCA *url.URL, registry GatewaySecretRegistry) (core.GatewayID, bool) {
func verifySPIFFE(ctx context.Context, logger hclog.Logger, registry GatewaySecretRegistry) (core.GatewayID, bool) {
if p, ok := peer.FromContext(ctx); ok {
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
// grab the peer certificate info
for _, item := range mtls.State.PeerCertificates {
// check each untyped SAN for spiffee information
for _, uri := range item.URIs {
// we skip validating the host value since not all of our potential roots (i.e. via Vault)
// have spiffe urls
if uri.Scheme == "spiffe" {
// we've found a spiffee SAN, check that it aligns with the CA info
if uri.Host != spiffeCA.Host {
logger.Warn("found mismatching spiffe hosts, skipping", "caHost", spiffeCA.Host, "clientHost", uri.Host)
continue
}
// make sure we have a leaf certificate that has been issued by consul
// with namespace, datacenter, and service information -- the namespace
// and service are used to inform us what gateway is trying to connect
Expand Down
15 changes: 0 additions & 15 deletions internal/envoy/mocks/sds.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions internal/envoy/sds.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"net"
"net/url"
"sync"
"time"

Expand Down Expand Up @@ -40,7 +39,6 @@ var logOnce sync.Once
// CertificateFetcher is used to fetch the CA and server certificate
// that the server should use for TLS
type CertificateFetcher interface {
SPIFFE() *url.URL
RootPool() *x509.CertPool
TLSCertificate() *tls.Certificate
}
Expand Down
2 changes: 0 additions & 2 deletions internal/envoy/sds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,7 @@ func runTestServer(t *testing.T, ca []byte, registryFn func(*gomock.Controller)
require.NoError(t, err)
certPool := x509.NewCertPool()
certPool.AddCert(caCert)
spiffe := caCert.URIs[0]

fetcher.EXPECT().SPIFFE().AnyTimes().Return(spiffe)
fetcher.EXPECT().RootPool().AnyTimes().Return(certPool)
secretClient.EXPECT().FetchSecret(gomock.Any(), "test").AnyTimes().Return(&envoyTLS.Secret{
Name: "test",
Expand Down