feat(webhook): validate dashboard auth spec

- will check whether either OIDC issuer or oauth2 endpoints are set
- will check whether basic auth credentials are configured
This commit is contained in:
Peter 2025-02-05 21:07:22 +01:00
parent 3c13eb0d6b
commit 9d02a2d90b
Signed by: prskr
GPG key ID: F56BED6903BC5E37
2 changed files with 60 additions and 2 deletions
api/v1alpha1
internal/webhook/v1alpha1

View file

@ -204,6 +204,14 @@ func (s *DashboardEndpointSpec) OAuth2() *DashboardOAuth2Spec {
return s.Auth.OAuth2
}
func (s *DashboardEndpointSpec) Basic() *DashboardBasicAuthSpec {
if s == nil || s.Auth == nil {
return nil
}
return s.Auth.Basic
}
// APIGatewaySpec defines the desired state of APIGateway.
type APIGatewaySpec struct {
// Envoy - configure the envoy instance and most importantly the control-plane

View file

@ -36,6 +36,8 @@ var apigatewaylog = logf.Log.WithName("apigateway-resource")
var (
ErrMissingEnvoySpec = errors.New("envoy needs to be configured")
ErrMissingControlPlaneSpec = errors.New("envoy control plane needs to be configured")
ErrOAuth2EndpointsMissing = errors.New("oauth2 endpoints missing")
ErrBasicAuthNoUsers = errors.New("no users configured for basic auth")
)
// +kubebuilder:webhook:path=/validate-supabase-k8s-icb4dc0-de-v1alpha1-apigateway,mutating=false,failurePolicy=fail,sideEffects=None,groups=supabase.k8s.icb4dc0.de,resources=apigateways,verbs=create;update,versions=v1alpha1,name=vapigateway-v1alpha1.kb.io,admissionReviewVersions=v1
@ -57,7 +59,18 @@ func (v *APIGatewayCustomValidator) ValidateCreate(ctx context.Context, obj runt
}
apigatewaylog.Info("Validation for APIGateway upon creation", "name", apigateway.GetName())
return validateEnvoyControlPlane(apigateway)
warnings, err := validateEnvoyControlPlane(apigateway)
if err != nil {
return warnings, err
}
if warns, err := validateDashboardEndpointSpec(apigateway); err != nil {
return append(warnings, warns...), err
} else {
warnings = append(warnings, warns...)
}
return warnings, nil
}
// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type APIGateway.
@ -68,7 +81,18 @@ func (v *APIGatewayCustomValidator) ValidateUpdate(ctx context.Context, oldObj,
}
apigatewaylog.Info("Validation for APIGateway upon update", "name", apigateway.GetName())
return validateEnvoyControlPlane(apigateway)
warnings, err := validateEnvoyControlPlane(apigateway)
if err != nil {
return warnings, err
}
if warns, err := validateDashboardEndpointSpec(apigateway); err != nil {
return append(warnings, warns...), err
} else {
warnings = append(warnings, warns...)
}
return warnings, nil
}
// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type APIGateway.
@ -95,3 +119,29 @@ func validateEnvoyControlPlane(gateway *supabasev1alpha1.APIGateway) (admission.
return nil, nil
}
func validateDashboardEndpointSpec(gateway *supabasev1alpha1.APIGateway) (warnings admission.Warnings, err error) {
dashboardEndpointSpec := gateway.Spec.DashboardEndpoint
if dashboardEndpointSpec == nil {
return nil, nil
}
switch dashboardEndpointSpec.AuthType() {
case supabasev1alpha1.DashboardAuthTypeOAuth2:
oauth2Spec := dashboardEndpointSpec.OAuth2()
if oauth2Spec.OpenIDIssuer == "" && oauth2Spec.AuthorizationEndpoint == "" && oauth2Spec.TokenEndpoint == "" {
return nil, fmt.Errorf("%w: you have to either set the OpenID issuer or authorization and token endpoints for oauth2 authentication", ErrOAuth2EndpointsMissing)
}
case supabasev1alpha1.DashboardAuthTypeBasic:
basicAuthSpec := dashboardEndpointSpec.Basic()
if len(basicAuthSpec.UsersInline) == 0 && basicAuthSpec.PlaintextUsersSecretRef == "" {
return nil, fmt.Errorf("%w: neither inline users are specified nor a secret for plaintext credentials was referenced", ErrBasicAuthNoUsers)
}
if len(basicAuthSpec.UsersInline) == 0 {
warnings = append(warnings, "no inline users were specified, make sure to have at least one username - password pair in the referenced secret otherwise the setup will be skipped")
}
}
return warnings, nil
}