-
Notifications
You must be signed in to change notification settings - Fork 522
Improve performance for fetching authorized entries #6034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b2cd8c5
3364cdb
dab993d
bcaba48
ac26ea3
40a5983
9ea2eaf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -11,12 +11,130 @@ import ( | |||
"github.com/spiffe/spire/pkg/common/protoutil" | ||||
"github.com/spiffe/spire/pkg/common/x509util" | ||||
"github.com/spiffe/spire/proto/spire/common" | ||||
"google.golang.org/protobuf/proto" | ||||
) | ||||
|
||||
const ( | ||||
hintMaximumLength = 1024 | ||||
) | ||||
|
||||
type ReadOnlyEntry struct { | ||||
entry *types.Entry | ||||
} | ||||
|
||||
func NewReadOnlyEntry(entry *types.Entry) ReadOnlyEntry { | ||||
return ReadOnlyEntry{ | ||||
entry: entry, | ||||
} | ||||
} | ||||
|
||||
func (e ReadOnlyEntry) GetId() string { | ||||
return e.entry.Id | ||||
} | ||||
|
||||
func (e *ReadOnlyEntry) GetSpiffeId() *types.SPIFFEID { | ||||
return &types.SPIFFEID{ | ||||
TrustDomain: e.entry.SpiffeId.TrustDomain, | ||||
Path: e.entry.SpiffeId.Path, | ||||
} | ||||
} | ||||
|
||||
func (e *ReadOnlyEntry) GetX509SvidTtl() int32 { | ||||
return e.entry.X509SvidTtl | ||||
} | ||||
|
||||
func (e *ReadOnlyEntry) GetJwtSvidTtl() int32 { | ||||
return e.entry.JwtSvidTtl | ||||
} | ||||
|
||||
func (e *ReadOnlyEntry) GetDnsNames() []string { | ||||
return slices.Clone(e.entry.DnsNames) | ||||
} | ||||
|
||||
func (e *ReadOnlyEntry) GetRevisionNumber() int64 { | ||||
return e.entry.RevisionNumber | ||||
} | ||||
|
||||
func (e *ReadOnlyEntry) GetCreatedAt() int64 { | ||||
return e.entry.CreatedAt | ||||
} | ||||
|
||||
// Manually clone the entry instead of using the protobuf helpers | ||||
// since those are two times slower. | ||||
func (e *ReadOnlyEntry) Clone(mask *types.EntryMask) *types.Entry { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a bit concerned about the potential for field skew here. If the types.Entry struct is updated in the future (e.g., new fields are added), the manual Clone implementation will also need to be updated. Otherwise, newly added fields won't be cloned, which could lead to subtle, hard-to-detect bugs. It might be helpful to add a comment warning about this, or ideally, include a test (perhaps using reflection) that ensures all fields are properly cloned. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a test for this, which indeed uses reflection to make sure all fields are cloned: spire/pkg/server/api/entry_test.go Line 727 in d73d8a7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed that, thanks! |
||||
if mask == nil { | ||||
return proto.Clone(e.entry).(*types.Entry) | ||||
} | ||||
|
||||
clone := &types.Entry{} | ||||
clone.Id = e.entry.Id | ||||
if mask.SpiffeId { | ||||
clone.SpiffeId = e.GetSpiffeId() | ||||
} | ||||
|
||||
if mask.ParentId { | ||||
clone.ParentId = &types.SPIFFEID{ | ||||
TrustDomain: e.entry.ParentId.TrustDomain, | ||||
Path: e.entry.ParentId.Path, | ||||
} | ||||
} | ||||
|
||||
if mask.Selectors { | ||||
for _, selector := range e.entry.Selectors { | ||||
clone.Selectors = append(clone.Selectors, &types.Selector{ | ||||
Type: selector.Type, | ||||
Value: selector.Value, | ||||
}) | ||||
} | ||||
} | ||||
|
||||
if mask.FederatesWith { | ||||
clone.FederatesWith = slices.Clone(e.entry.FederatesWith) | ||||
} | ||||
|
||||
if mask.Admin { | ||||
clone.Admin = e.entry.Admin | ||||
} | ||||
|
||||
if mask.Downstream { | ||||
clone.Downstream = e.entry.Admin | ||||
} | ||||
|
||||
if mask.ExpiresAt { | ||||
clone.ExpiresAt = e.entry.ExpiresAt | ||||
} | ||||
|
||||
if mask.DnsNames { | ||||
clone.DnsNames = slices.Clone(e.entry.DnsNames) | ||||
} | ||||
|
||||
if mask.RevisionNumber { | ||||
clone.RevisionNumber = e.entry.RevisionNumber | ||||
} | ||||
|
||||
if mask.StoreSvid { | ||||
clone.StoreSvid = e.entry.StoreSvid | ||||
} | ||||
|
||||
if mask.X509SvidTtl { | ||||
clone.X509SvidTtl = e.entry.X509SvidTtl | ||||
} | ||||
|
||||
if mask.JwtSvidTtl { | ||||
clone.JwtSvidTtl = e.entry.JwtSvidTtl | ||||
} | ||||
|
||||
if mask.Hint { | ||||
clone.Hint = e.entry.Hint | ||||
} | ||||
|
||||
if mask.CreatedAt { | ||||
clone.CreatedAt = e.entry.CreatedAt | ||||
} | ||||
|
||||
return clone | ||||
} | ||||
|
||||
// RegistrationEntriesToProto converts RegistrationEntry's into Entry's | ||||
func RegistrationEntriesToProto(es []*common.RegistrationEntry) ([]*types.Entry, error) { | ||||
if es == nil { | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem like we there is test coverage for this, could you add that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a test to verify that the getters return the expected value