From efc7313f0c3e2a1d829e916f6b905e4680712301 Mon Sep 17 00:00:00 2001 From: arndt-s <17650715+arndt-s@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:04:18 +0100 Subject: [PATCH 1/4] wip: implement broker api Signed-off-by: arndt-s <17650715+arndt-s@users.noreply.github.com> --- .data/.file | 1 - Makefile | 2 + cmd/spire-agent/cli/run/run.go | 10 + cmd/spire-agent/cli/run/run_posix.go | 35 + cmd/spire-agent/cli/run/run_windows.go | 8 + conf/agent/agent.conf | 5 + conf/agent/agent_full.conf | 3 + pkg/agent/agent.go | 19 + pkg/agent/attestor/node/node.go | 7 - pkg/agent/attestor/node/result.go | 40 ++ pkg/agent/broker/api/service.go | 367 +++++++++++ pkg/agent/broker/endpoints.go | 165 +++++ pkg/agent/broker/endpoints_fallback.go | 12 + pkg/agent/broker/endpoints_posix.go | 29 + pkg/agent/config.go | 3 + pkg/agent/manager/cache/bundle_cache.go | 13 + pkg/agent/manager/cache/lru_cache.go | 5 + pkg/agent/manager/manager.go | 10 + pkg/common/telemetry/names.go | 3 + proto/brokerapi/brokerapi.pb.go | 844 ++++++++++++++++++++++++ proto/brokerapi/brokerapi.proto | 167 +++++ proto/brokerapi/brokerapi_grpc.pb.go | 326 +++++++++ 22 files changed, 2066 insertions(+), 8 deletions(-) delete mode 100644 .data/.file create mode 100644 pkg/agent/attestor/node/result.go create mode 100644 pkg/agent/broker/api/service.go create mode 100644 pkg/agent/broker/endpoints.go create mode 100644 pkg/agent/broker/endpoints_fallback.go create mode 100644 pkg/agent/broker/endpoints_posix.go create mode 100644 proto/brokerapi/brokerapi.pb.go create mode 100644 proto/brokerapi/brokerapi.proto create mode 100644 proto/brokerapi/brokerapi_grpc.pb.go diff --git a/.data/.file b/.data/.file deleted file mode 100644 index 1917ccee65..0000000000 --- a/.data/.file +++ /dev/null @@ -1 +0,0 @@ -This directory contains runtime data only. This file serves as a Git placeholder in order to ensure its presence in development environments. diff --git a/Makefile b/Makefile index f9ca7f8311..606648b6ec 100644 --- a/Makefile +++ b/Makefile @@ -185,8 +185,10 @@ git_dirty := $(shell git status -s) protos := \ proto/private/server/journal/journal.proto \ proto/spire/common/common.proto \ + proto/brokerapi/brokerapi.proto api-protos := \ + proto/brokerapi/brokerapi.proto plugin-protos := \ proto/spire/common/plugin/plugin.proto diff --git a/cmd/spire-agent/cli/run/run.go b/cmd/spire-agent/cli/run/run.go index 374c344adb..67c6a877dc 100644 --- a/cmd/spire-agent/cli/run/run.go +++ b/cmd/spire-agent/cli/run/run.go @@ -66,6 +66,7 @@ type Config struct { type agentConfig struct { DataDir string `hcl:"data_dir"` AdminSocketPath string `hcl:"admin_socket_path"` + BrokerSocketPath string `hcl:"broker_socket_path"` InsecureBootstrap bool `hcl:"insecure_bootstrap"` RebootstrapMode string `hcl:"rebootstrap_mode"` RebootstrapDelay string `hcl:"rebootstrap_delay"` @@ -491,6 +492,15 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool) } ac.AdminBindAddress = adminAddr } + + if c.Agent.hasBrokerAddr() { + brokerAddr, err := c.Agent.getBrokerAddr() + if err != nil { + return nil, err + } + ac.BrokerBindAddress = brokerAddr + } + // Handle join token - read from file if specified if c.Agent.JoinTokenFile != "" { tokenBytes, err := os.ReadFile(c.Agent.JoinTokenFile) diff --git a/cmd/spire-agent/cli/run/run_posix.go b/cmd/spire-agent/cli/run/run_posix.go index 4c8ddd9d03..5bb8cde0e1 100644 --- a/cmd/spire-agent/cli/run/run_posix.go +++ b/cmd/spire-agent/cli/run/run_posix.go @@ -53,6 +53,30 @@ func (c *agentConfig) hasAdminAddr() bool { return c.AdminSocketPath != "" } +func (c *agentConfig) getBrokerAddr() (net.Addr, error) { + socketPathAbs, err := filepath.Abs(c.SocketPath) + if err != nil { + return nil, fmt.Errorf("failed to get absolute path for socket_path: %w", err) + } + brokerSocketPathAbs, err := filepath.Abs(c.BrokerSocketPath) + if err != nil { + return nil, fmt.Errorf("failed to get absolute path for broker_socket_path: %w", err) + } + + if strings.HasPrefix(brokerSocketPathAbs, filepath.Dir(socketPathAbs)+"/") { + return nil, errors.New("broker socket cannot be in the same directory or a subdirectory as that containing the Workload API socket") + } + + return &net.UnixAddr{ + Name: brokerSocketPathAbs, + Net: "unix", + }, nil +} + +func (c *agentConfig) hasBrokerAddr() bool { + return c.BrokerSocketPath != "" +} + // validateOS performs posix specific validations of the agent config func (c *agentConfig) validateOS() error { if c.Experimental.NamedPipeName != "" { @@ -88,5 +112,16 @@ func prepareEndpoints(c *agent.Config) error { } } + if c.BrokerBindAddress != nil { + // Create uds dir and parents if not exists + brokerDir := filepath.Dir(c.BrokerBindAddress.String()) + if _, statErr := os.Stat(brokerDir); os.IsNotExist(statErr) { + c.Log.WithField("dir", brokerDir).Infof("Creating broker UDS directory") + if err := os.MkdirAll(brokerDir, 0755); err != nil { + return err + } + } + } + return nil } diff --git a/cmd/spire-agent/cli/run/run_windows.go b/cmd/spire-agent/cli/run/run_windows.go index 015bbc3420..6ffcac1031 100644 --- a/cmd/spire-agent/cli/run/run_windows.go +++ b/cmd/spire-agent/cli/run/run_windows.go @@ -32,6 +32,14 @@ func (c *agentConfig) hasAdminAddr() bool { return c.Experimental.AdminNamedPipeName != "" } +func (c *agentConfig) getBrokerAddr() (net.Addr, error) { + return nil, errors.New("broker_socket_path is not supported in this platform") +} + +func (c *agentConfig) hasBrokerAddr() bool { + return false +} + // validateOS performs windows specific validations of the agent config func (c *agentConfig) validateOS() error { if c.SocketPath != "" { diff --git a/conf/agent/agent.conf b/conf/agent/agent.conf index cf1fcb353a..b10788ab03 100644 --- a/conf/agent/agent.conf +++ b/conf/agent/agent.conf @@ -6,6 +6,11 @@ agent { socket_path ="/tmp/spire-agent/public/api.sock" trust_bundle_path = "./conf/agent/dummy_root_ca.crt" trust_domain = "example.org" + + authorized_delegates = [ + "spiffe://example.org/broker", + ] + broker_socket_path = "/tmp/spire-agent/broker/api.sock" } plugins { diff --git a/conf/agent/agent_full.conf b/conf/agent/agent_full.conf index b7e0d3f52c..41c524611e 100644 --- a/conf/agent/agent_full.conf +++ b/conf/agent/agent_full.conf @@ -86,6 +86,9 @@ agent { # "spiffe://example.org/authorized_client1", # ] + # broker_socket_path: Location to bind the SPIFFE Broker Endpoint. + # broker_socket_path = "" + # sds: Optional SDS configuration section. # sds = { # # default_svid_name: The TLS Certificate resource name to use for the default diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index ceda18da67..b04c8c60c6 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -17,6 +17,7 @@ import ( admin_api "github.com/spiffe/spire/pkg/agent/api" node_attestor "github.com/spiffe/spire/pkg/agent/attestor/node" workload_attestor "github.com/spiffe/spire/pkg/agent/attestor/workload" + "github.com/spiffe/spire/pkg/agent/broker" "github.com/spiffe/spire/pkg/agent/catalog" "github.com/spiffe/spire/pkg/agent/endpoints" "github.com/spiffe/spire/pkg/agent/manager" @@ -255,6 +256,24 @@ func (a *Agent) Run(ctx context.Context) error { tasks = append(tasks, adminEndpoints.ListenAndServe) } + if a.c.BrokerBindAddress != nil { + brokerEndpoints, err := broker.New(&broker.Config{ + BindAddr: a.c.BrokerBindAddress, + Manager: manager, + Log: a.c.Log, + Metrics: metrics, + Attestor: workloadAttestor, + TrustDomain: a.c.TrustDomain, + AuthorizedDelegates: a.c.AuthorizedDelegates, + SVIDSource: as, + BundleSource: manager.GetX509Bundle(), + }) + if err != nil { + return fmt.Errorf("failed to create broker endpoints: %w", err) + } + tasks = append(tasks, brokerEndpoints.ListenAndServe) + } + if a.c.LogReopener != nil { tasks = append(tasks, a.c.LogReopener) } diff --git a/pkg/agent/attestor/node/node.go b/pkg/agent/attestor/node/node.go index ce4559ba28..a4a3d5c2a5 100644 --- a/pkg/agent/attestor/node/node.go +++ b/pkg/agent/attestor/node/node.go @@ -36,13 +36,6 @@ const ( roundRobinServiceConfig = `{ "loadBalancingConfig": [ { "round_robin": {} } ] }` ) -type AttestationResult struct { - SVID []*x509.Certificate - Key keymanager.Key - Bundle *spiffebundle.Bundle - Reattestable bool -} - type Attestor interface { Attest(ctx context.Context) (*AttestationResult, error) } diff --git a/pkg/agent/attestor/node/result.go b/pkg/agent/attestor/node/result.go new file mode 100644 index 0000000000..8001af040b --- /dev/null +++ b/pkg/agent/attestor/node/result.go @@ -0,0 +1,40 @@ +package attestor + +import ( + "crypto/x509" + "fmt" + + "github.com/spiffe/go-spiffe/v2/bundle/spiffebundle" + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" + "github.com/spiffe/go-spiffe/v2/spiffeid" + "github.com/spiffe/go-spiffe/v2/svid/x509svid" + "github.com/spiffe/spire/pkg/agent/plugin/keymanager" +) + +// Allow AttestationResult to be used as go-spiffe SVID and bundle sources. +// TODO(arndt): Check whether the key of the agent is ok to be exposed to other parties. +var ( + _ x509svid.Source = (*AttestationResult)(nil) + _ x509bundle.Source = (*AttestationResult)(nil) +) + +type AttestationResult struct { + SVID []*x509.Certificate + Key keymanager.Key + Bundle *spiffebundle.Bundle + Reattestable bool +} + +func (ar *AttestationResult) GetX509SVID() (*x509svid.SVID, error) { + return &x509svid.SVID{ + Certificates: ar.SVID, + PrivateKey: ar.Key, + }, nil +} + +func (ar *AttestationResult) GetX509BundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*x509bundle.Bundle, error) { + if ar.Bundle.TrustDomain() != trustDomain { + return nil, fmt.Errorf("bundle for trust domain %q not found", trustDomain) + } + return ar.Bundle.X509Bundle(), nil +} diff --git a/pkg/agent/broker/api/service.go b/pkg/agent/broker/api/service.go new file mode 100644 index 0000000000..9f3b0ff155 --- /dev/null +++ b/pkg/agent/broker/api/service.go @@ -0,0 +1,367 @@ +package api + +import ( + "context" + "crypto/x509" + "errors" + "fmt" + "time" + + "github.com/sirupsen/logrus" + "github.com/spiffe/go-spiffe/v2/spiffegrpc/grpccredentials" + "github.com/spiffe/go-spiffe/v2/spiffeid" + "github.com/spiffe/spire/pkg/agent/api/rpccontext" + workloadattestor "github.com/spiffe/spire/pkg/agent/attestor/workload" + "github.com/spiffe/spire/pkg/agent/client" + "github.com/spiffe/spire/pkg/agent/manager" + "github.com/spiffe/spire/pkg/agent/manager/cache" + "github.com/spiffe/spire/pkg/common/bundleutil" + "github.com/spiffe/spire/pkg/common/idutil" + "github.com/spiffe/spire/pkg/common/telemetry" + "github.com/spiffe/spire/pkg/common/telemetry/agent/adminapi" + "github.com/spiffe/spire/pkg/common/x509util" + "github.com/spiffe/spire/proto/brokerapi" + "github.com/spiffe/spire/proto/spire/common" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// RegisterService registers the delegated identity service on the provided server +func RegisterService(s *grpc.Server, service *Service) { + brokerapi.RegisterSpiffeBrokerAPIServer(s, service) +} + +type Config struct { + Log logrus.FieldLogger + Metrics telemetry.Metrics + Manager manager.Manager + Attestor workloadattestor.Attestor +} + +func New(config Config) *Service { + return &Service{ + manager: config.Manager, + peerAttestor: config.Attestor, + metrics: config.Metrics, + } +} + +// Service implements the delegated identity server +type Service struct { + brokerapi.UnimplementedSpiffeBrokerAPIServer + + manager manager.Manager + peerAttestor workloadattestor.Attestor + metrics telemetry.Metrics +} + +func (s *Service) getCallerContext(ctx context.Context) (spiffeid.ID, error) { + peer, ok := grpccredentials.PeerIDFromContext(ctx) + if !ok { + return spiffeid.ID{}, status.Error(codes.Unauthenticated, "unable to determine caller identity") + } + return peer, nil +} + +func (s *Service) FetchX509SVID(req *brokerapi.X509SVIDRequest, stream brokerapi.SpiffeBrokerAPI_FetchX509SVIDServer) error { + latency := adminapi.StartFirstX509SVIDUpdateLatency(s.metrics) + ctx := stream.Context() + log := rpccontext.Logger(ctx) + var receivedFirstUpdate bool + + peer, err := s.getCallerContext(ctx) + if err != nil { + return err + } + log = log.WithField("broker_peer", peer.String()) + + selectors, err := s.constructValidSelectorsFromReferences(ctx, log, req.References) + if err != nil { + return err + } + + log.WithFields(logrus.Fields{ + "request_selectors": selectors, + }).Debug("Subscribing to cache changes") + + subscriber, err := s.manager.SubscribeToCacheChanges(ctx, selectors) + if err != nil { + log.WithError(err).Error("Subscribe to cache changes failed") + return err + } + defer subscriber.Finish() + + for { + select { + case update := <-subscriber.Updates(): + if len(update.Identities) > 0 && !receivedFirstUpdate { + // emit latency metric for first update containing an SVID. + latency.Measure() + receivedFirstUpdate = true + } + + if err := sendX509SVIDResponse(update, stream, log); err != nil { + return err + } + case <-ctx.Done(): + return nil + } + } +} + +func (s *Service) FetchX509Bundles(_ *brokerapi.X509BundlesRequest, stream brokerapi.SpiffeBrokerAPI_FetchX509BundlesServer) error { + ctx := stream.Context() + + peer, err := s.getCallerContext(ctx) + if err != nil { + return err + } + _ = rpccontext.Logger(ctx).WithField("broker_peer", peer.String()) + + subscriber := s.manager.SubscribeToBundleChanges() + + // send initial update.... + caCerts := make(map[string][]byte) + for td, bundle := range subscriber.Value() { + caCerts[td.IDString()] = marshalBundle(bundle.X509Authorities()) + } + + resp := &brokerapi.X509BundlesResponse{ + Bundles: caCerts, + } + + if err := stream.Send(resp); err != nil { + return err + } + + for { + select { + case <-subscriber.Changes(): + for td, bundle := range subscriber.Next() { + caCerts[td.IDString()] = marshalBundle(bundle.X509Authorities()) + } + + resp := &brokerapi.X509BundlesResponse{ + Bundles: caCerts, + } + + if err := stream.Send(resp); err != nil { + return err + } + + case <-ctx.Done(): + return nil + } + } +} + +func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.JWTSVIDRequest) (*brokerapi.JWTSVIDResponse, error) { + log := rpccontext.Logger(ctx) + if len(req.Audience) == 0 { + log.Error("Missing required audience parameter") + return nil, status.Error(codes.InvalidArgument, "audience must be specified") + } + + peer, err := s.getCallerContext(ctx) + if err != nil { + return nil, err + } + log = log.WithField("broker_peer", peer.String()) + + selectors, err := s.constructValidSelectorsFromReferences(ctx, log, req.References) + if err != nil { + return nil, err + } + + resp := new(brokerapi.JWTSVIDResponse) + entries := s.manager.MatchingRegistrationEntries(selectors) + for _, entry := range entries { + spiffeID, err := spiffeid.FromString(entry.SpiffeId) + if err != nil { + log.WithField(telemetry.SPIFFEID, entry.SpiffeId).WithError(err).Error("Invalid requested SPIFFE ID") + return nil, status.Errorf(codes.InvalidArgument, "invalid requested SPIFFE ID: %v", err) + } + + loopLog := log.WithField(telemetry.SPIFFEID, spiffeID.String()) + + var svid *client.JWTSVID + svid, err = s.manager.FetchJWTSVID(ctx, entry, req.Audience) + if err != nil { + loopLog.WithError(err).Error("Could not fetch JWT-SVID") + return nil, status.Errorf(codes.Unavailable, "could not fetch JWT-SVID: %v", err) + } + resp.Svids = append(resp.Svids, &brokerapi.JWTSVID{ + SpiffeId: spiffeID.String(), + Hint: entry.Hint, + Svid: svid.Token, + }) + + ttl := time.Until(svid.ExpiresAt) + loopLog.WithField(telemetry.TTL, ttl.Seconds()).Debug("Fetched JWT SVID") + } + + if len(resp.Svids) == 0 { + log.Error("No identity issued") + return nil, status.Error(codes.PermissionDenied, "no identity issued") + } + + return resp, nil +} + +func (s *Service) FetchJWTBundles(_ *brokerapi.JWTBundlesRequest, stream brokerapi.SpiffeBrokerAPI_FetchJWTBundlesServer) error { + ctx := stream.Context() + + peer, err := s.getCallerContext(ctx) + if err != nil { + return err + } + _ = rpccontext.Logger(ctx).WithField("broker_peer", peer.String()) + + subscriber := s.manager.SubscribeToBundleChanges() + + // send initial update.... + jwtbundles := make(map[string][]byte) + for td, bundle := range subscriber.Value() { + jwksBytes, err := bundleutil.Marshal(bundle, bundleutil.NoX509SVIDKeys(), bundleutil.StandardJWKS()) + if err != nil { + return err + } + jwtbundles[td.IDString()] = jwksBytes + } + + resp := &brokerapi.JWTBundlesResponse{ + Bundles: jwtbundles, + } + + if err := stream.Send(resp); err != nil { + return err + } + for { + select { + case <-subscriber.Changes(): + for td, bundle := range subscriber.Next() { + jwksBytes, err := bundleutil.Marshal(bundle, bundleutil.NoX509SVIDKeys(), bundleutil.StandardJWKS()) + if err != nil { + return err + } + jwtbundles[td.IDString()] = jwksBytes + } + + resp := &brokerapi.JWTBundlesResponse{ + Bundles: jwtbundles, + } + if err := stream.Send(resp); err != nil { + return err + } + case <-ctx.Done(): + return nil + } + } +} + +func (s *Service) constructValidSelectorsFromReferences(ctx context.Context, log logrus.FieldLogger, refs []*brokerapi.WorkloadReference) ([]*common.Selector, error) { + if len(refs) == 0 { + log.Error("No workload references provided") + return nil, status.Error(codes.InvalidArgument, "no workload references provided") + } + + if len(refs) > 1 { + log.Error("Multiple workload references provided; only one is supported") + return nil, status.Error(codes.InvalidArgument, "multiple workload references provided; SPIRE only supports one at the moment") + } + + switch refs[0].Reference.TypeUrl { + case "type.googleapis.com/brokerapi.WorkloadPIDReference": + var pidRef brokerapi.WorkloadPIDReference + if err := refs[0].Reference.UnmarshalTo(&pidRef); err != nil { + log.WithError(err).Error("Failed to unmarshal PID workload reference") + return nil, status.Error(codes.InvalidArgument, "failed to unmarshal PID workload reference") + } + + selectors, err := s.peerAttestor.Attest(ctx, int(pidRef.Pid)) + if err != nil { + log.WithError(err).Error("Workload attestation with PID failed") + return nil, status.Error(codes.Internal, "workload attestation with PID failed") + } + return selectors, nil + default: + log.WithField("type_url", refs[0].Reference.TypeUrl).Error("Unsupported workload reference type") + return nil, status.Error(codes.InvalidArgument, "unsupported workload reference type") + } +} + +func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream brokerapi.SpiffeBrokerAPI_FetchX509SVIDServer, log logrus.FieldLogger) (err error) { + resp, err := composeX509SVIDBySelectors(update) + if err != nil { + log.WithError(err).Error("Could not serialize X.509 SVID response") + return status.Error(codes.Internal, "could not serialize response") + } + + if err := stream.Send(resp); err != nil { + log.WithError(err).Error("Failed to send X.509 SVID response") + return err + } + + log = log.WithField(telemetry.Count, len(resp.Svids)) + + // log details on each SVID + // a response has already been sent so nothing is + // blocked on this logic + for i, svid := range resp.Svids { + // Ideally ID Proto parsing should succeed, but if it fails, + // ignore the error and still log with empty spiffe_id. + ttl := time.Until(update.Identities[i].SVID[0].NotAfter) + log.WithFields(logrus.Fields{ + telemetry.SPIFFEID: svid.SpiffeId, + telemetry.TTL: ttl.Seconds(), + }).Debug("Fetched X.509 SVID for broker") + } + + return nil +} + +func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*brokerapi.X509SVIDResponse, error) { + resp := new(brokerapi.X509SVIDResponse) + resp.Svids = make([]*brokerapi.X509SVID, 0, len(update.Identities)) + + for _, identity := range update.Identities { + // Do not send admin nor downstream SVIDs to the caller + if identity.Entry.Admin || identity.Entry.Downstream { + continue + } + + // check if SVIDs exist for the identity + if len(identity.SVID) == 0 { + return nil, errors.New("unable to get SVID from identity") + } + + id, err := idutil.IDProtoFromString(identity.Entry.SpiffeId) + if err != nil { + return nil, fmt.Errorf("error during SPIFFE ID parsing: %w", err) + } + + keyData, err := x509.MarshalPKCS8PrivateKey(identity.PrivateKey) + if err != nil { + return nil, fmt.Errorf("marshal key for %v: %w", id, err) + } + + svid := &brokerapi.X509SVID{ + SpiffeId: id.String(), + X509Svid: x509util.DERFromCertificates(identity.SVID), + // TODO(arndt): what about bundle? + Hint: identity.Entry.Hint, + X509SvidKey: keyData, + } + resp.Svids = append(resp.Svids, svid) + } + return resp, nil +} + +func marshalBundle(certs []*x509.Certificate) []byte { + bundle := []byte{} + for _, c := range certs { + bundle = append(bundle, c.Raw...) + } + return bundle +} diff --git a/pkg/agent/broker/endpoints.go b/pkg/agent/broker/endpoints.go new file mode 100644 index 0000000000..225c994195 --- /dev/null +++ b/pkg/agent/broker/endpoints.go @@ -0,0 +1,165 @@ +package broker + +import ( + "context" + "fmt" + "net" + + "github.com/sirupsen/logrus" + "github.com/spiffe/go-spiffe/v2/spiffeid" + "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig" + attestor "github.com/spiffe/spire/pkg/agent/attestor/workload" + brokerapi "github.com/spiffe/spire/pkg/agent/broker/api" + "github.com/spiffe/spire/pkg/agent/endpoints" + "github.com/spiffe/spire/pkg/agent/manager" + "github.com/spiffe/spire/pkg/common/api/middleware" + "github.com/spiffe/spire/pkg/common/telemetry" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/reflection" + + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" + "github.com/spiffe/go-spiffe/v2/svid/x509svid" +) + +type Config struct { + BindAddr net.Addr + + Manager manager.Manager + + Log logrus.FieldLogger + + Metrics telemetry.Metrics + + Attestor attestor.Attestor + + TrustDomain spiffeid.TrustDomain + + AuthorizedDelegates []string + + SVIDSource x509svid.Source + BundleSource x509bundle.Source +} + +type Endpoints struct { + c *Config +} + +func New(c *Config) (*Endpoints, error) { + switch { + case c.BindAddr == nil: + return nil, fmt.Errorf("BindAddr is required") + case c.Manager == nil: + return nil, fmt.Errorf("Manager is required") + case c.Log == nil: + return nil, fmt.Errorf("Log is required") + case c.Metrics == nil: + return nil, fmt.Errorf("Metrics is required") + case c.Attestor == nil: + return nil, fmt.Errorf("Attestor is required") + case c.TrustDomain == spiffeid.TrustDomain{}: + return nil, fmt.Errorf("TrustDomain is required") + case c.SVIDSource == nil: + return nil, fmt.Errorf("SVIDSource is required") + case c.BundleSource == nil: + return nil, fmt.Errorf("BundleSource is required") + } + return &Endpoints{ + c: c, + }, nil +} + +func (e *Endpoints) ListenAndServe(ctx context.Context) error { + unaryInterceptor, streamInterceptor := middleware.Interceptors( + endpoints.Middleware(e.c.Log, e.c.Metrics), + ) + + // TODO(arndt): Delegated Identity API allows to be served without any authorized peer. + // I think it's better to fail as it's a misconfiguration and having that socket up + // without any authorized peer is just a potential security risk. + if len(e.c.AuthorizedDelegates) == 0 { + return fmt.Errorf("at least one authorized delegate is required") + } + + authorizedDelegates, err := delegatesFromStrings(e.c.AuthorizedDelegates, e.c.TrustDomain) + if err != nil { + return fmt.Errorf("failed to parse authorized delegates: %w", err) + } + + // In comparison to the admin endpoints, this API is secured by mutual TLS using X.509 SVIDs. + // Clients of this API are expected to use the Workload API to obtain their SVIDs first. + // This is to accommodate environments where this API is served over network. + tlsConfig := tlsconfig.MTLSServerConfig(e.c.SVIDSource, e.c.BundleSource, tlsconfig.AuthorizeOneOf(authorizedDelegates...)) + server := grpc.NewServer( + grpc.Creds(credentials.NewTLS(tlsConfig)), + grpc.UnaryInterceptor(unaryInterceptor), + grpc.StreamInterceptor(streamInterceptor), + ) + + e.registerBrokerAPI(server) + reflection.Register(server) + + var l net.Listener + switch e.c.BindAddr.Network() { + case "unix": + l, err = createUDSListener(e.c.BindAddr) + if err != nil { + return err + } + defer l.Close() + default: + return fmt.Errorf("unsupported network type %q for broker endpoint", e.c.BindAddr.Network()) + } + + log := e.c.Log.WithFields(logrus.Fields{ + telemetry.Network: l.Addr().Network(), + telemetry.Address: l.Addr().String()}) + log.Info("Starting SPIFFE Broker Endpoint") + + errChan := make(chan error) + go func() { errChan <- server.Serve(l) }() + + select { + case err = <-errChan: + log.WithError(err).Error("SPIFFE Broker Endpoint stopped prematurely") + return err + case <-ctx.Done(): + log.Info("Stopping SPIFFE Broker Endpoint") + server.Stop() + <-errChan + log.Info("SPIFFE Broker Endpoint has stopped") + return nil + } +} + +func (e *Endpoints) registerBrokerAPI(server *grpc.Server) { + service := brokerapi.New(brokerapi.Config{ + Manager: e.c.Manager, + Attestor: e.c.Attestor, + Metrics: e.c.Metrics, + Log: e.c.Log.WithField(telemetry.SubsystemName, telemetry.BrokerAPI), + }) + + brokerapi.RegisterService(server, service) +} + +func delegatesFromStrings(delegates []string, trustDomain spiffeid.TrustDomain) ([]spiffeid.ID, error) { + var ids []spiffeid.ID + for _, d := range delegates { + id, err := spiffeid.FromString(d) + if err != nil { + return nil, err + } + // TODO(arndt): This also differs from the admin API where it's possible to define delegates + // from other trust domains. Here we enforce that delegates must be in the same trust domain + // as the agent. + // I suppose technically it's not possible on the admin API to encounter this, but considering that + // the SPIFFE Broker Endpoint may be offered over the network in the future I think it's better to + // enforce this here. + if id.TrustDomain() != trustDomain { + return nil, fmt.Errorf("delegate %q is not in trust domain %q", d, trustDomain.Name()) + } + ids = append(ids, id) + } + return ids, nil +} diff --git a/pkg/agent/broker/endpoints_fallback.go b/pkg/agent/broker/endpoints_fallback.go new file mode 100644 index 0000000000..cf4fc353d8 --- /dev/null +++ b/pkg/agent/broker/endpoints_fallback.go @@ -0,0 +1,12 @@ +//go:build windows + +package broker + +import ( + "fmt" + "net" +) + +func createUDSListener(_ net.Addr) (net.Listener, error) { + return nil, fmt.Errorf("unsupported platform for broker API") +} diff --git a/pkg/agent/broker/endpoints_posix.go b/pkg/agent/broker/endpoints_posix.go new file mode 100644 index 0000000000..ef0f359c00 --- /dev/null +++ b/pkg/agent/broker/endpoints_posix.go @@ -0,0 +1,29 @@ +//go:build !windows + +package broker + +import ( + "fmt" + "net" + "os" + + "github.com/spiffe/spire/pkg/common/util" +) + +func createUDSListener(bindAddr net.Addr) (net.Listener, error) { + if bindAddr.Network() != "unix" { + return nil, fmt.Errorf("unsupported network type %q for UDS listener", bindAddr.Network()) + } + + // Remove uds if already exists + os.Remove(bindAddr.String()) + + l, err := net.ListenUnix(bindAddr.Network(), util.GetUnixAddr(bindAddr.String())) + if err != nil { + return nil, fmt.Errorf("error creating UDS listener: %w", err) + } + if err := os.Chmod(bindAddr.String(), 0770); err != nil { + return nil, fmt.Errorf("unable to change UDS permissions: %w", err) + } + return l, nil +} diff --git a/pkg/agent/config.go b/pkg/agent/config.go index 0163d2f7b9..5d35fd15ba 100644 --- a/pkg/agent/config.go +++ b/pkg/agent/config.go @@ -31,6 +31,9 @@ type Config struct { // Directory to bind the admin api to AdminBindAddress net.Addr + // Address to bind the broker endpoint to + BrokerBindAddress net.Addr + // The Validation Context resource name to use when fetching X.509 bundle together with federated bundles with Envoy SDS DefaultAllBundlesName string diff --git a/pkg/agent/manager/cache/bundle_cache.go b/pkg/agent/manager/cache/bundle_cache.go index 1f275ac630..5ffffc1d2a 100644 --- a/pkg/agent/manager/cache/bundle_cache.go +++ b/pkg/agent/manager/cache/bundle_cache.go @@ -1,15 +1,19 @@ package cache import ( + "fmt" "maps" "github.com/imkira/go-observer" "github.com/spiffe/go-spiffe/v2/bundle/spiffebundle" + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" "github.com/spiffe/go-spiffe/v2/spiffeid" ) type Bundle = spiffebundle.Bundle +var _ x509bundle.Source = (*BundleCache)(nil) + type BundleCache struct { trustDomain spiffeid.TrustDomain bundles observer.Property @@ -43,6 +47,15 @@ func (c *BundleCache) SubscribeToBundleChanges() *BundleStream { return NewBundleStream(c.bundles.Observe()) } +func (c *BundleCache) GetX509BundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*x509bundle.Bundle, error) { + bundles := c.Bundles() + bundle, ok := bundles[trustDomain] + if !ok { + return nil, fmt.Errorf("bundle for trust domain %q not found", trustDomain) + } + return bundle.X509Bundle(), nil +} + // Wraps an observer stream to provide a type safe interface type BundleStream struct { stream observer.Stream diff --git a/pkg/agent/manager/cache/lru_cache.go b/pkg/agent/manager/cache/lru_cache.go index e66e475db6..f21f545f8b 100644 --- a/pkg/agent/manager/cache/lru_cache.go +++ b/pkg/agent/manager/cache/lru_cache.go @@ -11,6 +11,7 @@ import ( "github.com/andres-erbsen/clock" "github.com/sirupsen/logrus" "github.com/spiffe/go-spiffe/v2/bundle/spiffebundle" + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" "github.com/spiffe/go-spiffe/v2/spiffeid" "github.com/spiffe/spire/pkg/common/backoff" "github.com/spiffe/spire/pkg/common/telemetry" @@ -585,6 +586,10 @@ func (c *LRUCache) SyncSVIDsWithSubscribers() { c.syncSVIDsWithSubscribers() } +func (c *LRUCache) X509Bundle() x509bundle.Source { + return c.BundleCache +} + // scheduleRotation processes SVID entries in batches, removing those tainted by X.509 authorities. // The process continues at regular intervals until all entries have been processed or the context is cancelled. func (c *LRUCache) scheduleRotation(ctx context.Context, entryIDs []string, taintedX509Authorities []*x509.Certificate) { diff --git a/pkg/agent/manager/manager.go b/pkg/agent/manager/manager.go index 28f6959954..426fdcf7e3 100644 --- a/pkg/agent/manager/manager.go +++ b/pkg/agent/manager/manager.go @@ -11,6 +11,7 @@ import ( "github.com/andres-erbsen/clock" observer "github.com/imkira/go-observer" "github.com/spiffe/go-spiffe/v2/bundle/spiffebundle" + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" "github.com/spiffe/go-spiffe/v2/spiffeid" "github.com/spiffe/spire/pkg/agent/client" "github.com/spiffe/spire/pkg/agent/manager/cache" @@ -93,6 +94,9 @@ type Manager interface { // GetBundle get latest cached bundle GetBundle() *cache.Bundle + + // GetX509Bundle returns an X509 bundle source + GetX509Bundle() x509bundle.Source } // Cache stores each registration entry, signed X509-SVIDs for those entries, @@ -135,6 +139,8 @@ type Cache interface { // Identities get all identities in cache Identities() []cache.Identity + + X509Bundle() x509bundle.Source } type manager struct { @@ -424,6 +430,10 @@ func (m *manager) GetBundle() *cache.Bundle { return m.cache.Bundle() } +func (m *manager) GetX509Bundle() x509bundle.Source { + return m.cache.X509Bundle() +} + func (m *manager) runSVIDObserver(ctx context.Context) error { svidStream := m.SubscribeToSVIDChanges() for { diff --git a/pkg/common/telemetry/names.go b/pkg/common/telemetry/names.go index e2bc775448..a04a177470 100644 --- a/pkg/common/telemetry/names.go +++ b/pkg/common/telemetry/names.go @@ -849,6 +849,9 @@ const ( // DelegatedIdentityAPI functionality related to delegated identity endpoints DelegatedIdentityAPI = "delegated_identity_api" + // BrokerAPI functionality related to delegated identity endpoints + BrokerAPI = "broker_api" + // DeleteFederatedBundle functionality related to deleting a federated bundle DeleteFederatedBundle = "delete_federated_bundle" diff --git a/proto/brokerapi/brokerapi.pb.go b/proto/brokerapi/brokerapi.pb.go new file mode 100644 index 0000000000..6aa24f05d5 --- /dev/null +++ b/proto/brokerapi/brokerapi.pb.go @@ -0,0 +1,844 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v6.32.1 +// source: brokerapi/brokerapi.proto + +package brokerapi + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The WorkloadReference message represents a single reference to a workload. +// The reference field contains one of the standard reference types or +// a vendor-specific extension type. +type WorkloadReference struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. The reference to the workload. + Reference *anypb.Any `protobuf:"bytes,1,opt,name=reference,proto3" json:"reference,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadReference) Reset() { + *x = WorkloadReference{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadReference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadReference) ProtoMessage() {} + +func (x *WorkloadReference) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadReference.ProtoReflect.Descriptor instead. +func (*WorkloadReference) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{0} +} + +func (x *WorkloadReference) GetReference() *anypb.Any { + if x != nil { + return x.Reference + } + return nil +} + +// The WorkloadPIDReference message conveys a process id reference of a workload +// running in the same environment. +type WorkloadPIDReference struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. The process id of the workload. MUST be a positive integer. + Pid int32 `protobuf:"varint,1,opt,name=pid,proto3" json:"pid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadPIDReference) Reset() { + *x = WorkloadPIDReference{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadPIDReference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadPIDReference) ProtoMessage() {} + +func (x *WorkloadPIDReference) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadPIDReference.ProtoReflect.Descriptor instead. +func (*WorkloadPIDReference) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{1} +} + +func (x *WorkloadPIDReference) GetPid() int32 { + if x != nil { + return x.Pid + } + return 0 +} + +// The X509SVIDRequest message conveys parameters for requesting an X.509-SVID. +type X509SVIDRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *X509SVIDRequest) Reset() { + *x = X509SVIDRequest{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *X509SVIDRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*X509SVIDRequest) ProtoMessage() {} + +func (x *X509SVIDRequest) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use X509SVIDRequest.ProtoReflect.Descriptor instead. +func (*X509SVIDRequest) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{2} +} + +func (x *X509SVIDRequest) GetReferences() []*WorkloadReference { + if x != nil { + return x.References + } + return nil +} + +// The X509SVIDResponse message carries X.509-SVIDs and related information, +// including a list of bundles the workload may use for federating with foreign +// trust domains. +type X509SVIDResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. A list of X509SVID messages, each of which includes a single + // X.509-SVID, its private key, and the bundle for the trust domain. + Svids []*X509SVID `protobuf:"bytes,1,rep,name=svids,proto3" json:"svids,omitempty"` + // Optional. ASN.1 DER encoded certificate revocation lists. + Crl [][]byte `protobuf:"bytes,2,rep,name=crl,proto3" json:"crl,omitempty"` + // Optional. CA certificate bundles belonging to foreign trust domains that + // the workload should trust, keyed by the SPIFFE ID of the foreign trust + // domain. Bundles are ASN.1 DER encoded. + FederatedBundles map[string][]byte `protobuf:"bytes,3,rep,name=federated_bundles,json=federatedBundles,proto3" json:"federated_bundles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *X509SVIDResponse) Reset() { + *x = X509SVIDResponse{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *X509SVIDResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*X509SVIDResponse) ProtoMessage() {} + +func (x *X509SVIDResponse) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use X509SVIDResponse.ProtoReflect.Descriptor instead. +func (*X509SVIDResponse) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{3} +} + +func (x *X509SVIDResponse) GetSvids() []*X509SVID { + if x != nil { + return x.Svids + } + return nil +} + +func (x *X509SVIDResponse) GetCrl() [][]byte { + if x != nil { + return x.Crl + } + return nil +} + +func (x *X509SVIDResponse) GetFederatedBundles() map[string][]byte { + if x != nil { + return x.FederatedBundles + } + return nil +} + +// The X509SVID message carries a single SVID and all associated information, +// including the X.509 bundle for the trust domain. +type X509SVID struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. The SPIFFE ID of the SVID in this entry + SpiffeId string `protobuf:"bytes,1,opt,name=spiffe_id,json=spiffeId,proto3" json:"spiffe_id,omitempty"` + // Required. ASN.1 DER encoded certificate chain. MAY include + // intermediates, the leaf certificate (or SVID itself) MUST come first. + X509Svid []byte `protobuf:"bytes,2,opt,name=x509_svid,json=x509Svid,proto3" json:"x509_svid,omitempty"` + // Required. ASN.1 DER encoded PKCS#8 private key. MUST be unencrypted. + X509SvidKey []byte `protobuf:"bytes,3,opt,name=x509_svid_key,json=x509SvidKey,proto3" json:"x509_svid_key,omitempty"` + // Required. ASN.1 DER encoded X.509 bundle for the trust domain. + Bundle []byte `protobuf:"bytes,4,opt,name=bundle,proto3" json:"bundle,omitempty"` + // Optional. An operator-specified string used to provide guidance on how this + // identity should be used by a broker or workload when more than one SVID is + // returned. For example, `internal` and `external` to indicate an SVID for + // internal or external use, respectively. + Hint string `protobuf:"bytes,5,opt,name=hint,proto3" json:"hint,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *X509SVID) Reset() { + *x = X509SVID{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *X509SVID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*X509SVID) ProtoMessage() {} + +func (x *X509SVID) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use X509SVID.ProtoReflect.Descriptor instead. +func (*X509SVID) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{4} +} + +func (x *X509SVID) GetSpiffeId() string { + if x != nil { + return x.SpiffeId + } + return "" +} + +func (x *X509SVID) GetX509Svid() []byte { + if x != nil { + return x.X509Svid + } + return nil +} + +func (x *X509SVID) GetX509SvidKey() []byte { + if x != nil { + return x.X509SvidKey + } + return nil +} + +func (x *X509SVID) GetBundle() []byte { + if x != nil { + return x.Bundle + } + return nil +} + +func (x *X509SVID) GetHint() string { + if x != nil { + return x.Hint + } + return "" +} + +// The X509BundlesRequest message conveys parameters for requesting X.509 +// bundles. +type X509BundlesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *X509BundlesRequest) Reset() { + *x = X509BundlesRequest{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *X509BundlesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*X509BundlesRequest) ProtoMessage() {} + +func (x *X509BundlesRequest) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use X509BundlesRequest.ProtoReflect.Descriptor instead. +func (*X509BundlesRequest) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{5} +} + +func (x *X509BundlesRequest) GetReferences() []*WorkloadReference { + if x != nil { + return x.References + } + return nil +} + +// The X509BundlesResponse message carries a map of trust bundles the workload +// should trust. +type X509BundlesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Optional. ASN.1 DER encoded certificate revocation lists. + Crl [][]byte `protobuf:"bytes,1,rep,name=crl,proto3" json:"crl,omitempty"` + // Required. CA certificate bundles belonging to trust domains that the + // workload should trust, keyed by the SPIFFE ID of the trust domain. + // Bundles are ASN.1 DER encoded. + Bundles map[string][]byte `protobuf:"bytes,2,rep,name=bundles,proto3" json:"bundles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *X509BundlesResponse) Reset() { + *x = X509BundlesResponse{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *X509BundlesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*X509BundlesResponse) ProtoMessage() {} + +func (x *X509BundlesResponse) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use X509BundlesResponse.ProtoReflect.Descriptor instead. +func (*X509BundlesResponse) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{6} +} + +func (x *X509BundlesResponse) GetCrl() [][]byte { + if x != nil { + return x.Crl + } + return nil +} + +func (x *X509BundlesResponse) GetBundles() map[string][]byte { + if x != nil { + return x.Bundles + } + return nil +} + +// The JWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. +type JWTSVIDRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` + // Required. The audience(s) the workload intends to authenticate against. + Audience []string `protobuf:"bytes,2,rep,name=audience,proto3" json:"audience,omitempty"` + // Optional. The requested SPIFFE ID for the JWT-SVID. If unset, all + // JWT-SVIDs to which the workload is entitled are requested. + SpiffeId string `protobuf:"bytes,3,opt,name=spiffe_id,json=spiffeId,proto3" json:"spiffe_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JWTSVIDRequest) Reset() { + *x = JWTSVIDRequest{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JWTSVIDRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JWTSVIDRequest) ProtoMessage() {} + +func (x *JWTSVIDRequest) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JWTSVIDRequest.ProtoReflect.Descriptor instead. +func (*JWTSVIDRequest) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{7} +} + +func (x *JWTSVIDRequest) GetReferences() []*WorkloadReference { + if x != nil { + return x.References + } + return nil +} + +func (x *JWTSVIDRequest) GetAudience() []string { + if x != nil { + return x.Audience + } + return nil +} + +func (x *JWTSVIDRequest) GetSpiffeId() string { + if x != nil { + return x.SpiffeId + } + return "" +} + +// The JWTSVIDResponse message conveys JWT-SVIDs. +type JWTSVIDResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. The list of returned JWT-SVIDs. + Svids []*JWTSVID `protobuf:"bytes,1,rep,name=svids,proto3" json:"svids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JWTSVIDResponse) Reset() { + *x = JWTSVIDResponse{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JWTSVIDResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JWTSVIDResponse) ProtoMessage() {} + +func (x *JWTSVIDResponse) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JWTSVIDResponse.ProtoReflect.Descriptor instead. +func (*JWTSVIDResponse) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{8} +} + +func (x *JWTSVIDResponse) GetSvids() []*JWTSVID { + if x != nil { + return x.Svids + } + return nil +} + +// The JWTSVID message carries the JWT-SVID token and associated metadata. +type JWTSVID struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. The SPIFFE ID of the JWT-SVID. + SpiffeId string `protobuf:"bytes,1,opt,name=spiffe_id,json=spiffeId,proto3" json:"spiffe_id,omitempty"` + // Required. Encoded JWT using JWS Compact Serialization. + Svid string `protobuf:"bytes,2,opt,name=svid,proto3" json:"svid,omitempty"` + // Optional. An operator-specified string used to provide guidance on how this + // identity should be used by a workload when more than one SVID is returned. + // For example, `internal` and `external` to indicate an SVID for internal or + // external use, respectively. + Hint string `protobuf:"bytes,3,opt,name=hint,proto3" json:"hint,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JWTSVID) Reset() { + *x = JWTSVID{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JWTSVID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JWTSVID) ProtoMessage() {} + +func (x *JWTSVID) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JWTSVID.ProtoReflect.Descriptor instead. +func (*JWTSVID) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{9} +} + +func (x *JWTSVID) GetSpiffeId() string { + if x != nil { + return x.SpiffeId + } + return "" +} + +func (x *JWTSVID) GetSvid() string { + if x != nil { + return x.Svid + } + return "" +} + +func (x *JWTSVID) GetHint() string { + if x != nil { + return x.Hint + } + return "" +} + +// The JWTBundlesRequest message conveys parameters for requesting JWT bundles. +type JWTBundlesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JWTBundlesRequest) Reset() { + *x = JWTBundlesRequest{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JWTBundlesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JWTBundlesRequest) ProtoMessage() {} + +func (x *JWTBundlesRequest) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JWTBundlesRequest.ProtoReflect.Descriptor instead. +func (*JWTBundlesRequest) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{10} +} + +func (x *JWTBundlesRequest) GetReferences() []*WorkloadReference { + if x != nil { + return x.References + } + return nil +} + +// The JWTBundlesReponse conveys JWT bundles. +type JWTBundlesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust + // domain. + Bundles map[string][]byte `protobuf:"bytes,1,rep,name=bundles,proto3" json:"bundles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JWTBundlesResponse) Reset() { + *x = JWTBundlesResponse{} + mi := &file_brokerapi_brokerapi_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JWTBundlesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JWTBundlesResponse) ProtoMessage() {} + +func (x *JWTBundlesResponse) ProtoReflect() protoreflect.Message { + mi := &file_brokerapi_brokerapi_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JWTBundlesResponse.ProtoReflect.Descriptor instead. +func (*JWTBundlesResponse) Descriptor() ([]byte, []int) { + return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{11} +} + +func (x *JWTBundlesResponse) GetBundles() map[string][]byte { + if x != nil { + return x.Bundles + } + return nil +} + +var File_brokerapi_brokerapi_proto protoreflect.FileDescriptor + +const file_brokerapi_brokerapi_proto_rawDesc = "" + + "\n" + + "\x19brokerapi/brokerapi.proto\x12\tbrokerapi\x1a\x19google/protobuf/any.proto\"G\n" + + "\x11WorkloadReference\x122\n" + + "\treference\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\treference\"(\n" + + "\x14WorkloadPIDReference\x12\x10\n" + + "\x03pid\x18\x01 \x01(\x05R\x03pid\"O\n" + + "\x0fX509SVIDRequest\x12<\n" + + "\n" + + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + + "references\"\xf4\x01\n" + + "\x10X509SVIDResponse\x12)\n" + + "\x05svids\x18\x01 \x03(\v2\x13.brokerapi.X509SVIDR\x05svids\x12\x10\n" + + "\x03crl\x18\x02 \x03(\fR\x03crl\x12^\n" + + "\x11federated_bundles\x18\x03 \x03(\v21.brokerapi.X509SVIDResponse.FederatedBundlesEntryR\x10federatedBundles\x1aC\n" + + "\x15FederatedBundlesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x94\x01\n" + + "\bX509SVID\x12\x1b\n" + + "\tspiffe_id\x18\x01 \x01(\tR\bspiffeId\x12\x1b\n" + + "\tx509_svid\x18\x02 \x01(\fR\bx509Svid\x12\"\n" + + "\rx509_svid_key\x18\x03 \x01(\fR\vx509SvidKey\x12\x16\n" + + "\x06bundle\x18\x04 \x01(\fR\x06bundle\x12\x12\n" + + "\x04hint\x18\x05 \x01(\tR\x04hint\"R\n" + + "\x12X509BundlesRequest\x12<\n" + + "\n" + + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + + "references\"\xaa\x01\n" + + "\x13X509BundlesResponse\x12\x10\n" + + "\x03crl\x18\x01 \x03(\fR\x03crl\x12E\n" + + "\abundles\x18\x02 \x03(\v2+.brokerapi.X509BundlesResponse.BundlesEntryR\abundles\x1a:\n" + + "\fBundlesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x87\x01\n" + + "\x0eJWTSVIDRequest\x12<\n" + + "\n" + + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + + "references\x12\x1a\n" + + "\baudience\x18\x02 \x03(\tR\baudience\x12\x1b\n" + + "\tspiffe_id\x18\x03 \x01(\tR\bspiffeId\";\n" + + "\x0fJWTSVIDResponse\x12(\n" + + "\x05svids\x18\x01 \x03(\v2\x12.brokerapi.JWTSVIDR\x05svids\"N\n" + + "\aJWTSVID\x12\x1b\n" + + "\tspiffe_id\x18\x01 \x01(\tR\bspiffeId\x12\x12\n" + + "\x04svid\x18\x02 \x01(\tR\x04svid\x12\x12\n" + + "\x04hint\x18\x03 \x01(\tR\x04hint\"Q\n" + + "\x11JWTBundlesRequest\x12<\n" + + "\n" + + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + + "references\"\x96\x01\n" + + "\x12JWTBundlesResponse\x12D\n" + + "\abundles\x18\x01 \x03(\v2*.brokerapi.JWTBundlesResponse.BundlesEntryR\abundles\x1a:\n" + + "\fBundlesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x012\xcb\x02\n" + + "\x0fSpiffeBrokerAPI\x12J\n" + + "\rFetchX509SVID\x12\x1a.brokerapi.X509SVIDRequest\x1a\x1b.brokerapi.X509SVIDResponse0\x01\x12S\n" + + "\x10FetchX509Bundles\x12\x1d.brokerapi.X509BundlesRequest\x1a\x1e.brokerapi.X509BundlesResponse0\x01\x12E\n" + + "\fFetchJWTSVID\x12\x19.brokerapi.JWTSVIDRequest\x1a\x1a.brokerapi.JWTSVIDResponse\x12P\n" + + "\x0fFetchJWTBundles\x12\x1c.brokerapi.JWTBundlesRequest\x1a\x1d.brokerapi.JWTBundlesResponse0\x01B)Z'github.com/spiffe/spire/proto/brokerapib\x06proto3" + +var ( + file_brokerapi_brokerapi_proto_rawDescOnce sync.Once + file_brokerapi_brokerapi_proto_rawDescData []byte +) + +func file_brokerapi_brokerapi_proto_rawDescGZIP() []byte { + file_brokerapi_brokerapi_proto_rawDescOnce.Do(func() { + file_brokerapi_brokerapi_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_brokerapi_brokerapi_proto_rawDesc), len(file_brokerapi_brokerapi_proto_rawDesc))) + }) + return file_brokerapi_brokerapi_proto_rawDescData +} + +var file_brokerapi_brokerapi_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_brokerapi_brokerapi_proto_goTypes = []any{ + (*WorkloadReference)(nil), // 0: brokerapi.WorkloadReference + (*WorkloadPIDReference)(nil), // 1: brokerapi.WorkloadPIDReference + (*X509SVIDRequest)(nil), // 2: brokerapi.X509SVIDRequest + (*X509SVIDResponse)(nil), // 3: brokerapi.X509SVIDResponse + (*X509SVID)(nil), // 4: brokerapi.X509SVID + (*X509BundlesRequest)(nil), // 5: brokerapi.X509BundlesRequest + (*X509BundlesResponse)(nil), // 6: brokerapi.X509BundlesResponse + (*JWTSVIDRequest)(nil), // 7: brokerapi.JWTSVIDRequest + (*JWTSVIDResponse)(nil), // 8: brokerapi.JWTSVIDResponse + (*JWTSVID)(nil), // 9: brokerapi.JWTSVID + (*JWTBundlesRequest)(nil), // 10: brokerapi.JWTBundlesRequest + (*JWTBundlesResponse)(nil), // 11: brokerapi.JWTBundlesResponse + nil, // 12: brokerapi.X509SVIDResponse.FederatedBundlesEntry + nil, // 13: brokerapi.X509BundlesResponse.BundlesEntry + nil, // 14: brokerapi.JWTBundlesResponse.BundlesEntry + (*anypb.Any)(nil), // 15: google.protobuf.Any +} +var file_brokerapi_brokerapi_proto_depIdxs = []int32{ + 15, // 0: brokerapi.WorkloadReference.reference:type_name -> google.protobuf.Any + 0, // 1: brokerapi.X509SVIDRequest.references:type_name -> brokerapi.WorkloadReference + 4, // 2: brokerapi.X509SVIDResponse.svids:type_name -> brokerapi.X509SVID + 12, // 3: brokerapi.X509SVIDResponse.federated_bundles:type_name -> brokerapi.X509SVIDResponse.FederatedBundlesEntry + 0, // 4: brokerapi.X509BundlesRequest.references:type_name -> brokerapi.WorkloadReference + 13, // 5: brokerapi.X509BundlesResponse.bundles:type_name -> brokerapi.X509BundlesResponse.BundlesEntry + 0, // 6: brokerapi.JWTSVIDRequest.references:type_name -> brokerapi.WorkloadReference + 9, // 7: brokerapi.JWTSVIDResponse.svids:type_name -> brokerapi.JWTSVID + 0, // 8: brokerapi.JWTBundlesRequest.references:type_name -> brokerapi.WorkloadReference + 14, // 9: brokerapi.JWTBundlesResponse.bundles:type_name -> brokerapi.JWTBundlesResponse.BundlesEntry + 2, // 10: brokerapi.SpiffeBrokerAPI.FetchX509SVID:input_type -> brokerapi.X509SVIDRequest + 5, // 11: brokerapi.SpiffeBrokerAPI.FetchX509Bundles:input_type -> brokerapi.X509BundlesRequest + 7, // 12: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:input_type -> brokerapi.JWTSVIDRequest + 10, // 13: brokerapi.SpiffeBrokerAPI.FetchJWTBundles:input_type -> brokerapi.JWTBundlesRequest + 3, // 14: brokerapi.SpiffeBrokerAPI.FetchX509SVID:output_type -> brokerapi.X509SVIDResponse + 6, // 15: brokerapi.SpiffeBrokerAPI.FetchX509Bundles:output_type -> brokerapi.X509BundlesResponse + 8, // 16: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:output_type -> brokerapi.JWTSVIDResponse + 11, // 17: brokerapi.SpiffeBrokerAPI.FetchJWTBundles:output_type -> brokerapi.JWTBundlesResponse + 14, // [14:18] is the sub-list for method output_type + 10, // [10:14] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_brokerapi_brokerapi_proto_init() } +func file_brokerapi_brokerapi_proto_init() { + if File_brokerapi_brokerapi_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_brokerapi_brokerapi_proto_rawDesc), len(file_brokerapi_brokerapi_proto_rawDesc)), + NumEnums: 0, + NumMessages: 15, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_brokerapi_brokerapi_proto_goTypes, + DependencyIndexes: file_brokerapi_brokerapi_proto_depIdxs, + MessageInfos: file_brokerapi_brokerapi_proto_msgTypes, + }.Build() + File_brokerapi_brokerapi_proto = out.File + file_brokerapi_brokerapi_proto_goTypes = nil + file_brokerapi_brokerapi_proto_depIdxs = nil +} diff --git a/proto/brokerapi/brokerapi.proto b/proto/brokerapi/brokerapi.proto new file mode 100644 index 0000000000..a2b9d8dec3 --- /dev/null +++ b/proto/brokerapi/brokerapi.proto @@ -0,0 +1,167 @@ +syntax = "proto3"; + +package brokerapi; + +import "google/protobuf/any.proto"; +option go_package = "github.com/spiffe/spire/proto/brokerapi"; + +service SpiffeBrokerAPI { + ///////////////////////////////////////////////////////////////////////// + // X509-SVID Profile + ///////////////////////////////////////////////////////////////////////// + + // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is + // entitled to, as well as related information like trust bundles. As this + // information changes, subsequent messages will be streamed from the server. + rpc FetchX509SVID(X509SVIDRequest) returns (stream X509SVIDResponse); + + // Fetch trust bundles of the referenced workload. Useful in situations that + // only need to validate SVIDs without obtaining an SVID for themself. As this + // information changes, subsequent messages will be streamed from the server. + rpc FetchX509Bundles(X509BundlesRequest) returns (stream X509BundlesResponse); + + ///////////////////////////////////////////////////////////////////////// + // JWT-SVID Profile + ///////////////////////////////////////////////////////////////////////// + + // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is + // entitled to, for the requested audience. If an optional SPIFFE ID is + // requested, only the JWT-SVID for that SPIFFE ID is returned. + rpc FetchJWTSVID(JWTSVIDRequest) returns (JWTSVIDResponse); + + // Fetches the JWT bundles, formatted as JWKS documents, keyed by the + // SPIFFE ID of the trust domain. As this information changes, subsequent + // messages will be streamed from the server. + rpc FetchJWTBundles(JWTBundlesRequest) returns (stream JWTBundlesResponse); +} + +// The WorkloadReference message represents a single reference to a workload. +// The reference field contains one of the standard reference types or +// a vendor-specific extension type. +message WorkloadReference { + // Required. The reference to the workload. + google.protobuf.Any reference = 1; +} + +// The WorkloadPIDReference message conveys a process id reference of a workload +// running in the same environment. +message WorkloadPIDReference { + // Required. The process id of the workload. MUST be a positive integer. + int32 pid = 1; +} + +// The X509SVIDRequest message conveys parameters for requesting an X.509-SVID. +message X509SVIDRequest { + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + repeated WorkloadReference references = 1; +} + +// The X509SVIDResponse message carries X.509-SVIDs and related information, +// including a list of bundles the workload may use for federating with foreign +// trust domains. +message X509SVIDResponse { + // Required. A list of X509SVID messages, each of which includes a single + // X.509-SVID, its private key, and the bundle for the trust domain. + repeated X509SVID svids = 1; + + // Optional. ASN.1 DER encoded certificate revocation lists. + repeated bytes crl = 2; + + // Optional. CA certificate bundles belonging to foreign trust domains that + // the workload should trust, keyed by the SPIFFE ID of the foreign trust + // domain. Bundles are ASN.1 DER encoded. + map federated_bundles = 3; +} + +// The X509SVID message carries a single SVID and all associated information, +// including the X.509 bundle for the trust domain. +message X509SVID { + // Required. The SPIFFE ID of the SVID in this entry + string spiffe_id = 1; + + // Required. ASN.1 DER encoded certificate chain. MAY include + // intermediates, the leaf certificate (or SVID itself) MUST come first. + bytes x509_svid = 2; + + // Required. ASN.1 DER encoded PKCS#8 private key. MUST be unencrypted. + bytes x509_svid_key = 3; + + // Required. ASN.1 DER encoded X.509 bundle for the trust domain. + bytes bundle = 4; + + // Optional. An operator-specified string used to provide guidance on how this + // identity should be used by a broker or workload when more than one SVID is + // returned. For example, `internal` and `external` to indicate an SVID for + // internal or external use, respectively. + string hint = 5; +} + +// The X509BundlesRequest message conveys parameters for requesting X.509 +// bundles. +message X509BundlesRequest { + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + repeated WorkloadReference references = 1; +} + +// The X509BundlesResponse message carries a map of trust bundles the workload +// should trust. +message X509BundlesResponse { + // Optional. ASN.1 DER encoded certificate revocation lists. + repeated bytes crl = 1; + + // Required. CA certificate bundles belonging to trust domains that the + // workload should trust, keyed by the SPIFFE ID of the trust domain. + // Bundles are ASN.1 DER encoded. + map bundles = 2; +} + +// The JWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. +message JWTSVIDRequest { + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + repeated WorkloadReference references = 1; + + // Required. The audience(s) the workload intends to authenticate against. + repeated string audience = 2; + + // Optional. The requested SPIFFE ID for the JWT-SVID. If unset, all + // JWT-SVIDs to which the workload is entitled are requested. + string spiffe_id = 3; +} + +// The JWTSVIDResponse message conveys JWT-SVIDs. +message JWTSVIDResponse { + // Required. The list of returned JWT-SVIDs. + repeated JWTSVID svids = 1; +} + +// The JWTSVID message carries the JWT-SVID token and associated metadata. +message JWTSVID { + // Required. The SPIFFE ID of the JWT-SVID. + string spiffe_id = 1; + + // Required. Encoded JWT using JWS Compact Serialization. + string svid = 2; + + // Optional. An operator-specified string used to provide guidance on how this + // identity should be used by a workload when more than one SVID is returned. + // For example, `internal` and `external` to indicate an SVID for internal or + // external use, respectively. + string hint = 3; +} + +// The JWTBundlesRequest message conveys parameters for requesting JWT bundles. +message JWTBundlesRequest { + // Required. One or more references identifying the workload. All references + // MUST resolve to the same workload. At least one reference is required. + repeated WorkloadReference references = 1; +} + +// The JWTBundlesReponse conveys JWT bundles. +message JWTBundlesResponse { + // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust + // domain. + map bundles = 1; +} \ No newline at end of file diff --git a/proto/brokerapi/brokerapi_grpc.pb.go b/proto/brokerapi/brokerapi_grpc.pb.go new file mode 100644 index 0000000000..bac428d3fc --- /dev/null +++ b/proto/brokerapi/brokerapi_grpc.pb.go @@ -0,0 +1,326 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v6.32.1 +// source: brokerapi/brokerapi.proto + +package brokerapi + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + SpiffeBrokerAPI_FetchX509SVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchX509SVID" + SpiffeBrokerAPI_FetchX509Bundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchX509Bundles" + SpiffeBrokerAPI_FetchJWTSVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchJWTSVID" + SpiffeBrokerAPI_FetchJWTBundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchJWTBundles" +) + +// SpiffeBrokerAPIClient is the client API for SpiffeBrokerAPI service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SpiffeBrokerAPIClient interface { + // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is + // entitled to, as well as related information like trust bundles. As this + // information changes, subsequent messages will be streamed from the server. + FetchX509SVID(ctx context.Context, in *X509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509SVIDClient, error) + // Fetch trust bundles of the referenced workload. Useful in situations that + // only need to validate SVIDs without obtaining an SVID for themself. As this + // information changes, subsequent messages will be streamed from the server. + FetchX509Bundles(ctx context.Context, in *X509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509BundlesClient, error) + // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is + // entitled to, for the requested audience. If an optional SPIFFE ID is + // requested, only the JWT-SVID for that SPIFFE ID is returned. + FetchJWTSVID(ctx context.Context, in *JWTSVIDRequest, opts ...grpc.CallOption) (*JWTSVIDResponse, error) + // Fetches the JWT bundles, formatted as JWKS documents, keyed by the + // SPIFFE ID of the trust domain. As this information changes, subsequent + // messages will be streamed from the server. + FetchJWTBundles(ctx context.Context, in *JWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchJWTBundlesClient, error) +} + +type spiffeBrokerAPIClient struct { + cc grpc.ClientConnInterface +} + +func NewSpiffeBrokerAPIClient(cc grpc.ClientConnInterface) SpiffeBrokerAPIClient { + return &spiffeBrokerAPIClient{cc} +} + +func (c *spiffeBrokerAPIClient) FetchX509SVID(ctx context.Context, in *X509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509SVIDClient, error) { + stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[0], SpiffeBrokerAPI_FetchX509SVID_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &spiffeBrokerAPIFetchX509SVIDClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type SpiffeBrokerAPI_FetchX509SVIDClient interface { + Recv() (*X509SVIDResponse, error) + grpc.ClientStream +} + +type spiffeBrokerAPIFetchX509SVIDClient struct { + grpc.ClientStream +} + +func (x *spiffeBrokerAPIFetchX509SVIDClient) Recv() (*X509SVIDResponse, error) { + m := new(X509SVIDResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *spiffeBrokerAPIClient) FetchX509Bundles(ctx context.Context, in *X509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509BundlesClient, error) { + stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[1], SpiffeBrokerAPI_FetchX509Bundles_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &spiffeBrokerAPIFetchX509BundlesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type SpiffeBrokerAPI_FetchX509BundlesClient interface { + Recv() (*X509BundlesResponse, error) + grpc.ClientStream +} + +type spiffeBrokerAPIFetchX509BundlesClient struct { + grpc.ClientStream +} + +func (x *spiffeBrokerAPIFetchX509BundlesClient) Recv() (*X509BundlesResponse, error) { + m := new(X509BundlesResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *spiffeBrokerAPIClient) FetchJWTSVID(ctx context.Context, in *JWTSVIDRequest, opts ...grpc.CallOption) (*JWTSVIDResponse, error) { + out := new(JWTSVIDResponse) + err := c.cc.Invoke(ctx, SpiffeBrokerAPI_FetchJWTSVID_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *spiffeBrokerAPIClient) FetchJWTBundles(ctx context.Context, in *JWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchJWTBundlesClient, error) { + stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[2], SpiffeBrokerAPI_FetchJWTBundles_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &spiffeBrokerAPIFetchJWTBundlesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type SpiffeBrokerAPI_FetchJWTBundlesClient interface { + Recv() (*JWTBundlesResponse, error) + grpc.ClientStream +} + +type spiffeBrokerAPIFetchJWTBundlesClient struct { + grpc.ClientStream +} + +func (x *spiffeBrokerAPIFetchJWTBundlesClient) Recv() (*JWTBundlesResponse, error) { + m := new(JWTBundlesResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// SpiffeBrokerAPIServer is the server API for SpiffeBrokerAPI service. +// All implementations must embed UnimplementedSpiffeBrokerAPIServer +// for forward compatibility +type SpiffeBrokerAPIServer interface { + // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is + // entitled to, as well as related information like trust bundles. As this + // information changes, subsequent messages will be streamed from the server. + FetchX509SVID(*X509SVIDRequest, SpiffeBrokerAPI_FetchX509SVIDServer) error + // Fetch trust bundles of the referenced workload. Useful in situations that + // only need to validate SVIDs without obtaining an SVID for themself. As this + // information changes, subsequent messages will be streamed from the server. + FetchX509Bundles(*X509BundlesRequest, SpiffeBrokerAPI_FetchX509BundlesServer) error + // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is + // entitled to, for the requested audience. If an optional SPIFFE ID is + // requested, only the JWT-SVID for that SPIFFE ID is returned. + FetchJWTSVID(context.Context, *JWTSVIDRequest) (*JWTSVIDResponse, error) + // Fetches the JWT bundles, formatted as JWKS documents, keyed by the + // SPIFFE ID of the trust domain. As this information changes, subsequent + // messages will be streamed from the server. + FetchJWTBundles(*JWTBundlesRequest, SpiffeBrokerAPI_FetchJWTBundlesServer) error + mustEmbedUnimplementedSpiffeBrokerAPIServer() +} + +// UnimplementedSpiffeBrokerAPIServer must be embedded to have forward compatible implementations. +type UnimplementedSpiffeBrokerAPIServer struct { +} + +func (UnimplementedSpiffeBrokerAPIServer) FetchX509SVID(*X509SVIDRequest, SpiffeBrokerAPI_FetchX509SVIDServer) error { + return status.Errorf(codes.Unimplemented, "method FetchX509SVID not implemented") +} +func (UnimplementedSpiffeBrokerAPIServer) FetchX509Bundles(*X509BundlesRequest, SpiffeBrokerAPI_FetchX509BundlesServer) error { + return status.Errorf(codes.Unimplemented, "method FetchX509Bundles not implemented") +} +func (UnimplementedSpiffeBrokerAPIServer) FetchJWTSVID(context.Context, *JWTSVIDRequest) (*JWTSVIDResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FetchJWTSVID not implemented") +} +func (UnimplementedSpiffeBrokerAPIServer) FetchJWTBundles(*JWTBundlesRequest, SpiffeBrokerAPI_FetchJWTBundlesServer) error { + return status.Errorf(codes.Unimplemented, "method FetchJWTBundles not implemented") +} +func (UnimplementedSpiffeBrokerAPIServer) mustEmbedUnimplementedSpiffeBrokerAPIServer() {} + +// UnsafeSpiffeBrokerAPIServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SpiffeBrokerAPIServer will +// result in compilation errors. +type UnsafeSpiffeBrokerAPIServer interface { + mustEmbedUnimplementedSpiffeBrokerAPIServer() +} + +func RegisterSpiffeBrokerAPIServer(s grpc.ServiceRegistrar, srv SpiffeBrokerAPIServer) { + s.RegisterService(&SpiffeBrokerAPI_ServiceDesc, srv) +} + +func _SpiffeBrokerAPI_FetchX509SVID_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(X509SVIDRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SpiffeBrokerAPIServer).FetchX509SVID(m, &spiffeBrokerAPIFetchX509SVIDServer{stream}) +} + +type SpiffeBrokerAPI_FetchX509SVIDServer interface { + Send(*X509SVIDResponse) error + grpc.ServerStream +} + +type spiffeBrokerAPIFetchX509SVIDServer struct { + grpc.ServerStream +} + +func (x *spiffeBrokerAPIFetchX509SVIDServer) Send(m *X509SVIDResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _SpiffeBrokerAPI_FetchX509Bundles_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(X509BundlesRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SpiffeBrokerAPIServer).FetchX509Bundles(m, &spiffeBrokerAPIFetchX509BundlesServer{stream}) +} + +type SpiffeBrokerAPI_FetchX509BundlesServer interface { + Send(*X509BundlesResponse) error + grpc.ServerStream +} + +type spiffeBrokerAPIFetchX509BundlesServer struct { + grpc.ServerStream +} + +func (x *spiffeBrokerAPIFetchX509BundlesServer) Send(m *X509BundlesResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _SpiffeBrokerAPI_FetchJWTSVID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(JWTSVIDRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SpiffeBrokerAPIServer).FetchJWTSVID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SpiffeBrokerAPI_FetchJWTSVID_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SpiffeBrokerAPIServer).FetchJWTSVID(ctx, req.(*JWTSVIDRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SpiffeBrokerAPI_FetchJWTBundles_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(JWTBundlesRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SpiffeBrokerAPIServer).FetchJWTBundles(m, &spiffeBrokerAPIFetchJWTBundlesServer{stream}) +} + +type SpiffeBrokerAPI_FetchJWTBundlesServer interface { + Send(*JWTBundlesResponse) error + grpc.ServerStream +} + +type spiffeBrokerAPIFetchJWTBundlesServer struct { + grpc.ServerStream +} + +func (x *spiffeBrokerAPIFetchJWTBundlesServer) Send(m *JWTBundlesResponse) error { + return x.ServerStream.SendMsg(m) +} + +// SpiffeBrokerAPI_ServiceDesc is the grpc.ServiceDesc for SpiffeBrokerAPI service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SpiffeBrokerAPI_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "brokerapi.SpiffeBrokerAPI", + HandlerType: (*SpiffeBrokerAPIServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "FetchJWTSVID", + Handler: _SpiffeBrokerAPI_FetchJWTSVID_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "FetchX509SVID", + Handler: _SpiffeBrokerAPI_FetchX509SVID_Handler, + ServerStreams: true, + }, + { + StreamName: "FetchX509Bundles", + Handler: _SpiffeBrokerAPI_FetchX509Bundles_Handler, + ServerStreams: true, + }, + { + StreamName: "FetchJWTBundles", + Handler: _SpiffeBrokerAPI_FetchJWTBundles_Handler, + ServerStreams: true, + }, + }, + Metadata: "brokerapi/brokerapi.proto", +} From ba52838e16cf840a304fed0f99b61cf47beb329e Mon Sep 17 00:00:00 2001 From: arndt-s <17650715+arndt-s@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:29:58 +0100 Subject: [PATCH 2/4] add bundles to response, change rpc names --- pkg/agent/broker/api/service.go | 37 ++-- proto/brokerapi/brokerapi.pb.go | 290 +++++++++++++-------------- proto/brokerapi/brokerapi.proto | 40 ++-- proto/brokerapi/brokerapi_grpc.pb.go | 148 +++++++------- 4 files changed, 261 insertions(+), 254 deletions(-) diff --git a/pkg/agent/broker/api/service.go b/pkg/agent/broker/api/service.go index 9f3b0ff155..d1935e2a91 100644 --- a/pkg/agent/broker/api/service.go +++ b/pkg/agent/broker/api/service.go @@ -64,7 +64,7 @@ func (s *Service) getCallerContext(ctx context.Context) (spiffeid.ID, error) { return peer, nil } -func (s *Service) FetchX509SVID(req *brokerapi.X509SVIDRequest, stream brokerapi.SpiffeBrokerAPI_FetchX509SVIDServer) error { +func (s *Service) SubscribeToX509SVID(req *brokerapi.SubscribeToX509SVIDRequest, stream brokerapi.SpiffeBrokerAPI_SubscribeToX509SVIDServer) error { latency := adminapi.StartFirstX509SVIDUpdateLatency(s.metrics) ctx := stream.Context() log := rpccontext.Logger(ctx) @@ -110,7 +110,7 @@ func (s *Service) FetchX509SVID(req *brokerapi.X509SVIDRequest, stream brokerapi } } -func (s *Service) FetchX509Bundles(_ *brokerapi.X509BundlesRequest, stream brokerapi.SpiffeBrokerAPI_FetchX509BundlesServer) error { +func (s *Service) SubscribeToX509Bundles(_ *brokerapi.SubscribeToX509BundlesRequest, stream brokerapi.SpiffeBrokerAPI_SubscribeToX509BundlesServer) error { ctx := stream.Context() peer, err := s.getCallerContext(ctx) @@ -127,7 +127,7 @@ func (s *Service) FetchX509Bundles(_ *brokerapi.X509BundlesRequest, stream broke caCerts[td.IDString()] = marshalBundle(bundle.X509Authorities()) } - resp := &brokerapi.X509BundlesResponse{ + resp := &brokerapi.SubscribeToX509BundlesResponse{ Bundles: caCerts, } @@ -142,7 +142,7 @@ func (s *Service) FetchX509Bundles(_ *brokerapi.X509BundlesRequest, stream broke caCerts[td.IDString()] = marshalBundle(bundle.X509Authorities()) } - resp := &brokerapi.X509BundlesResponse{ + resp := &brokerapi.SubscribeToX509BundlesResponse{ Bundles: caCerts, } @@ -156,7 +156,7 @@ func (s *Service) FetchX509Bundles(_ *brokerapi.X509BundlesRequest, stream broke } } -func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.JWTSVIDRequest) (*brokerapi.JWTSVIDResponse, error) { +func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.FetchJWTSVIDRequest) (*brokerapi.FetchJWTSVIDResponse, error) { log := rpccontext.Logger(ctx) if len(req.Audience) == 0 { log.Error("Missing required audience parameter") @@ -174,7 +174,7 @@ func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.JWTSVIDReques return nil, err } - resp := new(brokerapi.JWTSVIDResponse) + resp := new(brokerapi.FetchJWTSVIDResponse) entries := s.manager.MatchingRegistrationEntries(selectors) for _, entry := range entries { spiffeID, err := spiffeid.FromString(entry.SpiffeId) @@ -209,7 +209,7 @@ func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.JWTSVIDReques return resp, nil } -func (s *Service) FetchJWTBundles(_ *brokerapi.JWTBundlesRequest, stream brokerapi.SpiffeBrokerAPI_FetchJWTBundlesServer) error { +func (s *Service) SubscribeToJWTBundles(_ *brokerapi.SubscribeToJWTBundlesRequest, stream brokerapi.SpiffeBrokerAPI_SubscribeToJWTBundlesServer) error { ctx := stream.Context() peer, err := s.getCallerContext(ctx) @@ -230,7 +230,7 @@ func (s *Service) FetchJWTBundles(_ *brokerapi.JWTBundlesRequest, stream brokera jwtbundles[td.IDString()] = jwksBytes } - resp := &brokerapi.JWTBundlesResponse{ + resp := &brokerapi.SubscribeToJWTBundlesResponse{ Bundles: jwtbundles, } @@ -248,7 +248,7 @@ func (s *Service) FetchJWTBundles(_ *brokerapi.JWTBundlesRequest, stream brokera jwtbundles[td.IDString()] = jwksBytes } - resp := &brokerapi.JWTBundlesResponse{ + resp := &brokerapi.SubscribeToJWTBundlesResponse{ Bundles: jwtbundles, } if err := stream.Send(resp); err != nil { @@ -291,7 +291,7 @@ func (s *Service) constructValidSelectorsFromReferences(ctx context.Context, log } } -func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream brokerapi.SpiffeBrokerAPI_FetchX509SVIDServer, log logrus.FieldLogger) (err error) { +func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream brokerapi.SpiffeBrokerAPI_SubscribeToX509SVIDServer, log logrus.FieldLogger) (err error) { resp, err := composeX509SVIDBySelectors(update) if err != nil { log.WithError(err).Error("Could not serialize X.509 SVID response") @@ -321,10 +321,12 @@ func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream brokerapi.SpiffeB return nil } -func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*brokerapi.X509SVIDResponse, error) { - resp := new(brokerapi.X509SVIDResponse) +func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*brokerapi.SubscribeToX509SVIDResponse, error) { + resp := new(brokerapi.SubscribeToX509SVIDResponse) resp.Svids = make([]*brokerapi.X509SVID, 0, len(update.Identities)) + resp.FederatedBundles = make(map[string][]byte, len(update.FederatedBundles)) + x509Bundle := marshalBundle(update.Bundle.X509Authorities()) for _, identity := range update.Identities { // Do not send admin nor downstream SVIDs to the caller if identity.Entry.Admin || identity.Entry.Downstream { @@ -347,14 +349,19 @@ func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*brokerapi.X509SV } svid := &brokerapi.X509SVID{ - SpiffeId: id.String(), - X509Svid: x509util.DERFromCertificates(identity.SVID), - // TODO(arndt): what about bundle? + SpiffeId: id.String(), + X509Svid: x509util.DERFromCertificates(identity.SVID), + Bundle: x509Bundle, Hint: identity.Entry.Hint, X509SvidKey: keyData, } resp.Svids = append(resp.Svids, svid) } + + for td, bundle := range update.FederatedBundles { + resp.FederatedBundles[td.IDString()] = marshalBundle(bundle.X509Authorities()) + } + return resp, nil } diff --git a/proto/brokerapi/brokerapi.pb.go b/proto/brokerapi/brokerapi.pb.go index 6aa24f05d5..554af2e7ce 100644 --- a/proto/brokerapi/brokerapi.pb.go +++ b/proto/brokerapi/brokerapi.pb.go @@ -117,8 +117,8 @@ func (x *WorkloadPIDReference) GetPid() int32 { return 0 } -// The X509SVIDRequest message conveys parameters for requesting an X.509-SVID. -type X509SVIDRequest struct { +// The SubscribeToX509SVIDRequest message conveys parameters for requesting an X.509-SVID. +type SubscribeToX509SVIDRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. @@ -127,20 +127,20 @@ type X509SVIDRequest struct { sizeCache protoimpl.SizeCache } -func (x *X509SVIDRequest) Reset() { - *x = X509SVIDRequest{} +func (x *SubscribeToX509SVIDRequest) Reset() { + *x = SubscribeToX509SVIDRequest{} mi := &file_brokerapi_brokerapi_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *X509SVIDRequest) String() string { +func (x *SubscribeToX509SVIDRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*X509SVIDRequest) ProtoMessage() {} +func (*SubscribeToX509SVIDRequest) ProtoMessage() {} -func (x *X509SVIDRequest) ProtoReflect() protoreflect.Message { +func (x *SubscribeToX509SVIDRequest) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -152,22 +152,22 @@ func (x *X509SVIDRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use X509SVIDRequest.ProtoReflect.Descriptor instead. -func (*X509SVIDRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use SubscribeToX509SVIDRequest.ProtoReflect.Descriptor instead. +func (*SubscribeToX509SVIDRequest) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{2} } -func (x *X509SVIDRequest) GetReferences() []*WorkloadReference { +func (x *SubscribeToX509SVIDRequest) GetReferences() []*WorkloadReference { if x != nil { return x.References } return nil } -// The X509SVIDResponse message carries X.509-SVIDs and related information, +// The SubscribeToX509SVIDResponse message carries X.509-SVIDs and related information, // including a list of bundles the workload may use for federating with foreign // trust domains. -type X509SVIDResponse struct { +type SubscribeToX509SVIDResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. A list of X509SVID messages, each of which includes a single // X.509-SVID, its private key, and the bundle for the trust domain. @@ -182,20 +182,20 @@ type X509SVIDResponse struct { sizeCache protoimpl.SizeCache } -func (x *X509SVIDResponse) Reset() { - *x = X509SVIDResponse{} +func (x *SubscribeToX509SVIDResponse) Reset() { + *x = SubscribeToX509SVIDResponse{} mi := &file_brokerapi_brokerapi_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *X509SVIDResponse) String() string { +func (x *SubscribeToX509SVIDResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*X509SVIDResponse) ProtoMessage() {} +func (*SubscribeToX509SVIDResponse) ProtoMessage() {} -func (x *X509SVIDResponse) ProtoReflect() protoreflect.Message { +func (x *SubscribeToX509SVIDResponse) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -207,26 +207,26 @@ func (x *X509SVIDResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use X509SVIDResponse.ProtoReflect.Descriptor instead. -func (*X509SVIDResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use SubscribeToX509SVIDResponse.ProtoReflect.Descriptor instead. +func (*SubscribeToX509SVIDResponse) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{3} } -func (x *X509SVIDResponse) GetSvids() []*X509SVID { +func (x *SubscribeToX509SVIDResponse) GetSvids() []*X509SVID { if x != nil { return x.Svids } return nil } -func (x *X509SVIDResponse) GetCrl() [][]byte { +func (x *SubscribeToX509SVIDResponse) GetCrl() [][]byte { if x != nil { return x.Crl } return nil } -func (x *X509SVIDResponse) GetFederatedBundles() map[string][]byte { +func (x *SubscribeToX509SVIDResponse) GetFederatedBundles() map[string][]byte { if x != nil { return x.FederatedBundles } @@ -320,9 +320,9 @@ func (x *X509SVID) GetHint() string { return "" } -// The X509BundlesRequest message conveys parameters for requesting X.509 +// The SubscribeToX509BundlesRequest message conveys parameters for requesting X.509 // bundles. -type X509BundlesRequest struct { +type SubscribeToX509BundlesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. @@ -331,20 +331,20 @@ type X509BundlesRequest struct { sizeCache protoimpl.SizeCache } -func (x *X509BundlesRequest) Reset() { - *x = X509BundlesRequest{} +func (x *SubscribeToX509BundlesRequest) Reset() { + *x = SubscribeToX509BundlesRequest{} mi := &file_brokerapi_brokerapi_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *X509BundlesRequest) String() string { +func (x *SubscribeToX509BundlesRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*X509BundlesRequest) ProtoMessage() {} +func (*SubscribeToX509BundlesRequest) ProtoMessage() {} -func (x *X509BundlesRequest) ProtoReflect() protoreflect.Message { +func (x *SubscribeToX509BundlesRequest) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -356,21 +356,21 @@ func (x *X509BundlesRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use X509BundlesRequest.ProtoReflect.Descriptor instead. -func (*X509BundlesRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use SubscribeToX509BundlesRequest.ProtoReflect.Descriptor instead. +func (*SubscribeToX509BundlesRequest) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{5} } -func (x *X509BundlesRequest) GetReferences() []*WorkloadReference { +func (x *SubscribeToX509BundlesRequest) GetReferences() []*WorkloadReference { if x != nil { return x.References } return nil } -// The X509BundlesResponse message carries a map of trust bundles the workload +// The SubscribeToX509BundlesResponse message carries a map of trust bundles the workload // should trust. -type X509BundlesResponse struct { +type SubscribeToX509BundlesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Optional. ASN.1 DER encoded certificate revocation lists. Crl [][]byte `protobuf:"bytes,1,rep,name=crl,proto3" json:"crl,omitempty"` @@ -382,20 +382,20 @@ type X509BundlesResponse struct { sizeCache protoimpl.SizeCache } -func (x *X509BundlesResponse) Reset() { - *x = X509BundlesResponse{} +func (x *SubscribeToX509BundlesResponse) Reset() { + *x = SubscribeToX509BundlesResponse{} mi := &file_brokerapi_brokerapi_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *X509BundlesResponse) String() string { +func (x *SubscribeToX509BundlesResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*X509BundlesResponse) ProtoMessage() {} +func (*SubscribeToX509BundlesResponse) ProtoMessage() {} -func (x *X509BundlesResponse) ProtoReflect() protoreflect.Message { +func (x *SubscribeToX509BundlesResponse) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -407,27 +407,27 @@ func (x *X509BundlesResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use X509BundlesResponse.ProtoReflect.Descriptor instead. -func (*X509BundlesResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use SubscribeToX509BundlesResponse.ProtoReflect.Descriptor instead. +func (*SubscribeToX509BundlesResponse) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{6} } -func (x *X509BundlesResponse) GetCrl() [][]byte { +func (x *SubscribeToX509BundlesResponse) GetCrl() [][]byte { if x != nil { return x.Crl } return nil } -func (x *X509BundlesResponse) GetBundles() map[string][]byte { +func (x *SubscribeToX509BundlesResponse) GetBundles() map[string][]byte { if x != nil { return x.Bundles } return nil } -// The JWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. -type JWTSVIDRequest struct { +// The FetchJWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. +type FetchJWTSVIDRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. @@ -441,20 +441,20 @@ type JWTSVIDRequest struct { sizeCache protoimpl.SizeCache } -func (x *JWTSVIDRequest) Reset() { - *x = JWTSVIDRequest{} +func (x *FetchJWTSVIDRequest) Reset() { + *x = FetchJWTSVIDRequest{} mi := &file_brokerapi_brokerapi_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *JWTSVIDRequest) String() string { +func (x *FetchJWTSVIDRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*JWTSVIDRequest) ProtoMessage() {} +func (*FetchJWTSVIDRequest) ProtoMessage() {} -func (x *JWTSVIDRequest) ProtoReflect() protoreflect.Message { +func (x *FetchJWTSVIDRequest) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -466,34 +466,34 @@ func (x *JWTSVIDRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use JWTSVIDRequest.ProtoReflect.Descriptor instead. -func (*JWTSVIDRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use FetchJWTSVIDRequest.ProtoReflect.Descriptor instead. +func (*FetchJWTSVIDRequest) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{7} } -func (x *JWTSVIDRequest) GetReferences() []*WorkloadReference { +func (x *FetchJWTSVIDRequest) GetReferences() []*WorkloadReference { if x != nil { return x.References } return nil } -func (x *JWTSVIDRequest) GetAudience() []string { +func (x *FetchJWTSVIDRequest) GetAudience() []string { if x != nil { return x.Audience } return nil } -func (x *JWTSVIDRequest) GetSpiffeId() string { +func (x *FetchJWTSVIDRequest) GetSpiffeId() string { if x != nil { return x.SpiffeId } return "" } -// The JWTSVIDResponse message conveys JWT-SVIDs. -type JWTSVIDResponse struct { +// The FetchJWTSVIDResponse message conveys JWT-SVIDs. +type FetchJWTSVIDResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The list of returned JWT-SVIDs. Svids []*JWTSVID `protobuf:"bytes,1,rep,name=svids,proto3" json:"svids,omitempty"` @@ -501,20 +501,20 @@ type JWTSVIDResponse struct { sizeCache protoimpl.SizeCache } -func (x *JWTSVIDResponse) Reset() { - *x = JWTSVIDResponse{} +func (x *FetchJWTSVIDResponse) Reset() { + *x = FetchJWTSVIDResponse{} mi := &file_brokerapi_brokerapi_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *JWTSVIDResponse) String() string { +func (x *FetchJWTSVIDResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*JWTSVIDResponse) ProtoMessage() {} +func (*FetchJWTSVIDResponse) ProtoMessage() {} -func (x *JWTSVIDResponse) ProtoReflect() protoreflect.Message { +func (x *FetchJWTSVIDResponse) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -526,12 +526,12 @@ func (x *JWTSVIDResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use JWTSVIDResponse.ProtoReflect.Descriptor instead. -func (*JWTSVIDResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use FetchJWTSVIDResponse.ProtoReflect.Descriptor instead. +func (*FetchJWTSVIDResponse) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{8} } -func (x *JWTSVIDResponse) GetSvids() []*JWTSVID { +func (x *FetchJWTSVIDResponse) GetSvids() []*JWTSVID { if x != nil { return x.Svids } @@ -605,8 +605,8 @@ func (x *JWTSVID) GetHint() string { return "" } -// The JWTBundlesRequest message conveys parameters for requesting JWT bundles. -type JWTBundlesRequest struct { +// The SubscribeToJWTBundlesRequest message conveys parameters for requesting JWT bundles. +type SubscribeToJWTBundlesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. @@ -615,20 +615,20 @@ type JWTBundlesRequest struct { sizeCache protoimpl.SizeCache } -func (x *JWTBundlesRequest) Reset() { - *x = JWTBundlesRequest{} +func (x *SubscribeToJWTBundlesRequest) Reset() { + *x = SubscribeToJWTBundlesRequest{} mi := &file_brokerapi_brokerapi_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *JWTBundlesRequest) String() string { +func (x *SubscribeToJWTBundlesRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*JWTBundlesRequest) ProtoMessage() {} +func (*SubscribeToJWTBundlesRequest) ProtoMessage() {} -func (x *JWTBundlesRequest) ProtoReflect() protoreflect.Message { +func (x *SubscribeToJWTBundlesRequest) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -640,20 +640,20 @@ func (x *JWTBundlesRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use JWTBundlesRequest.ProtoReflect.Descriptor instead. -func (*JWTBundlesRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use SubscribeToJWTBundlesRequest.ProtoReflect.Descriptor instead. +func (*SubscribeToJWTBundlesRequest) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{10} } -func (x *JWTBundlesRequest) GetReferences() []*WorkloadReference { +func (x *SubscribeToJWTBundlesRequest) GetReferences() []*WorkloadReference { if x != nil { return x.References } return nil } -// The JWTBundlesReponse conveys JWT bundles. -type JWTBundlesResponse struct { +// The SubscribeToJWTBundlesResponse message conveys JWT bundles. +type SubscribeToJWTBundlesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust // domain. @@ -662,20 +662,20 @@ type JWTBundlesResponse struct { sizeCache protoimpl.SizeCache } -func (x *JWTBundlesResponse) Reset() { - *x = JWTBundlesResponse{} +func (x *SubscribeToJWTBundlesResponse) Reset() { + *x = SubscribeToJWTBundlesResponse{} mi := &file_brokerapi_brokerapi_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *JWTBundlesResponse) String() string { +func (x *SubscribeToJWTBundlesResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*JWTBundlesResponse) ProtoMessage() {} +func (*SubscribeToJWTBundlesResponse) ProtoMessage() {} -func (x *JWTBundlesResponse) ProtoReflect() protoreflect.Message { +func (x *SubscribeToJWTBundlesResponse) ProtoReflect() protoreflect.Message { mi := &file_brokerapi_brokerapi_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -687,12 +687,12 @@ func (x *JWTBundlesResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use JWTBundlesResponse.ProtoReflect.Descriptor instead. -func (*JWTBundlesResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use SubscribeToJWTBundlesResponse.ProtoReflect.Descriptor instead. +func (*SubscribeToJWTBundlesResponse) Descriptor() ([]byte, []int) { return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{11} } -func (x *JWTBundlesResponse) GetBundles() map[string][]byte { +func (x *SubscribeToJWTBundlesResponse) GetBundles() map[string][]byte { if x != nil { return x.Bundles } @@ -707,15 +707,15 @@ const file_brokerapi_brokerapi_proto_rawDesc = "" + "\x11WorkloadReference\x122\n" + "\treference\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\treference\"(\n" + "\x14WorkloadPIDReference\x12\x10\n" + - "\x03pid\x18\x01 \x01(\x05R\x03pid\"O\n" + - "\x0fX509SVIDRequest\x12<\n" + + "\x03pid\x18\x01 \x01(\x05R\x03pid\"Z\n" + + "\x1aSubscribeToX509SVIDRequest\x12<\n" + "\n" + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\"\xf4\x01\n" + - "\x10X509SVIDResponse\x12)\n" + + "references\"\x8a\x02\n" + + "\x1bSubscribeToX509SVIDResponse\x12)\n" + "\x05svids\x18\x01 \x03(\v2\x13.brokerapi.X509SVIDR\x05svids\x12\x10\n" + - "\x03crl\x18\x02 \x03(\fR\x03crl\x12^\n" + - "\x11federated_bundles\x18\x03 \x03(\v21.brokerapi.X509SVIDResponse.FederatedBundlesEntryR\x10federatedBundles\x1aC\n" + + "\x03crl\x18\x02 \x03(\fR\x03crl\x12i\n" + + "\x11federated_bundles\x18\x03 \x03(\v2<.brokerapi.SubscribeToX509SVIDResponse.FederatedBundlesEntryR\x10federatedBundles\x1aC\n" + "\x15FederatedBundlesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x94\x01\n" + @@ -724,43 +724,43 @@ const file_brokerapi_brokerapi_proto_rawDesc = "" + "\tx509_svid\x18\x02 \x01(\fR\bx509Svid\x12\"\n" + "\rx509_svid_key\x18\x03 \x01(\fR\vx509SvidKey\x12\x16\n" + "\x06bundle\x18\x04 \x01(\fR\x06bundle\x12\x12\n" + - "\x04hint\x18\x05 \x01(\tR\x04hint\"R\n" + - "\x12X509BundlesRequest\x12<\n" + + "\x04hint\x18\x05 \x01(\tR\x04hint\"]\n" + + "\x1dSubscribeToX509BundlesRequest\x12<\n" + "\n" + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\"\xaa\x01\n" + - "\x13X509BundlesResponse\x12\x10\n" + - "\x03crl\x18\x01 \x03(\fR\x03crl\x12E\n" + - "\abundles\x18\x02 \x03(\v2+.brokerapi.X509BundlesResponse.BundlesEntryR\abundles\x1a:\n" + + "references\"\xc0\x01\n" + + "\x1eSubscribeToX509BundlesResponse\x12\x10\n" + + "\x03crl\x18\x01 \x03(\fR\x03crl\x12P\n" + + "\abundles\x18\x02 \x03(\v26.brokerapi.SubscribeToX509BundlesResponse.BundlesEntryR\abundles\x1a:\n" + "\fBundlesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x87\x01\n" + - "\x0eJWTSVIDRequest\x12<\n" + + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x8c\x01\n" + + "\x13FetchJWTSVIDRequest\x12<\n" + "\n" + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + "references\x12\x1a\n" + "\baudience\x18\x02 \x03(\tR\baudience\x12\x1b\n" + - "\tspiffe_id\x18\x03 \x01(\tR\bspiffeId\";\n" + - "\x0fJWTSVIDResponse\x12(\n" + + "\tspiffe_id\x18\x03 \x01(\tR\bspiffeId\"@\n" + + "\x14FetchJWTSVIDResponse\x12(\n" + "\x05svids\x18\x01 \x03(\v2\x12.brokerapi.JWTSVIDR\x05svids\"N\n" + "\aJWTSVID\x12\x1b\n" + "\tspiffe_id\x18\x01 \x01(\tR\bspiffeId\x12\x12\n" + "\x04svid\x18\x02 \x01(\tR\x04svid\x12\x12\n" + - "\x04hint\x18\x03 \x01(\tR\x04hint\"Q\n" + - "\x11JWTBundlesRequest\x12<\n" + + "\x04hint\x18\x03 \x01(\tR\x04hint\"\\\n" + + "\x1cSubscribeToJWTBundlesRequest\x12<\n" + "\n" + "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\"\x96\x01\n" + - "\x12JWTBundlesResponse\x12D\n" + - "\abundles\x18\x01 \x03(\v2*.brokerapi.JWTBundlesResponse.BundlesEntryR\abundles\x1a:\n" + + "references\"\xac\x01\n" + + "\x1dSubscribeToJWTBundlesResponse\x12O\n" + + "\abundles\x18\x01 \x03(\v25.brokerapi.SubscribeToJWTBundlesResponse.BundlesEntryR\abundles\x1a:\n" + "\fBundlesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\fR\x05value:\x028\x012\xcb\x02\n" + - "\x0fSpiffeBrokerAPI\x12J\n" + - "\rFetchX509SVID\x12\x1a.brokerapi.X509SVIDRequest\x1a\x1b.brokerapi.X509SVIDResponse0\x01\x12S\n" + - "\x10FetchX509Bundles\x12\x1d.brokerapi.X509BundlesRequest\x1a\x1e.brokerapi.X509BundlesResponse0\x01\x12E\n" + - "\fFetchJWTSVID\x12\x19.brokerapi.JWTSVIDRequest\x1a\x1a.brokerapi.JWTSVIDResponse\x12P\n" + - "\x0fFetchJWTBundles\x12\x1c.brokerapi.JWTBundlesRequest\x1a\x1d.brokerapi.JWTBundlesResponse0\x01B)Z'github.com/spiffe/spire/proto/brokerapib\x06proto3" + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x012\xa9\x03\n" + + "\x0fSpiffeBrokerAPI\x12f\n" + + "\x13SubscribeToX509SVID\x12%.brokerapi.SubscribeToX509SVIDRequest\x1a&.brokerapi.SubscribeToX509SVIDResponse0\x01\x12o\n" + + "\x16SubscribeToX509Bundles\x12(.brokerapi.SubscribeToX509BundlesRequest\x1a).brokerapi.SubscribeToX509BundlesResponse0\x01\x12O\n" + + "\fFetchJWTSVID\x12\x1e.brokerapi.FetchJWTSVIDRequest\x1a\x1f.brokerapi.FetchJWTSVIDResponse\x12l\n" + + "\x15SubscribeToJWTBundles\x12'.brokerapi.SubscribeToJWTBundlesRequest\x1a(.brokerapi.SubscribeToJWTBundlesResponse0\x01B)Z'github.com/spiffe/spire/proto/brokerapib\x06proto3" var ( file_brokerapi_brokerapi_proto_rawDescOnce sync.Once @@ -776,42 +776,42 @@ func file_brokerapi_brokerapi_proto_rawDescGZIP() []byte { var file_brokerapi_brokerapi_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_brokerapi_brokerapi_proto_goTypes = []any{ - (*WorkloadReference)(nil), // 0: brokerapi.WorkloadReference - (*WorkloadPIDReference)(nil), // 1: brokerapi.WorkloadPIDReference - (*X509SVIDRequest)(nil), // 2: brokerapi.X509SVIDRequest - (*X509SVIDResponse)(nil), // 3: brokerapi.X509SVIDResponse - (*X509SVID)(nil), // 4: brokerapi.X509SVID - (*X509BundlesRequest)(nil), // 5: brokerapi.X509BundlesRequest - (*X509BundlesResponse)(nil), // 6: brokerapi.X509BundlesResponse - (*JWTSVIDRequest)(nil), // 7: brokerapi.JWTSVIDRequest - (*JWTSVIDResponse)(nil), // 8: brokerapi.JWTSVIDResponse - (*JWTSVID)(nil), // 9: brokerapi.JWTSVID - (*JWTBundlesRequest)(nil), // 10: brokerapi.JWTBundlesRequest - (*JWTBundlesResponse)(nil), // 11: brokerapi.JWTBundlesResponse - nil, // 12: brokerapi.X509SVIDResponse.FederatedBundlesEntry - nil, // 13: brokerapi.X509BundlesResponse.BundlesEntry - nil, // 14: brokerapi.JWTBundlesResponse.BundlesEntry - (*anypb.Any)(nil), // 15: google.protobuf.Any + (*WorkloadReference)(nil), // 0: brokerapi.WorkloadReference + (*WorkloadPIDReference)(nil), // 1: brokerapi.WorkloadPIDReference + (*SubscribeToX509SVIDRequest)(nil), // 2: brokerapi.SubscribeToX509SVIDRequest + (*SubscribeToX509SVIDResponse)(nil), // 3: brokerapi.SubscribeToX509SVIDResponse + (*X509SVID)(nil), // 4: brokerapi.X509SVID + (*SubscribeToX509BundlesRequest)(nil), // 5: brokerapi.SubscribeToX509BundlesRequest + (*SubscribeToX509BundlesResponse)(nil), // 6: brokerapi.SubscribeToX509BundlesResponse + (*FetchJWTSVIDRequest)(nil), // 7: brokerapi.FetchJWTSVIDRequest + (*FetchJWTSVIDResponse)(nil), // 8: brokerapi.FetchJWTSVIDResponse + (*JWTSVID)(nil), // 9: brokerapi.JWTSVID + (*SubscribeToJWTBundlesRequest)(nil), // 10: brokerapi.SubscribeToJWTBundlesRequest + (*SubscribeToJWTBundlesResponse)(nil), // 11: brokerapi.SubscribeToJWTBundlesResponse + nil, // 12: brokerapi.SubscribeToX509SVIDResponse.FederatedBundlesEntry + nil, // 13: brokerapi.SubscribeToX509BundlesResponse.BundlesEntry + nil, // 14: brokerapi.SubscribeToJWTBundlesResponse.BundlesEntry + (*anypb.Any)(nil), // 15: google.protobuf.Any } var file_brokerapi_brokerapi_proto_depIdxs = []int32{ 15, // 0: brokerapi.WorkloadReference.reference:type_name -> google.protobuf.Any - 0, // 1: brokerapi.X509SVIDRequest.references:type_name -> brokerapi.WorkloadReference - 4, // 2: brokerapi.X509SVIDResponse.svids:type_name -> brokerapi.X509SVID - 12, // 3: brokerapi.X509SVIDResponse.federated_bundles:type_name -> brokerapi.X509SVIDResponse.FederatedBundlesEntry - 0, // 4: brokerapi.X509BundlesRequest.references:type_name -> brokerapi.WorkloadReference - 13, // 5: brokerapi.X509BundlesResponse.bundles:type_name -> brokerapi.X509BundlesResponse.BundlesEntry - 0, // 6: brokerapi.JWTSVIDRequest.references:type_name -> brokerapi.WorkloadReference - 9, // 7: brokerapi.JWTSVIDResponse.svids:type_name -> brokerapi.JWTSVID - 0, // 8: brokerapi.JWTBundlesRequest.references:type_name -> brokerapi.WorkloadReference - 14, // 9: brokerapi.JWTBundlesResponse.bundles:type_name -> brokerapi.JWTBundlesResponse.BundlesEntry - 2, // 10: brokerapi.SpiffeBrokerAPI.FetchX509SVID:input_type -> brokerapi.X509SVIDRequest - 5, // 11: brokerapi.SpiffeBrokerAPI.FetchX509Bundles:input_type -> brokerapi.X509BundlesRequest - 7, // 12: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:input_type -> brokerapi.JWTSVIDRequest - 10, // 13: brokerapi.SpiffeBrokerAPI.FetchJWTBundles:input_type -> brokerapi.JWTBundlesRequest - 3, // 14: brokerapi.SpiffeBrokerAPI.FetchX509SVID:output_type -> brokerapi.X509SVIDResponse - 6, // 15: brokerapi.SpiffeBrokerAPI.FetchX509Bundles:output_type -> brokerapi.X509BundlesResponse - 8, // 16: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:output_type -> brokerapi.JWTSVIDResponse - 11, // 17: brokerapi.SpiffeBrokerAPI.FetchJWTBundles:output_type -> brokerapi.JWTBundlesResponse + 0, // 1: brokerapi.SubscribeToX509SVIDRequest.references:type_name -> brokerapi.WorkloadReference + 4, // 2: brokerapi.SubscribeToX509SVIDResponse.svids:type_name -> brokerapi.X509SVID + 12, // 3: brokerapi.SubscribeToX509SVIDResponse.federated_bundles:type_name -> brokerapi.SubscribeToX509SVIDResponse.FederatedBundlesEntry + 0, // 4: brokerapi.SubscribeToX509BundlesRequest.references:type_name -> brokerapi.WorkloadReference + 13, // 5: brokerapi.SubscribeToX509BundlesResponse.bundles:type_name -> brokerapi.SubscribeToX509BundlesResponse.BundlesEntry + 0, // 6: brokerapi.FetchJWTSVIDRequest.references:type_name -> brokerapi.WorkloadReference + 9, // 7: brokerapi.FetchJWTSVIDResponse.svids:type_name -> brokerapi.JWTSVID + 0, // 8: brokerapi.SubscribeToJWTBundlesRequest.references:type_name -> brokerapi.WorkloadReference + 14, // 9: brokerapi.SubscribeToJWTBundlesResponse.bundles:type_name -> brokerapi.SubscribeToJWTBundlesResponse.BundlesEntry + 2, // 10: brokerapi.SpiffeBrokerAPI.SubscribeToX509SVID:input_type -> brokerapi.SubscribeToX509SVIDRequest + 5, // 11: brokerapi.SpiffeBrokerAPI.SubscribeToX509Bundles:input_type -> brokerapi.SubscribeToX509BundlesRequest + 7, // 12: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:input_type -> brokerapi.FetchJWTSVIDRequest + 10, // 13: brokerapi.SpiffeBrokerAPI.SubscribeToJWTBundles:input_type -> brokerapi.SubscribeToJWTBundlesRequest + 3, // 14: brokerapi.SpiffeBrokerAPI.SubscribeToX509SVID:output_type -> brokerapi.SubscribeToX509SVIDResponse + 6, // 15: brokerapi.SpiffeBrokerAPI.SubscribeToX509Bundles:output_type -> brokerapi.SubscribeToX509BundlesResponse + 8, // 16: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:output_type -> brokerapi.FetchJWTSVIDResponse + 11, // 17: brokerapi.SpiffeBrokerAPI.SubscribeToJWTBundles:output_type -> brokerapi.SubscribeToJWTBundlesResponse 14, // [14:18] is the sub-list for method output_type 10, // [10:14] is the sub-list for method input_type 10, // [10:10] is the sub-list for extension type_name diff --git a/proto/brokerapi/brokerapi.proto b/proto/brokerapi/brokerapi.proto index a2b9d8dec3..64662229a7 100644 --- a/proto/brokerapi/brokerapi.proto +++ b/proto/brokerapi/brokerapi.proto @@ -13,12 +13,12 @@ service SpiffeBrokerAPI { // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is // entitled to, as well as related information like trust bundles. As this // information changes, subsequent messages will be streamed from the server. - rpc FetchX509SVID(X509SVIDRequest) returns (stream X509SVIDResponse); + rpc SubscribeToX509SVID(SubscribeToX509SVIDRequest) returns (stream SubscribeToX509SVIDResponse); // Fetch trust bundles of the referenced workload. Useful in situations that // only need to validate SVIDs without obtaining an SVID for themself. As this // information changes, subsequent messages will be streamed from the server. - rpc FetchX509Bundles(X509BundlesRequest) returns (stream X509BundlesResponse); + rpc SubscribeToX509Bundles(SubscribeToX509BundlesRequest) returns (stream SubscribeToX509BundlesResponse); ///////////////////////////////////////////////////////////////////////// // JWT-SVID Profile @@ -27,12 +27,12 @@ service SpiffeBrokerAPI { // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is // entitled to, for the requested audience. If an optional SPIFFE ID is // requested, only the JWT-SVID for that SPIFFE ID is returned. - rpc FetchJWTSVID(JWTSVIDRequest) returns (JWTSVIDResponse); + rpc FetchJWTSVID(FetchJWTSVIDRequest) returns (FetchJWTSVIDResponse); // Fetches the JWT bundles, formatted as JWKS documents, keyed by the // SPIFFE ID of the trust domain. As this information changes, subsequent // messages will be streamed from the server. - rpc FetchJWTBundles(JWTBundlesRequest) returns (stream JWTBundlesResponse); + rpc SubscribeToJWTBundles(SubscribeToJWTBundlesRequest) returns (stream SubscribeToJWTBundlesResponse); } // The WorkloadReference message represents a single reference to a workload. @@ -50,17 +50,17 @@ message WorkloadPIDReference { int32 pid = 1; } -// The X509SVIDRequest message conveys parameters for requesting an X.509-SVID. -message X509SVIDRequest { +// The SubscribeToX509SVIDRequest message conveys parameters for requesting an X.509-SVID. +message SubscribeToX509SVIDRequest { // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. repeated WorkloadReference references = 1; } -// The X509SVIDResponse message carries X.509-SVIDs and related information, +// The SubscribeToX509SVIDResponse message carries X.509-SVIDs and related information, // including a list of bundles the workload may use for federating with foreign // trust domains. -message X509SVIDResponse { +message SubscribeToX509SVIDResponse { // Required. A list of X509SVID messages, each of which includes a single // X.509-SVID, its private key, and the bundle for the trust domain. repeated X509SVID svids = 1; @@ -97,17 +97,17 @@ message X509SVID { string hint = 5; } -// The X509BundlesRequest message conveys parameters for requesting X.509 +// The SubscribeToX509BundlesRequest message conveys parameters for requesting X.509 // bundles. -message X509BundlesRequest { +message SubscribeToX509BundlesRequest { // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. repeated WorkloadReference references = 1; } -// The X509BundlesResponse message carries a map of trust bundles the workload +// The SubscribeToX509BundlesResponse message carries a map of trust bundles the workload // should trust. -message X509BundlesResponse { +message SubscribeToX509BundlesResponse { // Optional. ASN.1 DER encoded certificate revocation lists. repeated bytes crl = 1; @@ -117,8 +117,8 @@ message X509BundlesResponse { map bundles = 2; } -// The JWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. -message JWTSVIDRequest { +// The FetchJWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. +message FetchJWTSVIDRequest { // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. repeated WorkloadReference references = 1; @@ -131,8 +131,8 @@ message JWTSVIDRequest { string spiffe_id = 3; } -// The JWTSVIDResponse message conveys JWT-SVIDs. -message JWTSVIDResponse { +// The FetchJWTSVIDResponse message conveys JWT-SVIDs. +message FetchJWTSVIDResponse { // Required. The list of returned JWT-SVIDs. repeated JWTSVID svids = 1; } @@ -152,15 +152,15 @@ message JWTSVID { string hint = 3; } -// The JWTBundlesRequest message conveys parameters for requesting JWT bundles. -message JWTBundlesRequest { +// The SubscribeToJWTBundlesRequest message conveys parameters for requesting JWT bundles. +message SubscribeToJWTBundlesRequest { // Required. One or more references identifying the workload. All references // MUST resolve to the same workload. At least one reference is required. repeated WorkloadReference references = 1; } -// The JWTBundlesReponse conveys JWT bundles. -message JWTBundlesResponse { +// The SubscribeToJWTBundlesResponse message conveys JWT bundles. +message SubscribeToJWTBundlesResponse { // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust // domain. map bundles = 1; diff --git a/proto/brokerapi/brokerapi_grpc.pb.go b/proto/brokerapi/brokerapi_grpc.pb.go index bac428d3fc..8ccebd0ab5 100644 --- a/proto/brokerapi/brokerapi_grpc.pb.go +++ b/proto/brokerapi/brokerapi_grpc.pb.go @@ -19,10 +19,10 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - SpiffeBrokerAPI_FetchX509SVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchX509SVID" - SpiffeBrokerAPI_FetchX509Bundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchX509Bundles" - SpiffeBrokerAPI_FetchJWTSVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchJWTSVID" - SpiffeBrokerAPI_FetchJWTBundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchJWTBundles" + SpiffeBrokerAPI_SubscribeToX509SVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/SubscribeToX509SVID" + SpiffeBrokerAPI_SubscribeToX509Bundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/SubscribeToX509Bundles" + SpiffeBrokerAPI_FetchJWTSVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchJWTSVID" + SpiffeBrokerAPI_SubscribeToJWTBundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/SubscribeToJWTBundles" ) // SpiffeBrokerAPIClient is the client API for SpiffeBrokerAPI service. @@ -32,19 +32,19 @@ type SpiffeBrokerAPIClient interface { // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is // entitled to, as well as related information like trust bundles. As this // information changes, subsequent messages will be streamed from the server. - FetchX509SVID(ctx context.Context, in *X509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509SVIDClient, error) + SubscribeToX509SVID(ctx context.Context, in *SubscribeToX509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509SVIDClient, error) // Fetch trust bundles of the referenced workload. Useful in situations that // only need to validate SVIDs without obtaining an SVID for themself. As this // information changes, subsequent messages will be streamed from the server. - FetchX509Bundles(ctx context.Context, in *X509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509BundlesClient, error) + SubscribeToX509Bundles(ctx context.Context, in *SubscribeToX509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509BundlesClient, error) // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is // entitled to, for the requested audience. If an optional SPIFFE ID is // requested, only the JWT-SVID for that SPIFFE ID is returned. - FetchJWTSVID(ctx context.Context, in *JWTSVIDRequest, opts ...grpc.CallOption) (*JWTSVIDResponse, error) + FetchJWTSVID(ctx context.Context, in *FetchJWTSVIDRequest, opts ...grpc.CallOption) (*FetchJWTSVIDResponse, error) // Fetches the JWT bundles, formatted as JWKS documents, keyed by the // SPIFFE ID of the trust domain. As this information changes, subsequent // messages will be streamed from the server. - FetchJWTBundles(ctx context.Context, in *JWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchJWTBundlesClient, error) + SubscribeToJWTBundles(ctx context.Context, in *SubscribeToJWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToJWTBundlesClient, error) } type spiffeBrokerAPIClient struct { @@ -55,12 +55,12 @@ func NewSpiffeBrokerAPIClient(cc grpc.ClientConnInterface) SpiffeBrokerAPIClient return &spiffeBrokerAPIClient{cc} } -func (c *spiffeBrokerAPIClient) FetchX509SVID(ctx context.Context, in *X509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509SVIDClient, error) { - stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[0], SpiffeBrokerAPI_FetchX509SVID_FullMethodName, opts...) +func (c *spiffeBrokerAPIClient) SubscribeToX509SVID(ctx context.Context, in *SubscribeToX509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509SVIDClient, error) { + stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[0], SpiffeBrokerAPI_SubscribeToX509SVID_FullMethodName, opts...) if err != nil { return nil, err } - x := &spiffeBrokerAPIFetchX509SVIDClient{stream} + x := &spiffeBrokerAPISubscribeToX509SVIDClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -70,29 +70,29 @@ func (c *spiffeBrokerAPIClient) FetchX509SVID(ctx context.Context, in *X509SVIDR return x, nil } -type SpiffeBrokerAPI_FetchX509SVIDClient interface { - Recv() (*X509SVIDResponse, error) +type SpiffeBrokerAPI_SubscribeToX509SVIDClient interface { + Recv() (*SubscribeToX509SVIDResponse, error) grpc.ClientStream } -type spiffeBrokerAPIFetchX509SVIDClient struct { +type spiffeBrokerAPISubscribeToX509SVIDClient struct { grpc.ClientStream } -func (x *spiffeBrokerAPIFetchX509SVIDClient) Recv() (*X509SVIDResponse, error) { - m := new(X509SVIDResponse) +func (x *spiffeBrokerAPISubscribeToX509SVIDClient) Recv() (*SubscribeToX509SVIDResponse, error) { + m := new(SubscribeToX509SVIDResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } -func (c *spiffeBrokerAPIClient) FetchX509Bundles(ctx context.Context, in *X509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchX509BundlesClient, error) { - stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[1], SpiffeBrokerAPI_FetchX509Bundles_FullMethodName, opts...) +func (c *spiffeBrokerAPIClient) SubscribeToX509Bundles(ctx context.Context, in *SubscribeToX509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509BundlesClient, error) { + stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[1], SpiffeBrokerAPI_SubscribeToX509Bundles_FullMethodName, opts...) if err != nil { return nil, err } - x := &spiffeBrokerAPIFetchX509BundlesClient{stream} + x := &spiffeBrokerAPISubscribeToX509BundlesClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -102,25 +102,25 @@ func (c *spiffeBrokerAPIClient) FetchX509Bundles(ctx context.Context, in *X509Bu return x, nil } -type SpiffeBrokerAPI_FetchX509BundlesClient interface { - Recv() (*X509BundlesResponse, error) +type SpiffeBrokerAPI_SubscribeToX509BundlesClient interface { + Recv() (*SubscribeToX509BundlesResponse, error) grpc.ClientStream } -type spiffeBrokerAPIFetchX509BundlesClient struct { +type spiffeBrokerAPISubscribeToX509BundlesClient struct { grpc.ClientStream } -func (x *spiffeBrokerAPIFetchX509BundlesClient) Recv() (*X509BundlesResponse, error) { - m := new(X509BundlesResponse) +func (x *spiffeBrokerAPISubscribeToX509BundlesClient) Recv() (*SubscribeToX509BundlesResponse, error) { + m := new(SubscribeToX509BundlesResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } -func (c *spiffeBrokerAPIClient) FetchJWTSVID(ctx context.Context, in *JWTSVIDRequest, opts ...grpc.CallOption) (*JWTSVIDResponse, error) { - out := new(JWTSVIDResponse) +func (c *spiffeBrokerAPIClient) FetchJWTSVID(ctx context.Context, in *FetchJWTSVIDRequest, opts ...grpc.CallOption) (*FetchJWTSVIDResponse, error) { + out := new(FetchJWTSVIDResponse) err := c.cc.Invoke(ctx, SpiffeBrokerAPI_FetchJWTSVID_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -128,12 +128,12 @@ func (c *spiffeBrokerAPIClient) FetchJWTSVID(ctx context.Context, in *JWTSVIDReq return out, nil } -func (c *spiffeBrokerAPIClient) FetchJWTBundles(ctx context.Context, in *JWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_FetchJWTBundlesClient, error) { - stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[2], SpiffeBrokerAPI_FetchJWTBundles_FullMethodName, opts...) +func (c *spiffeBrokerAPIClient) SubscribeToJWTBundles(ctx context.Context, in *SubscribeToJWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToJWTBundlesClient, error) { + stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[2], SpiffeBrokerAPI_SubscribeToJWTBundles_FullMethodName, opts...) if err != nil { return nil, err } - x := &spiffeBrokerAPIFetchJWTBundlesClient{stream} + x := &spiffeBrokerAPISubscribeToJWTBundlesClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -143,17 +143,17 @@ func (c *spiffeBrokerAPIClient) FetchJWTBundles(ctx context.Context, in *JWTBund return x, nil } -type SpiffeBrokerAPI_FetchJWTBundlesClient interface { - Recv() (*JWTBundlesResponse, error) +type SpiffeBrokerAPI_SubscribeToJWTBundlesClient interface { + Recv() (*SubscribeToJWTBundlesResponse, error) grpc.ClientStream } -type spiffeBrokerAPIFetchJWTBundlesClient struct { +type spiffeBrokerAPISubscribeToJWTBundlesClient struct { grpc.ClientStream } -func (x *spiffeBrokerAPIFetchJWTBundlesClient) Recv() (*JWTBundlesResponse, error) { - m := new(JWTBundlesResponse) +func (x *spiffeBrokerAPISubscribeToJWTBundlesClient) Recv() (*SubscribeToJWTBundlesResponse, error) { + m := new(SubscribeToJWTBundlesResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } @@ -167,19 +167,19 @@ type SpiffeBrokerAPIServer interface { // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is // entitled to, as well as related information like trust bundles. As this // information changes, subsequent messages will be streamed from the server. - FetchX509SVID(*X509SVIDRequest, SpiffeBrokerAPI_FetchX509SVIDServer) error + SubscribeToX509SVID(*SubscribeToX509SVIDRequest, SpiffeBrokerAPI_SubscribeToX509SVIDServer) error // Fetch trust bundles of the referenced workload. Useful in situations that // only need to validate SVIDs without obtaining an SVID for themself. As this // information changes, subsequent messages will be streamed from the server. - FetchX509Bundles(*X509BundlesRequest, SpiffeBrokerAPI_FetchX509BundlesServer) error + SubscribeToX509Bundles(*SubscribeToX509BundlesRequest, SpiffeBrokerAPI_SubscribeToX509BundlesServer) error // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is // entitled to, for the requested audience. If an optional SPIFFE ID is // requested, only the JWT-SVID for that SPIFFE ID is returned. - FetchJWTSVID(context.Context, *JWTSVIDRequest) (*JWTSVIDResponse, error) + FetchJWTSVID(context.Context, *FetchJWTSVIDRequest) (*FetchJWTSVIDResponse, error) // Fetches the JWT bundles, formatted as JWKS documents, keyed by the // SPIFFE ID of the trust domain. As this information changes, subsequent // messages will be streamed from the server. - FetchJWTBundles(*JWTBundlesRequest, SpiffeBrokerAPI_FetchJWTBundlesServer) error + SubscribeToJWTBundles(*SubscribeToJWTBundlesRequest, SpiffeBrokerAPI_SubscribeToJWTBundlesServer) error mustEmbedUnimplementedSpiffeBrokerAPIServer() } @@ -187,17 +187,17 @@ type SpiffeBrokerAPIServer interface { type UnimplementedSpiffeBrokerAPIServer struct { } -func (UnimplementedSpiffeBrokerAPIServer) FetchX509SVID(*X509SVIDRequest, SpiffeBrokerAPI_FetchX509SVIDServer) error { - return status.Errorf(codes.Unimplemented, "method FetchX509SVID not implemented") +func (UnimplementedSpiffeBrokerAPIServer) SubscribeToX509SVID(*SubscribeToX509SVIDRequest, SpiffeBrokerAPI_SubscribeToX509SVIDServer) error { + return status.Errorf(codes.Unimplemented, "method SubscribeToX509SVID not implemented") } -func (UnimplementedSpiffeBrokerAPIServer) FetchX509Bundles(*X509BundlesRequest, SpiffeBrokerAPI_FetchX509BundlesServer) error { - return status.Errorf(codes.Unimplemented, "method FetchX509Bundles not implemented") +func (UnimplementedSpiffeBrokerAPIServer) SubscribeToX509Bundles(*SubscribeToX509BundlesRequest, SpiffeBrokerAPI_SubscribeToX509BundlesServer) error { + return status.Errorf(codes.Unimplemented, "method SubscribeToX509Bundles not implemented") } -func (UnimplementedSpiffeBrokerAPIServer) FetchJWTSVID(context.Context, *JWTSVIDRequest) (*JWTSVIDResponse, error) { +func (UnimplementedSpiffeBrokerAPIServer) FetchJWTSVID(context.Context, *FetchJWTSVIDRequest) (*FetchJWTSVIDResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method FetchJWTSVID not implemented") } -func (UnimplementedSpiffeBrokerAPIServer) FetchJWTBundles(*JWTBundlesRequest, SpiffeBrokerAPI_FetchJWTBundlesServer) error { - return status.Errorf(codes.Unimplemented, "method FetchJWTBundles not implemented") +func (UnimplementedSpiffeBrokerAPIServer) SubscribeToJWTBundles(*SubscribeToJWTBundlesRequest, SpiffeBrokerAPI_SubscribeToJWTBundlesServer) error { + return status.Errorf(codes.Unimplemented, "method SubscribeToJWTBundles not implemented") } func (UnimplementedSpiffeBrokerAPIServer) mustEmbedUnimplementedSpiffeBrokerAPIServer() {} @@ -212,50 +212,50 @@ func RegisterSpiffeBrokerAPIServer(s grpc.ServiceRegistrar, srv SpiffeBrokerAPIS s.RegisterService(&SpiffeBrokerAPI_ServiceDesc, srv) } -func _SpiffeBrokerAPI_FetchX509SVID_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(X509SVIDRequest) +func _SpiffeBrokerAPI_SubscribeToX509SVID_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeToX509SVIDRequest) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SpiffeBrokerAPIServer).FetchX509SVID(m, &spiffeBrokerAPIFetchX509SVIDServer{stream}) + return srv.(SpiffeBrokerAPIServer).SubscribeToX509SVID(m, &spiffeBrokerAPISubscribeToX509SVIDServer{stream}) } -type SpiffeBrokerAPI_FetchX509SVIDServer interface { - Send(*X509SVIDResponse) error +type SpiffeBrokerAPI_SubscribeToX509SVIDServer interface { + Send(*SubscribeToX509SVIDResponse) error grpc.ServerStream } -type spiffeBrokerAPIFetchX509SVIDServer struct { +type spiffeBrokerAPISubscribeToX509SVIDServer struct { grpc.ServerStream } -func (x *spiffeBrokerAPIFetchX509SVIDServer) Send(m *X509SVIDResponse) error { +func (x *spiffeBrokerAPISubscribeToX509SVIDServer) Send(m *SubscribeToX509SVIDResponse) error { return x.ServerStream.SendMsg(m) } -func _SpiffeBrokerAPI_FetchX509Bundles_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(X509BundlesRequest) +func _SpiffeBrokerAPI_SubscribeToX509Bundles_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeToX509BundlesRequest) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SpiffeBrokerAPIServer).FetchX509Bundles(m, &spiffeBrokerAPIFetchX509BundlesServer{stream}) + return srv.(SpiffeBrokerAPIServer).SubscribeToX509Bundles(m, &spiffeBrokerAPISubscribeToX509BundlesServer{stream}) } -type SpiffeBrokerAPI_FetchX509BundlesServer interface { - Send(*X509BundlesResponse) error +type SpiffeBrokerAPI_SubscribeToX509BundlesServer interface { + Send(*SubscribeToX509BundlesResponse) error grpc.ServerStream } -type spiffeBrokerAPIFetchX509BundlesServer struct { +type spiffeBrokerAPISubscribeToX509BundlesServer struct { grpc.ServerStream } -func (x *spiffeBrokerAPIFetchX509BundlesServer) Send(m *X509BundlesResponse) error { +func (x *spiffeBrokerAPISubscribeToX509BundlesServer) Send(m *SubscribeToX509BundlesResponse) error { return x.ServerStream.SendMsg(m) } func _SpiffeBrokerAPI_FetchJWTSVID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(JWTSVIDRequest) + in := new(FetchJWTSVIDRequest) if err := dec(in); err != nil { return nil, err } @@ -267,29 +267,29 @@ func _SpiffeBrokerAPI_FetchJWTSVID_Handler(srv interface{}, ctx context.Context, FullMethod: SpiffeBrokerAPI_FetchJWTSVID_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(SpiffeBrokerAPIServer).FetchJWTSVID(ctx, req.(*JWTSVIDRequest)) + return srv.(SpiffeBrokerAPIServer).FetchJWTSVID(ctx, req.(*FetchJWTSVIDRequest)) } return interceptor(ctx, in, info, handler) } -func _SpiffeBrokerAPI_FetchJWTBundles_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(JWTBundlesRequest) +func _SpiffeBrokerAPI_SubscribeToJWTBundles_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeToJWTBundlesRequest) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SpiffeBrokerAPIServer).FetchJWTBundles(m, &spiffeBrokerAPIFetchJWTBundlesServer{stream}) + return srv.(SpiffeBrokerAPIServer).SubscribeToJWTBundles(m, &spiffeBrokerAPISubscribeToJWTBundlesServer{stream}) } -type SpiffeBrokerAPI_FetchJWTBundlesServer interface { - Send(*JWTBundlesResponse) error +type SpiffeBrokerAPI_SubscribeToJWTBundlesServer interface { + Send(*SubscribeToJWTBundlesResponse) error grpc.ServerStream } -type spiffeBrokerAPIFetchJWTBundlesServer struct { +type spiffeBrokerAPISubscribeToJWTBundlesServer struct { grpc.ServerStream } -func (x *spiffeBrokerAPIFetchJWTBundlesServer) Send(m *JWTBundlesResponse) error { +func (x *spiffeBrokerAPISubscribeToJWTBundlesServer) Send(m *SubscribeToJWTBundlesResponse) error { return x.ServerStream.SendMsg(m) } @@ -307,18 +307,18 @@ var SpiffeBrokerAPI_ServiceDesc = grpc.ServiceDesc{ }, Streams: []grpc.StreamDesc{ { - StreamName: "FetchX509SVID", - Handler: _SpiffeBrokerAPI_FetchX509SVID_Handler, + StreamName: "SubscribeToX509SVID", + Handler: _SpiffeBrokerAPI_SubscribeToX509SVID_Handler, ServerStreams: true, }, { - StreamName: "FetchX509Bundles", - Handler: _SpiffeBrokerAPI_FetchX509Bundles_Handler, + StreamName: "SubscribeToX509Bundles", + Handler: _SpiffeBrokerAPI_SubscribeToX509Bundles_Handler, ServerStreams: true, }, { - StreamName: "FetchJWTBundles", - Handler: _SpiffeBrokerAPI_FetchJWTBundles_Handler, + StreamName: "SubscribeToJWTBundles", + Handler: _SpiffeBrokerAPI_SubscribeToJWTBundles_Handler, ServerStreams: true, }, }, From 237083e0f13cba23ba56918fa552bff98d4fac51 Mon Sep 17 00:00:00 2001 From: arndt-s <17650715+arndt-s@users.noreply.github.com> Date: Mon, 16 Feb 2026 09:39:48 +0100 Subject: [PATCH 3/4] wip --- Dockerfile | 8 +- Dockerfile.windows | 6 +- Makefile | 10 +- go.mod | 3 + go.sum | 4 +- .../api/delegatedidentity/v1/service_test.go | 6 + pkg/agent/attestor/workload/workload.go | 71 +- pkg/agent/broker/api/service.go | 84 +- pkg/agent/catalog/workloadattestor.go | 7 +- pkg/agent/endpoints/peertracker_test.go | 6 + pkg/agent/plugin/workloadattestor/k8s/k8s.go | 42 +- .../plugin/workloadattestor/k8s/k8s_posix.go | 28 +- .../workloadattestor/k8s/k8s_windows.go | 14 +- .../workloadattestor/k8s/k8s_windows_test.go | 32 +- pkg/agent/plugin/workloadattestor/v1.go | 24 + pkg/agent/plugin/workloadattestor/v2.go | 56 ++ .../workloadattestor/workloadattestor.go | 2 + pkg/common/containerinfo/extract.go | 3 + proto/brokerapi/brokerapi.pb.go | 844 ------------------ proto/brokerapi/brokerapi.proto | 167 ---- proto/brokerapi/brokerapi_grpc.pb.go | 326 ------- 21 files changed, 295 insertions(+), 1448 deletions(-) create mode 100644 pkg/agent/plugin/workloadattestor/v2.go delete mode 100644 proto/brokerapi/brokerapi.pb.go delete mode 100644 proto/brokerapi/brokerapi.proto delete mode 100644 proto/brokerapi/brokerapi_grpc.pb.go diff --git a/Dockerfile b/Dockerfile index caff36914e..608e8bb715 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,10 +5,12 @@ ARG goversion FROM --platform=${BUILDPLATFORM} golang:${goversion}-alpine3.22 as base WORKDIR /spire RUN apk --no-cache --update add file bash clang lld pkgconfig git make -COPY go.* ./ +COPY spire/go.* ./ +COPY spire-plugin-sdk/ /spire-plugin-sdk/ +COPY spire-api-sdk/ /spire-api-sdk/ # https://go.dev/ref/mod#module-cache RUN --mount=type=cache,target=/go/pkg/mod go mod download -COPY . . +COPY spire/ . # xx is a helper for cross-compilation # when bumping to a new version analyze the new version for security issues @@ -31,7 +33,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ make build-static git_tag=$TAG git_dirty="" && \ for f in $(find bin -executable -type f); do xx-verify --static $f; done -FROM --platform=${BUILDPLATFORM} scratch AS spire-base +FROM --platform=${BUILDPLATFORM} golang:${goversion}-alpine3.22 AS spire-base COPY --link --from=builder --chown=root:root --chmod=755 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ WORKDIR /opt/spire diff --git a/Dockerfile.windows b/Dockerfile.windows index a0510926ea..a40d75a459 100644 --- a/Dockerfile.windows +++ b/Dockerfile.windows @@ -10,14 +10,14 @@ CMD [] # SPIRE Server FROM spire-base-windows AS spire-server-windows ENTRYPOINT ["c:/spire/bin/spire-server.exe", "run"] -COPY bin/spire-server.exe C:/spire/bin/spire-server.exe +COPY spire/bin/spire-server.exe C:/spire/bin/spire-server.exe # SPIRE Agent FROM spire-base-windows AS spire-agent-windows ENTRYPOINT ["c:/spire/bin/spire-agent.exe", "run"] -COPY ./bin/spire-agent.exe C:/spire/bin/spire-agent.exe +COPY spire/bin/spire-agent.exe C:/spire/bin/spire-agent.exe # OIDC Discovery Provider FROM spire-base-windows AS oidc-discovery-provider-windows ENTRYPOINT ["c:/spire/bin/oidc-discovery-provider.exe"] -COPY ./bin/oidc-discovery-provider.exe c:/spire/bin/oidc-discovery-provider.exe +COPY spire/bin/oidc-discovery-provider.exe c:/spire/bin/oidc-discovery-provider.exe diff --git a/Makefile b/Makefile index 606648b6ec..ce3ea239fa 100644 --- a/Makefile +++ b/Makefile @@ -184,11 +184,9 @@ git_dirty := $(shell git status -s) protos := \ proto/private/server/journal/journal.proto \ - proto/spire/common/common.proto \ - proto/brokerapi/brokerapi.proto + proto/spire/common/common.proto api-protos := \ - proto/brokerapi/brokerapi.proto plugin-protos := \ proto/spire/common/plugin/plugin.proto @@ -344,7 +342,7 @@ $1: $3 container-builder --target $2 \ -o type=oci,dest=$2-image.tar \ -f $3 \ - . + .. endef @@ -375,7 +373,7 @@ $1: $3 --target $2 \ -t $2 -t $2:latest-local \ -f $3 \ - . + .. endef @@ -479,7 +477,7 @@ endif .PHONY: dev-shell dev-image dev-image: - $(E)docker build -t spire-dev -f Dockerfile.dev . + $(E)docker build -t spire-dev -f Dockerfile.dev .. dev-shell: | go-check $(E)docker run --rm -v "$(call goenv,GOCACHE)":/root/.cache/go-build -v "$(DIR):/spire" -v "$(call goenv,GOPATH)/pkg/mod":/root/go/pkg/mod -it -h spire-dev spire-dev diff --git a/go.mod b/go.mod index 242f342b04..3e6cd825b1 100644 --- a/go.mod +++ b/go.mod @@ -330,3 +330,6 @@ require ( sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) + +replace github.com/spiffe/spire-plugin-sdk => ../spire-plugin-sdk +replace github.com/spiffe/spire-api-sdk => ../spire-api-sdk diff --git a/go.sum b/go.sum index 25804ecdfb..8d334b9f51 100644 --- a/go.sum +++ b/go.sum @@ -814,8 +814,6 @@ github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMps github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/spiffe/spire-api-sdk v1.2.5-0.20260115194754-bcd1999bdd05 h1:wJPyPSXHtKEc9SuK83sr40OoRSaYUTf1+wncvWvogHE= github.com/spiffe/spire-api-sdk v1.2.5-0.20260115194754-bcd1999bdd05/go.mod h1:9hXJcMzatM1KwAtBDO3s6HccDCic++/5c2yOc5Iln8Y= -github.com/spiffe/spire-plugin-sdk v1.4.4-0.20251120194148-791bbd274dc7 h1:OAvr7TNirmBpXnAp82cTosuB+JAus5cyFCRqXHE0WHs= -github.com/spiffe/spire-plugin-sdk v1.4.4-0.20251120194148-791bbd274dc7/go.mod h1:QvrRDiBlXiJ7kNd176ZHsF5eklxxeTRgJSu2CXe0MKw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -1114,6 +1112,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go. google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/grpc/examples v0.0.0-20250407062114-b368379ef8f6 h1:ExN12ndbJ608cboPYflpTny6mXSzPrDLh0iTaVrRrds= +google.golang.org/grpc/examples v0.0.0-20250407062114-b368379ef8f6/go.mod h1:6ytKWczdvnpnO+m+JiG9NjEDzR1FJfsnmJdG7B8QVZ8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/pkg/agent/api/delegatedidentity/v1/service_test.go b/pkg/agent/api/delegatedidentity/v1/service_test.go index 6cdc659ab0..c5d1dae147 100644 --- a/pkg/agent/api/delegatedidentity/v1/service_test.go +++ b/pkg/agent/api/delegatedidentity/v1/service_test.go @@ -36,6 +36,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/types/known/anypb" ) var ( @@ -870,6 +871,11 @@ func (fa FakeWorkloadPIDAttestor) Attest(_ context.Context, _ int) ([]*common.Se return fa.selectors, fa.err } +func (fa FakeWorkloadPIDAttestor) AttestReference(_ context.Context, _ *anypb.Any) ([]*common.Selector, error) { + // TODO(arndt) do we want more logic here? + return fa.selectors, fa.err +} + type FakeManager struct { manager.Manager diff --git a/pkg/agent/attestor/workload/workload.go b/pkg/agent/attestor/workload/workload.go index 1ff65b42c5..222b84b722 100644 --- a/pkg/agent/attestor/workload/workload.go +++ b/pkg/agent/attestor/workload/workload.go @@ -3,7 +3,6 @@ package attestor import ( "context" "fmt" - "os" "github.com/sirupsen/logrus" "github.com/spiffe/spire/pkg/agent/catalog" @@ -11,6 +10,7 @@ import ( "github.com/spiffe/spire/pkg/common/telemetry" telemetry_workload "github.com/spiffe/spire/pkg/common/telemetry/agent/workloadapi" "github.com/spiffe/spire/proto/spire/common" + "google.golang.org/protobuf/types/known/anypb" ) type attestor struct { @@ -19,6 +19,7 @@ type attestor struct { type Attestor interface { Attest(ctx context.Context, pid int) ([]*common.Selector, error) + AttestReference(ctx context.Context, reference *anypb.Any) ([]*common.Selector, error) } func New(config *Config) Attestor { @@ -45,18 +46,50 @@ type Config struct { // Attest invokes all workload attestor plugins against the provided PID. If an error // is encountered, it is logged and selectors from the failing plugin are discarded. func (wla *attestor) Attest(ctx context.Context, pid int) ([]*common.Selector, error) { + log := wla.c.Log.WithField(telemetry.PID, pid) + + return wla.attest(ctx, func(a workloadattestor.WorkloadAttestor) ([]*common.Selector, error) { + var err error + counter := telemetry_workload.StartAttestorCall(wla.c.Metrics, a.Name()) + defer counter.Done(&err) + + selectors, err := a.Attest(ctx, pid) + if err != nil { + log.WithError(err).Errorf("workload attestor %q failed", a.Name()) + return nil, fmt.Errorf("workload attestor %q failed: %w", a.Name(), err) + } + return selectors, nil + }) +} + +func (wla *attestor) AttestReference(ctx context.Context, reference *anypb.Any) ([]*common.Selector, error) { + // TODO(arndt) add references to log context + log := wla.c.Log + return wla.attest(ctx, func(a workloadattestor.WorkloadAttestor) ([]*common.Selector, error) { + var err error + counter := telemetry_workload.StartAttestorCall(wla.c.Metrics, a.Name()) + defer counter.Done(&err) + + selectors, err := a.AttestReference(ctx, reference) + if err != nil { + log.WithError(err).Errorf("workload attestor %q failed", a.Name()) + return nil, fmt.Errorf("workload attestor %q failed: %w", a.Name(), err) + } + return selectors, nil + }) +} + +func (wla *attestor) attest(ctx context.Context, attestFunc func(attestor workloadattestor.WorkloadAttestor) ([]*common.Selector, error)) ([]*common.Selector, error) { counter := telemetry_workload.StartAttestationCall(wla.c.Metrics) defer counter.Done(nil) - log := wla.c.Log.WithField(telemetry.PID, pid) - plugins := wla.c.Catalog.GetWorkloadAttestors() sChan := make(chan []*common.Selector) errChan := make(chan error) for _, p := range plugins { go func(p workloadattestor.WorkloadAttestor) { - if selectors, err := wla.invokeAttestor(ctx, p, pid); err == nil { + if selectors, err := attestFunc(p); err == nil { sChan <- selectors } else { errChan <- err @@ -72,34 +105,22 @@ func (wla *attestor) Attest(ctx context.Context, pid int) ([]*common.Selector, e selectors = append(selectors, s...) wla.c.selectorHook(selectors) case err := <-errChan: - log.WithError(err).Error("Failed to collect all selectors for PID") + wla.c.Log.WithError(err).Error("Failed to collect all selectors") case <-ctx.Done(): // If the client times out before all workload attestation plugins have reported selectors or an error, // it can be helpful to see the partial set of selectors discovered for debugging purposes. - log.WithField(telemetry.PartialSelectors, selectors).Error("Timed out collecting selectors for PID") + wla.c.Log.WithField(telemetry.PartialSelectors, selectors).Error("Timed out collecting selectors") return nil, ctx.Err() } } telemetry_workload.AddDiscoveredSelectorsSample(wla.c.Metrics, float32(len(selectors))) - // The agent health check currently exercises the Workload API. Since this - // can happen with some frequency, it has a tendency to fill up logs with - // hard-to-filter details if we're not careful (e.g. issue #1537). Only log - // if it is not the agent itself. - if pid != os.Getpid() { - log.WithField(telemetry.Selectors, selectors).Debug("PID attested to have selectors") - } - return selectors, nil -} - -// invokeAttestor invokes attestation against the supplied plugin. Should be called from a goroutine. -func (wla *attestor) invokeAttestor(ctx context.Context, a workloadattestor.WorkloadAttestor, pid int) (_ []*common.Selector, err error) { - counter := telemetry_workload.StartAttestorCall(wla.c.Metrics, a.Name()) - defer counter.Done(&err) - - selectors, err := a.Attest(ctx, pid) - if err != nil { - return nil, fmt.Errorf("workload attestor %q failed: %w", a.Name(), err) - } + // // The agent health check currently exercises the Workload API. Since this + // // can happen with some frequency, it has a tendency to fill up logs with + // // hard-to-filter details if we're not careful (e.g. issue #1537). Only log + // // if it is not the agent itself. + // if pid != os.Getpid() { + // log.WithField(telemetry.Selectors, selectors).Debug("PID attested to have selectors") + // } return selectors, nil } diff --git a/pkg/agent/broker/api/service.go b/pkg/agent/broker/api/service.go index d1935e2a91..6f6c3dfd90 100644 --- a/pkg/agent/broker/api/service.go +++ b/pkg/agent/broker/api/service.go @@ -10,6 +10,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spiffe/go-spiffe/v2/spiffegrpc/grpccredentials" "github.com/spiffe/go-spiffe/v2/spiffeid" + "github.com/spiffe/spire-api-sdk/proto/spiffe/broker" "github.com/spiffe/spire/pkg/agent/api/rpccontext" workloadattestor "github.com/spiffe/spire/pkg/agent/attestor/workload" "github.com/spiffe/spire/pkg/agent/client" @@ -20,7 +21,6 @@ import ( "github.com/spiffe/spire/pkg/common/telemetry" "github.com/spiffe/spire/pkg/common/telemetry/agent/adminapi" "github.com/spiffe/spire/pkg/common/x509util" - "github.com/spiffe/spire/proto/brokerapi" "github.com/spiffe/spire/proto/spire/common" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -29,7 +29,7 @@ import ( // RegisterService registers the delegated identity service on the provided server func RegisterService(s *grpc.Server, service *Service) { - brokerapi.RegisterSpiffeBrokerAPIServer(s, service) + broker.RegisterAPIServer(s, service) } type Config struct { @@ -49,7 +49,7 @@ func New(config Config) *Service { // Service implements the delegated identity server type Service struct { - brokerapi.UnimplementedSpiffeBrokerAPIServer + broker.UnimplementedAPIServer manager manager.Manager peerAttestor workloadattestor.Attestor @@ -64,19 +64,19 @@ func (s *Service) getCallerContext(ctx context.Context) (spiffeid.ID, error) { return peer, nil } -func (s *Service) SubscribeToX509SVID(req *brokerapi.SubscribeToX509SVIDRequest, stream brokerapi.SpiffeBrokerAPI_SubscribeToX509SVIDServer) error { +func (s *Service) SubscribeToX509SVID(req *broker.SubscribeToX509SVIDRequest, stream broker.API_SubscribeToX509SVIDServer) error { latency := adminapi.StartFirstX509SVIDUpdateLatency(s.metrics) ctx := stream.Context() log := rpccontext.Logger(ctx) var receivedFirstUpdate bool - peer, err := s.getCallerContext(ctx) - if err != nil { - return err - } - log = log.WithField("broker_peer", peer.String()) + // peer, err := s.getCallerContext(ctx) + // if err != nil { + // return err + // } + // log = log.WithField("broker_peer", peer.String()) - selectors, err := s.constructValidSelectorsFromReferences(ctx, log, req.References) + selectors, err := s.constructValidSelectorsFromReference(ctx, log, req.Reference) if err != nil { return err } @@ -110,7 +110,7 @@ func (s *Service) SubscribeToX509SVID(req *brokerapi.SubscribeToX509SVIDRequest, } } -func (s *Service) SubscribeToX509Bundles(_ *brokerapi.SubscribeToX509BundlesRequest, stream brokerapi.SpiffeBrokerAPI_SubscribeToX509BundlesServer) error { +func (s *Service) SubscribeToX509Bundles(_ *broker.SubscribeToX509BundlesRequest, stream broker.API_SubscribeToX509BundlesServer) error { ctx := stream.Context() peer, err := s.getCallerContext(ctx) @@ -127,7 +127,7 @@ func (s *Service) SubscribeToX509Bundles(_ *brokerapi.SubscribeToX509BundlesRequ caCerts[td.IDString()] = marshalBundle(bundle.X509Authorities()) } - resp := &brokerapi.SubscribeToX509BundlesResponse{ + resp := &broker.SubscribeToX509BundlesResponse{ Bundles: caCerts, } @@ -142,7 +142,7 @@ func (s *Service) SubscribeToX509Bundles(_ *brokerapi.SubscribeToX509BundlesRequ caCerts[td.IDString()] = marshalBundle(bundle.X509Authorities()) } - resp := &brokerapi.SubscribeToX509BundlesResponse{ + resp := &broker.SubscribeToX509BundlesResponse{ Bundles: caCerts, } @@ -156,7 +156,7 @@ func (s *Service) SubscribeToX509Bundles(_ *brokerapi.SubscribeToX509BundlesRequ } } -func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.FetchJWTSVIDRequest) (*brokerapi.FetchJWTSVIDResponse, error) { +func (s *Service) FetchJWTSVID(ctx context.Context, req *broker.FetchJWTSVIDRequest) (*broker.FetchJWTSVIDResponse, error) { log := rpccontext.Logger(ctx) if len(req.Audience) == 0 { log.Error("Missing required audience parameter") @@ -169,12 +169,12 @@ func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.FetchJWTSVIDR } log = log.WithField("broker_peer", peer.String()) - selectors, err := s.constructValidSelectorsFromReferences(ctx, log, req.References) + selectors, err := s.constructValidSelectorsFromReference(ctx, log, req.Reference) if err != nil { return nil, err } - resp := new(brokerapi.FetchJWTSVIDResponse) + resp := new(broker.FetchJWTSVIDResponse) entries := s.manager.MatchingRegistrationEntries(selectors) for _, entry := range entries { spiffeID, err := spiffeid.FromString(entry.SpiffeId) @@ -191,7 +191,7 @@ func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.FetchJWTSVIDR loopLog.WithError(err).Error("Could not fetch JWT-SVID") return nil, status.Errorf(codes.Unavailable, "could not fetch JWT-SVID: %v", err) } - resp.Svids = append(resp.Svids, &brokerapi.JWTSVID{ + resp.Svids = append(resp.Svids, &broker.JWTSVID{ SpiffeId: spiffeID.String(), Hint: entry.Hint, Svid: svid.Token, @@ -209,7 +209,7 @@ func (s *Service) FetchJWTSVID(ctx context.Context, req *brokerapi.FetchJWTSVIDR return resp, nil } -func (s *Service) SubscribeToJWTBundles(_ *brokerapi.SubscribeToJWTBundlesRequest, stream brokerapi.SpiffeBrokerAPI_SubscribeToJWTBundlesServer) error { +func (s *Service) SubscribeToJWTBundles(_ *broker.SubscribeToJWTBundlesRequest, stream broker.API_SubscribeToJWTBundlesServer) error { ctx := stream.Context() peer, err := s.getCallerContext(ctx) @@ -230,7 +230,7 @@ func (s *Service) SubscribeToJWTBundles(_ *brokerapi.SubscribeToJWTBundlesReques jwtbundles[td.IDString()] = jwksBytes } - resp := &brokerapi.SubscribeToJWTBundlesResponse{ + resp := &broker.SubscribeToJWTBundlesResponse{ Bundles: jwtbundles, } @@ -248,7 +248,7 @@ func (s *Service) SubscribeToJWTBundles(_ *brokerapi.SubscribeToJWTBundlesReques jwtbundles[td.IDString()] = jwksBytes } - resp := &brokerapi.SubscribeToJWTBundlesResponse{ + resp := &broker.SubscribeToJWTBundlesResponse{ Bundles: jwtbundles, } if err := stream.Send(resp); err != nil { @@ -260,38 +260,22 @@ func (s *Service) SubscribeToJWTBundles(_ *brokerapi.SubscribeToJWTBundlesReques } } -func (s *Service) constructValidSelectorsFromReferences(ctx context.Context, log logrus.FieldLogger, refs []*brokerapi.WorkloadReference) ([]*common.Selector, error) { - if len(refs) == 0 { - log.Error("No workload references provided") - return nil, status.Error(codes.InvalidArgument, "no workload references provided") +func (s *Service) constructValidSelectorsFromReference(ctx context.Context, log logrus.FieldLogger, ref *broker.WorkloadReference) ([]*common.Selector, error) { + if ref == nil { + log.Error("No workload reference provided") + return nil, status.Error(codes.InvalidArgument, "workload reference must be provided") } - if len(refs) > 1 { - log.Error("Multiple workload references provided; only one is supported") - return nil, status.Error(codes.InvalidArgument, "multiple workload references provided; SPIRE only supports one at the moment") + selectors, err := s.peerAttestor.AttestReference(ctx, ref.Reference) + if err != nil { + log.WithError(err).Error("Workload attestation failed") + return nil, status.Errorf(codes.Unauthenticated, "workload attestation failed: %v", err) } - switch refs[0].Reference.TypeUrl { - case "type.googleapis.com/brokerapi.WorkloadPIDReference": - var pidRef brokerapi.WorkloadPIDReference - if err := refs[0].Reference.UnmarshalTo(&pidRef); err != nil { - log.WithError(err).Error("Failed to unmarshal PID workload reference") - return nil, status.Error(codes.InvalidArgument, "failed to unmarshal PID workload reference") - } - - selectors, err := s.peerAttestor.Attest(ctx, int(pidRef.Pid)) - if err != nil { - log.WithError(err).Error("Workload attestation with PID failed") - return nil, status.Error(codes.Internal, "workload attestation with PID failed") - } - return selectors, nil - default: - log.WithField("type_url", refs[0].Reference.TypeUrl).Error("Unsupported workload reference type") - return nil, status.Error(codes.InvalidArgument, "unsupported workload reference type") - } + return selectors, nil } -func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream brokerapi.SpiffeBrokerAPI_SubscribeToX509SVIDServer, log logrus.FieldLogger) (err error) { +func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream broker.API_SubscribeToX509SVIDServer, log logrus.FieldLogger) (err error) { resp, err := composeX509SVIDBySelectors(update) if err != nil { log.WithError(err).Error("Could not serialize X.509 SVID response") @@ -321,9 +305,9 @@ func sendX509SVIDResponse(update *cache.WorkloadUpdate, stream brokerapi.SpiffeB return nil } -func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*brokerapi.SubscribeToX509SVIDResponse, error) { - resp := new(brokerapi.SubscribeToX509SVIDResponse) - resp.Svids = make([]*brokerapi.X509SVID, 0, len(update.Identities)) +func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*broker.SubscribeToX509SVIDResponse, error) { + resp := new(broker.SubscribeToX509SVIDResponse) + resp.Svids = make([]*broker.X509SVID, 0, len(update.Identities)) resp.FederatedBundles = make(map[string][]byte, len(update.FederatedBundles)) x509Bundle := marshalBundle(update.Bundle.X509Authorities()) @@ -348,7 +332,7 @@ func composeX509SVIDBySelectors(update *cache.WorkloadUpdate) (*brokerapi.Subscr return nil, fmt.Errorf("marshal key for %v: %w", id, err) } - svid := &brokerapi.X509SVID{ + svid := &broker.X509SVID{ SpiffeId: id.String(), X509Svid: x509util.DERFromCertificates(identity.SVID), Bundle: x509Bundle, diff --git a/pkg/agent/catalog/workloadattestor.go b/pkg/agent/catalog/workloadattestor.go index 4e367815bc..7328c5da37 100644 --- a/pkg/agent/catalog/workloadattestor.go +++ b/pkg/agent/catalog/workloadattestor.go @@ -23,7 +23,7 @@ func (repo *workloadAttestorRepository) Constraints() catalog.Constraints { } func (repo *workloadAttestorRepository) Versions() []catalog.Version { - return []catalog.Version{workloadAttestorV1{}} + return []catalog.Version{workloadAttestorV1{}, workloadAttestorV2{}} } func (repo *workloadAttestorRepository) BuiltIns() []catalog.BuiltIn { @@ -40,3 +40,8 @@ type workloadAttestorV1 struct{} func (workloadAttestorV1) New() catalog.Facade { return new(workloadattestor.V1) } func (workloadAttestorV1) Deprecated() bool { return false } + +type workloadAttestorV2 struct{} + +func (workloadAttestorV2) New() catalog.Facade { return new(workloadattestor.V2) } +func (workloadAttestorV2) Deprecated() bool { return true } diff --git a/pkg/agent/endpoints/peertracker_test.go b/pkg/agent/endpoints/peertracker_test.go index 3f559c2ccc..dbaf726281 100644 --- a/pkg/agent/endpoints/peertracker_test.go +++ b/pkg/agent/endpoints/peertracker_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "google.golang.org/grpc/codes" "google.golang.org/grpc/peer" + "google.golang.org/protobuf/types/known/anypb" ) func TestPeerTrackerAttestor(t *testing.T) { @@ -44,6 +45,11 @@ func (a FakeAttestor) Attest(_ context.Context, pid int) ([]*common.Selector, er return nil, nil } +func (a FakeAttestor) AttestReference(_ context.Context, _ *anypb.Any) ([]*common.Selector, error) { + // TODO(arndt) do we want more logic here? + return []*common.Selector{{Type: "Type", Value: "Value"}}, nil +} + func WithFakeWatcher(alive bool) context.Context { return peer.NewContext(context.Background(), &peer.Peer{ AuthInfo: peertracker.AuthInfo{ diff --git a/pkg/agent/plugin/workloadattestor/k8s/k8s.go b/pkg/agent/plugin/workloadattestor/k8s/k8s.go index 2b3ddac8c3..b4cd5e137e 100644 --- a/pkg/agent/plugin/workloadattestor/k8s/k8s.go +++ b/pkg/agent/plugin/workloadattestor/k8s/k8s.go @@ -20,7 +20,8 @@ import ( "github.com/andres-erbsen/clock" "github.com/hashicorp/go-hclog" "github.com/hashicorp/hcl" - workloadattestorv1 "github.com/spiffe/spire-plugin-sdk/proto/spire/plugin/agent/workloadattestor/v1" + "github.com/spiffe/spire-api-sdk/proto/spiffe/reference" + workloadattestorv2 "github.com/spiffe/spire-plugin-sdk/proto/spire/plugin/agent/workloadattestor/v2" configv1 "github.com/spiffe/spire-plugin-sdk/proto/spire/service/common/config/v1" "github.com/spiffe/spire/pkg/agent/common/sigstore" "github.com/spiffe/spire/pkg/common/catalog" @@ -31,6 +32,7 @@ import ( "golang.org/x/sync/singleflight" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/anypb" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" ) @@ -52,7 +54,7 @@ func BuiltIn() catalog.BuiltIn { func builtin(p *Plugin) catalog.BuiltIn { return catalog.MakeBuiltIn(pluginName, - workloadattestorv1.WorkloadAttestorPluginServer(p), + workloadattestorv2.WorkloadAttestorPluginServer(p), configv1.ConfigServiceServer(p), ) } @@ -257,11 +259,11 @@ func (p *Plugin) buildConfig(coreConfig catalog.CoreConfig, hclText string, stat type ContainerHelper interface { Configure(config *HCLConfig, log hclog.Logger) error - GetPodUIDAndContainerID(pID int32, log hclog.Logger) (types.UID, string, error) + GetPodUIDAndContainerID(reference *anypb.Any, log hclog.Logger) (types.UID, string, bool, error) } type Plugin struct { - workloadattestorv1.UnsafeWorkloadAttestorServer + workloadattestorv2.UnsafeWorkloadAttestorServer configv1.UnsafeConfigServer log hclog.Logger @@ -290,13 +292,15 @@ func (p *Plugin) SetLogger(log hclog.Logger) { p.log = log } -func (p *Plugin) Attest(ctx context.Context, req *workloadattestorv1.AttestRequest) (*workloadattestorv1.AttestResponse, error) { +func (p *Plugin) AttestReference(ctx context.Context, req *workloadattestorv2.AttestReferenceRequest) (*workloadattestorv2.AttestReferenceResponse, error) { + p.log.Info("skip kubelet verification", p.config.SkipKubeletVerification) + config, containerHelper, sigstoreVerifier, err := p.getConfig() if err != nil { return nil, err } - podUID, containerID, err := containerHelper.GetPodUIDAndContainerID(req.Pid, p.log) + podUID, containerID, _, err := containerHelper.GetPodUIDAndContainerID(req.Reference, p.log) if err != nil { return nil, err } @@ -304,7 +308,7 @@ func (p *Plugin) Attest(ctx context.Context, req *workloadattestorv1.AttestReque // Not a Kubernetes pod if containerID == "" { - return &workloadattestorv1.AttestResponse{}, nil + return &workloadattestorv2.AttestReferenceResponse{}, nil } log := p.log.With( @@ -323,7 +327,7 @@ func (p *Plugin) Attest(ctx context.Context, req *workloadattestorv1.AttestReque return nil, err } - var attestResponse *workloadattestorv1.AttestResponse + var attestResponse *workloadattestorv2.AttestReferenceResponse for podKey, podValue := range podList { if podKnown { if podKey != string(podUID) { @@ -375,7 +379,7 @@ func (p *Plugin) Attest(ctx context.Context, req *workloadattestorv1.AttestReque log.Warn("Two pods found with same container Id") return nil, status.Error(codes.Internal, "two pods found with same container Id") } - attestResponse = &workloadattestorv1.AttestResponse{SelectorValues: selectorValues} + attestResponse = &workloadattestorv2.AttestReferenceResponse{SelectorValues: selectorValues} } } @@ -846,3 +850,23 @@ func newCertPool(certs []*x509.Certificate) *x509.CertPool { } return certPool } + +func extractRelevantReference(ref *anypb.Any) (types.UID, int32, error) { + switch ref.TypeUrl { + case "type.googleapis.com/spiffe.broker.WorkloadPIDReference": + var pidRef reference.WorkloadPIDReference + if err := ref.UnmarshalTo(&pidRef); err != nil { + return "", -1, fmt.Errorf("unable to unmarshal PID reference: %w", err) + } + return "", pidRef.Pid, nil + case "type.googleapis.com/spiffe.broker.KubernetesPodUIDReference": + var podUIDRef reference.KubernetesPodUIDReference + if err := ref.UnmarshalTo(&podUIDRef); err != nil { + return "", -1, fmt.Errorf("unable to unmarshal Pod UID reference: %w", err) + } + uid := types.UID(podUIDRef.Uid) + return uid, -1, nil + default: + return "", -1, fmt.Errorf("unsupported reference type: %s", ref.TypeUrl) + } +} diff --git a/pkg/agent/plugin/workloadattestor/k8s/k8s_posix.go b/pkg/agent/plugin/workloadattestor/k8s/k8s_posix.go index 35510de46c..1688836656 100644 --- a/pkg/agent/plugin/workloadattestor/k8s/k8s_posix.go +++ b/pkg/agent/plugin/workloadattestor/k8s/k8s_posix.go @@ -3,6 +3,7 @@ package k8s import ( + "fmt" "io" "log" "os" @@ -16,6 +17,7 @@ import ( "github.com/spiffe/spire/pkg/common/containerinfo" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/anypb" "k8s.io/apimachinery/pkg/types" ) @@ -34,6 +36,7 @@ func createHelper(c *Plugin) ContainerHelper { } return &containerHelper{ rootDir: rootDir, + log: c.log, } } @@ -41,6 +44,7 @@ type containerHelper struct { rootDir string useNewContainerLocator bool verboseContainerLocatorLogs bool + log hclog.Logger } func (h *containerHelper) Configure(config *HCLConfig, log hclog.Logger) error { @@ -55,12 +59,34 @@ func (h *containerHelper) Configure(config *HCLConfig, log hclog.Logger) error { return nil } -func (h *containerHelper) GetPodUIDAndContainerID(pID int32, log hclog.Logger) (types.UID, string, error) { +func (h *containerHelper) GetPodUIDAndContainerID(ref *anypb.Any, log hclog.Logger) (types.UID, string, bool, error) { + podUID, pid, err := extractRelevantReference(ref) + + h.log.Info("Extracted reference from AttestReference request", "podUID", podUID, "pid", pid) + + switch { + case err != nil: + return "", "", false, fmt.Errorf("unable to extract relevant reference: %w", err) + case pid != -1: + // instruct that in the later state we require a container ID match in the pod spec. + requiredContainerIDMatch := true + podUID, containerID, err := h.getPodUIDAndContainerIDFromPID(pid, log) + h.log.Info("Obtained pod UID and container ID from PID reference", "podUID", podUID, "containerID", containerID, "pid", pid) + return podUID, containerID, requiredContainerIDMatch, err + case podUID != "": + return podUID, "", false, nil + default: + return "", "", false, status.Errorf(codes.InvalidArgument, "reference did not contain a valid Pod UID or PID") + } +} + +func (h *containerHelper) getPodUIDAndContainerIDFromPID(pID int32, log hclog.Logger) (types.UID, string, error) { if !h.useNewContainerLocator { cgroups, err := cgroups.GetCgroups(pID, dirFS(h.rootDir)) if err != nil { return "", "", status.Errorf(codes.Internal, "unable to obtain cgroups: %v", err) } + h.log.Info("Obtained cgroups for PID", "pid", pID, "cgroups", cgroups) return getPodUIDAndContainerIDFromCGroups(cgroups) } diff --git a/pkg/agent/plugin/workloadattestor/k8s/k8s_windows.go b/pkg/agent/plugin/workloadattestor/k8s/k8s_windows.go index 2d55ea3b24..1c70cf9c5a 100644 --- a/pkg/agent/plugin/workloadattestor/k8s/k8s_windows.go +++ b/pkg/agent/plugin/workloadattestor/k8s/k8s_windows.go @@ -9,6 +9,7 @@ import ( "github.com/spiffe/spire/pkg/common/container/process" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/anypb" "k8s.io/apimachinery/pkg/types" ) @@ -30,13 +31,18 @@ func (h *containerHelper) Configure(_ *HCLConfig, _ hclog.Logger) error { return nil } -func (h *containerHelper) GetPodUIDAndContainerID(pID int32, log hclog.Logger) (types.UID, string, error) { - containerID, err := h.ph.GetContainerIDByProcess(pID, log) +func (h *containerHelper) GetPodUIDAndContainerID(ref *anypb.Any, log hclog.Logger) (types.UID, string, bool, error) { + _, pid, err := extractRelevantReference(ref) if err != nil { - return types.UID(""), "", status.Errorf(codes.Internal, "failed to get container ID: %v", err) + return "", "", false, status.Errorf(codes.Internal, "failed to extract relevant reference: %v", err) } - return types.UID(""), containerID, nil + containerID, err := h.ph.GetContainerIDByProcess(pid, log) + if err != nil { + return types.UID(""), "", false, status.Errorf(codes.Internal, "failed to get container ID: %v", err) + } + + return types.UID(""), containerID, true, nil } func (p *Plugin) defaultKubeletCAPath() string { diff --git a/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go b/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go index 90efb51628..82b76ec14f 100644 --- a/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go +++ b/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go @@ -8,10 +8,12 @@ import ( "testing" "github.com/hashicorp/go-hclog" + "github.com/spiffe/spire/proto/brokerapi" "github.com/spiffe/spire/test/spiretest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/types/known/anypb" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" ) @@ -48,17 +50,22 @@ func (h *fakeContainerHelper) GetOSSelectors(context.Context, hclog.Logger, *cor return h.osSelectors, nil } -func (h *fakeContainerHelper) GetPodUIDAndContainerID(pID int32, _ hclog.Logger) (types.UID, string, error) { +func (h *fakeContainerHelper) GetPodUIDAndContainerID(ref *anypb.Any, _ hclog.Logger) (types.UID, string, bool, error) { if h.err != nil { - return types.UID(""), "", h.err + return types.UID(""), "", false, h.err } - cID, ok := h.cIDs[pID] + _, pid, err := extractRelevantReference(ref) + if err != nil { + return "", "", false, err + } + + cID, ok := h.cIDs[pid] if !ok { - return types.UID(""), "", nil + return types.UID(""), "", false, nil } - return types.UID(""), cID, nil + return types.UID(""), cID, true, nil } func (s *Suite) addGetContainerResponsePidInPod() { @@ -75,7 +82,9 @@ func TestContainerHelper(t *testing.T) { t.Run("containerID found", func(t *testing.T) { fakeHelper.containerID = "123" - podID, containerID, err := cHelper.GetPodUIDAndContainerID(123, nil) + ref, err := buildReferenceWithPID(123) + require.NoError(t, err) + podID, containerID, _, err := cHelper.GetPodUIDAndContainerID(ref, nil) require.NoError(t, err) assert.Empty(t, podID) @@ -84,7 +93,9 @@ func TestContainerHelper(t *testing.T) { t.Run("get fails", func(t *testing.T) { fakeHelper.err = errors.New("oh no") - podID, containerID, err := cHelper.GetPodUIDAndContainerID(123, nil) + ref, err := buildReferenceWithPID(123) + require.NoError(t, err) + podID, containerID, _, err := cHelper.GetPodUIDAndContainerID(ref, nil) spiretest.RequireGRPCStatus(t, err, codes.Internal, "failed to get container ID: oh no") assert.Empty(t, podID) @@ -104,3 +115,10 @@ func (f *fakeProcessHelper) GetContainerIDByProcess(int32, hclog.Logger) (string return f.containerID, nil } + +func buildReferenceWithPID(pid int32) (*anypb.Any, error) { + pidReference := brokerapi.WorkloadPIDReference{ + Pid: pid, + } + return anypb.New(&pidReference) +} diff --git a/pkg/agent/plugin/workloadattestor/v1.go b/pkg/agent/plugin/workloadattestor/v1.go index 329a7a17de..df7c936962 100644 --- a/pkg/agent/plugin/workloadattestor/v1.go +++ b/pkg/agent/plugin/workloadattestor/v1.go @@ -2,12 +2,16 @@ package workloadattestor import ( "context" + "errors" "fmt" + "github.com/spiffe/spire-api-sdk/proto/spiffe/reference" workloadattestorv1 "github.com/spiffe/spire-plugin-sdk/proto/spire/plugin/agent/workloadattestor/v1" "github.com/spiffe/spire/pkg/common/plugin" "github.com/spiffe/spire/pkg/common/util" "github.com/spiffe/spire/proto/spire/common" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" ) type V1 struct { @@ -39,3 +43,23 @@ func (v1 *V1) Attest(ctx context.Context, pid int) ([]*common.Selector, error) { } return selectors, nil } + +func (v1 *V1) AttestReference(ctx context.Context, reference *anypb.Any) ([]*common.Selector, error) { + pid, err := extractPIDReference(reference) + if err != nil { + return nil, v1.WrapErr(err) + } + + return v1.Attest(ctx, int(pid)) +} + +func extractPIDReference(ref *anypb.Any) (int32, error) { + if ref.GetTypeUrl() == "type.googleapis.com/spiffe.broker.WorkloadPIDReference" { + var pidRef reference.WorkloadPIDReference + if err := anypb.UnmarshalTo(ref, &pidRef, proto.UnmarshalOptions{}); err != nil { + return 0, fmt.Errorf("unmarshaling PID reference: %w", err) + } + return pidRef.Pid, nil + } + return -1, errors.New("PID reference not found") +} diff --git a/pkg/agent/plugin/workloadattestor/v2.go b/pkg/agent/plugin/workloadattestor/v2.go new file mode 100644 index 0000000000..de25e76c4f --- /dev/null +++ b/pkg/agent/plugin/workloadattestor/v2.go @@ -0,0 +1,56 @@ +package workloadattestor + +import ( + "context" + "fmt" + + workloadattestorv2 "github.com/spiffe/spire-plugin-sdk/proto/spire/plugin/agent/workloadattestor/v2" + + "github.com/spiffe/spire-api-sdk/proto/spiffe/reference" + "github.com/spiffe/spire/pkg/common/plugin" + "github.com/spiffe/spire/pkg/common/util" + "github.com/spiffe/spire/proto/spire/common" + "google.golang.org/protobuf/types/known/anypb" +) + +type V2 struct { + plugin.Facade + workloadattestorv2.WorkloadAttestorPluginClient +} + +func (v2 *V2) Attest(ctx context.Context, pid int) ([]*common.Selector, error) { + pidInt32, err := util.CheckedCast[int32](pid) + if err != nil { + return nil, v2.WrapErr(fmt.Errorf("invalid value for PID: %w", err)) + } + pidReference := reference.WorkloadPIDReference{ + Pid: pidInt32, + } + anyPidReference, err := anypb.New(&pidReference) + if err != nil { + return nil, v2.WrapErr(err) + } + + return v2.AttestReference(ctx, anyPidReference) +} + +func (v2 *V2) AttestReference(ctx context.Context, reference *anypb.Any) ([]*common.Selector, error) { + resp, err := v2.WorkloadAttestorPluginClient.AttestReference(ctx, &workloadattestorv2.AttestReferenceRequest{ + Reference: reference, + }) + if err != nil { + return nil, v2.WrapErr(err) + } + + var selectors []*common.Selector + if resp.SelectorValues != nil { + selectors = make([]*common.Selector, 0, len(resp.SelectorValues)) + for _, selectorValue := range resp.SelectorValues { + selectors = append(selectors, &common.Selector{ + Type: v2.Name(), + Value: selectorValue, + }) + } + } + return selectors, nil +} diff --git a/pkg/agent/plugin/workloadattestor/workloadattestor.go b/pkg/agent/plugin/workloadattestor/workloadattestor.go index b17a586866..ba4458f0d9 100644 --- a/pkg/agent/plugin/workloadattestor/workloadattestor.go +++ b/pkg/agent/plugin/workloadattestor/workloadattestor.go @@ -5,10 +5,12 @@ import ( "github.com/spiffe/spire/pkg/common/catalog" "github.com/spiffe/spire/proto/spire/common" + "google.golang.org/protobuf/types/known/anypb" ) type WorkloadAttestor interface { catalog.PluginInfo Attest(ctx context.Context, pid int) ([]*common.Selector, error) + AttestReference(ctx context.Context, reference *anypb.Any) ([]*common.Selector, error) } diff --git a/pkg/common/containerinfo/extract.go b/pkg/common/containerinfo/extract.go index ae4cb2d1d4..c741d50cb2 100644 --- a/pkg/common/containerinfo/extract.go +++ b/pkg/common/containerinfo/extract.go @@ -64,11 +64,14 @@ func (e *Extractor) extractInfo(pid int32, log hclog.Logger, extractPodUID bool) return "", "", err } + log.Info("Extracted pod UID and container ID from mount info", "podUID", podUID, "containerID", containerID, "pid", pid) + if containerID == "" { podUID, containerID, err = e.extractPodUIDAndContainerIDFromCGroups(pid, log, extractPodUID) if err != nil { return "", "", err } + log.Info("Extracted pod UID and container ID from cgroups", "podUID", podUID, "containerID", containerID, "pid", pid) } return podUID, containerID, nil diff --git a/proto/brokerapi/brokerapi.pb.go b/proto/brokerapi/brokerapi.pb.go deleted file mode 100644 index 554af2e7ce..0000000000 --- a/proto/brokerapi/brokerapi.pb.go +++ /dev/null @@ -1,844 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc v6.32.1 -// source: brokerapi/brokerapi.proto - -package brokerapi - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The WorkloadReference message represents a single reference to a workload. -// The reference field contains one of the standard reference types or -// a vendor-specific extension type. -type WorkloadReference struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The reference to the workload. - Reference *anypb.Any `protobuf:"bytes,1,opt,name=reference,proto3" json:"reference,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *WorkloadReference) Reset() { - *x = WorkloadReference{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *WorkloadReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkloadReference) ProtoMessage() {} - -func (x *WorkloadReference) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkloadReference.ProtoReflect.Descriptor instead. -func (*WorkloadReference) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{0} -} - -func (x *WorkloadReference) GetReference() *anypb.Any { - if x != nil { - return x.Reference - } - return nil -} - -// The WorkloadPIDReference message conveys a process id reference of a workload -// running in the same environment. -type WorkloadPIDReference struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The process id of the workload. MUST be a positive integer. - Pid int32 `protobuf:"varint,1,opt,name=pid,proto3" json:"pid,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *WorkloadPIDReference) Reset() { - *x = WorkloadPIDReference{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *WorkloadPIDReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkloadPIDReference) ProtoMessage() {} - -func (x *WorkloadPIDReference) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkloadPIDReference.ProtoReflect.Descriptor instead. -func (*WorkloadPIDReference) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{1} -} - -func (x *WorkloadPIDReference) GetPid() int32 { - if x != nil { - return x.Pid - } - return 0 -} - -// The SubscribeToX509SVIDRequest message conveys parameters for requesting an X.509-SVID. -type SubscribeToX509SVIDRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeToX509SVIDRequest) Reset() { - *x = SubscribeToX509SVIDRequest{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeToX509SVIDRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeToX509SVIDRequest) ProtoMessage() {} - -func (x *SubscribeToX509SVIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeToX509SVIDRequest.ProtoReflect.Descriptor instead. -func (*SubscribeToX509SVIDRequest) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{2} -} - -func (x *SubscribeToX509SVIDRequest) GetReferences() []*WorkloadReference { - if x != nil { - return x.References - } - return nil -} - -// The SubscribeToX509SVIDResponse message carries X.509-SVIDs and related information, -// including a list of bundles the workload may use for federating with foreign -// trust domains. -type SubscribeToX509SVIDResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. A list of X509SVID messages, each of which includes a single - // X.509-SVID, its private key, and the bundle for the trust domain. - Svids []*X509SVID `protobuf:"bytes,1,rep,name=svids,proto3" json:"svids,omitempty"` - // Optional. ASN.1 DER encoded certificate revocation lists. - Crl [][]byte `protobuf:"bytes,2,rep,name=crl,proto3" json:"crl,omitempty"` - // Optional. CA certificate bundles belonging to foreign trust domains that - // the workload should trust, keyed by the SPIFFE ID of the foreign trust - // domain. Bundles are ASN.1 DER encoded. - FederatedBundles map[string][]byte `protobuf:"bytes,3,rep,name=federated_bundles,json=federatedBundles,proto3" json:"federated_bundles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeToX509SVIDResponse) Reset() { - *x = SubscribeToX509SVIDResponse{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeToX509SVIDResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeToX509SVIDResponse) ProtoMessage() {} - -func (x *SubscribeToX509SVIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeToX509SVIDResponse.ProtoReflect.Descriptor instead. -func (*SubscribeToX509SVIDResponse) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{3} -} - -func (x *SubscribeToX509SVIDResponse) GetSvids() []*X509SVID { - if x != nil { - return x.Svids - } - return nil -} - -func (x *SubscribeToX509SVIDResponse) GetCrl() [][]byte { - if x != nil { - return x.Crl - } - return nil -} - -func (x *SubscribeToX509SVIDResponse) GetFederatedBundles() map[string][]byte { - if x != nil { - return x.FederatedBundles - } - return nil -} - -// The X509SVID message carries a single SVID and all associated information, -// including the X.509 bundle for the trust domain. -type X509SVID struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The SPIFFE ID of the SVID in this entry - SpiffeId string `protobuf:"bytes,1,opt,name=spiffe_id,json=spiffeId,proto3" json:"spiffe_id,omitempty"` - // Required. ASN.1 DER encoded certificate chain. MAY include - // intermediates, the leaf certificate (or SVID itself) MUST come first. - X509Svid []byte `protobuf:"bytes,2,opt,name=x509_svid,json=x509Svid,proto3" json:"x509_svid,omitempty"` - // Required. ASN.1 DER encoded PKCS#8 private key. MUST be unencrypted. - X509SvidKey []byte `protobuf:"bytes,3,opt,name=x509_svid_key,json=x509SvidKey,proto3" json:"x509_svid_key,omitempty"` - // Required. ASN.1 DER encoded X.509 bundle for the trust domain. - Bundle []byte `protobuf:"bytes,4,opt,name=bundle,proto3" json:"bundle,omitempty"` - // Optional. An operator-specified string used to provide guidance on how this - // identity should be used by a broker or workload when more than one SVID is - // returned. For example, `internal` and `external` to indicate an SVID for - // internal or external use, respectively. - Hint string `protobuf:"bytes,5,opt,name=hint,proto3" json:"hint,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *X509SVID) Reset() { - *x = X509SVID{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *X509SVID) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*X509SVID) ProtoMessage() {} - -func (x *X509SVID) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use X509SVID.ProtoReflect.Descriptor instead. -func (*X509SVID) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{4} -} - -func (x *X509SVID) GetSpiffeId() string { - if x != nil { - return x.SpiffeId - } - return "" -} - -func (x *X509SVID) GetX509Svid() []byte { - if x != nil { - return x.X509Svid - } - return nil -} - -func (x *X509SVID) GetX509SvidKey() []byte { - if x != nil { - return x.X509SvidKey - } - return nil -} - -func (x *X509SVID) GetBundle() []byte { - if x != nil { - return x.Bundle - } - return nil -} - -func (x *X509SVID) GetHint() string { - if x != nil { - return x.Hint - } - return "" -} - -// The SubscribeToX509BundlesRequest message conveys parameters for requesting X.509 -// bundles. -type SubscribeToX509BundlesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeToX509BundlesRequest) Reset() { - *x = SubscribeToX509BundlesRequest{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeToX509BundlesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeToX509BundlesRequest) ProtoMessage() {} - -func (x *SubscribeToX509BundlesRequest) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeToX509BundlesRequest.ProtoReflect.Descriptor instead. -func (*SubscribeToX509BundlesRequest) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{5} -} - -func (x *SubscribeToX509BundlesRequest) GetReferences() []*WorkloadReference { - if x != nil { - return x.References - } - return nil -} - -// The SubscribeToX509BundlesResponse message carries a map of trust bundles the workload -// should trust. -type SubscribeToX509BundlesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Optional. ASN.1 DER encoded certificate revocation lists. - Crl [][]byte `protobuf:"bytes,1,rep,name=crl,proto3" json:"crl,omitempty"` - // Required. CA certificate bundles belonging to trust domains that the - // workload should trust, keyed by the SPIFFE ID of the trust domain. - // Bundles are ASN.1 DER encoded. - Bundles map[string][]byte `protobuf:"bytes,2,rep,name=bundles,proto3" json:"bundles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeToX509BundlesResponse) Reset() { - *x = SubscribeToX509BundlesResponse{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeToX509BundlesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeToX509BundlesResponse) ProtoMessage() {} - -func (x *SubscribeToX509BundlesResponse) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeToX509BundlesResponse.ProtoReflect.Descriptor instead. -func (*SubscribeToX509BundlesResponse) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{6} -} - -func (x *SubscribeToX509BundlesResponse) GetCrl() [][]byte { - if x != nil { - return x.Crl - } - return nil -} - -func (x *SubscribeToX509BundlesResponse) GetBundles() map[string][]byte { - if x != nil { - return x.Bundles - } - return nil -} - -// The FetchJWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. -type FetchJWTSVIDRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` - // Required. The audience(s) the workload intends to authenticate against. - Audience []string `protobuf:"bytes,2,rep,name=audience,proto3" json:"audience,omitempty"` - // Optional. The requested SPIFFE ID for the JWT-SVID. If unset, all - // JWT-SVIDs to which the workload is entitled are requested. - SpiffeId string `protobuf:"bytes,3,opt,name=spiffe_id,json=spiffeId,proto3" json:"spiffe_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *FetchJWTSVIDRequest) Reset() { - *x = FetchJWTSVIDRequest{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *FetchJWTSVIDRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FetchJWTSVIDRequest) ProtoMessage() {} - -func (x *FetchJWTSVIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FetchJWTSVIDRequest.ProtoReflect.Descriptor instead. -func (*FetchJWTSVIDRequest) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{7} -} - -func (x *FetchJWTSVIDRequest) GetReferences() []*WorkloadReference { - if x != nil { - return x.References - } - return nil -} - -func (x *FetchJWTSVIDRequest) GetAudience() []string { - if x != nil { - return x.Audience - } - return nil -} - -func (x *FetchJWTSVIDRequest) GetSpiffeId() string { - if x != nil { - return x.SpiffeId - } - return "" -} - -// The FetchJWTSVIDResponse message conveys JWT-SVIDs. -type FetchJWTSVIDResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The list of returned JWT-SVIDs. - Svids []*JWTSVID `protobuf:"bytes,1,rep,name=svids,proto3" json:"svids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *FetchJWTSVIDResponse) Reset() { - *x = FetchJWTSVIDResponse{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *FetchJWTSVIDResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FetchJWTSVIDResponse) ProtoMessage() {} - -func (x *FetchJWTSVIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FetchJWTSVIDResponse.ProtoReflect.Descriptor instead. -func (*FetchJWTSVIDResponse) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{8} -} - -func (x *FetchJWTSVIDResponse) GetSvids() []*JWTSVID { - if x != nil { - return x.Svids - } - return nil -} - -// The JWTSVID message carries the JWT-SVID token and associated metadata. -type JWTSVID struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The SPIFFE ID of the JWT-SVID. - SpiffeId string `protobuf:"bytes,1,opt,name=spiffe_id,json=spiffeId,proto3" json:"spiffe_id,omitempty"` - // Required. Encoded JWT using JWS Compact Serialization. - Svid string `protobuf:"bytes,2,opt,name=svid,proto3" json:"svid,omitempty"` - // Optional. An operator-specified string used to provide guidance on how this - // identity should be used by a workload when more than one SVID is returned. - // For example, `internal` and `external` to indicate an SVID for internal or - // external use, respectively. - Hint string `protobuf:"bytes,3,opt,name=hint,proto3" json:"hint,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *JWTSVID) Reset() { - *x = JWTSVID{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *JWTSVID) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*JWTSVID) ProtoMessage() {} - -func (x *JWTSVID) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use JWTSVID.ProtoReflect.Descriptor instead. -func (*JWTSVID) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{9} -} - -func (x *JWTSVID) GetSpiffeId() string { - if x != nil { - return x.SpiffeId - } - return "" -} - -func (x *JWTSVID) GetSvid() string { - if x != nil { - return x.Svid - } - return "" -} - -func (x *JWTSVID) GetHint() string { - if x != nil { - return x.Hint - } - return "" -} - -// The SubscribeToJWTBundlesRequest message conveys parameters for requesting JWT bundles. -type SubscribeToJWTBundlesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - References []*WorkloadReference `protobuf:"bytes,1,rep,name=references,proto3" json:"references,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeToJWTBundlesRequest) Reset() { - *x = SubscribeToJWTBundlesRequest{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeToJWTBundlesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeToJWTBundlesRequest) ProtoMessage() {} - -func (x *SubscribeToJWTBundlesRequest) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeToJWTBundlesRequest.ProtoReflect.Descriptor instead. -func (*SubscribeToJWTBundlesRequest) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{10} -} - -func (x *SubscribeToJWTBundlesRequest) GetReferences() []*WorkloadReference { - if x != nil { - return x.References - } - return nil -} - -// The SubscribeToJWTBundlesResponse message conveys JWT bundles. -type SubscribeToJWTBundlesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust - // domain. - Bundles map[string][]byte `protobuf:"bytes,1,rep,name=bundles,proto3" json:"bundles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeToJWTBundlesResponse) Reset() { - *x = SubscribeToJWTBundlesResponse{} - mi := &file_brokerapi_brokerapi_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeToJWTBundlesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeToJWTBundlesResponse) ProtoMessage() {} - -func (x *SubscribeToJWTBundlesResponse) ProtoReflect() protoreflect.Message { - mi := &file_brokerapi_brokerapi_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeToJWTBundlesResponse.ProtoReflect.Descriptor instead. -func (*SubscribeToJWTBundlesResponse) Descriptor() ([]byte, []int) { - return file_brokerapi_brokerapi_proto_rawDescGZIP(), []int{11} -} - -func (x *SubscribeToJWTBundlesResponse) GetBundles() map[string][]byte { - if x != nil { - return x.Bundles - } - return nil -} - -var File_brokerapi_brokerapi_proto protoreflect.FileDescriptor - -const file_brokerapi_brokerapi_proto_rawDesc = "" + - "\n" + - "\x19brokerapi/brokerapi.proto\x12\tbrokerapi\x1a\x19google/protobuf/any.proto\"G\n" + - "\x11WorkloadReference\x122\n" + - "\treference\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\treference\"(\n" + - "\x14WorkloadPIDReference\x12\x10\n" + - "\x03pid\x18\x01 \x01(\x05R\x03pid\"Z\n" + - "\x1aSubscribeToX509SVIDRequest\x12<\n" + - "\n" + - "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\"\x8a\x02\n" + - "\x1bSubscribeToX509SVIDResponse\x12)\n" + - "\x05svids\x18\x01 \x03(\v2\x13.brokerapi.X509SVIDR\x05svids\x12\x10\n" + - "\x03crl\x18\x02 \x03(\fR\x03crl\x12i\n" + - "\x11federated_bundles\x18\x03 \x03(\v2<.brokerapi.SubscribeToX509SVIDResponse.FederatedBundlesEntryR\x10federatedBundles\x1aC\n" + - "\x15FederatedBundlesEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x94\x01\n" + - "\bX509SVID\x12\x1b\n" + - "\tspiffe_id\x18\x01 \x01(\tR\bspiffeId\x12\x1b\n" + - "\tx509_svid\x18\x02 \x01(\fR\bx509Svid\x12\"\n" + - "\rx509_svid_key\x18\x03 \x01(\fR\vx509SvidKey\x12\x16\n" + - "\x06bundle\x18\x04 \x01(\fR\x06bundle\x12\x12\n" + - "\x04hint\x18\x05 \x01(\tR\x04hint\"]\n" + - "\x1dSubscribeToX509BundlesRequest\x12<\n" + - "\n" + - "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\"\xc0\x01\n" + - "\x1eSubscribeToX509BundlesResponse\x12\x10\n" + - "\x03crl\x18\x01 \x03(\fR\x03crl\x12P\n" + - "\abundles\x18\x02 \x03(\v26.brokerapi.SubscribeToX509BundlesResponse.BundlesEntryR\abundles\x1a:\n" + - "\fBundlesEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"\x8c\x01\n" + - "\x13FetchJWTSVIDRequest\x12<\n" + - "\n" + - "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\x12\x1a\n" + - "\baudience\x18\x02 \x03(\tR\baudience\x12\x1b\n" + - "\tspiffe_id\x18\x03 \x01(\tR\bspiffeId\"@\n" + - "\x14FetchJWTSVIDResponse\x12(\n" + - "\x05svids\x18\x01 \x03(\v2\x12.brokerapi.JWTSVIDR\x05svids\"N\n" + - "\aJWTSVID\x12\x1b\n" + - "\tspiffe_id\x18\x01 \x01(\tR\bspiffeId\x12\x12\n" + - "\x04svid\x18\x02 \x01(\tR\x04svid\x12\x12\n" + - "\x04hint\x18\x03 \x01(\tR\x04hint\"\\\n" + - "\x1cSubscribeToJWTBundlesRequest\x12<\n" + - "\n" + - "references\x18\x01 \x03(\v2\x1c.brokerapi.WorkloadReferenceR\n" + - "references\"\xac\x01\n" + - "\x1dSubscribeToJWTBundlesResponse\x12O\n" + - "\abundles\x18\x01 \x03(\v25.brokerapi.SubscribeToJWTBundlesResponse.BundlesEntryR\abundles\x1a:\n" + - "\fBundlesEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\fR\x05value:\x028\x012\xa9\x03\n" + - "\x0fSpiffeBrokerAPI\x12f\n" + - "\x13SubscribeToX509SVID\x12%.brokerapi.SubscribeToX509SVIDRequest\x1a&.brokerapi.SubscribeToX509SVIDResponse0\x01\x12o\n" + - "\x16SubscribeToX509Bundles\x12(.brokerapi.SubscribeToX509BundlesRequest\x1a).brokerapi.SubscribeToX509BundlesResponse0\x01\x12O\n" + - "\fFetchJWTSVID\x12\x1e.brokerapi.FetchJWTSVIDRequest\x1a\x1f.brokerapi.FetchJWTSVIDResponse\x12l\n" + - "\x15SubscribeToJWTBundles\x12'.brokerapi.SubscribeToJWTBundlesRequest\x1a(.brokerapi.SubscribeToJWTBundlesResponse0\x01B)Z'github.com/spiffe/spire/proto/brokerapib\x06proto3" - -var ( - file_brokerapi_brokerapi_proto_rawDescOnce sync.Once - file_brokerapi_brokerapi_proto_rawDescData []byte -) - -func file_brokerapi_brokerapi_proto_rawDescGZIP() []byte { - file_brokerapi_brokerapi_proto_rawDescOnce.Do(func() { - file_brokerapi_brokerapi_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_brokerapi_brokerapi_proto_rawDesc), len(file_brokerapi_brokerapi_proto_rawDesc))) - }) - return file_brokerapi_brokerapi_proto_rawDescData -} - -var file_brokerapi_brokerapi_proto_msgTypes = make([]protoimpl.MessageInfo, 15) -var file_brokerapi_brokerapi_proto_goTypes = []any{ - (*WorkloadReference)(nil), // 0: brokerapi.WorkloadReference - (*WorkloadPIDReference)(nil), // 1: brokerapi.WorkloadPIDReference - (*SubscribeToX509SVIDRequest)(nil), // 2: brokerapi.SubscribeToX509SVIDRequest - (*SubscribeToX509SVIDResponse)(nil), // 3: brokerapi.SubscribeToX509SVIDResponse - (*X509SVID)(nil), // 4: brokerapi.X509SVID - (*SubscribeToX509BundlesRequest)(nil), // 5: brokerapi.SubscribeToX509BundlesRequest - (*SubscribeToX509BundlesResponse)(nil), // 6: brokerapi.SubscribeToX509BundlesResponse - (*FetchJWTSVIDRequest)(nil), // 7: brokerapi.FetchJWTSVIDRequest - (*FetchJWTSVIDResponse)(nil), // 8: brokerapi.FetchJWTSVIDResponse - (*JWTSVID)(nil), // 9: brokerapi.JWTSVID - (*SubscribeToJWTBundlesRequest)(nil), // 10: brokerapi.SubscribeToJWTBundlesRequest - (*SubscribeToJWTBundlesResponse)(nil), // 11: brokerapi.SubscribeToJWTBundlesResponse - nil, // 12: brokerapi.SubscribeToX509SVIDResponse.FederatedBundlesEntry - nil, // 13: brokerapi.SubscribeToX509BundlesResponse.BundlesEntry - nil, // 14: brokerapi.SubscribeToJWTBundlesResponse.BundlesEntry - (*anypb.Any)(nil), // 15: google.protobuf.Any -} -var file_brokerapi_brokerapi_proto_depIdxs = []int32{ - 15, // 0: brokerapi.WorkloadReference.reference:type_name -> google.protobuf.Any - 0, // 1: brokerapi.SubscribeToX509SVIDRequest.references:type_name -> brokerapi.WorkloadReference - 4, // 2: brokerapi.SubscribeToX509SVIDResponse.svids:type_name -> brokerapi.X509SVID - 12, // 3: brokerapi.SubscribeToX509SVIDResponse.federated_bundles:type_name -> brokerapi.SubscribeToX509SVIDResponse.FederatedBundlesEntry - 0, // 4: brokerapi.SubscribeToX509BundlesRequest.references:type_name -> brokerapi.WorkloadReference - 13, // 5: brokerapi.SubscribeToX509BundlesResponse.bundles:type_name -> brokerapi.SubscribeToX509BundlesResponse.BundlesEntry - 0, // 6: brokerapi.FetchJWTSVIDRequest.references:type_name -> brokerapi.WorkloadReference - 9, // 7: brokerapi.FetchJWTSVIDResponse.svids:type_name -> brokerapi.JWTSVID - 0, // 8: brokerapi.SubscribeToJWTBundlesRequest.references:type_name -> brokerapi.WorkloadReference - 14, // 9: brokerapi.SubscribeToJWTBundlesResponse.bundles:type_name -> brokerapi.SubscribeToJWTBundlesResponse.BundlesEntry - 2, // 10: brokerapi.SpiffeBrokerAPI.SubscribeToX509SVID:input_type -> brokerapi.SubscribeToX509SVIDRequest - 5, // 11: brokerapi.SpiffeBrokerAPI.SubscribeToX509Bundles:input_type -> brokerapi.SubscribeToX509BundlesRequest - 7, // 12: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:input_type -> brokerapi.FetchJWTSVIDRequest - 10, // 13: brokerapi.SpiffeBrokerAPI.SubscribeToJWTBundles:input_type -> brokerapi.SubscribeToJWTBundlesRequest - 3, // 14: brokerapi.SpiffeBrokerAPI.SubscribeToX509SVID:output_type -> brokerapi.SubscribeToX509SVIDResponse - 6, // 15: brokerapi.SpiffeBrokerAPI.SubscribeToX509Bundles:output_type -> brokerapi.SubscribeToX509BundlesResponse - 8, // 16: brokerapi.SpiffeBrokerAPI.FetchJWTSVID:output_type -> brokerapi.FetchJWTSVIDResponse - 11, // 17: brokerapi.SpiffeBrokerAPI.SubscribeToJWTBundles:output_type -> brokerapi.SubscribeToJWTBundlesResponse - 14, // [14:18] is the sub-list for method output_type - 10, // [10:14] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name -} - -func init() { file_brokerapi_brokerapi_proto_init() } -func file_brokerapi_brokerapi_proto_init() { - if File_brokerapi_brokerapi_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_brokerapi_brokerapi_proto_rawDesc), len(file_brokerapi_brokerapi_proto_rawDesc)), - NumEnums: 0, - NumMessages: 15, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_brokerapi_brokerapi_proto_goTypes, - DependencyIndexes: file_brokerapi_brokerapi_proto_depIdxs, - MessageInfos: file_brokerapi_brokerapi_proto_msgTypes, - }.Build() - File_brokerapi_brokerapi_proto = out.File - file_brokerapi_brokerapi_proto_goTypes = nil - file_brokerapi_brokerapi_proto_depIdxs = nil -} diff --git a/proto/brokerapi/brokerapi.proto b/proto/brokerapi/brokerapi.proto deleted file mode 100644 index 64662229a7..0000000000 --- a/proto/brokerapi/brokerapi.proto +++ /dev/null @@ -1,167 +0,0 @@ -syntax = "proto3"; - -package brokerapi; - -import "google/protobuf/any.proto"; -option go_package = "github.com/spiffe/spire/proto/brokerapi"; - -service SpiffeBrokerAPI { - ///////////////////////////////////////////////////////////////////////// - // X509-SVID Profile - ///////////////////////////////////////////////////////////////////////// - - // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is - // entitled to, as well as related information like trust bundles. As this - // information changes, subsequent messages will be streamed from the server. - rpc SubscribeToX509SVID(SubscribeToX509SVIDRequest) returns (stream SubscribeToX509SVIDResponse); - - // Fetch trust bundles of the referenced workload. Useful in situations that - // only need to validate SVIDs without obtaining an SVID for themself. As this - // information changes, subsequent messages will be streamed from the server. - rpc SubscribeToX509Bundles(SubscribeToX509BundlesRequest) returns (stream SubscribeToX509BundlesResponse); - - ///////////////////////////////////////////////////////////////////////// - // JWT-SVID Profile - ///////////////////////////////////////////////////////////////////////// - - // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is - // entitled to, for the requested audience. If an optional SPIFFE ID is - // requested, only the JWT-SVID for that SPIFFE ID is returned. - rpc FetchJWTSVID(FetchJWTSVIDRequest) returns (FetchJWTSVIDResponse); - - // Fetches the JWT bundles, formatted as JWKS documents, keyed by the - // SPIFFE ID of the trust domain. As this information changes, subsequent - // messages will be streamed from the server. - rpc SubscribeToJWTBundles(SubscribeToJWTBundlesRequest) returns (stream SubscribeToJWTBundlesResponse); -} - -// The WorkloadReference message represents a single reference to a workload. -// The reference field contains one of the standard reference types or -// a vendor-specific extension type. -message WorkloadReference { - // Required. The reference to the workload. - google.protobuf.Any reference = 1; -} - -// The WorkloadPIDReference message conveys a process id reference of a workload -// running in the same environment. -message WorkloadPIDReference { - // Required. The process id of the workload. MUST be a positive integer. - int32 pid = 1; -} - -// The SubscribeToX509SVIDRequest message conveys parameters for requesting an X.509-SVID. -message SubscribeToX509SVIDRequest { - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - repeated WorkloadReference references = 1; -} - -// The SubscribeToX509SVIDResponse message carries X.509-SVIDs and related information, -// including a list of bundles the workload may use for federating with foreign -// trust domains. -message SubscribeToX509SVIDResponse { - // Required. A list of X509SVID messages, each of which includes a single - // X.509-SVID, its private key, and the bundle for the trust domain. - repeated X509SVID svids = 1; - - // Optional. ASN.1 DER encoded certificate revocation lists. - repeated bytes crl = 2; - - // Optional. CA certificate bundles belonging to foreign trust domains that - // the workload should trust, keyed by the SPIFFE ID of the foreign trust - // domain. Bundles are ASN.1 DER encoded. - map federated_bundles = 3; -} - -// The X509SVID message carries a single SVID and all associated information, -// including the X.509 bundle for the trust domain. -message X509SVID { - // Required. The SPIFFE ID of the SVID in this entry - string spiffe_id = 1; - - // Required. ASN.1 DER encoded certificate chain. MAY include - // intermediates, the leaf certificate (or SVID itself) MUST come first. - bytes x509_svid = 2; - - // Required. ASN.1 DER encoded PKCS#8 private key. MUST be unencrypted. - bytes x509_svid_key = 3; - - // Required. ASN.1 DER encoded X.509 bundle for the trust domain. - bytes bundle = 4; - - // Optional. An operator-specified string used to provide guidance on how this - // identity should be used by a broker or workload when more than one SVID is - // returned. For example, `internal` and `external` to indicate an SVID for - // internal or external use, respectively. - string hint = 5; -} - -// The SubscribeToX509BundlesRequest message conveys parameters for requesting X.509 -// bundles. -message SubscribeToX509BundlesRequest { - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - repeated WorkloadReference references = 1; -} - -// The SubscribeToX509BundlesResponse message carries a map of trust bundles the workload -// should trust. -message SubscribeToX509BundlesResponse { - // Optional. ASN.1 DER encoded certificate revocation lists. - repeated bytes crl = 1; - - // Required. CA certificate bundles belonging to trust domains that the - // workload should trust, keyed by the SPIFFE ID of the trust domain. - // Bundles are ASN.1 DER encoded. - map bundles = 2; -} - -// The FetchJWTSVIDRequest message conveys parameters for requesting JWT-SVIDs. -message FetchJWTSVIDRequest { - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - repeated WorkloadReference references = 1; - - // Required. The audience(s) the workload intends to authenticate against. - repeated string audience = 2; - - // Optional. The requested SPIFFE ID for the JWT-SVID. If unset, all - // JWT-SVIDs to which the workload is entitled are requested. - string spiffe_id = 3; -} - -// The FetchJWTSVIDResponse message conveys JWT-SVIDs. -message FetchJWTSVIDResponse { - // Required. The list of returned JWT-SVIDs. - repeated JWTSVID svids = 1; -} - -// The JWTSVID message carries the JWT-SVID token and associated metadata. -message JWTSVID { - // Required. The SPIFFE ID of the JWT-SVID. - string spiffe_id = 1; - - // Required. Encoded JWT using JWS Compact Serialization. - string svid = 2; - - // Optional. An operator-specified string used to provide guidance on how this - // identity should be used by a workload when more than one SVID is returned. - // For example, `internal` and `external` to indicate an SVID for internal or - // external use, respectively. - string hint = 3; -} - -// The SubscribeToJWTBundlesRequest message conveys parameters for requesting JWT bundles. -message SubscribeToJWTBundlesRequest { - // Required. One or more references identifying the workload. All references - // MUST resolve to the same workload. At least one reference is required. - repeated WorkloadReference references = 1; -} - -// The SubscribeToJWTBundlesResponse message conveys JWT bundles. -message SubscribeToJWTBundlesResponse { - // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust - // domain. - map bundles = 1; -} \ No newline at end of file diff --git a/proto/brokerapi/brokerapi_grpc.pb.go b/proto/brokerapi/brokerapi_grpc.pb.go deleted file mode 100644 index 8ccebd0ab5..0000000000 --- a/proto/brokerapi/brokerapi_grpc.pb.go +++ /dev/null @@ -1,326 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v6.32.1 -// source: brokerapi/brokerapi.proto - -package brokerapi - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - SpiffeBrokerAPI_SubscribeToX509SVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/SubscribeToX509SVID" - SpiffeBrokerAPI_SubscribeToX509Bundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/SubscribeToX509Bundles" - SpiffeBrokerAPI_FetchJWTSVID_FullMethodName = "/brokerapi.SpiffeBrokerAPI/FetchJWTSVID" - SpiffeBrokerAPI_SubscribeToJWTBundles_FullMethodName = "/brokerapi.SpiffeBrokerAPI/SubscribeToJWTBundles" -) - -// SpiffeBrokerAPIClient is the client API for SpiffeBrokerAPI service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type SpiffeBrokerAPIClient interface { - // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is - // entitled to, as well as related information like trust bundles. As this - // information changes, subsequent messages will be streamed from the server. - SubscribeToX509SVID(ctx context.Context, in *SubscribeToX509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509SVIDClient, error) - // Fetch trust bundles of the referenced workload. Useful in situations that - // only need to validate SVIDs without obtaining an SVID for themself. As this - // information changes, subsequent messages will be streamed from the server. - SubscribeToX509Bundles(ctx context.Context, in *SubscribeToX509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509BundlesClient, error) - // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is - // entitled to, for the requested audience. If an optional SPIFFE ID is - // requested, only the JWT-SVID for that SPIFFE ID is returned. - FetchJWTSVID(ctx context.Context, in *FetchJWTSVIDRequest, opts ...grpc.CallOption) (*FetchJWTSVIDResponse, error) - // Fetches the JWT bundles, formatted as JWKS documents, keyed by the - // SPIFFE ID of the trust domain. As this information changes, subsequent - // messages will be streamed from the server. - SubscribeToJWTBundles(ctx context.Context, in *SubscribeToJWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToJWTBundlesClient, error) -} - -type spiffeBrokerAPIClient struct { - cc grpc.ClientConnInterface -} - -func NewSpiffeBrokerAPIClient(cc grpc.ClientConnInterface) SpiffeBrokerAPIClient { - return &spiffeBrokerAPIClient{cc} -} - -func (c *spiffeBrokerAPIClient) SubscribeToX509SVID(ctx context.Context, in *SubscribeToX509SVIDRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509SVIDClient, error) { - stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[0], SpiffeBrokerAPI_SubscribeToX509SVID_FullMethodName, opts...) - if err != nil { - return nil, err - } - x := &spiffeBrokerAPISubscribeToX509SVIDClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type SpiffeBrokerAPI_SubscribeToX509SVIDClient interface { - Recv() (*SubscribeToX509SVIDResponse, error) - grpc.ClientStream -} - -type spiffeBrokerAPISubscribeToX509SVIDClient struct { - grpc.ClientStream -} - -func (x *spiffeBrokerAPISubscribeToX509SVIDClient) Recv() (*SubscribeToX509SVIDResponse, error) { - m := new(SubscribeToX509SVIDResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *spiffeBrokerAPIClient) SubscribeToX509Bundles(ctx context.Context, in *SubscribeToX509BundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToX509BundlesClient, error) { - stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[1], SpiffeBrokerAPI_SubscribeToX509Bundles_FullMethodName, opts...) - if err != nil { - return nil, err - } - x := &spiffeBrokerAPISubscribeToX509BundlesClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type SpiffeBrokerAPI_SubscribeToX509BundlesClient interface { - Recv() (*SubscribeToX509BundlesResponse, error) - grpc.ClientStream -} - -type spiffeBrokerAPISubscribeToX509BundlesClient struct { - grpc.ClientStream -} - -func (x *spiffeBrokerAPISubscribeToX509BundlesClient) Recv() (*SubscribeToX509BundlesResponse, error) { - m := new(SubscribeToX509BundlesResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *spiffeBrokerAPIClient) FetchJWTSVID(ctx context.Context, in *FetchJWTSVIDRequest, opts ...grpc.CallOption) (*FetchJWTSVIDResponse, error) { - out := new(FetchJWTSVIDResponse) - err := c.cc.Invoke(ctx, SpiffeBrokerAPI_FetchJWTSVID_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *spiffeBrokerAPIClient) SubscribeToJWTBundles(ctx context.Context, in *SubscribeToJWTBundlesRequest, opts ...grpc.CallOption) (SpiffeBrokerAPI_SubscribeToJWTBundlesClient, error) { - stream, err := c.cc.NewStream(ctx, &SpiffeBrokerAPI_ServiceDesc.Streams[2], SpiffeBrokerAPI_SubscribeToJWTBundles_FullMethodName, opts...) - if err != nil { - return nil, err - } - x := &spiffeBrokerAPISubscribeToJWTBundlesClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type SpiffeBrokerAPI_SubscribeToJWTBundlesClient interface { - Recv() (*SubscribeToJWTBundlesResponse, error) - grpc.ClientStream -} - -type spiffeBrokerAPISubscribeToJWTBundlesClient struct { - grpc.ClientStream -} - -func (x *spiffeBrokerAPISubscribeToJWTBundlesClient) Recv() (*SubscribeToJWTBundlesResponse, error) { - m := new(SubscribeToJWTBundlesResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// SpiffeBrokerAPIServer is the server API for SpiffeBrokerAPI service. -// All implementations must embed UnimplementedSpiffeBrokerAPIServer -// for forward compatibility -type SpiffeBrokerAPIServer interface { - // Fetch X.509-SVIDs for all SPIFFE identities the referenced workload is - // entitled to, as well as related information like trust bundles. As this - // information changes, subsequent messages will be streamed from the server. - SubscribeToX509SVID(*SubscribeToX509SVIDRequest, SpiffeBrokerAPI_SubscribeToX509SVIDServer) error - // Fetch trust bundles of the referenced workload. Useful in situations that - // only need to validate SVIDs without obtaining an SVID for themself. As this - // information changes, subsequent messages will be streamed from the server. - SubscribeToX509Bundles(*SubscribeToX509BundlesRequest, SpiffeBrokerAPI_SubscribeToX509BundlesServer) error - // Fetch JWT-SVIDs for all SPIFFE identities the referenced workload is - // entitled to, for the requested audience. If an optional SPIFFE ID is - // requested, only the JWT-SVID for that SPIFFE ID is returned. - FetchJWTSVID(context.Context, *FetchJWTSVIDRequest) (*FetchJWTSVIDResponse, error) - // Fetches the JWT bundles, formatted as JWKS documents, keyed by the - // SPIFFE ID of the trust domain. As this information changes, subsequent - // messages will be streamed from the server. - SubscribeToJWTBundles(*SubscribeToJWTBundlesRequest, SpiffeBrokerAPI_SubscribeToJWTBundlesServer) error - mustEmbedUnimplementedSpiffeBrokerAPIServer() -} - -// UnimplementedSpiffeBrokerAPIServer must be embedded to have forward compatible implementations. -type UnimplementedSpiffeBrokerAPIServer struct { -} - -func (UnimplementedSpiffeBrokerAPIServer) SubscribeToX509SVID(*SubscribeToX509SVIDRequest, SpiffeBrokerAPI_SubscribeToX509SVIDServer) error { - return status.Errorf(codes.Unimplemented, "method SubscribeToX509SVID not implemented") -} -func (UnimplementedSpiffeBrokerAPIServer) SubscribeToX509Bundles(*SubscribeToX509BundlesRequest, SpiffeBrokerAPI_SubscribeToX509BundlesServer) error { - return status.Errorf(codes.Unimplemented, "method SubscribeToX509Bundles not implemented") -} -func (UnimplementedSpiffeBrokerAPIServer) FetchJWTSVID(context.Context, *FetchJWTSVIDRequest) (*FetchJWTSVIDResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method FetchJWTSVID not implemented") -} -func (UnimplementedSpiffeBrokerAPIServer) SubscribeToJWTBundles(*SubscribeToJWTBundlesRequest, SpiffeBrokerAPI_SubscribeToJWTBundlesServer) error { - return status.Errorf(codes.Unimplemented, "method SubscribeToJWTBundles not implemented") -} -func (UnimplementedSpiffeBrokerAPIServer) mustEmbedUnimplementedSpiffeBrokerAPIServer() {} - -// UnsafeSpiffeBrokerAPIServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to SpiffeBrokerAPIServer will -// result in compilation errors. -type UnsafeSpiffeBrokerAPIServer interface { - mustEmbedUnimplementedSpiffeBrokerAPIServer() -} - -func RegisterSpiffeBrokerAPIServer(s grpc.ServiceRegistrar, srv SpiffeBrokerAPIServer) { - s.RegisterService(&SpiffeBrokerAPI_ServiceDesc, srv) -} - -func _SpiffeBrokerAPI_SubscribeToX509SVID_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SubscribeToX509SVIDRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(SpiffeBrokerAPIServer).SubscribeToX509SVID(m, &spiffeBrokerAPISubscribeToX509SVIDServer{stream}) -} - -type SpiffeBrokerAPI_SubscribeToX509SVIDServer interface { - Send(*SubscribeToX509SVIDResponse) error - grpc.ServerStream -} - -type spiffeBrokerAPISubscribeToX509SVIDServer struct { - grpc.ServerStream -} - -func (x *spiffeBrokerAPISubscribeToX509SVIDServer) Send(m *SubscribeToX509SVIDResponse) error { - return x.ServerStream.SendMsg(m) -} - -func _SpiffeBrokerAPI_SubscribeToX509Bundles_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SubscribeToX509BundlesRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(SpiffeBrokerAPIServer).SubscribeToX509Bundles(m, &spiffeBrokerAPISubscribeToX509BundlesServer{stream}) -} - -type SpiffeBrokerAPI_SubscribeToX509BundlesServer interface { - Send(*SubscribeToX509BundlesResponse) error - grpc.ServerStream -} - -type spiffeBrokerAPISubscribeToX509BundlesServer struct { - grpc.ServerStream -} - -func (x *spiffeBrokerAPISubscribeToX509BundlesServer) Send(m *SubscribeToX509BundlesResponse) error { - return x.ServerStream.SendMsg(m) -} - -func _SpiffeBrokerAPI_FetchJWTSVID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(FetchJWTSVIDRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(SpiffeBrokerAPIServer).FetchJWTSVID(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: SpiffeBrokerAPI_FetchJWTSVID_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(SpiffeBrokerAPIServer).FetchJWTSVID(ctx, req.(*FetchJWTSVIDRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _SpiffeBrokerAPI_SubscribeToJWTBundles_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SubscribeToJWTBundlesRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(SpiffeBrokerAPIServer).SubscribeToJWTBundles(m, &spiffeBrokerAPISubscribeToJWTBundlesServer{stream}) -} - -type SpiffeBrokerAPI_SubscribeToJWTBundlesServer interface { - Send(*SubscribeToJWTBundlesResponse) error - grpc.ServerStream -} - -type spiffeBrokerAPISubscribeToJWTBundlesServer struct { - grpc.ServerStream -} - -func (x *spiffeBrokerAPISubscribeToJWTBundlesServer) Send(m *SubscribeToJWTBundlesResponse) error { - return x.ServerStream.SendMsg(m) -} - -// SpiffeBrokerAPI_ServiceDesc is the grpc.ServiceDesc for SpiffeBrokerAPI service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var SpiffeBrokerAPI_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "brokerapi.SpiffeBrokerAPI", - HandlerType: (*SpiffeBrokerAPIServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "FetchJWTSVID", - Handler: _SpiffeBrokerAPI_FetchJWTSVID_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "SubscribeToX509SVID", - Handler: _SpiffeBrokerAPI_SubscribeToX509SVID_Handler, - ServerStreams: true, - }, - { - StreamName: "SubscribeToX509Bundles", - Handler: _SpiffeBrokerAPI_SubscribeToX509Bundles_Handler, - ServerStreams: true, - }, - { - StreamName: "SubscribeToJWTBundles", - Handler: _SpiffeBrokerAPI_SubscribeToJWTBundles_Handler, - ServerStreams: true, - }, - }, - Metadata: "brokerapi/brokerapi.proto", -} From 2e67e90d3796cd07cf120328082cefaca9b676ab Mon Sep 17 00:00:00 2001 From: arndt-s <17650715+arndt-s@users.noreply.github.com> Date: Mon, 16 Feb 2026 11:02:05 +0100 Subject: [PATCH 4/4] use sdk repos, fix bugs --- pkg/agent/plugin/workloadattestor/k8s/k8s.go | 4 ++-- pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go | 4 ++-- pkg/agent/plugin/workloadattestor/v1.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/agent/plugin/workloadattestor/k8s/k8s.go b/pkg/agent/plugin/workloadattestor/k8s/k8s.go index b4cd5e137e..0f3aed6676 100644 --- a/pkg/agent/plugin/workloadattestor/k8s/k8s.go +++ b/pkg/agent/plugin/workloadattestor/k8s/k8s.go @@ -853,13 +853,13 @@ func newCertPool(certs []*x509.Certificate) *x509.CertPool { func extractRelevantReference(ref *anypb.Any) (types.UID, int32, error) { switch ref.TypeUrl { - case "type.googleapis.com/spiffe.broker.WorkloadPIDReference": + case "type.googleapis.com/spiffe.reference.WorkloadPIDReference": var pidRef reference.WorkloadPIDReference if err := ref.UnmarshalTo(&pidRef); err != nil { return "", -1, fmt.Errorf("unable to unmarshal PID reference: %w", err) } return "", pidRef.Pid, nil - case "type.googleapis.com/spiffe.broker.KubernetesPodUIDReference": + case "type.googleapis.com/spiffe.reference.KubernetesPodUIDReference": var podUIDRef reference.KubernetesPodUIDReference if err := ref.UnmarshalTo(&podUIDRef); err != nil { return "", -1, fmt.Errorf("unable to unmarshal Pod UID reference: %w", err) diff --git a/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go b/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go index 82b76ec14f..a9801ca49b 100644 --- a/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go +++ b/pkg/agent/plugin/workloadattestor/k8s/k8s_windows_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/hashicorp/go-hclog" - "github.com/spiffe/spire/proto/brokerapi" + "github.com/spiffe/spire-api-sdk/proto/spiffe/reference" "github.com/spiffe/spire/test/spiretest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -117,7 +117,7 @@ func (f *fakeProcessHelper) GetContainerIDByProcess(int32, hclog.Logger) (string } func buildReferenceWithPID(pid int32) (*anypb.Any, error) { - pidReference := brokerapi.WorkloadPIDReference{ + pidReference := reference.WorkloadPIDReference{ Pid: pid, } return anypb.New(&pidReference) diff --git a/pkg/agent/plugin/workloadattestor/v1.go b/pkg/agent/plugin/workloadattestor/v1.go index df7c936962..2442fce867 100644 --- a/pkg/agent/plugin/workloadattestor/v1.go +++ b/pkg/agent/plugin/workloadattestor/v1.go @@ -54,7 +54,7 @@ func (v1 *V1) AttestReference(ctx context.Context, reference *anypb.Any) ([]*com } func extractPIDReference(ref *anypb.Any) (int32, error) { - if ref.GetTypeUrl() == "type.googleapis.com/spiffe.broker.WorkloadPIDReference" { + if ref.GetTypeUrl() == "type.googleapis.com/spiffe.reference.WorkloadPIDReference" { var pidRef reference.WorkloadPIDReference if err := anypb.UnmarshalTo(ref, &pidRef, proto.UnmarshalOptions{}); err != nil { return 0, fmt.Errorf("unmarshaling PID reference: %w", err)