Skip to content

x509 cache hint for registration entries#6360

Open
ValFadeev wants to merge 37 commits intospiffe:mainfrom
ValFadeev:jwt-preference-entry
Open

x509 cache hint for registration entries#6360
ValFadeev wants to merge 37 commits intospiffe:mainfrom
ValFadeev:jwt-preference-entry

Conversation

@ValFadeev
Copy link
Contributor

@ValFadeev ValFadeev commented Oct 6, 2025

This is a draft PR aiming to implement some of the suggestions discussed in #6129. It adds a new field to RegisteredEntry represented by an opaque protobuf-encoded message. The message is meant to contain flags and other fields guiding the agent's behavior with respect to pre-fetching and caching of X509 SVIDs. The intention is to reduce unnecessary work performed by the agent, in case the client is unlikely to ever ask for an X509 SVID and prefers JWT instead. For now only one boolean flag JWTOnly is introduced. Other fields may be added later to fine-tune the logic and cover various edge-cases.
The bulk of this draft is to define the new field in the message definition, update the datastore and have the existing tests pass. The actual usage of the field in fetchEntries is purely indicative and requires further consideration.

Pull Request check list

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

Affected functionality

  • adds a new field to RegisteredEntry and the underlying datastore table
  • allows flagging registration entries as preferring JWT SVID over X509
    Description of change

Which issue this PR fixes

Fixes #6129

Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
@amartinezfayo
Copy link
Member

Hi @ValFadeev, are you planning to go back to this PR?

@ValFadeev
Copy link
Contributor Author

Hi @amartinezfayo, apologies for the delay. I had a few conflicting priorities lately, but I do plan to pick this back up over the coming week.

Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
@ValFadeev ValFadeev force-pushed the jwt-preference-entry branch from a3460c8 to 33440fc Compare November 27, 2025 22:51
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
@ValFadeev ValFadeev changed the title [WIP] - x509 cache hint for registration entries x509 cache hint for registration entries Nov 30, 2025
@ValFadeev ValFadeev marked this pull request as ready for review November 30, 2025 21:59
@ValFadeev ValFadeev marked this pull request as draft November 30, 2025 22:02
@ValFadeev
Copy link
Contributor Author

@amartinezfayo offering this for another review. I am not sure I implemented the semantics of an optional field the right way when loading from row. I also understand this change may have to be split in two, with the schema migration going first. But hopefully, this gives an outline of the functionality, as it was last described.

Comment on lines 348 to 350
if !entry.CacheHintFlags.GetDisableX509SvidPrefetch() {
cacheEntries[entryID] = entry
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would mean that the entry is not added to the cache, which means that no workload would be able to request a SVID for it. I think the flag should end up in the lru cache where it can inform if the entry needs to prefetched or not but still allow a workload to request an x509-svid if it so desires.

I think syncSVIDsWithSubscribers might be the place to do this.

Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
@sorindumitru
Copy link
Collaborator

I think you'll also need to make changes to the Entry type in spire-api-sdk for the agent to get and be able to use the new field.

/** Represents a set of flags informing the agent behaviour with respect to
pre-fecthing and caching SVIDs. This is meant to prevent unnecessary effort
spent on generating SVIDs of types, which are unlikely to be needed. */
message CacheHintFlags {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since we're likely going to use this even for non-flag fields, could we call it something else? Nothing better than OptionalFields comes to me right now, let me know if you have other suggestions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would say something like AdditionalAttributes. This is to distinguish them from optional fields in the containing struct, such as Expiry.


// CacheHintFlags contains a set of options and flags that inform the
// agent behaviour with respect to pre-fetching and refreshing X509 SVIDs
CacheHintFlags []byte `gorm:"size:255,column:cache_hint_flags"` // corresponds to TINYBLOB in MySQL
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since we may end up having other bigger fields in there, maybe we can go one size up to have some more space? I think that would be size:65535

@ValFadeev ValFadeev marked this pull request as ready for review January 22, 2026 22:31
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
func migrateToV24(tx *gorm.DB) error {
// Add agent_version column to attested_node_entries table
if err := tx.AutoMigrate(&AttestedNode{}).Error; err != nil {
if err := tx.AutoMigrate(&AttestedNode{}, &RegisteredEntry{}).Error; err != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since there is currently no released version between my changes and #6542, I am temporarily combining migrations here to have tests pass. Once 1.14.2 is released, I will only leave my table and increment the version.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Usually we seemed to have created independent migrations for different data store changes. I think they're not strictly speaking needed, but they might be useful for the case of local development.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This still needs to be addressed.

Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Copy link
Collaborator

@sorindumitru sorindumitru left a comment

Choose a reason for hiding this comment

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

Thanks for these changes, @ValFadeev. Are you also planning on adding support for this to the CLI?

func migrateToV24(tx *gorm.DB) error {
// Add agent_version column to attested_node_entries table
if err := tx.AutoMigrate(&AttestedNode{}).Error; err != nil {
if err := tx.AutoMigrate(&AttestedNode{}, &RegisteredEntry{}).Error; err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Usually we seemed to have created independent migrations for different data store changes. I think they're not strictly speaking needed, but they might be useful for the case of local development.

Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Copy link
Collaborator

@sorindumitru sorindumitru left a comment

Choose a reason for hiding this comment

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

It would be good to also add something to the intergration tests to verify that these entries are not prefetching SVIDs. Maybe that's possible in the entries test, e.g. by creating a entry at the start of that script and making sure at the end it the agent(s) didn't prefetch it?

I think you're also missing some changes to pkg/agent/client.go to specify the new field in the mask and possibly to parse it.

Comment on lines 219 to 221
additionalAttributes := &types.Entry_AdditionalAttributes{}
additionalAttributes.DisableX509SvidPrefetch = c.disableX509SVIDPrefetch
e.AdditionalAttributes = additionalAttributes
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we only create the additional attributes if one of the attributes in it is defined? Would avoid having to parse the whole field.

Comment on lines +212 to +218
func ProtoFromAdditionalAttributes(in *common.RegistrationEntry_AdditionalAttributes) *types.Entry_AdditionalAttributes {
if in != nil {
return &types.Entry_AdditionalAttributes{
DisableX509SvidPrefetch: in.DisableX509SvidPrefetch,
}
}
return nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we would also need a similar item for doing the reverse, and it should be used in ProtoToRegistrationEntryWithMask.

func migrateToV24(tx *gorm.DB) error {
// Add agent_version column to attested_node_entries table
if err := tx.AutoMigrate(&AttestedNode{}).Error; err != nil {
if err := tx.AutoMigrate(&AttestedNode{}, &RegisteredEntry{}).Error; err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This still needs to be addressed.

Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
Signed-off-by: Valentin Fadeev <vfadeev@bloomberg.net>
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.

Flag for jwt preference entry

4 participants

Comments