Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SubscribeToRotatedIdentities interface #24300

Merged
merged 1 commit into from
Apr 25, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Documentation/cmdref/cilium-agent.md

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

47 changes: 24 additions & 23 deletions Documentation/cmdref/cilium-agent_hive.md

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

45 changes: 23 additions & 22 deletions Documentation/cmdref/cilium-agent_hive_dot-graph.md

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

5 changes: 5 additions & 0 deletions pkg/auth/always_fail_authhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package auth
import (
"errors"

"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/policy"
)

Expand All @@ -26,3 +27,7 @@ func (r *alwaysFailAuthHandler) authenticate(authReq *authRequest) (*authRespons
func (r *alwaysFailAuthHandler) authType() policy.AuthType {
return policy.AuthTypeAlwaysFail
}

func (r *alwaysFailAuthHandler) subscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent {
return nil
}
7 changes: 7 additions & 0 deletions pkg/auth/certs/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"github.com/cilium/cilium/pkg/identity"
)

type CertificateRotationEvent struct {
Identity identity.NumericIdentity
}

type CertificateProvider interface {
// GetTrustBundle gives the CA trust bundle for the certificate provider
// this is then used to verify the certificates given by the peer in the handshake
Expand All @@ -29,4 +33,7 @@ type CertificateProvider interface {

// SNIToNumericIdentity will return the Cilium Identity for a given SNI
SNIToNumericIdentity(sni string) (identity.NumericIdentity, error)

// SubscribeToRotatedIdentities will return a channel with the identities that have rotated certificates
SubscribeToRotatedIdentities() <-chan CertificateRotationEvent
}
2 changes: 2 additions & 0 deletions pkg/auth/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net"
"time"

"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/identity"
"github.com/cilium/cilium/pkg/ip"
"github.com/cilium/cilium/pkg/monitor"
Expand All @@ -30,6 +31,7 @@ type ipCache interface {
type authHandler interface {
authenticate(*authRequest) (*authResponse, error)
authType() policy.AuthType
subscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent
mhofstetter marked this conversation as resolved.
Show resolved Hide resolved
}

type authRequest struct {
Expand Down
5 changes: 5 additions & 0 deletions pkg/auth/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/assert"

"github.com/cilium/cilium/api/v1/flow"
"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/monitor"
monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
"github.com/cilium/cilium/pkg/policy"
Expand Down Expand Up @@ -163,6 +164,10 @@ func (r *fakeAuthHandler) authType() policy.AuthType {
return policy.AuthType(255)
}

func (r *fakeAuthHandler) subscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent {
return nil
}

// Fake DatapathAuthenticator
type fakeDatapathAuthenticator struct {
authenticated bool
Expand Down
4 changes: 4 additions & 0 deletions pkg/auth/mtls_authhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,7 @@ func (m *mtlsAuthHandler) verifyPeerCertificate(id *identity.NumericIdentity, ca

return expirationTime, nil
}

func (m *mtlsAuthHandler) subscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent {
return m.cert.SubscribeToRotatedIdentities()
}
5 changes: 5 additions & 0 deletions pkg/auth/mtls_authhandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"testing"
"time"

"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/identity"
)

Expand Down Expand Up @@ -79,6 +80,10 @@ func (f *fakeCertificateProvider) SNIToNumericIdentity(sni string) (identity.Num
return identity.ParseNumericIdentity(idStr)
}

func (f *fakeCertificateProvider) SubscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent {
return nil
}

func generateTestCertificates(t *testing.T) (map[string]*x509.Certificate, map[string]*ecdsa.PrivateKey, *x509.CertPool) {
caPool := x509.NewCertPool()

Expand Down
5 changes: 5 additions & 0 deletions pkg/auth/null_authhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package auth
import (
"time"

"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/policy"
)

Expand All @@ -25,3 +26,7 @@ func (r *nullAuthHandler) authenticate(authReq *authRequest) (*authResponse, err
func (r *nullAuthHandler) authType() policy.AuthType {
return policy.AuthTypeNull
}

func (r *nullAuthHandler) subscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent {
return nil
}
15 changes: 15 additions & 0 deletions pkg/auth/spire/certificate_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"strings"

"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/identity"
)

Expand Down Expand Up @@ -67,6 +68,16 @@ func (s *SpireDelegateClient) sniToSPIFFEID(id identity.NumericIdentity) string
return "spiffe://" + s.cfg.SpiffeTrustDomain + "/identity/" + id.String()
}

func (s *SpireDelegateClient) spiffeIDToNumericIdentity(spiffeID string) (identity.NumericIdentity, error) {
prefix := "spiffe://" + s.cfg.SpiffeTrustDomain + "/identity/"
if !strings.HasPrefix(spiffeID, prefix) {
return 0, fmt.Errorf("SPIFFE ID %s does not belong to our trust domain or is not in the valid format", spiffeID)
}

idStr := strings.TrimPrefix(spiffeID, prefix)
return identity.ParseNumericIdentity(idStr)
}

func (s *SpireDelegateClient) ValidateIdentity(id identity.NumericIdentity, cert *x509.Certificate) (bool, error) {
spiffeID := s.sniToSPIFFEID(id)

Expand All @@ -91,3 +102,7 @@ func (s *SpireDelegateClient) SNIToNumericIdentity(sni string) (identity.Numeric
idStr := strings.TrimSuffix(sni, suffix)
return identity.ParseNumericIdentity(idStr)
}

func (s *SpireDelegateClient) SubscribeToRotatedIdentities() <-chan certs.CertificateRotationEvent {
return s.rotatedIdentitiesChan
}
92 changes: 92 additions & 0 deletions pkg/auth/spire/certificate_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
delegatedidentityv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/agent/delegatedidentity/v1"
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"

"github.com/cilium/cilium/pkg/auth/certs"
"github.com/cilium/cilium/pkg/identity"
"github.com/cilium/cilium/pkg/logging"
"github.com/cilium/cilium/pkg/logging/logfields"
Expand Down Expand Up @@ -396,3 +397,94 @@ func TestSpireDelegateClient_GetCertificateForIdentity(t *testing.T) {
})
}
}

func TestSpireDelegateClient_SubscribeToRotatedIdentities(t *testing.T) {
tests := []struct {
name string
actions []func(t *testing.T, s *SpireDelegateClient)
events []certs.CertificateRotationEvent
}{
{
name: "receive no event on a new ID",
actions: []func(t *testing.T, s *SpireDelegateClient){
func(t *testing.T, s *SpireDelegateClient) {
s.handleX509SVIDUpdate([]*delegatedidentityv1.X509SVIDWithKey{
{
X509Svid: &types.X509SVID{
Id: &types.SPIFFEID{
TrustDomain: "test.cilium.io",
Path: "/identity/1234",
},
ExpiresAt: time.Now().Add(time.Hour).Unix(),
},
},
})
},
},
events: []certs.CertificateRotationEvent{},
},
{
name: "receive 1 updated event",
actions: []func(t *testing.T, s *SpireDelegateClient){
func(t *testing.T, s *SpireDelegateClient) {
s.handleX509SVIDUpdate([]*delegatedidentityv1.X509SVIDWithKey{
{
X509Svid: &types.X509SVID{
Id: &types.SPIFFEID{
TrustDomain: "test.cilium.io",
Path: "/identity/1234",
},
ExpiresAt: time.Now().Add(time.Hour).Unix(),
},
},
})
},
func(t *testing.T, s *SpireDelegateClient) {
// Update the certificate
s.handleX509SVIDUpdate([]*delegatedidentityv1.X509SVIDWithKey{
{
X509Svid: &types.X509SVID{
Id: &types.SPIFFEID{
TrustDomain: "test.cilium.io",
Path: "/identity/1234",
},
ExpiresAt: time.Now().Add(2 * time.Hour).Unix(),
},
},
})
},
},
events: []certs.CertificateRotationEvent{
{
Identity: 1234,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &SpireDelegateClient{
cfg: SpireDelegateConfig{
SpiffeTrustDomain: "test.cilium.io",
},
log: log,
rotatedIdentitiesChan: make(chan certs.CertificateRotationEvent, 10),
svidStore: make(map[string]*delegatedidentityv1.X509SVIDWithKey),
}
for _, action := range tt.actions {
action(t, s)
}
got := []certs.CertificateRotationEvent{}
select {
case event := <-s.SubscribeToRotatedIdentities():
got = append(got, event)
default:
break
}

if !reflect.DeepEqual(got, tt.events) {
t.Errorf("SpireDelegateClient.SubscribeToRotatedIdentities() = %v, want %v", got, tt.events)
}
})
}
}