diff --git a/models/idp_configuration.go b/models/idp_configuration.go
index e70e2f49f..3814b9c5b 100644
--- a/models/idp_configuration.go
+++ b/models/idp_configuration.go
@@ -237,7 +237,8 @@ type IdpConfigurationActiveDirectory struct {
GroupSearchFilter string `json:"group_search_filter,omitempty"`
// lookup bind dn
- LookupBindDn string `json:"lookup_bind_dn,omitempty"`
+ // Required: true
+ LookupBindDn *string `json:"lookup_bind_dn"`
// lookup bind password
LookupBindPassword string `json:"lookup_bind_password,omitempty"`
@@ -269,6 +270,10 @@ type IdpConfigurationActiveDirectory struct {
func (m *IdpConfigurationActiveDirectory) Validate(formats strfmt.Registry) error {
var res []error
+ if err := m.validateLookupBindDn(formats); err != nil {
+ res = append(res, err)
+ }
+
if err := m.validateURL(formats); err != nil {
res = append(res, err)
}
@@ -279,6 +284,15 @@ func (m *IdpConfigurationActiveDirectory) Validate(formats strfmt.Registry) erro
return nil
}
+func (m *IdpConfigurationActiveDirectory) validateLookupBindDn(formats strfmt.Registry) error {
+
+ if err := validate.Required("active_directory"+"."+"lookup_bind_dn", "body", m.LookupBindDn); err != nil {
+ return err
+ }
+
+ return nil
+}
+
func (m *IdpConfigurationActiveDirectory) validateURL(formats strfmt.Registry) error {
if err := validate.Required("active_directory"+"."+"url", "body", m.URL); err != nil {
diff --git a/operatorapi/embedded_spec.go b/operatorapi/embedded_spec.go
index 878cf0fb6..0093b6af6 100644
--- a/operatorapi/embedded_spec.go
+++ b/operatorapi/embedded_spec.go
@@ -803,6 +803,83 @@ func init() {
}
}
},
+ "/namespaces/{namespace}/tenants/{tenant}/identity-provider": {
+ "get": {
+ "tags": [
+ "OperatorAPI"
+ ],
+ "summary": "Tenant Identity Provider",
+ "operationId": "TenantIdentityProvider",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "namespace",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "tenant",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/idpConfiguration"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "OperatorAPI"
+ ],
+ "summary": "Update Tenant Identity Provider",
+ "operationId": "UpdateTenantIdentityProvider",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "namespace",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "tenant",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/idpConfiguration"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "A successful response."
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/namespaces/{namespace}/tenants/{tenant}/log": {
"get": {
"tags": [
@@ -2434,7 +2511,8 @@ func init() {
"active_directory": {
"type": "object",
"required": [
- "url"
+ "url",
+ "lookup_bind_dn"
],
"properties": {
"group_search_base_dn": {
@@ -4719,6 +4797,83 @@ func init() {
}
}
},
+ "/namespaces/{namespace}/tenants/{tenant}/identity-provider": {
+ "get": {
+ "tags": [
+ "OperatorAPI"
+ ],
+ "summary": "Tenant Identity Provider",
+ "operationId": "TenantIdentityProvider",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "namespace",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "tenant",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/idpConfiguration"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "OperatorAPI"
+ ],
+ "summary": "Update Tenant Identity Provider",
+ "operationId": "UpdateTenantIdentityProvider",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "namespace",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "tenant",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/idpConfiguration"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "A successful response."
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/namespaces/{namespace}/tenants/{tenant}/log": {
"get": {
"tags": [
@@ -5971,7 +6126,8 @@ func init() {
"IdpConfigurationActiveDirectory": {
"type": "object",
"required": [
- "url"
+ "url",
+ "lookup_bind_dn"
],
"properties": {
"group_search_base_dn": {
@@ -7192,7 +7348,8 @@ func init() {
"active_directory": {
"type": "object",
"required": [
- "url"
+ "url",
+ "lookup_bind_dn"
],
"properties": {
"group_search_base_dn": {
diff --git a/operatorapi/operations/operator_api.go b/operatorapi/operations/operator_api.go
index 61e60d49d..e6b1e8ecf 100644
--- a/operatorapi/operations/operator_api.go
+++ b/operatorapi/operations/operator_api.go
@@ -189,6 +189,9 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
OperatorAPITenantEncryptionInfoHandler: operator_api.TenantEncryptionInfoHandlerFunc(func(params operator_api.TenantEncryptionInfoParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation operator_api.TenantEncryptionInfo has not yet been implemented")
}),
+ OperatorAPITenantIdentityProviderHandler: operator_api.TenantIdentityProviderHandlerFunc(func(params operator_api.TenantIdentityProviderParams, principal *models.Principal) middleware.Responder {
+ return middleware.NotImplemented("operation operator_api.TenantIdentityProvider has not yet been implemented")
+ }),
OperatorAPITenantSecurityHandler: operator_api.TenantSecurityHandlerFunc(func(params operator_api.TenantSecurityParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation operator_api.TenantSecurity has not yet been implemented")
}),
@@ -204,6 +207,9 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
OperatorAPIUpdateTenantHandler: operator_api.UpdateTenantHandlerFunc(func(params operator_api.UpdateTenantParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation operator_api.UpdateTenant has not yet been implemented")
}),
+ OperatorAPIUpdateTenantIdentityProviderHandler: operator_api.UpdateTenantIdentityProviderHandlerFunc(func(params operator_api.UpdateTenantIdentityProviderParams, principal *models.Principal) middleware.Responder {
+ return middleware.NotImplemented("operation operator_api.UpdateTenantIdentityProvider has not yet been implemented")
+ }),
OperatorAPIUpdateTenantSecurityHandler: operator_api.UpdateTenantSecurityHandlerFunc(func(params operator_api.UpdateTenantSecurityParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation operator_api.UpdateTenantSecurity has not yet been implemented")
}),
@@ -340,6 +346,8 @@ type OperatorAPI struct {
OperatorAPITenantDetailsHandler operator_api.TenantDetailsHandler
// OperatorAPITenantEncryptionInfoHandler sets the operation handler for the tenant encryption info operation
OperatorAPITenantEncryptionInfoHandler operator_api.TenantEncryptionInfoHandler
+ // OperatorAPITenantIdentityProviderHandler sets the operation handler for the tenant identity provider operation
+ OperatorAPITenantIdentityProviderHandler operator_api.TenantIdentityProviderHandler
// OperatorAPITenantSecurityHandler sets the operation handler for the tenant security operation
OperatorAPITenantSecurityHandler operator_api.TenantSecurityHandler
// OperatorAPITenantUpdateCertificateHandler sets the operation handler for the tenant update certificate operation
@@ -350,6 +358,8 @@ type OperatorAPI struct {
OperatorAPITenantUpdatePoolsHandler operator_api.TenantUpdatePoolsHandler
// OperatorAPIUpdateTenantHandler sets the operation handler for the update tenant operation
OperatorAPIUpdateTenantHandler operator_api.UpdateTenantHandler
+ // OperatorAPIUpdateTenantIdentityProviderHandler sets the operation handler for the update tenant identity provider operation
+ OperatorAPIUpdateTenantIdentityProviderHandler operator_api.UpdateTenantIdentityProviderHandler
// OperatorAPIUpdateTenantSecurityHandler sets the operation handler for the update tenant security operation
OperatorAPIUpdateTenantSecurityHandler operator_api.UpdateTenantSecurityHandler
@@ -559,6 +569,9 @@ func (o *OperatorAPI) Validate() error {
if o.OperatorAPITenantEncryptionInfoHandler == nil {
unregistered = append(unregistered, "operator_api.TenantEncryptionInfoHandler")
}
+ if o.OperatorAPITenantIdentityProviderHandler == nil {
+ unregistered = append(unregistered, "operator_api.TenantIdentityProviderHandler")
+ }
if o.OperatorAPITenantSecurityHandler == nil {
unregistered = append(unregistered, "operator_api.TenantSecurityHandler")
}
@@ -574,6 +587,9 @@ func (o *OperatorAPI) Validate() error {
if o.OperatorAPIUpdateTenantHandler == nil {
unregistered = append(unregistered, "operator_api.UpdateTenantHandler")
}
+ if o.OperatorAPIUpdateTenantIdentityProviderHandler == nil {
+ unregistered = append(unregistered, "operator_api.UpdateTenantIdentityProviderHandler")
+ }
if o.OperatorAPIUpdateTenantSecurityHandler == nil {
unregistered = append(unregistered, "operator_api.UpdateTenantSecurityHandler")
}
@@ -846,6 +862,10 @@ func (o *OperatorAPI) initHandlerCache() {
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
+ o.handlers["GET"]["/namespaces/{namespace}/tenants/{tenant}/identity-provider"] = operator_api.NewTenantIdentityProvider(o.context, o.OperatorAPITenantIdentityProviderHandler)
+ if o.handlers["GET"] == nil {
+ o.handlers["GET"] = make(map[string]http.Handler)
+ }
o.handlers["GET"]["/namespaces/{namespace}/tenants/{tenant}/security"] = operator_api.NewTenantSecurity(o.context, o.OperatorAPITenantSecurityHandler)
if o.handlers["PUT"] == nil {
o.handlers["PUT"] = make(map[string]http.Handler)
@@ -866,6 +886,10 @@ func (o *OperatorAPI) initHandlerCache() {
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
+ o.handlers["POST"]["/namespaces/{namespace}/tenants/{tenant}/identity-provider"] = operator_api.NewUpdateTenantIdentityProvider(o.context, o.OperatorAPIUpdateTenantIdentityProviderHandler)
+ if o.handlers["POST"] == nil {
+ o.handlers["POST"] = make(map[string]http.Handler)
+ }
o.handlers["POST"]["/namespaces/{namespace}/tenants/{tenant}/security"] = operator_api.NewUpdateTenantSecurity(o.context, o.OperatorAPIUpdateTenantSecurityHandler)
}
diff --git a/operatorapi/operations/operator_api/tenant_identity_provider.go b/operatorapi/operations/operator_api/tenant_identity_provider.go
new file mode 100644
index 000000000..378234361
--- /dev/null
+++ b/operatorapi/operations/operator_api/tenant_identity_provider.go
@@ -0,0 +1,88 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/minio/console/models"
+)
+
+// TenantIdentityProviderHandlerFunc turns a function with the right signature into a tenant identity provider handler
+type TenantIdentityProviderHandlerFunc func(TenantIdentityProviderParams, *models.Principal) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn TenantIdentityProviderHandlerFunc) Handle(params TenantIdentityProviderParams, principal *models.Principal) middleware.Responder {
+ return fn(params, principal)
+}
+
+// TenantIdentityProviderHandler interface for that can handle valid tenant identity provider params
+type TenantIdentityProviderHandler interface {
+ Handle(TenantIdentityProviderParams, *models.Principal) middleware.Responder
+}
+
+// NewTenantIdentityProvider creates a new http.Handler for the tenant identity provider operation
+func NewTenantIdentityProvider(ctx *middleware.Context, handler TenantIdentityProviderHandler) *TenantIdentityProvider {
+ return &TenantIdentityProvider{Context: ctx, Handler: handler}
+}
+
+/* TenantIdentityProvider swagger:route GET /namespaces/{namespace}/tenants/{tenant}/identity-provider OperatorAPI tenantIdentityProvider
+
+Tenant Identity Provider
+
+*/
+type TenantIdentityProvider struct {
+ Context *middleware.Context
+ Handler TenantIdentityProviderHandler
+}
+
+func (o *TenantIdentityProvider) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ *r = *rCtx
+ }
+ var Params = NewTenantIdentityProviderParams()
+ uprinc, aCtx, err := o.Context.Authorize(r, route)
+ if err != nil {
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ if aCtx != nil {
+ *r = *aCtx
+ }
+ var principal *models.Principal
+ if uprinc != nil {
+ principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
+ }
+
+ if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+
+ res := o.Handler.Handle(Params, principal) // actually handle the request
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/operatorapi/operations/operator_api/tenant_identity_provider_parameters.go b/operatorapi/operations/operator_api/tenant_identity_provider_parameters.go
new file mode 100644
index 000000000..8b6324a56
--- /dev/null
+++ b/operatorapi/operations/operator_api/tenant_identity_provider_parameters.go
@@ -0,0 +1,112 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/strfmt"
+)
+
+// NewTenantIdentityProviderParams creates a new TenantIdentityProviderParams object
+//
+// There are no default values defined in the spec.
+func NewTenantIdentityProviderParams() TenantIdentityProviderParams {
+
+ return TenantIdentityProviderParams{}
+}
+
+// TenantIdentityProviderParams contains all the bound params for the tenant identity provider operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters TenantIdentityProvider
+type TenantIdentityProviderParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+
+ /*
+ Required: true
+ In: path
+ */
+ Namespace string
+ /*
+ Required: true
+ In: path
+ */
+ Tenant string
+}
+
+// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
+// for simple values it will use straight method calls.
+//
+// To ensure default values, the struct must have been initialized with NewTenantIdentityProviderParams() beforehand.
+func (o *TenantIdentityProviderParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace")
+ if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ rTenant, rhkTenant, _ := route.Params.GetOK("tenant")
+ if err := o.bindTenant(rTenant, rhkTenant, route.Formats); err != nil {
+ res = append(res, err)
+ }
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+// bindNamespace binds and validates parameter Namespace from path.
+func (o *TenantIdentityProviderParams) bindNamespace(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // Parameter is provided by construction from the route
+ o.Namespace = raw
+
+ return nil
+}
+
+// bindTenant binds and validates parameter Tenant from path.
+func (o *TenantIdentityProviderParams) bindTenant(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // Parameter is provided by construction from the route
+ o.Tenant = raw
+
+ return nil
+}
diff --git a/operatorapi/operations/operator_api/tenant_identity_provider_responses.go b/operatorapi/operations/operator_api/tenant_identity_provider_responses.go
new file mode 100644
index 000000000..68e362c17
--- /dev/null
+++ b/operatorapi/operations/operator_api/tenant_identity_provider_responses.go
@@ -0,0 +1,133 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+
+ "github.com/minio/console/models"
+)
+
+// TenantIdentityProviderOKCode is the HTTP code returned for type TenantIdentityProviderOK
+const TenantIdentityProviderOKCode int = 200
+
+/*TenantIdentityProviderOK A successful response.
+
+swagger:response tenantIdentityProviderOK
+*/
+type TenantIdentityProviderOK struct {
+
+ /*
+ In: Body
+ */
+ Payload *models.IdpConfiguration `json:"body,omitempty"`
+}
+
+// NewTenantIdentityProviderOK creates TenantIdentityProviderOK with default headers values
+func NewTenantIdentityProviderOK() *TenantIdentityProviderOK {
+
+ return &TenantIdentityProviderOK{}
+}
+
+// WithPayload adds the payload to the tenant identity provider o k response
+func (o *TenantIdentityProviderOK) WithPayload(payload *models.IdpConfiguration) *TenantIdentityProviderOK {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the tenant identity provider o k response
+func (o *TenantIdentityProviderOK) SetPayload(payload *models.IdpConfiguration) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *TenantIdentityProviderOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(200)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
+
+/*TenantIdentityProviderDefault Generic error response.
+
+swagger:response tenantIdentityProviderDefault
+*/
+type TenantIdentityProviderDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewTenantIdentityProviderDefault creates TenantIdentityProviderDefault with default headers values
+func NewTenantIdentityProviderDefault(code int) *TenantIdentityProviderDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &TenantIdentityProviderDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the tenant identity provider default response
+func (o *TenantIdentityProviderDefault) WithStatusCode(code int) *TenantIdentityProviderDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the tenant identity provider default response
+func (o *TenantIdentityProviderDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the tenant identity provider default response
+func (o *TenantIdentityProviderDefault) WithPayload(payload *models.Error) *TenantIdentityProviderDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the tenant identity provider default response
+func (o *TenantIdentityProviderDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *TenantIdentityProviderDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(o._statusCode)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/operatorapi/operations/operator_api/tenant_identity_provider_urlbuilder.go b/operatorapi/operations/operator_api/tenant_identity_provider_urlbuilder.go
new file mode 100644
index 000000000..d3ad63941
--- /dev/null
+++ b/operatorapi/operations/operator_api/tenant_identity_provider_urlbuilder.go
@@ -0,0 +1,124 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "errors"
+ "net/url"
+ golangswaggerpaths "path"
+ "strings"
+)
+
+// TenantIdentityProviderURL generates an URL for the tenant identity provider operation
+type TenantIdentityProviderURL struct {
+ Namespace string
+ Tenant string
+
+ _basePath string
+ // avoid unkeyed usage
+ _ struct{}
+}
+
+// WithBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *TenantIdentityProviderURL) WithBasePath(bp string) *TenantIdentityProviderURL {
+ o.SetBasePath(bp)
+ return o
+}
+
+// SetBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *TenantIdentityProviderURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *TenantIdentityProviderURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/namespaces/{namespace}/tenants/{tenant}/identity-provider"
+
+ namespace := o.Namespace
+ if namespace != "" {
+ _path = strings.Replace(_path, "{namespace}", namespace, -1)
+ } else {
+ return nil, errors.New("namespace is required on TenantIdentityProviderURL")
+ }
+
+ tenant := o.Tenant
+ if tenant != "" {
+ _path = strings.Replace(_path, "{tenant}", tenant, -1)
+ } else {
+ return nil, errors.New("tenant is required on TenantIdentityProviderURL")
+ }
+
+ _basePath := o._basePath
+ if _basePath == "" {
+ _basePath = "/api/v1"
+ }
+ _result.Path = golangswaggerpaths.Join(_basePath, _path)
+
+ return &_result, nil
+}
+
+// Must is a helper function to panic when the url builder returns an error
+func (o *TenantIdentityProviderURL) Must(u *url.URL, err error) *url.URL {
+ if err != nil {
+ panic(err)
+ }
+ if u == nil {
+ panic("url can't be nil")
+ }
+ return u
+}
+
+// String returns the string representation of the path with query string
+func (o *TenantIdentityProviderURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *TenantIdentityProviderURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on TenantIdentityProviderURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on TenantIdentityProviderURL")
+ }
+
+ base, err := o.Build()
+ if err != nil {
+ return nil, err
+ }
+
+ base.Scheme = scheme
+ base.Host = host
+ return base, nil
+}
+
+// StringFull returns the string representation of a complete url
+func (o *TenantIdentityProviderURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/operatorapi/operations/operator_api/update_tenant_identity_provider.go b/operatorapi/operations/operator_api/update_tenant_identity_provider.go
new file mode 100644
index 000000000..8538888c4
--- /dev/null
+++ b/operatorapi/operations/operator_api/update_tenant_identity_provider.go
@@ -0,0 +1,88 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/minio/console/models"
+)
+
+// UpdateTenantIdentityProviderHandlerFunc turns a function with the right signature into a update tenant identity provider handler
+type UpdateTenantIdentityProviderHandlerFunc func(UpdateTenantIdentityProviderParams, *models.Principal) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn UpdateTenantIdentityProviderHandlerFunc) Handle(params UpdateTenantIdentityProviderParams, principal *models.Principal) middleware.Responder {
+ return fn(params, principal)
+}
+
+// UpdateTenantIdentityProviderHandler interface for that can handle valid update tenant identity provider params
+type UpdateTenantIdentityProviderHandler interface {
+ Handle(UpdateTenantIdentityProviderParams, *models.Principal) middleware.Responder
+}
+
+// NewUpdateTenantIdentityProvider creates a new http.Handler for the update tenant identity provider operation
+func NewUpdateTenantIdentityProvider(ctx *middleware.Context, handler UpdateTenantIdentityProviderHandler) *UpdateTenantIdentityProvider {
+ return &UpdateTenantIdentityProvider{Context: ctx, Handler: handler}
+}
+
+/* UpdateTenantIdentityProvider swagger:route POST /namespaces/{namespace}/tenants/{tenant}/identity-provider OperatorAPI updateTenantIdentityProvider
+
+Update Tenant Identity Provider
+
+*/
+type UpdateTenantIdentityProvider struct {
+ Context *middleware.Context
+ Handler UpdateTenantIdentityProviderHandler
+}
+
+func (o *UpdateTenantIdentityProvider) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ *r = *rCtx
+ }
+ var Params = NewUpdateTenantIdentityProviderParams()
+ uprinc, aCtx, err := o.Context.Authorize(r, route)
+ if err != nil {
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ if aCtx != nil {
+ *r = *aCtx
+ }
+ var principal *models.Principal
+ if uprinc != nil {
+ principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
+ }
+
+ if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+
+ res := o.Handler.Handle(Params, principal) // actually handle the request
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/operatorapi/operations/operator_api/update_tenant_identity_provider_parameters.go b/operatorapi/operations/operator_api/update_tenant_identity_provider_parameters.go
new file mode 100644
index 000000000..c78a07426
--- /dev/null
+++ b/operatorapi/operations/operator_api/update_tenant_identity_provider_parameters.go
@@ -0,0 +1,151 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "context"
+ "io"
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/validate"
+
+ "github.com/minio/console/models"
+)
+
+// NewUpdateTenantIdentityProviderParams creates a new UpdateTenantIdentityProviderParams object
+//
+// There are no default values defined in the spec.
+func NewUpdateTenantIdentityProviderParams() UpdateTenantIdentityProviderParams {
+
+ return UpdateTenantIdentityProviderParams{}
+}
+
+// UpdateTenantIdentityProviderParams contains all the bound params for the update tenant identity provider operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters UpdateTenantIdentityProvider
+type UpdateTenantIdentityProviderParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+
+ /*
+ Required: true
+ In: body
+ */
+ Body *models.IdpConfiguration
+ /*
+ Required: true
+ In: path
+ */
+ Namespace string
+ /*
+ Required: true
+ In: path
+ */
+ Tenant string
+}
+
+// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
+// for simple values it will use straight method calls.
+//
+// To ensure default values, the struct must have been initialized with NewUpdateTenantIdentityProviderParams() beforehand.
+func (o *UpdateTenantIdentityProviderParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ if runtime.HasBody(r) {
+ defer r.Body.Close()
+ var body models.IdpConfiguration
+ if err := route.Consumer.Consume(r.Body, &body); err != nil {
+ if err == io.EOF {
+ res = append(res, errors.Required("body", "body", ""))
+ } else {
+ res = append(res, errors.NewParseError("body", "body", "", err))
+ }
+ } else {
+ // validate body object
+ if err := body.Validate(route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ ctx := validate.WithOperationRequest(context.Background())
+ if err := body.ContextValidate(ctx, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) == 0 {
+ o.Body = &body
+ }
+ }
+ } else {
+ res = append(res, errors.Required("body", "body", ""))
+ }
+
+ rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace")
+ if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ rTenant, rhkTenant, _ := route.Params.GetOK("tenant")
+ if err := o.bindTenant(rTenant, rhkTenant, route.Formats); err != nil {
+ res = append(res, err)
+ }
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+// bindNamespace binds and validates parameter Namespace from path.
+func (o *UpdateTenantIdentityProviderParams) bindNamespace(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // Parameter is provided by construction from the route
+ o.Namespace = raw
+
+ return nil
+}
+
+// bindTenant binds and validates parameter Tenant from path.
+func (o *UpdateTenantIdentityProviderParams) bindTenant(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // Parameter is provided by construction from the route
+ o.Tenant = raw
+
+ return nil
+}
diff --git a/operatorapi/operations/operator_api/update_tenant_identity_provider_responses.go b/operatorapi/operations/operator_api/update_tenant_identity_provider_responses.go
new file mode 100644
index 000000000..d02140d8a
--- /dev/null
+++ b/operatorapi/operations/operator_api/update_tenant_identity_provider_responses.go
@@ -0,0 +1,113 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+
+ "github.com/minio/console/models"
+)
+
+// UpdateTenantIdentityProviderNoContentCode is the HTTP code returned for type UpdateTenantIdentityProviderNoContent
+const UpdateTenantIdentityProviderNoContentCode int = 204
+
+/*UpdateTenantIdentityProviderNoContent A successful response.
+
+swagger:response updateTenantIdentityProviderNoContent
+*/
+type UpdateTenantIdentityProviderNoContent struct {
+}
+
+// NewUpdateTenantIdentityProviderNoContent creates UpdateTenantIdentityProviderNoContent with default headers values
+func NewUpdateTenantIdentityProviderNoContent() *UpdateTenantIdentityProviderNoContent {
+
+ return &UpdateTenantIdentityProviderNoContent{}
+}
+
+// WriteResponse to the client
+func (o *UpdateTenantIdentityProviderNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
+
+ rw.WriteHeader(204)
+}
+
+/*UpdateTenantIdentityProviderDefault Generic error response.
+
+swagger:response updateTenantIdentityProviderDefault
+*/
+type UpdateTenantIdentityProviderDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewUpdateTenantIdentityProviderDefault creates UpdateTenantIdentityProviderDefault with default headers values
+func NewUpdateTenantIdentityProviderDefault(code int) *UpdateTenantIdentityProviderDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &UpdateTenantIdentityProviderDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the update tenant identity provider default response
+func (o *UpdateTenantIdentityProviderDefault) WithStatusCode(code int) *UpdateTenantIdentityProviderDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the update tenant identity provider default response
+func (o *UpdateTenantIdentityProviderDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the update tenant identity provider default response
+func (o *UpdateTenantIdentityProviderDefault) WithPayload(payload *models.Error) *UpdateTenantIdentityProviderDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the update tenant identity provider default response
+func (o *UpdateTenantIdentityProviderDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *UpdateTenantIdentityProviderDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(o._statusCode)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/operatorapi/operations/operator_api/update_tenant_identity_provider_urlbuilder.go b/operatorapi/operations/operator_api/update_tenant_identity_provider_urlbuilder.go
new file mode 100644
index 000000000..48bf33ed6
--- /dev/null
+++ b/operatorapi/operations/operator_api/update_tenant_identity_provider_urlbuilder.go
@@ -0,0 +1,124 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package operator_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "errors"
+ "net/url"
+ golangswaggerpaths "path"
+ "strings"
+)
+
+// UpdateTenantIdentityProviderURL generates an URL for the update tenant identity provider operation
+type UpdateTenantIdentityProviderURL struct {
+ Namespace string
+ Tenant string
+
+ _basePath string
+ // avoid unkeyed usage
+ _ struct{}
+}
+
+// WithBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *UpdateTenantIdentityProviderURL) WithBasePath(bp string) *UpdateTenantIdentityProviderURL {
+ o.SetBasePath(bp)
+ return o
+}
+
+// SetBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *UpdateTenantIdentityProviderURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *UpdateTenantIdentityProviderURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/namespaces/{namespace}/tenants/{tenant}/identity-provider"
+
+ namespace := o.Namespace
+ if namespace != "" {
+ _path = strings.Replace(_path, "{namespace}", namespace, -1)
+ } else {
+ return nil, errors.New("namespace is required on UpdateTenantIdentityProviderURL")
+ }
+
+ tenant := o.Tenant
+ if tenant != "" {
+ _path = strings.Replace(_path, "{tenant}", tenant, -1)
+ } else {
+ return nil, errors.New("tenant is required on UpdateTenantIdentityProviderURL")
+ }
+
+ _basePath := o._basePath
+ if _basePath == "" {
+ _basePath = "/api/v1"
+ }
+ _result.Path = golangswaggerpaths.Join(_basePath, _path)
+
+ return &_result, nil
+}
+
+// Must is a helper function to panic when the url builder returns an error
+func (o *UpdateTenantIdentityProviderURL) Must(u *url.URL, err error) *url.URL {
+ if err != nil {
+ panic(err)
+ }
+ if u == nil {
+ panic("url can't be nil")
+ }
+ return u
+}
+
+// String returns the string representation of the path with query string
+func (o *UpdateTenantIdentityProviderURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *UpdateTenantIdentityProviderURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on UpdateTenantIdentityProviderURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on UpdateTenantIdentityProviderURL")
+ }
+
+ base, err := o.Build()
+ if err != nil {
+ return nil, err
+ }
+
+ base.Scheme = scheme
+ base.Host = host
+ return base, nil
+}
+
+// StringFull returns the string representation of a complete url
+func (o *UpdateTenantIdentityProviderURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/operatorapi/tenant_add.go b/operatorapi/tenant_add.go
index dcde7d7b4..8d2912785 100644
--- a/operatorapi/tenant_add.go
+++ b/operatorapi/tenant_add.go
@@ -153,7 +153,7 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
serverAddress := *tenantReq.Idp.ActiveDirectory.URL
tlsSkipVerify := tenantReq.Idp.ActiveDirectory.SkipTLSVerification
serverInsecure := tenantReq.Idp.ActiveDirectory.ServerInsecure
- lookupBindDN := tenantReq.Idp.ActiveDirectory.LookupBindDn
+ lookupBindDN := *tenantReq.Idp.ActiveDirectory.LookupBindDn
lookupBindPassword := tenantReq.Idp.ActiveDirectory.LookupBindPassword
userDNSearchBaseDN := tenantReq.Idp.ActiveDirectory.UserDnSearchBaseDn
userDNSearchFilter := tenantReq.Idp.ActiveDirectory.UserDnSearchFilter
diff --git a/operatorapi/tenants.go b/operatorapi/tenants.go
index 6515f8c1e..cff175dc0 100644
--- a/operatorapi/tenants.go
+++ b/operatorapi/tenants.go
@@ -132,6 +132,26 @@ func registerTenantHandlers(api *operations.OperatorAPI) {
})
+ // Tenant identity provider details
+ api.OperatorAPITenantIdentityProviderHandler = operator_api.TenantIdentityProviderHandlerFunc(func(params operator_api.TenantIdentityProviderParams, session *models.Principal) middleware.Responder {
+ resp, err := getTenantIdentityProviderResponse(session, params)
+ if err != nil {
+ return operator_api.NewTenantIdentityProviderDefault(int(err.Code)).WithPayload(err)
+ }
+ return operator_api.NewTenantIdentityProviderOK().WithPayload(resp)
+
+ })
+
+ // Update Tenant identity provider configuration
+ api.OperatorAPIUpdateTenantIdentityProviderHandler = operator_api.UpdateTenantIdentityProviderHandlerFunc(func(params operator_api.UpdateTenantIdentityProviderParams, session *models.Principal) middleware.Responder {
+ err := getUpdateTenantIdentityProviderResponse(session, params)
+ if err != nil {
+ return operator_api.NewUpdateTenantIdentityProviderDefault(int(err.Code)).WithPayload(err)
+ }
+ return operator_api.NewUpdateTenantIdentityProviderNoContent()
+
+ })
+
// Delete Tenant
api.OperatorAPIDeleteTenantHandler = operator_api.DeleteTenantHandlerFunc(func(params operator_api.DeleteTenantParams, session *models.Principal) middleware.Responder {
err := getDeleteTenantResponse(session, params)
@@ -635,6 +655,239 @@ func getTenantSecurity(ctx context.Context, clientSet K8sClientI, tenant *miniov
}, nil
}
+func getTenantIdentityProvider(ctx context.Context, clientSet K8sClientI, tenant *miniov2.Tenant) (response *models.IdpConfiguration, err error) {
+ tenantConfiguration, err := GetTenantConfiguration(ctx, clientSet, tenant)
+ if err != nil {
+ return nil, err
+ }
+
+ var idpConfiguration *models.IdpConfiguration
+
+ if tenantConfiguration["MINIO_IDENTITY_OPENID_CONFIG_URL"] != "" {
+
+ callbackURL := tenantConfiguration["MINIO_IDENTITY_OPENID_REDIRECT_URI"]
+ claimName := tenantConfiguration["MINIO_IDENTITY_OPENID_CLAIM_NAME"]
+ clientID := tenantConfiguration["MINIO_IDENTITY_OPENID_CLIENT_ID"]
+ configurationURL := tenantConfiguration["MINIO_IDENTITY_OPENID_CONFIG_URL"]
+ scopes := tenantConfiguration["MINIO_IDENTITY_OPENID_SCOPES"]
+ secretID := tenantConfiguration["MINIO_IDENTITY_OPENID_CLIENT_SECRET"]
+
+ idpConfiguration = &models.IdpConfiguration{
+ Oidc: &models.IdpConfigurationOidc{
+ CallbackURL: callbackURL,
+ ClaimName: &claimName,
+ ClientID: &clientID,
+ ConfigurationURL: &configurationURL,
+ Scopes: scopes,
+ SecretID: &secretID,
+ },
+ }
+ }
+ if tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_ADDR"] != "" {
+
+ groupSearchBaseDN := tenantConfiguration["MINIO_IDENTITY_LDAP_GROUP_SEARCH_BASE_DN"]
+ groupSearchFilter := tenantConfiguration["MINIO_IDENTITY_LDAP_GROUP_SEARCH_FILTER"]
+ lookupBindDN := tenantConfiguration["MINIO_IDENTITY_LDAP_LOOKUP_BIND_DN"]
+ lookupBindPassword := tenantConfiguration["MINIO_IDENTITY_LDAP_LOOKUP_BIND_PASSWORD"]
+ serverInsecure := tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_INSECURE"] == "on"
+ serverStartTLS := tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_STARTTLS"] == "on"
+ tlsSkipVerify := tenantConfiguration["MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY"] == "on"
+ serverAddress := tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_ADDR"]
+ userDNSearchBaseDN := tenantConfiguration["MINIO_IDENTITY_LDAP_USER_DN_SEARCH_BASE_DN"]
+ userDNSearchFilter := tenantConfiguration["MINIO_IDENTITY_LDAP_USER_DN_SEARCH_FILTER"]
+
+ idpConfiguration = &models.IdpConfiguration{
+ ActiveDirectory: &models.IdpConfigurationActiveDirectory{
+ GroupSearchBaseDn: groupSearchBaseDN,
+ GroupSearchFilter: groupSearchFilter,
+ LookupBindDn: &lookupBindDN,
+ LookupBindPassword: lookupBindPassword,
+ ServerInsecure: serverInsecure,
+ ServerStartTLS: serverStartTLS,
+ SkipTLSVerification: tlsSkipVerify,
+ URL: &serverAddress,
+ UserDnSearchBaseDn: userDNSearchBaseDN,
+ UserDnSearchFilter: userDNSearchFilter,
+ },
+ }
+ }
+ return idpConfiguration, nil
+}
+
+func updateTenantIdentityProvider(ctx context.Context, operatorClient OperatorClientI, client K8sClientI, namespace string, params operator_api.UpdateTenantIdentityProviderParams) error {
+ tenant, err := operatorClient.TenantGet(ctx, namespace, params.Tenant, metav1.GetOptions{})
+ if err != nil {
+ return err
+ }
+ tenantConfiguration, err := GetTenantConfiguration(ctx, client, tenant)
+ if err != nil {
+ return err
+ }
+
+ delete(tenantConfiguration, "accesskey")
+ delete(tenantConfiguration, "secretkey")
+
+ oidcConfig := params.Body.Oidc
+ // set new oidc configuration fields
+ if oidcConfig != nil {
+ configurationURL := *oidcConfig.ConfigurationURL
+ clientID := *oidcConfig.ClientID
+ secretID := *oidcConfig.SecretID
+ claimName := *oidcConfig.ClaimName
+ scopes := oidcConfig.Scopes
+ callbackURL := oidcConfig.CallbackURL
+ // oidc config
+ tenantConfiguration["MINIO_IDENTITY_OPENID_CONFIG_URL"] = configurationURL
+ tenantConfiguration["MINIO_IDENTITY_OPENID_CLIENT_ID"] = clientID
+ tenantConfiguration["MINIO_IDENTITY_OPENID_CLIENT_SECRET"] = secretID
+ tenantConfiguration["MINIO_IDENTITY_OPENID_CLAIM_NAME"] = claimName
+ tenantConfiguration["MINIO_IDENTITY_OPENID_REDIRECT_URI"] = callbackURL
+ if scopes == "" {
+ scopes = "openid,profile,email"
+ }
+ tenantConfiguration["MINIO_IDENTITY_OPENID_SCOPES"] = scopes
+ } else {
+ // reset oidc configuration fields
+ delete(tenantConfiguration, "MINIO_IDENTITY_OPENID_CLAIM_NAME")
+ delete(tenantConfiguration, "MINIO_IDENTITY_OPENID_CLIENT_ID")
+ delete(tenantConfiguration, "MINIO_IDENTITY_OPENID_CONFIG_URL")
+ delete(tenantConfiguration, "MINIO_IDENTITY_OPENID_SCOPES")
+ delete(tenantConfiguration, "MINIO_IDENTITY_OPENID_CLIENT_SECRET")
+ delete(tenantConfiguration, "MINIO_IDENTITY_OPENID_REDIRECT_URI")
+ }
+ ldapConfig := params.Body.ActiveDirectory
+ // set new active directory configuration fields
+ if ldapConfig != nil {
+ // ldap config
+ serverAddress := *ldapConfig.URL
+ tlsSkipVerify := ldapConfig.SkipTLSVerification
+ serverInsecure := ldapConfig.ServerInsecure
+ lookupBindDN := *ldapConfig.LookupBindDn
+ lookupBindPassword := ldapConfig.LookupBindPassword
+ userDNSearchBaseDN := ldapConfig.UserDnSearchBaseDn
+ userDNSearchFilter := ldapConfig.UserDnSearchFilter
+ groupSearchBaseDN := ldapConfig.GroupSearchBaseDn
+ groupSearchFilter := ldapConfig.GroupSearchFilter
+ serverStartTLS := ldapConfig.ServerStartTLS
+ // LDAP Server
+ tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_ADDR"] = serverAddress
+ if tlsSkipVerify {
+ tenantConfiguration["MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY"] = "on"
+ }
+ if serverInsecure {
+ tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_INSECURE"] = "on"
+ }
+ if serverStartTLS {
+ tenantConfiguration["MINIO_IDENTITY_LDAP_SERVER_STARTTLS"] = "on"
+ }
+ // LDAP Lookup
+ tenantConfiguration["MINIO_IDENTITY_LDAP_LOOKUP_BIND_DN"] = lookupBindDN
+ tenantConfiguration["MINIO_IDENTITY_LDAP_LOOKUP_BIND_PASSWORD"] = lookupBindPassword
+ // LDAP User DN
+ tenantConfiguration["MINIO_IDENTITY_LDAP_USER_DN_SEARCH_BASE_DN"] = userDNSearchBaseDN
+ tenantConfiguration["MINIO_IDENTITY_LDAP_USER_DN_SEARCH_FILTER"] = userDNSearchFilter
+ // LDAP Group
+ tenantConfiguration["MINIO_IDENTITY_LDAP_GROUP_SEARCH_BASE_DN"] = groupSearchBaseDN
+ tenantConfiguration["MINIO_IDENTITY_LDAP_GROUP_SEARCH_FILTER"] = groupSearchFilter
+ } else {
+ // reset active directory configuration fields
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_GROUP_SEARCH_BASE_DN")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_GROUP_SEARCH_FILTER")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_LOOKUP_BIND_DN")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_LOOKUP_BIND_PASSWORD")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_SERVER_INSECURE")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_SERVER_STARTTLS")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_SERVER_ADDR")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_USER_DN_SEARCH_BASE_DN")
+ delete(tenantConfiguration, "MINIO_IDENTITY_LDAP_USER_DN_SEARCH_FILTER")
+ }
+ // write tenant configuration to secret that contains config.env
+ tenantConfigurationName := fmt.Sprintf("%s-env-configuration", tenant.Name)
+ _, err = createOrReplaceSecrets(ctx, client, tenant.Namespace, []tenantSecret{
+ {
+ Name: tenantConfigurationName,
+ Content: map[string][]byte{
+ "config.env": []byte(GenerateTenantConfigurationFile(tenantConfiguration)),
+ },
+ },
+ }, tenant.Name)
+ if err != nil {
+ return err
+ }
+ tenant.Spec.Configuration = &corev1.LocalObjectReference{Name: tenantConfigurationName}
+ tenant.EnsureDefaults()
+ // update tenant CRD
+ _, err = operatorClient.TenantUpdate(ctx, tenant, metav1.UpdateOptions{})
+ if err != nil {
+ return err
+ }
+ // restart all MinIO pods at the same time
+ err = client.deletePodCollection(ctx, namespace, metav1.DeleteOptions{}, metav1.ListOptions{
+ LabelSelector: fmt.Sprintf("%s=%s", miniov2.TenantLabel, tenant.Name),
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func getTenantIdentityProviderResponse(session *models.Principal, params operator_api.TenantIdentityProviderParams) (*models.IdpConfiguration, *models.Error) {
+ // 5 seconds timeout
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
+ if err != nil {
+ return nil, prepareError(err)
+ }
+ opClient := &operatorClient{
+ client: opClientClientSet,
+ }
+ minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
+ if err != nil {
+ return nil, prepareError(err)
+ }
+ // get Kubernetes Client
+ clientSet, err := cluster.K8sClient(session.STSSessionToken)
+ k8sClient := k8sClient{
+ client: clientSet,
+ }
+ if err != nil {
+ return nil, prepareError(err)
+ }
+ info, err := getTenantIdentityProvider(ctx, &k8sClient, minTenant)
+ if err != nil {
+ return nil, prepareError(err)
+ }
+ return info, nil
+}
+
+func getUpdateTenantIdentityProviderResponse(session *models.Principal, params operator_api.UpdateTenantIdentityProviderParams) *models.Error {
+ // 5 seconds timeout
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
+ if err != nil {
+ return prepareError(err)
+ }
+ // get Kubernetes Client
+ clientSet, err := cluster.K8sClient(session.STSSessionToken)
+ if err != nil {
+ return prepareError(err)
+ }
+ k8sClient := k8sClient{
+ client: clientSet,
+ }
+ opClient := &operatorClient{
+ client: opClientClientSet,
+ }
+ if err := updateTenantIdentityProvider(ctx, opClient, &k8sClient, params.Namespace, params); err != nil {
+ return prepareError(err, errors.New("unable to update tenant"))
+ }
+ return nil
+}
+
func getTenantSecurityResponse(session *models.Principal, params operator_api.TenantSecurityParams) (*models.TenantSecurityResponse, *models.Error) {
// 5 seconds timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
@@ -764,12 +1017,12 @@ func updateTenantSecurity(ctx context.Context, operatorClient OperatorClientI, c
if err != nil {
return err
}
- // Remove Certificate Secrets from Tenant namespace
- for _, secretName := range params.Body.CustomCertificates.SecretsToBeDeleted {
- err = client.deleteSecret(ctx, minInst.Namespace, secretName, metav1.DeleteOptions{})
- if err != nil {
- restapi.LogError("error deleting secret: %v", err)
- }
+ // restart all MinIO pods at the same time
+ err = client.deletePodCollection(ctx, namespace, metav1.DeleteOptions{}, metav1.ListOptions{
+ LabelSelector: fmt.Sprintf("%s=%s", miniov2.TenantLabel, minInst.Name),
+ })
+ if err != nil {
+ return err
}
return nil
}
@@ -1002,7 +1255,7 @@ func addTenantPool(ctx context.Context, operatorClient OperatorClientI, params o
return err
}
- _, err = operatorClient.TenantPatch(ctx, params.Namespace, tenant.Name, types.MergePatchType, payloadBytes, metav1.PatchOptions{})
+ _, err = operatorClient.TenantPatch(ctx, tenant.Namespace, tenant.Name, types.MergePatchType, payloadBytes, metav1.PatchOptions{})
if err != nil {
return err
}
@@ -2207,7 +2460,7 @@ func getTenantYAML(session *models.Principal, params operator_api.GetTenantYAMLP
tenant.ManagedFields = []metav1.ManagedFieldsEntry{}
//yb, err := yaml.Marshal(tenant)
- serializer := k8sJson.NewSerializerWithOptions(
+ j8sJSONSerializer := k8sJson.NewSerializerWithOptions(
k8sJson.DefaultMetaFactory, nil, nil,
k8sJson.SerializerOptions{
Yaml: true,
@@ -2217,7 +2470,7 @@ func getTenantYAML(session *models.Principal, params operator_api.GetTenantYAMLP
)
buf := new(bytes.Buffer)
- err = serializer.Encode(tenant, buf)
+ err = j8sJSONSerializer.Encode(tenant, buf)
if err != nil {
return nil, prepareError(err)
}
@@ -2259,7 +2512,7 @@ func getUpdateTenantYAML(session *models.Principal, params operator_api.PutTenan
upTenant.Finalizers = inTenant.Finalizers
upTenant.Spec = inTenant.Spec
- _, err = opClient.MinioV2().Tenants(params.Namespace).Update(params.HTTPRequest.Context(), upTenant, metav1.UpdateOptions{})
+ _, err = opClient.MinioV2().Tenants(upTenant.Namespace).Update(params.HTTPRequest.Context(), upTenant, metav1.UpdateOptions{})
if err != nil {
return &models.Error{Code: 400, Message: swag.String(err.Error())}
}
diff --git a/portal-ui/src/common/SecureComponent/permissions.ts b/portal-ui/src/common/SecureComponent/permissions.ts
index b37d587bd..62a38951c 100644
--- a/portal-ui/src/common/SecureComponent/permissions.ts
+++ b/portal-ui/src/common/SecureComponent/permissions.ts
@@ -187,6 +187,8 @@ export const IAM_PAGES = {
"/namespaces/:tenantNamespace/tenants/:tenantName/volumes",
NAMESPACE_TENANT_LICENSE:
"/namespaces/:tenantNamespace/tenants/:tenantName/license",
+ NAMESPACE_TENANT_IDENTITY_PROVIDER:
+ "/namespaces/:tenantNamespace/tenants/:tenantName/identity-provider",
NAMESPACE_TENANT_SECURITY:
"/namespaces/:tenantNamespace/tenants/:tenantName/security",
NAMESPACE_TENANT_ENCRYPTION:
diff --git a/portal-ui/src/screens/Console/Console.tsx b/portal-ui/src/screens/Console/Console.tsx
index 1997e3760..6d7756111 100644
--- a/portal-ui/src/screens/Console/Console.tsx
+++ b/portal-ui/src/screens/Console/Console.tsx
@@ -449,6 +449,11 @@ const Console = ({
path: IAM_PAGES.NAMESPACE_TENANT_LICENSE,
forceDisplay: true,
},
+ {
+ component: TenantDetails,
+ path: IAM_PAGES.NAMESPACE_TENANT_IDENTITY_PROVIDER,
+ forceDisplay: true,
+ },
{
component: TenantDetails,
path: IAM_PAGES.NAMESPACE_TENANT_SECURITY,
diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx
index 29843bf37..cc64eaeb1 100644
--- a/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx
+++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx
@@ -68,6 +68,9 @@ const TenantTrace = withSuspense(React.lazy(() => import("./TenantTrace")));
const TenantVolumes = withSuspense(
React.lazy(() => import("./pvcs/TenantVolumes"))
);
+const TenantIdentityProvider = withSuspense(
+ React.lazy(() => import("./TenantIdentityProvider"))
+);
const TenantSecurity = withSuspense(
React.lazy(() => import("./TenantSecurity"))
);
@@ -451,6 +454,10 @@ const TenantDetails = ({
path={IAM_PAGES.NAMESPACE_TENANT_TRACE}
component={TenantTrace}
/>
+
Encryption
-
+
{
+ onChange={() => {
setEncryptionEnabled(!encryptionEnabled);
}}
description=""
@@ -746,7 +752,7 @@ const TenantEncryption = ({
{encryptionType === "vault" && (
-
+
-
+
-
+
-
+
-
+
-
+
- Mutual TLS authentication with KMS (optional)
+ Vault Certificates (optional)
+
+
)}
-
+
-
+
-
+
-
+