diff options
| author | chrislu <chris.lu@gmail.com> | 2025-08-30 11:18:03 -0700 |
|---|---|---|
| committer | chrislu <chris.lu@gmail.com> | 2025-08-30 11:18:03 -0700 |
| commit | 87021a146027f83f911619f71b9c27bd51e9d55a (patch) | |
| tree | c7720f1c285683ce19d28931bd7c11b5475a2844 /weed/s3api/s3api_server.go | |
| parent | 0748214c8e2f497a84b9392d2d7d4ec976bc84eb (diff) | |
| parent | 879d512b552d834136cfb746a239e6168e5c4ffb (diff) | |
| download | seaweedfs-origin/add-ec-vacuum.tar.xz seaweedfs-origin/add-ec-vacuum.zip | |
Merge branch 'master' into add-ec-vacuumorigin/add-ec-vacuum
Diffstat (limited to 'weed/s3api/s3api_server.go')
| -rw-r--r-- | weed/s3api/s3api_server.go | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/weed/s3api/s3api_server.go b/weed/s3api/s3api_server.go index 23a8e49a8..7f5b88566 100644 --- a/weed/s3api/s3api_server.go +++ b/weed/s3api/s3api_server.go @@ -2,15 +2,20 @@ package s3api import ( "context" + "encoding/json" "fmt" "net" "net/http" + "os" "strings" "time" "github.com/seaweedfs/seaweedfs/weed/credential" "github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/glog" + "github.com/seaweedfs/seaweedfs/weed/iam/integration" + "github.com/seaweedfs/seaweedfs/weed/iam/policy" + "github.com/seaweedfs/seaweedfs/weed/iam/sts" "github.com/seaweedfs/seaweedfs/weed/pb/s3_pb" "github.com/seaweedfs/seaweedfs/weed/util/grace" @@ -38,12 +43,14 @@ type S3ApiServerOption struct { LocalFilerSocket string DataCenter string FilerGroup string + IamConfig string // Advanced IAM configuration file path } type S3ApiServer struct { s3_pb.UnimplementedSeaweedS3Server option *S3ApiServerOption iam *IdentityAccessManagement + iamIntegration *S3IAMIntegration // Advanced IAM integration for JWT authentication cb *CircuitBreaker randomClientId int32 filerGuard *security.Guard @@ -91,6 +98,29 @@ func NewS3ApiServerWithStore(router *mux.Router, option *S3ApiServerOption, expl bucketConfigCache: NewBucketConfigCache(60 * time.Minute), // Increased TTL since cache is now event-driven } + // Initialize advanced IAM system if config is provided + if option.IamConfig != "" { + glog.V(0).Infof("Loading advanced IAM configuration from: %s", option.IamConfig) + + iamManager, err := loadIAMManagerFromConfig(option.IamConfig, func() string { + return string(option.Filer) + }) + if err != nil { + glog.Errorf("Failed to load IAM configuration: %v", err) + } else { + // Create S3 IAM integration with the loaded IAM manager + s3iam := NewS3IAMIntegration(iamManager, string(option.Filer)) + + // Set IAM integration in server + s3ApiServer.iamIntegration = s3iam + + // Set the integration in the traditional IAM for compatibility + iam.SetIAMIntegration(s3iam) + + glog.V(0).Infof("Advanced IAM system initialized successfully") + } + } + if option.Config != "" { grace.OnReload(func() { if err := s3ApiServer.iam.loadS3ApiConfigurationFromFile(option.Config); err != nil { @@ -382,3 +412,83 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) { apiRouter.NotFoundHandler = http.HandlerFunc(s3err.NotFoundHandler) } + +// loadIAMManagerFromConfig loads the advanced IAM manager from configuration file +func loadIAMManagerFromConfig(configPath string, filerAddressProvider func() string) (*integration.IAMManager, error) { + // Read configuration file + configData, err := os.ReadFile(configPath) + if err != nil { + return nil, fmt.Errorf("failed to read config file: %w", err) + } + + // Parse configuration structure + var configRoot struct { + STS *sts.STSConfig `json:"sts"` + Policy *policy.PolicyEngineConfig `json:"policy"` + Providers []map[string]interface{} `json:"providers"` + Roles []*integration.RoleDefinition `json:"roles"` + Policies []struct { + Name string `json:"name"` + Document *policy.PolicyDocument `json:"document"` + } `json:"policies"` + } + + if err := json.Unmarshal(configData, &configRoot); err != nil { + return nil, fmt.Errorf("failed to parse config: %w", err) + } + + // Create IAM configuration + iamConfig := &integration.IAMConfig{ + STS: configRoot.STS, + Policy: configRoot.Policy, + Roles: &integration.RoleStoreConfig{ + StoreType: "memory", // Use memory store for JSON config-based setup + }, + } + + // Initialize IAM manager + iamManager := integration.NewIAMManager() + if err := iamManager.Initialize(iamConfig, filerAddressProvider); err != nil { + return nil, fmt.Errorf("failed to initialize IAM manager: %w", err) + } + + // Load identity providers + providerFactory := sts.NewProviderFactory() + for _, providerConfig := range configRoot.Providers { + provider, err := providerFactory.CreateProvider(&sts.ProviderConfig{ + Name: providerConfig["name"].(string), + Type: providerConfig["type"].(string), + Enabled: true, + Config: providerConfig["config"].(map[string]interface{}), + }) + if err != nil { + glog.Warningf("Failed to create provider %s: %v", providerConfig["name"], err) + continue + } + if provider != nil { + if err := iamManager.RegisterIdentityProvider(provider); err != nil { + glog.Warningf("Failed to register provider %s: %v", providerConfig["name"], err) + } else { + glog.V(1).Infof("Registered identity provider: %s", providerConfig["name"]) + } + } + } + + // Load policies + for _, policyDef := range configRoot.Policies { + if err := iamManager.CreatePolicy(context.Background(), "", policyDef.Name, policyDef.Document); err != nil { + glog.Warningf("Failed to create policy %s: %v", policyDef.Name, err) + } + } + + // Load roles + for _, roleDef := range configRoot.Roles { + if err := iamManager.CreateRole(context.Background(), "", roleDef.RoleName, roleDef); err != nil { + glog.Warningf("Failed to create role %s: %v", roleDef.RoleName, err) + } + } + + glog.V(0).Infof("Loaded %d providers, %d policies and %d roles from config", len(configRoot.Providers), len(configRoot.Policies), len(configRoot.Roles)) + + return iamManager, nil +} |
