Implement managed policy storage (#8385)
* Persist managed IAM policies * Add IAM list/get policy integration test * Faster marker lookup and cleanup * Handle delete conflict and improve listing * Add delete-in-use policy integration test * Stabilize policy ID and guard path prefix * Tighten CreatePolicy guard and reload * Add ListPolicyNames to credential store
This commit is contained in:
@@ -144,6 +144,11 @@ func (cm *CredentialManager) GetPolicy(ctx context.Context, name string) (*polic
|
||||
return cm.Store.GetPolicy(ctx, name)
|
||||
}
|
||||
|
||||
// ListPolicyNames returns the names of all policies
|
||||
func (cm *CredentialManager) ListPolicyNames(ctx context.Context) ([]string, error) {
|
||||
return cm.Store.ListPolicyNames(ctx)
|
||||
}
|
||||
|
||||
// CreatePolicy creates a new policy (if supported by the store)
|
||||
func (cm *CredentialManager) CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
// Check if the store implements PolicyManager interface with CreatePolicy
|
||||
|
||||
@@ -71,6 +71,8 @@ type CredentialStore interface {
|
||||
|
||||
// Policy Management
|
||||
GetPolicies(ctx context.Context) (map[string]policy_engine.PolicyDocument, error)
|
||||
// ListPolicyNames returns the names of all policies
|
||||
ListPolicyNames(ctx context.Context) ([]string, error)
|
||||
// PutPolicy creates or replaces a policy document.
|
||||
PutPolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error
|
||||
DeletePolicy(ctx context.Context, name string) error
|
||||
|
||||
@@ -235,3 +235,45 @@ func (store *FilerEtcStore) GetPolicy(ctx context.Context, name string) (*policy
|
||||
|
||||
return nil, nil // Policy not found
|
||||
}
|
||||
|
||||
// ListPolicyNames returns all managed policy names stored in the filer.
|
||||
func (store *FilerEtcStore) ListPolicyNames(ctx context.Context) ([]string, error) {
|
||||
names := make([]string, 0)
|
||||
|
||||
store.mu.RLock()
|
||||
configured := store.filerAddressFunc != nil
|
||||
store.mu.RUnlock()
|
||||
|
||||
if !configured {
|
||||
return names, nil
|
||||
}
|
||||
|
||||
err := store.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
|
||||
dir := filer.IamConfigDirectory + "/" + IamPoliciesDirectory
|
||||
entries, err := listEntries(ctx, client, dir)
|
||||
if err != nil {
|
||||
if err == filer_pb.ErrNotFound {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDirectory {
|
||||
continue
|
||||
}
|
||||
name := entry.Name
|
||||
if strings.HasSuffix(name, ".json") {
|
||||
name = name[:len(name)-5]
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
@@ -79,6 +79,22 @@ func (store *IamGrpcStore) CreatePolicy(ctx context.Context, name string, docume
|
||||
return store.PutPolicy(ctx, name, document)
|
||||
}
|
||||
|
||||
// ListPolicyNames retrieves names of all IAM policies via gRPC.
|
||||
func (store *IamGrpcStore) ListPolicyNames(ctx context.Context) ([]string, error) {
|
||||
var names []string
|
||||
err := store.withIamClient(func(client iam_pb.SeaweedIdentityAccessManagementClient) error {
|
||||
resp, err := client.ListPolicies(ctx, &iam_pb.ListPoliciesRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, policy := range resp.Policies {
|
||||
names = append(names, policy.Name)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return names, err
|
||||
}
|
||||
|
||||
// UpdatePolicy updates an existing policy (delegates to PutPolicy)
|
||||
func (store *IamGrpcStore) UpdatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
return store.PutPolicy(ctx, name, document)
|
||||
|
||||
@@ -25,6 +25,23 @@ func (store *MemoryStore) GetPolicies(ctx context.Context) (map[string]policy_en
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
// ListPolicyNames returns all stored policy names.
|
||||
func (store *MemoryStore) ListPolicyNames(ctx context.Context) ([]string, error) {
|
||||
store.mu.RLock()
|
||||
defer store.mu.RUnlock()
|
||||
|
||||
if !store.initialized {
|
||||
return nil, fmt.Errorf("store not initialized")
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(store.policies))
|
||||
for name := range store.policies {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// GetPolicy retrieves a specific IAM policy by name from memory
|
||||
func (store *MemoryStore) GetPolicy(ctx context.Context, name string) (*policy_engine.PolicyDocument, error) {
|
||||
store.mu.RLock()
|
||||
|
||||
@@ -41,6 +41,30 @@ func (store *PostgresStore) GetPolicies(ctx context.Context) (map[string]policy_
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
// ListPolicyNames returns all managed policy names from PostgreSQL.
|
||||
func (store *PostgresStore) ListPolicyNames(ctx context.Context) ([]string, error) {
|
||||
if !store.configured {
|
||||
return nil, fmt.Errorf("store not configured")
|
||||
}
|
||||
|
||||
var names []string
|
||||
rows, err := store.db.QueryContext(ctx, "SELECT name FROM policies")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query policy names: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan policy name: %w", err)
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// CreatePolicy creates a new IAM policy in PostgreSQL
|
||||
func (store *PostgresStore) CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
if !store.configured {
|
||||
|
||||
@@ -236,6 +236,10 @@ func (s *PropagatingCredentialStore) DeletePolicy(ctx context.Context, name stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PropagatingCredentialStore) ListPolicyNames(ctx context.Context) ([]string, error) {
|
||||
return s.CredentialStore.ListPolicyNames(ctx)
|
||||
}
|
||||
|
||||
func (s *PropagatingCredentialStore) CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
if pm, ok := s.CredentialStore.(PolicyManager); ok {
|
||||
if err := pm.CreatePolicy(ctx, name, document); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user