mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-09-22 22:33:33 +08:00
Add policy engine (#6970)
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util"
|
||||
)
|
||||
|
||||
@@ -86,26 +87,13 @@ type UserCredentials struct {
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
// PolicyStatement represents a single policy statement in an IAM policy
|
||||
type PolicyStatement struct {
|
||||
Effect string `json:"Effect"`
|
||||
Action []string `json:"Action"`
|
||||
Resource []string `json:"Resource"`
|
||||
}
|
||||
|
||||
// PolicyDocument represents an IAM policy document
|
||||
type PolicyDocument struct {
|
||||
Version string `json:"Version"`
|
||||
Statement []*PolicyStatement `json:"Statement"`
|
||||
}
|
||||
|
||||
// PolicyManager interface for managing IAM policies
|
||||
type PolicyManager interface {
|
||||
GetPolicies(ctx context.Context) (map[string]PolicyDocument, error)
|
||||
CreatePolicy(ctx context.Context, name string, document PolicyDocument) error
|
||||
UpdatePolicy(ctx context.Context, name string, document PolicyDocument) error
|
||||
GetPolicies(ctx context.Context) (map[string]policy_engine.PolicyDocument, error)
|
||||
CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error
|
||||
UpdatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error
|
||||
DeletePolicy(ctx context.Context, name string) error
|
||||
GetPolicy(ctx context.Context, name string) (*PolicyDocument, error)
|
||||
GetPolicy(ctx context.Context, name string) (*policy_engine.PolicyDocument, error)
|
||||
}
|
||||
|
||||
// Stores holds all available credential store implementations
|
||||
|
@@ -5,20 +5,20 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/credential"
|
||||
"github.com/seaweedfs/seaweedfs/weed/filer"
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
|
||||
)
|
||||
|
||||
type PoliciesCollection struct {
|
||||
Policies map[string]credential.PolicyDocument `json:"policies"`
|
||||
Policies map[string]policy_engine.PolicyDocument `json:"policies"`
|
||||
}
|
||||
|
||||
// GetPolicies retrieves all IAM policies from the filer
|
||||
func (store *FilerEtcStore) GetPolicies(ctx context.Context) (map[string]credential.PolicyDocument, error) {
|
||||
func (store *FilerEtcStore) GetPolicies(ctx context.Context) (map[string]policy_engine.PolicyDocument, error) {
|
||||
policiesCollection := &PoliciesCollection{
|
||||
Policies: make(map[string]credential.PolicyDocument),
|
||||
Policies: make(map[string]policy_engine.PolicyDocument),
|
||||
}
|
||||
|
||||
// Check if filer client is configured
|
||||
@@ -53,28 +53,28 @@ func (store *FilerEtcStore) GetPolicies(ctx context.Context) (map[string]credent
|
||||
}
|
||||
|
||||
// CreatePolicy creates a new IAM policy in the filer
|
||||
func (store *FilerEtcStore) CreatePolicy(ctx context.Context, name string, document credential.PolicyDocument) error {
|
||||
return store.updatePolicies(ctx, func(policies map[string]credential.PolicyDocument) {
|
||||
func (store *FilerEtcStore) CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
return store.updatePolicies(ctx, func(policies map[string]policy_engine.PolicyDocument) {
|
||||
policies[name] = document
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatePolicy updates an existing IAM policy in the filer
|
||||
func (store *FilerEtcStore) UpdatePolicy(ctx context.Context, name string, document credential.PolicyDocument) error {
|
||||
return store.updatePolicies(ctx, func(policies map[string]credential.PolicyDocument) {
|
||||
func (store *FilerEtcStore) UpdatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
return store.updatePolicies(ctx, func(policies map[string]policy_engine.PolicyDocument) {
|
||||
policies[name] = document
|
||||
})
|
||||
}
|
||||
|
||||
// DeletePolicy deletes an IAM policy from the filer
|
||||
func (store *FilerEtcStore) DeletePolicy(ctx context.Context, name string) error {
|
||||
return store.updatePolicies(ctx, func(policies map[string]credential.PolicyDocument) {
|
||||
return store.updatePolicies(ctx, func(policies map[string]policy_engine.PolicyDocument) {
|
||||
delete(policies, name)
|
||||
})
|
||||
}
|
||||
|
||||
// updatePolicies is a helper method to update policies atomically
|
||||
func (store *FilerEtcStore) updatePolicies(ctx context.Context, updateFunc func(map[string]credential.PolicyDocument)) error {
|
||||
func (store *FilerEtcStore) updatePolicies(ctx context.Context, updateFunc func(map[string]policy_engine.PolicyDocument)) error {
|
||||
// Load existing policies
|
||||
policies, err := store.GetPolicies(ctx)
|
||||
if err != nil {
|
||||
@@ -100,7 +100,7 @@ func (store *FilerEtcStore) updatePolicies(ctx context.Context, updateFunc func(
|
||||
}
|
||||
|
||||
// GetPolicy retrieves a specific IAM policy by name from the filer
|
||||
func (store *FilerEtcStore) GetPolicy(ctx context.Context, name string) (*credential.PolicyDocument, error) {
|
||||
func (store *FilerEtcStore) GetPolicy(ctx context.Context, name string) (*policy_engine.PolicyDocument, error) {
|
||||
policies, err := store.GetPolicies(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/credential"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
|
||||
)
|
||||
|
||||
// GetPolicies retrieves all IAM policies from memory
|
||||
func (store *MemoryStore) GetPolicies(ctx context.Context) (map[string]credential.PolicyDocument, error) {
|
||||
func (store *MemoryStore) GetPolicies(ctx context.Context) (map[string]policy_engine.PolicyDocument, error) {
|
||||
store.mu.RLock()
|
||||
defer store.mu.RUnlock()
|
||||
|
||||
@@ -17,7 +17,7 @@ func (store *MemoryStore) GetPolicies(ctx context.Context) (map[string]credentia
|
||||
}
|
||||
|
||||
// Create a copy of the policies map to avoid mutation issues
|
||||
policies := make(map[string]credential.PolicyDocument)
|
||||
policies := make(map[string]policy_engine.PolicyDocument)
|
||||
for name, doc := range store.policies {
|
||||
policies[name] = doc
|
||||
}
|
||||
@@ -26,7 +26,7 @@ func (store *MemoryStore) GetPolicies(ctx context.Context) (map[string]credentia
|
||||
}
|
||||
|
||||
// GetPolicy retrieves a specific IAM policy by name from memory
|
||||
func (store *MemoryStore) GetPolicy(ctx context.Context, name string) (*credential.PolicyDocument, error) {
|
||||
func (store *MemoryStore) GetPolicy(ctx context.Context, name string) (*policy_engine.PolicyDocument, error) {
|
||||
store.mu.RLock()
|
||||
defer store.mu.RUnlock()
|
||||
|
||||
@@ -38,7 +38,7 @@ func (store *MemoryStore) GetPolicy(ctx context.Context, name string) (*credenti
|
||||
}
|
||||
|
||||
// CreatePolicy creates a new IAM policy in memory
|
||||
func (store *MemoryStore) CreatePolicy(ctx context.Context, name string, document credential.PolicyDocument) error {
|
||||
func (store *MemoryStore) CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
|
||||
@@ -51,7 +51,7 @@ func (store *MemoryStore) CreatePolicy(ctx context.Context, name string, documen
|
||||
}
|
||||
|
||||
// UpdatePolicy updates an existing IAM policy in memory
|
||||
func (store *MemoryStore) UpdatePolicy(ctx context.Context, name string, document credential.PolicyDocument) error {
|
||||
func (store *MemoryStore) UpdatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/credential"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util"
|
||||
)
|
||||
|
||||
@@ -16,9 +17,9 @@ func init() {
|
||||
// This is primarily intended for testing purposes
|
||||
type MemoryStore struct {
|
||||
mu sync.RWMutex
|
||||
users map[string]*iam_pb.Identity // username -> identity
|
||||
accessKeys map[string]string // access_key -> username
|
||||
policies map[string]credential.PolicyDocument // policy_name -> policy_document
|
||||
users map[string]*iam_pb.Identity // username -> identity
|
||||
accessKeys map[string]string // access_key -> username
|
||||
policies map[string]policy_engine.PolicyDocument // policy_name -> policy_document
|
||||
initialized bool
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ func (store *MemoryStore) Initialize(configuration util.Configuration, prefix st
|
||||
|
||||
store.users = make(map[string]*iam_pb.Identity)
|
||||
store.accessKeys = make(map[string]string)
|
||||
store.policies = make(map[string]credential.PolicyDocument)
|
||||
store.policies = make(map[string]policy_engine.PolicyDocument)
|
||||
store.initialized = true
|
||||
|
||||
return nil
|
||||
|
@@ -5,16 +5,16 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/credential"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
|
||||
)
|
||||
|
||||
// GetPolicies retrieves all IAM policies from PostgreSQL
|
||||
func (store *PostgresStore) GetPolicies(ctx context.Context) (map[string]credential.PolicyDocument, error) {
|
||||
func (store *PostgresStore) GetPolicies(ctx context.Context) (map[string]policy_engine.PolicyDocument, error) {
|
||||
if !store.configured {
|
||||
return nil, fmt.Errorf("store not configured")
|
||||
}
|
||||
|
||||
policies := make(map[string]credential.PolicyDocument)
|
||||
policies := make(map[string]policy_engine.PolicyDocument)
|
||||
|
||||
rows, err := store.db.QueryContext(ctx, "SELECT name, document FROM policies")
|
||||
if err != nil {
|
||||
@@ -30,7 +30,7 @@ func (store *PostgresStore) GetPolicies(ctx context.Context) (map[string]credent
|
||||
return nil, fmt.Errorf("failed to scan policy row: %v", err)
|
||||
}
|
||||
|
||||
var document credential.PolicyDocument
|
||||
var document policy_engine.PolicyDocument
|
||||
if err := json.Unmarshal(documentJSON, &document); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal policy document for %s: %v", name, err)
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (store *PostgresStore) GetPolicies(ctx context.Context) (map[string]credent
|
||||
}
|
||||
|
||||
// CreatePolicy creates a new IAM policy in PostgreSQL
|
||||
func (store *PostgresStore) CreatePolicy(ctx context.Context, name string, document credential.PolicyDocument) error {
|
||||
func (store *PostgresStore) CreatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
if !store.configured {
|
||||
return fmt.Errorf("store not configured")
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (store *PostgresStore) CreatePolicy(ctx context.Context, name string, docum
|
||||
}
|
||||
|
||||
// UpdatePolicy updates an existing IAM policy in PostgreSQL
|
||||
func (store *PostgresStore) UpdatePolicy(ctx context.Context, name string, document credential.PolicyDocument) error {
|
||||
func (store *PostgresStore) UpdatePolicy(ctx context.Context, name string, document policy_engine.PolicyDocument) error {
|
||||
if !store.configured {
|
||||
return fmt.Errorf("store not configured")
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func (store *PostgresStore) DeletePolicy(ctx context.Context, name string) error
|
||||
}
|
||||
|
||||
// GetPolicy retrieves a specific IAM policy by name from PostgreSQL
|
||||
func (store *PostgresStore) GetPolicy(ctx context.Context, name string) (*credential.PolicyDocument, error) {
|
||||
func (store *PostgresStore) GetPolicy(ctx context.Context, name string) (*policy_engine.PolicyDocument, error) {
|
||||
policies, err := store.GetPolicies(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/credential"
|
||||
"github.com/seaweedfs/seaweedfs/weed/credential/memory"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
|
||||
|
||||
// Import all store implementations to register them
|
||||
_ "github.com/seaweedfs/seaweedfs/weed/credential/filer_etc"
|
||||
@@ -46,13 +47,13 @@ func testPolicyOperations(t *testing.T, ctx context.Context, credentialManager *
|
||||
}
|
||||
|
||||
// Test CreatePolicy
|
||||
testPolicy := credential.PolicyDocument{
|
||||
testPolicy := policy_engine.PolicyDocument{
|
||||
Version: "2012-10-17",
|
||||
Statement: []*credential.PolicyStatement{
|
||||
Statement: []policy_engine.PolicyStatement{
|
||||
{
|
||||
Effect: "Allow",
|
||||
Action: []string{"s3:GetObject"},
|
||||
Resource: []string{"arn:aws:s3:::test-bucket/*"},
|
||||
Effect: policy_engine.PolicyEffectAllow,
|
||||
Action: policy_engine.NewStringOrStringSlice("s3:GetObject"),
|
||||
Resource: policy_engine.NewStringOrStringSlice("arn:aws:s3:::test-bucket/*"),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -84,13 +85,13 @@ func testPolicyOperations(t *testing.T, ctx context.Context, credentialManager *
|
||||
}
|
||||
|
||||
// Test UpdatePolicy
|
||||
updatedPolicy := credential.PolicyDocument{
|
||||
updatedPolicy := policy_engine.PolicyDocument{
|
||||
Version: "2012-10-17",
|
||||
Statement: []*credential.PolicyStatement{
|
||||
Statement: []policy_engine.PolicyStatement{
|
||||
{
|
||||
Effect: "Allow",
|
||||
Action: []string{"s3:GetObject", "s3:PutObject"},
|
||||
Resource: []string{"arn:aws:s3:::test-bucket/*"},
|
||||
Effect: policy_engine.PolicyEffectAllow,
|
||||
Action: policy_engine.NewStringOrStringSlice("s3:GetObject", "s3:PutObject"),
|
||||
Resource: policy_engine.NewStringOrStringSlice("arn:aws:s3:::test-bucket/*"),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -113,8 +114,8 @@ func testPolicyOperations(t *testing.T, ctx context.Context, credentialManager *
|
||||
if len(updatedPolicyResult.Statement) != 1 {
|
||||
t.Errorf("Expected 1 statement after update, got %d", len(updatedPolicyResult.Statement))
|
||||
}
|
||||
if len(updatedPolicyResult.Statement[0].Action) != 2 {
|
||||
t.Errorf("Expected 2 actions after update, got %d", len(updatedPolicyResult.Statement[0].Action))
|
||||
if len(updatedPolicyResult.Statement[0].Action.Strings()) != 2 {
|
||||
t.Errorf("Expected 2 actions after update, got %d", len(updatedPolicyResult.Statement[0].Action.Strings()))
|
||||
}
|
||||
|
||||
// Test DeletePolicy
|
||||
|
Reference in New Issue
Block a user