rally oidc configuration logic in 'shareOidc' (#991)

This commit is contained in:
Michael Quigley 2025-06-24 13:48:35 -04:00
parent 716003f99b
commit 0f81d7aa6e
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
2 changed files with 70 additions and 53 deletions

View File

@ -2,14 +2,12 @@ package controller
import ( import (
"encoding/json" "encoding/json"
"fmt"
"net/http"
"strings"
"time" "time"
"github.com/go-openapi/runtime/middleware" "github.com/go-openapi/runtime/middleware"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/openziti/edge-api/rest_management_api_client" "github.com/openziti/edge-api/rest_management_api_client"
"github.com/openziti/zrok/controller/shareOidc"
"github.com/openziti/zrok/controller/store" "github.com/openziti/zrok/controller/store"
"github.com/openziti/zrok/controller/zrokEdgeSdk" "github.com/openziti/zrok/controller/zrokEdgeSdk"
"github.com/openziti/zrok/rest_model_zrok" "github.com/openziti/zrok/rest_model_zrok"
@ -22,23 +20,6 @@ import (
type shareHandler struct{} type shareHandler struct{}
type oidcMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
JwksURI string `json:"jwks_uri"`
ScopesSupported []string `json:"scopes_supported"`
}
func (m *oidcMetadata) String() string {
jsonBytes, err := json.MarshalIndent(m, "", " ")
if err != nil {
return fmt.Sprintf("error marshaling OIDC metadata: %v", err)
}
return string(jsonBytes)
}
func newShareHandler() *shareHandler { func newShareHandler() *shareHandler {
return &shareHandler{} return &shareHandler{}
} }
@ -355,39 +336,9 @@ func (h *shareHandler) validateOidcConfiguration(oidcConfig *rest_model_zrok.Oid
return errors.New("issuer URL is required") return errors.New("issuer URL is required")
} }
// fetch the OIDC configuration from the well-known endpoint metadata, err := shareOidc.FetchAndValidateIssuerMetadata(oidcConfig.IssuerURL)
wellKnownURL := oidcConfig.IssuerURL
if !strings.HasSuffix(wellKnownURL, "/") {
wellKnownURL += "/"
}
wellKnownURL += ".well-known/openid-configuration"
resp, err := http.Get(wellKnownURL)
if err != nil { if err != nil {
return errors.Wrapf(err, "error fetching OIDC configuration from %s", wellKnownURL) return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return errors.Errorf("received non-200 status code (%d) from OIDC configuration endpoint '%v'", resp.StatusCode, wellKnownURL)
}
var metadata oidcMetadata
if err := json.NewDecoder(resp.Body).Decode(&metadata); err != nil {
return errors.Wrap(err, "error decoding OIDC configuration")
}
if metadata.Issuer == "" {
return errors.New("issuer not found in OIDC configuration")
}
if metadata.AuthorizationEndpoint == "" {
return errors.New("authorization_endpoint not found in OIDC configuration")
}
if metadata.TokenEndpoint == "" {
return errors.New("token_endpoint not found in OIDC configuration")
}
if metadata.UserinfoEndpoint == "" {
return errors.New("userinfo_endpoint not found in OIDC configuration")
} }
if oidcConfig.ClientID == "" { if oidcConfig.ClientID == "" {
@ -429,7 +380,7 @@ func (h *shareHandler) validateOidcConfiguration(oidcConfig *rest_model_zrok.Oid
} }
} }
logrus.Infof("validated OIDC metadata: %s", &metadata) logrus.Infof("validated OIDC metadata: %s", metadata)
return nil return nil
} }

View File

@ -0,0 +1,66 @@
package shareOidc
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"github.com/pkg/errors"
)
type IssuerMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
JwksURI string `json:"jwks_uri"`
ScopesSupported []string `json:"scopes_supported"`
}
func (m *IssuerMetadata) String() string {
jsonBytes, err := json.MarshalIndent(m, "", " ")
if err != nil {
return fmt.Sprintf("error marshaling OIDC metadata: %v", err)
}
return string(jsonBytes)
}
func FetchAndValidateIssuerMetadata(issuerUrl string) (*IssuerMetadata, error) {
// fetch the OIDC configuration from the well-known endpoint
wellKnownURL := issuerUrl
if !strings.HasSuffix(wellKnownURL, "/") {
wellKnownURL += "/"
}
wellKnownURL += ".well-known/openid-configuration"
resp, err := http.Get(wellKnownURL)
if err != nil {
return nil, errors.Wrapf(err, "error fetching OIDC configuration from %s", wellKnownURL)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, errors.Errorf("received non-200 status code (%d) from OIDC configuration endpoint '%v'", resp.StatusCode, wellKnownURL)
}
metadata := &IssuerMetadata{}
if err := json.NewDecoder(resp.Body).Decode(&metadata); err != nil {
return nil, errors.Wrap(err, "error decoding OIDC configuration")
}
if metadata.Issuer == "" {
return nil, errors.New("issuer not found in OIDC configuration")
}
if metadata.AuthorizationEndpoint == "" {
return nil, errors.New("authorization_endpoint not found in OIDC configuration")
}
if metadata.TokenEndpoint == "" {
return nil, errors.New("token_endpoint not found in OIDC configuration")
}
if metadata.UserinfoEndpoint == "" {
return nil, errors.New("userinfo_endpoint not found in OIDC configuration")
}
return metadata, nil
}