Skip to content

Implement SPIFFE Broker Endpoint & API#6594

Draft
arndt-s wants to merge 5 commits intospiffe:mainfrom
arndt-s:arndt/implement_broker_endpoint_and_api
Draft

Implement SPIFFE Broker Endpoint & API#6594
arndt-s wants to merge 5 commits intospiffe:mainfrom
arndt-s:arndt/implement_broker_endpoint_and_api

Conversation

@arndt-s
Copy link
Member

@arndt-s arndt-s commented Jan 21, 2026

This is a Work In Progress.

Reference implementation for spiffe/spiffe#340

api-sdk PR: spiffe/spire-api-sdk#92
plugin-sdk PR: spiffe/spire-plugin-sdk#71

Pull Request check list

  • Commit conforms to CONTRIBUTING.md?
  • Proper tests/regressions included?
  • Documentation updated?

Affected functionality

Description of change

Which issue this PR fixes

Signed-off-by: arndt-s <17650715+arndt-s@users.noreply.github.com>
Copy link
Member Author

@arndt-s arndt-s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self review highlighting parts that I would like to get feedback/opinions on please.

# admin_socket_path = ""

# authorized_delegates: SPIFFE ID list of the authorized delegates
# authorized_delegates = [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure whether we should allow for a dedicated allow list for the broker endpoint or reuse the same?

return c.AdminSocketPath != ""
}

func (c *agentConfig) getBrokerAddr() (net.Addr, error) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I'm only supporting UDS, once the Broker API evolves we may allow serving it on TCP too.

)

// 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.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is worth a discussion.

TrustDomain: a.c.TrustDomain,
AuthorizedDelegates: a.c.AuthorizedDelegates,
SVIDSource: as,
BundleSource: manager.GetX509Bundle(),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure what's better here, us the attestation result as a bundle source or the one from the manager?

if err != nil {
return err
}
_ = rpccontext.Logger(ctx).WithField("broker_peer", peer.String())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no log here .. I'm considering to add Debug logs for each RPC?

}

func New(c *Config) (*Endpoints, error) {
switch {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this pattern ok? Delegated Identity doesn't have it and would panic if misconfigured?


// 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.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also worth a discussion

)

e.registerBrokerAPI(server)
reflection.Register(server)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any objections in having it here? I don't see a drawback and could help brokers that don't want to know the proto?

// 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 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a configuration sanity check here. Any objections?

// 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 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arndt-s
This means the authorized delegates SpiffeIDs must be well known and configured ahead the deployment happens.
The problem is that when deploying SPIRE on K8s/OCP you not necessary know what they are.
Let's take Istio as an example.
First user deployed SPIRE, next deploys Istio.
The SPIFFE IDs are created dynamically based on the ClusterSPIFFEID CRs
With if len(e.c.AuthorizedDelegates) == 0 the Spire agent won't become healthy until relevant Spiffe ID is created and the Spire-Agent config map being updated.

I think we should disable this constraint, or at least make it optional.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally you should be able to determine what SPIFFE IDs your workload is going to receive ahead of time. For example in k8s most of the time this is defined from namespace and service account names, which I imagine you have some control over.

It's possible to include more randomised information in there, e.g. pod uid in k8s, but I don't think that's particularly common. If that's the case, the policy specified here through this authorised delegates list could get some support for wildcarding.

Before doing that we'd like to see that there is an actually need for it, so if you have a use case where that's necessary let us know. Either way, that's not something that needs to be handled by this PR.

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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can broker use agent PID? I'd like to block that? What if it uses the pod UID of the agent?

TODO for myself to find a solution so that workload.go get's to know it's itself without knowing the details of the reference.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do others make images with custom api & plugin packages?

@arndt-s
Copy link
Member Author

arndt-s commented Feb 17, 2026

Things to discuss:

  • Workload Attestor v2 interface
    • v1 <-> v2 compatability
    • proto Any
  • Broker Endpoint Socket
    • authn (bundle & svid source from agent <-> server comms)
      @sorindumitru mentioned that there could be an API on the server that allows both. Also to check key manager and locking during rotation.
    • authz (re-using admin socket allowlist)
    • -> do dedicated allowlist
    • gRPC reflection API
  • Windows support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants