mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-15 16:28:30 +01:00
fix(iam): preserve CreatedAt across boots + paginate ListProviders
Two medium-priority issues gemini flagged on the read-only IAM API: 1. The static-config bootstrap was setting CreatedAt = time.Now() on every server start, so the IAM GetOpenIDConnectProvider response's CreateDate shifted on each restart even when backed by a persistent store. Look up the existing record via GetProviderByARN first and preserve its CreatedAt; only the UpdatedAt advances. 2. FilerOIDCProviderStore.ListProviders had a hardcoded Limit: 1000 that silently truncated above that. Stream-paginate via StartFromFileName, returning io.EOF naturally and surfacing all other errors instead of swallowing them. Addresses two gemini medium reviews on PR #9319.
This commit is contained in:
1 parent
12688c249e
commit
ef1acaa98c
2 files changed
+52
-23
No files matched your search
@@ -286,16 +286,24 @@ func (m *IAMManager) initOIDCProviderStore(config *IAMConfig) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
clientIDs := extractClientIDs(pc.Config)
|
clientIDs := extractClientIDs(pc.Config)
|
||||||
now := time.Now()
|
ctx := context.Background()
|
||||||
|
// Preserve CreatedAt across reboots when a persistent store already
|
||||||
|
// has this provider — IAM's GetOpenIDConnectProvider response
|
||||||
|
// shouldn't shift its CreateDate every time the server restarts.
|
||||||
|
now := time.Now().UTC()
|
||||||
|
createdAt := now
|
||||||
|
if existing, err := store.GetProviderByARN(ctx, m.getFilerAddress(), arn); err == nil && existing != nil && !existing.CreatedAt.IsZero() {
|
||||||
|
createdAt = existing.CreatedAt
|
||||||
|
}
|
||||||
rec := &OIDCProviderRecord{
|
rec := &OIDCProviderRecord{
|
||||||
AccountID: accountID,
|
AccountID: accountID,
|
||||||
ARN: arn,
|
ARN: arn,
|
||||||
URL: issuer,
|
URL: issuer,
|
||||||
ClientIDs: clientIDs,
|
ClientIDs: clientIDs,
|
||||||
CreatedAt: now,
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
}
|
}
|
||||||
if err := store.StoreProvider(context.Background(), m.getFilerAddress(), rec); err != nil {
|
if err := store.StoreProvider(ctx, m.getFilerAddress(), rec); err != nil {
|
||||||
glog.Warningf("mirror static OIDC provider %s into store: %v", pc.Name, err)
|
glog.Warningf("mirror static OIDC provider %s into store: %v", pc.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -281,30 +283,49 @@ func (f *FilerOIDCProviderStore) ListProviders(ctx context.Context, filerAddress
|
|||||||
|
|
||||||
var out []*OIDCProviderRecord
|
var out []*OIDCProviderRecord
|
||||||
err := f.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error {
|
err := f.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error {
|
||||||
stream, err := client.ListEntries(ctx, &filer_pb.ListEntriesRequest{
|
// Stream-paginate via StartFromFileName so deployments with more
|
||||||
Directory: f.basePath,
|
// than 1000 providers don't get a silently truncated list.
|
||||||
Limit: 1000,
|
const pageSize = 1000
|
||||||
})
|
startFrom := ""
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("list OIDC providers: %v", err)
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
resp, err := stream.Recv()
|
stream, err := client.ListEntries(ctx, &filer_pb.ListEntriesRequest{
|
||||||
|
Directory: f.basePath,
|
||||||
|
Limit: pageSize,
|
||||||
|
StartFromFileName: startFrom,
|
||||||
|
InclusiveStartFrom: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return fmt.Errorf("list OIDC providers: %v", err)
|
||||||
|
}
|
||||||
|
lastName := ""
|
||||||
|
pageCount := 0
|
||||||
|
for {
|
||||||
|
resp, recvErr := stream.Recv()
|
||||||
|
if recvErr != nil {
|
||||||
|
if errors.Is(recvErr, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return fmt.Errorf("recv OIDC provider entry: %w", recvErr)
|
||||||
|
}
|
||||||
|
if resp.Entry == nil || resp.Entry.IsDirectory {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lastName = resp.Entry.Name
|
||||||
|
pageCount++
|
||||||
|
if !strings.HasSuffix(resp.Entry.Name, ".json") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var rec OIDCProviderRecord
|
||||||
|
if err := json.Unmarshal(resp.Entry.Content, &rec); err != nil {
|
||||||
|
glog.Warningf("skipping malformed OIDC provider record %s: %v", resp.Entry.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, &rec)
|
||||||
|
}
|
||||||
|
if pageCount < pageSize {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if resp.Entry == nil || resp.Entry.IsDirectory {
|
startFrom = lastName
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.HasSuffix(resp.Entry.Name, ".json") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var rec OIDCProviderRecord
|
|
||||||
if err := json.Unmarshal(resp.Entry.Content, &rec); err != nil {
|
|
||||||
glog.Warningf("skipping malformed OIDC provider record %s: %v", resp.Entry.Name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
out = append(out, &rec)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in new issue
Block a user