You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

142 lines
4.5 KiB

package filer_etc
import (
"context"
"encoding/json"
"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]policy_engine.PolicyDocument `json:"policies"`
}
// GetPolicies retrieves all IAM policies from the filer
func (store *FilerEtcStore) GetPolicies(ctx context.Context) (map[string]policy_engine.PolicyDocument, error) {
policiesCollection := &PoliciesCollection{
Policies: make(map[string]policy_engine.PolicyDocument),
}
// Check if filer client is configured
if store.filerGrpcAddress == "" {
glog.V(1).Infof("Filer client not configured for policy retrieval, returning empty policies")
// Return empty policies if filer client is not configured
return policiesCollection.Policies, nil
}
glog.V(2).Infof("Loading IAM policies from %s/%s (filer: %s)",
filer.IamConfigDirectory, filer.IamPoliciesFile, store.filerGrpcAddress)
err := store.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
// Use ReadInsideFiler instead of ReadEntry since policies.json is small
// and stored inline. ReadEntry requires a master client for chunked files,
// but ReadInsideFiler only reads inline content.
content, err := filer.ReadInsideFiler(client, filer.IamConfigDirectory, filer.IamPoliciesFile)
if err != nil {
if err == filer_pb.ErrNotFound {
glog.V(1).Infof("Policies file not found at %s/%s, returning empty policies",
filer.IamConfigDirectory, filer.IamPoliciesFile)
// If file doesn't exist, return empty collection
return nil
}
glog.Errorf("Failed to read IAM policies file from %s/%s: %v",
filer.IamConfigDirectory, filer.IamPoliciesFile, err)
return err
}
if len(content) == 0 {
glog.V(2).Infof("IAM policies file at %s/%s is empty",
filer.IamConfigDirectory, filer.IamPoliciesFile)
return nil
}
glog.V(2).Infof("Read %d bytes from %s/%s",
len(content), filer.IamConfigDirectory, filer.IamPoliciesFile)
if err := json.Unmarshal(content, policiesCollection); err != nil {
glog.Errorf("Failed to parse IAM policies from %s/%s: %v",
filer.IamConfigDirectory, filer.IamPoliciesFile, err)
return err
}
glog.V(1).Infof("Successfully loaded %d IAM policies", len(policiesCollection.Policies))
return nil
})
if err != nil {
return nil, err
}
// Log policy names for debugging
if glog.V(2) && len(policiesCollection.Policies) > 0 {
for policyName := range policiesCollection.Policies {
glog.V(2).Infof(" Policy: %s", policyName)
}
}
return policiesCollection.Policies, nil
}
// CreatePolicy creates a new IAM policy in the filer
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 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]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]policy_engine.PolicyDocument)) error {
// Load existing policies
policies, err := store.GetPolicies(ctx)
if err != nil {
return err
}
// Apply update
updateFunc(policies)
// Save back to filer
policiesCollection := &PoliciesCollection{
Policies: policies,
}
data, err := json.Marshal(policiesCollection)
if err != nil {
return err
}
return store.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
return filer.SaveInsideFiler(client, filer.IamConfigDirectory, filer.IamPoliciesFile, data)
})
}
// GetPolicy retrieves a specific IAM policy by name from the filer
func (store *FilerEtcStore) GetPolicy(ctx context.Context, name string) (*policy_engine.PolicyDocument, error) {
policies, err := store.GetPolicies(ctx)
if err != nil {
return nil, err
}
if policy, exists := policies[name]; exists {
return &policy, nil
}
return nil, nil // Policy not found
}