Fixes to Multiple IDP support in console (#2392)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2022-10-20 20:08:54 -05:00
committed by GitHub
parent 139e90830f
commit dab4eb7664
19 changed files with 380 additions and 112 deletions

View File

@@ -6349,12 +6349,6 @@ func init() {
"loginDetails": {
"type": "object",
"properties": {
"displayNames": {
"type": "array",
"items": {
"type": "string"
}
},
"isDirectPV": {
"type": "boolean"
},
@@ -6367,10 +6361,10 @@ func init() {
"redirect-service-account"
]
},
"redirect": {
"redirectRules": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/redirectRule"
}
}
}
@@ -7038,6 +7032,17 @@ func init() {
}
}
},
"redirectRule": {
"type": "object",
"properties": {
"displayName": {
"type": "string"
},
"redirect": {
"type": "string"
}
}
},
"remoteBucket": {
"type": "object",
"required": [
@@ -14605,12 +14610,6 @@ func init() {
"loginDetails": {
"type": "object",
"properties": {
"displayNames": {
"type": "array",
"items": {
"type": "string"
}
},
"isDirectPV": {
"type": "boolean"
},
@@ -14623,10 +14622,10 @@ func init() {
"redirect-service-account"
]
},
"redirect": {
"redirectRules": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/redirectRule"
}
}
}
@@ -15294,6 +15293,17 @@ func init() {
}
}
},
"redirectRule": {
"type": "object",
"properties": {
"displayName": {
"type": "string"
},
"redirect": {
"type": "string"
}
}
},
"remoteBucket": {
"type": "object",
"required": [

View File

@@ -66,7 +66,6 @@ func replaceJwtVariables(rawPolicy []byte, claims map[string]interface{}) json.R
for _, field := range jwtFields {
if val, ok := claims[field]; ok {
variable := fmt.Sprintf("${jwt:%s}", field)
fmt.Println("found", variable)
rawPolicy = bytes.ReplaceAll(rawPolicy, []byte(variable), []byte(fmt.Sprintf("%v", val)))
}
}

View File

@@ -18,11 +18,10 @@ package restapi
import (
"context"
"encoding/base64"
"encoding/json"
"net/http"
"github.com/minio/madmin-go"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
@@ -30,12 +29,14 @@ import (
"github.com/minio/console/pkg/auth/idp/oauth2"
"github.com/minio/console/restapi/operations"
authApi "github.com/minio/console/restapi/operations/auth"
"github.com/minio/madmin-go"
"github.com/minio/minio-go/v7/pkg/credentials"
)
func registerLoginHandlers(api *operations.ConsoleAPI) {
// GET login strategy
api.AuthLoginDetailHandler = authApi.LoginDetailHandlerFunc(func(params authApi.LoginDetailParams) middleware.Responder {
loginDetails, err := getLoginDetailsResponse(params, GlobalMinIOConfig.OpenIDProviders, oauth2.DefaultIDPConfig)
loginDetails, err := getLoginDetailsResponse(params, GlobalMinIOConfig.OpenIDProviders)
if err != nil {
return authApi.NewLoginDetailDefault(int(err.Code)).WithPayload(err)
}
@@ -56,7 +57,7 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
})
// POST login using external IDP
api.AuthLoginOauth2AuthHandler = authApi.LoginOauth2AuthHandlerFunc(func(params authApi.LoginOauth2AuthParams) middleware.Responder {
loginResponse, err := getLoginOauth2AuthResponse(params, GlobalMinIOConfig.OpenIDProviders, oauth2.DefaultIDPConfig)
loginResponse, err := getLoginOauth2AuthResponse(params, GlobalMinIOConfig.OpenIDProviders)
if err != nil {
return authApi.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
}
@@ -145,12 +146,12 @@ func getLoginResponse(params authApi.LoginParams) (*models.LoginResponse, *model
}
// getLoginDetailsResponse returns information regarding the Console authentication mechanism.
func getLoginDetailsResponse(params authApi.LoginDetailParams, openIDProviders oauth2.OpenIDPCfg, idpName string) (*models.LoginDetails, *models.Error) {
func getLoginDetailsResponse(params authApi.LoginDetailParams, openIDProviders oauth2.OpenIDPCfg) (*models.LoginDetails, *models.Error) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
loginStrategy := models.LoginDetailsLoginStrategyForm
redirectURL := []string{}
displayNames := []string{}
var redirectRules []*models.RedirectRule
r := params.HTTPRequest
var loginDetails *models.LoginDetails
if len(openIDProviders) >= 1 {
@@ -166,18 +167,24 @@ func getLoginDetailsResponse(params authApi.LoginDetailParams, openIDProviders o
KeyFunc: provider.GetStateKeyFunc(),
Client: oauth2Client,
}
redirectURL = append(redirectURL, identityProvider.GenerateLoginURL())
displayName := "Login with SSO"
if provider.DisplayName != "" {
displayNames = append(displayNames, provider.DisplayName)
} else {
displayNames = append(displayNames, "Login with SSO")
displayName = provider.DisplayName
}
redirectRule := models.RedirectRule{
Redirect: identityProvider.GenerateLoginURL(),
DisplayName: displayName,
}
redirectRules = append(redirectRules, &redirectRule)
}
}
loginDetails = &models.LoginDetails{
LoginStrategy: loginStrategy,
Redirect: redirectURL,
DisplayNames: displayNames,
RedirectRules: redirectRules,
}
return loginDetails, nil
}
@@ -187,29 +194,50 @@ func verifyUserAgainstIDP(ctx context.Context, provider auth.IdentityProviderI,
userCredentials, err := provider.VerifyIdentity(ctx, code, state)
if err != nil {
LogError("error validating user identity against idp: %v", err)
return nil, ErrInvalidLogin
return nil, err
}
return userCredentials, nil
}
func getLoginOauth2AuthResponse(params authApi.LoginOauth2AuthParams, openIDProviders oauth2.OpenIDPCfg, idpName string) (*models.LoginResponse, *models.Error) {
func getLoginOauth2AuthResponse(params authApi.LoginOauth2AuthParams, openIDProviders oauth2.OpenIDPCfg) (*models.LoginResponse, *models.Error) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
r := params.HTTPRequest
lr := params.Body
if openIDProviders != nil {
// initialize new oauth2 client
oauth2Client, err := openIDProviders.NewOauth2ProviderClient(idpName, nil, r, GetConsoleHTTPClient(""))
// we read state
rState := *lr.State
decodedRState, err := base64.StdEncoding.DecodeString(rState)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
var requestItems oauth2.LoginURLParams
err = json.Unmarshal(decodedRState, &requestItems)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
IDPName := requestItems.IDPName
state := requestItems.State
providerCfg := openIDProviders[IDPName]
oauth2Client, err := openIDProviders.NewOauth2ProviderClient(IDPName, nil, r, GetConsoleHTTPClient(""))
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
// initialize new identity provider
identityProvider := auth.IdentityProvider{
KeyFunc: openIDProviders[idpName].GetStateKeyFunc(),
KeyFunc: providerCfg.GetStateKeyFunc(),
Client: oauth2Client,
RoleARN: providerCfg.RoleArn,
}
// Validate user against IDP
userCredentials, err := verifyUserAgainstIDP(ctx, identityProvider, *lr.Code, *lr.State)
userCredentials, err := verifyUserAgainstIDP(ctx, identityProvider, *lr.Code, state)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}