provider_factory.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. package sts
  2. import (
  3. "fmt"
  4. "github.com/seaweedfs/seaweedfs/weed/glog"
  5. "github.com/seaweedfs/seaweedfs/weed/iam/oidc"
  6. "github.com/seaweedfs/seaweedfs/weed/iam/providers"
  7. )
  8. // ProviderFactory creates identity providers from configuration
  9. type ProviderFactory struct{}
  10. // NewProviderFactory creates a new provider factory
  11. func NewProviderFactory() *ProviderFactory {
  12. return &ProviderFactory{}
  13. }
  14. // CreateProvider creates an identity provider from configuration
  15. func (f *ProviderFactory) CreateProvider(config *ProviderConfig) (providers.IdentityProvider, error) {
  16. if config == nil {
  17. return nil, fmt.Errorf(ErrConfigCannotBeNil)
  18. }
  19. if config.Name == "" {
  20. return nil, fmt.Errorf(ErrProviderNameEmpty)
  21. }
  22. if config.Type == "" {
  23. return nil, fmt.Errorf(ErrProviderTypeEmpty)
  24. }
  25. if !config.Enabled {
  26. glog.V(2).Infof("Provider %s is disabled, skipping", config.Name)
  27. return nil, nil
  28. }
  29. glog.V(2).Infof("Creating provider: name=%s, type=%s", config.Name, config.Type)
  30. switch config.Type {
  31. case ProviderTypeOIDC:
  32. return f.createOIDCProvider(config)
  33. case ProviderTypeLDAP:
  34. return f.createLDAPProvider(config)
  35. case ProviderTypeSAML:
  36. return f.createSAMLProvider(config)
  37. default:
  38. return nil, fmt.Errorf(ErrUnsupportedProviderType, config.Type)
  39. }
  40. }
  41. // createOIDCProvider creates an OIDC provider from configuration
  42. func (f *ProviderFactory) createOIDCProvider(config *ProviderConfig) (providers.IdentityProvider, error) {
  43. oidcConfig, err := f.convertToOIDCConfig(config.Config)
  44. if err != nil {
  45. return nil, fmt.Errorf("failed to convert OIDC config: %w", err)
  46. }
  47. provider := oidc.NewOIDCProvider(config.Name)
  48. if err := provider.Initialize(oidcConfig); err != nil {
  49. return nil, fmt.Errorf("failed to initialize OIDC provider: %w", err)
  50. }
  51. return provider, nil
  52. }
  53. // createLDAPProvider creates an LDAP provider from configuration
  54. func (f *ProviderFactory) createLDAPProvider(config *ProviderConfig) (providers.IdentityProvider, error) {
  55. // TODO: Implement LDAP provider when available
  56. return nil, fmt.Errorf("LDAP provider not implemented yet")
  57. }
  58. // createSAMLProvider creates a SAML provider from configuration
  59. func (f *ProviderFactory) createSAMLProvider(config *ProviderConfig) (providers.IdentityProvider, error) {
  60. // TODO: Implement SAML provider when available
  61. return nil, fmt.Errorf("SAML provider not implemented yet")
  62. }
  63. // convertToOIDCConfig converts generic config map to OIDC config struct
  64. func (f *ProviderFactory) convertToOIDCConfig(configMap map[string]interface{}) (*oidc.OIDCConfig, error) {
  65. config := &oidc.OIDCConfig{}
  66. // Required fields
  67. if issuer, ok := configMap[ConfigFieldIssuer].(string); ok {
  68. config.Issuer = issuer
  69. } else {
  70. return nil, fmt.Errorf(ErrIssuerRequired)
  71. }
  72. if clientID, ok := configMap[ConfigFieldClientID].(string); ok {
  73. config.ClientID = clientID
  74. } else {
  75. return nil, fmt.Errorf(ErrClientIDRequired)
  76. }
  77. // Optional fields
  78. if clientSecret, ok := configMap[ConfigFieldClientSecret].(string); ok {
  79. config.ClientSecret = clientSecret
  80. }
  81. if jwksUri, ok := configMap[ConfigFieldJWKSUri].(string); ok {
  82. config.JWKSUri = jwksUri
  83. }
  84. if userInfoUri, ok := configMap[ConfigFieldUserInfoUri].(string); ok {
  85. config.UserInfoUri = userInfoUri
  86. }
  87. // Convert scopes array
  88. if scopesInterface, ok := configMap[ConfigFieldScopes]; ok {
  89. scopes, err := f.convertToStringSlice(scopesInterface)
  90. if err != nil {
  91. return nil, fmt.Errorf("failed to convert scopes: %w", err)
  92. }
  93. config.Scopes = scopes
  94. }
  95. // Convert claims mapping
  96. if claimsMapInterface, ok := configMap["claimsMapping"]; ok {
  97. claimsMap, err := f.convertToStringMap(claimsMapInterface)
  98. if err != nil {
  99. return nil, fmt.Errorf("failed to convert claimsMapping: %w", err)
  100. }
  101. config.ClaimsMapping = claimsMap
  102. }
  103. // Convert role mapping
  104. if roleMappingInterface, ok := configMap["roleMapping"]; ok {
  105. roleMapping, err := f.convertToRoleMapping(roleMappingInterface)
  106. if err != nil {
  107. return nil, fmt.Errorf("failed to convert roleMapping: %w", err)
  108. }
  109. config.RoleMapping = roleMapping
  110. }
  111. glog.V(3).Infof("Converted OIDC config: issuer=%s, clientId=%s, jwksUri=%s",
  112. config.Issuer, config.ClientID, config.JWKSUri)
  113. return config, nil
  114. }
  115. // convertToStringSlice converts interface{} to []string
  116. func (f *ProviderFactory) convertToStringSlice(value interface{}) ([]string, error) {
  117. switch v := value.(type) {
  118. case []string:
  119. return v, nil
  120. case []interface{}:
  121. result := make([]string, len(v))
  122. for i, item := range v {
  123. if str, ok := item.(string); ok {
  124. result[i] = str
  125. } else {
  126. return nil, fmt.Errorf("non-string item in slice: %v", item)
  127. }
  128. }
  129. return result, nil
  130. default:
  131. return nil, fmt.Errorf("cannot convert %T to []string", value)
  132. }
  133. }
  134. // convertToStringMap converts interface{} to map[string]string
  135. func (f *ProviderFactory) convertToStringMap(value interface{}) (map[string]string, error) {
  136. switch v := value.(type) {
  137. case map[string]string:
  138. return v, nil
  139. case map[string]interface{}:
  140. result := make(map[string]string)
  141. for key, val := range v {
  142. if str, ok := val.(string); ok {
  143. result[key] = str
  144. } else {
  145. return nil, fmt.Errorf("non-string value for key %s: %v", key, val)
  146. }
  147. }
  148. return result, nil
  149. default:
  150. return nil, fmt.Errorf("cannot convert %T to map[string]string", value)
  151. }
  152. }
  153. // LoadProvidersFromConfig creates providers from configuration
  154. func (f *ProviderFactory) LoadProvidersFromConfig(configs []*ProviderConfig) (map[string]providers.IdentityProvider, error) {
  155. providersMap := make(map[string]providers.IdentityProvider)
  156. for _, config := range configs {
  157. if config == nil {
  158. glog.V(1).Infof("Skipping nil provider config")
  159. continue
  160. }
  161. glog.V(2).Infof("Loading provider: %s (type: %s, enabled: %t)",
  162. config.Name, config.Type, config.Enabled)
  163. if !config.Enabled {
  164. glog.V(2).Infof("Provider %s is disabled, skipping", config.Name)
  165. continue
  166. }
  167. provider, err := f.CreateProvider(config)
  168. if err != nil {
  169. glog.Errorf("Failed to create provider %s: %v", config.Name, err)
  170. return nil, fmt.Errorf("failed to create provider %s: %w", config.Name, err)
  171. }
  172. if provider != nil {
  173. providersMap[config.Name] = provider
  174. glog.V(1).Infof("Successfully loaded provider: %s", config.Name)
  175. }
  176. }
  177. glog.V(1).Infof("Loaded %d identity providers from configuration", len(providersMap))
  178. return providersMap, nil
  179. }
  180. // convertToRoleMapping converts interface{} to *providers.RoleMapping
  181. func (f *ProviderFactory) convertToRoleMapping(value interface{}) (*providers.RoleMapping, error) {
  182. roleMappingMap, ok := value.(map[string]interface{})
  183. if !ok {
  184. return nil, fmt.Errorf("roleMapping must be an object")
  185. }
  186. roleMapping := &providers.RoleMapping{}
  187. // Convert rules
  188. if rulesInterface, ok := roleMappingMap["rules"]; ok {
  189. rulesSlice, ok := rulesInterface.([]interface{})
  190. if !ok {
  191. return nil, fmt.Errorf("rules must be an array")
  192. }
  193. rules := make([]providers.MappingRule, len(rulesSlice))
  194. for i, ruleInterface := range rulesSlice {
  195. ruleMap, ok := ruleInterface.(map[string]interface{})
  196. if !ok {
  197. return nil, fmt.Errorf("rule must be an object")
  198. }
  199. rule := providers.MappingRule{}
  200. if claim, ok := ruleMap["claim"].(string); ok {
  201. rule.Claim = claim
  202. }
  203. if value, ok := ruleMap["value"].(string); ok {
  204. rule.Value = value
  205. }
  206. if role, ok := ruleMap["role"].(string); ok {
  207. rule.Role = role
  208. }
  209. if condition, ok := ruleMap["condition"].(string); ok {
  210. rule.Condition = condition
  211. }
  212. rules[i] = rule
  213. }
  214. roleMapping.Rules = rules
  215. }
  216. // Convert default role
  217. if defaultRole, ok := roleMappingMap["defaultRole"].(string); ok {
  218. roleMapping.DefaultRole = defaultRole
  219. }
  220. return roleMapping, nil
  221. }
  222. // ValidateProviderConfig validates a provider configuration
  223. func (f *ProviderFactory) ValidateProviderConfig(config *ProviderConfig) error {
  224. if config == nil {
  225. return fmt.Errorf("provider config cannot be nil")
  226. }
  227. if config.Name == "" {
  228. return fmt.Errorf("provider name cannot be empty")
  229. }
  230. if config.Type == "" {
  231. return fmt.Errorf("provider type cannot be empty")
  232. }
  233. if config.Config == nil {
  234. return fmt.Errorf("provider config cannot be nil")
  235. }
  236. // Type-specific validation
  237. switch config.Type {
  238. case "oidc":
  239. return f.validateOIDCConfig(config.Config)
  240. case "ldap":
  241. return f.validateLDAPConfig(config.Config)
  242. case "saml":
  243. return f.validateSAMLConfig(config.Config)
  244. default:
  245. return fmt.Errorf("unsupported provider type: %s", config.Type)
  246. }
  247. }
  248. // validateOIDCConfig validates OIDC provider configuration
  249. func (f *ProviderFactory) validateOIDCConfig(config map[string]interface{}) error {
  250. if _, ok := config[ConfigFieldIssuer]; !ok {
  251. return fmt.Errorf("OIDC provider requires '%s' field", ConfigFieldIssuer)
  252. }
  253. if _, ok := config[ConfigFieldClientID]; !ok {
  254. return fmt.Errorf("OIDC provider requires '%s' field", ConfigFieldClientID)
  255. }
  256. return nil
  257. }
  258. // validateLDAPConfig validates LDAP provider configuration
  259. func (f *ProviderFactory) validateLDAPConfig(config map[string]interface{}) error {
  260. // TODO: Implement when LDAP provider is available
  261. return nil
  262. }
  263. // validateSAMLConfig validates SAML provider configuration
  264. func (f *ProviderFactory) validateSAMLConfig(config map[string]interface{}) error {
  265. // TODO: Implement when SAML provider is available
  266. return nil
  267. }
  268. // GetSupportedProviderTypes returns list of supported provider types
  269. func (f *ProviderFactory) GetSupportedProviderTypes() []string {
  270. return []string{ProviderTypeOIDC}
  271. }