feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
@@ -1,29 +1,14 @@
|
||||
/*
|
||||
Copyright 2020 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
)
|
||||
|
||||
type GrantHandlerType string
|
||||
@@ -31,36 +16,22 @@ type MappingMethod string
|
||||
type IdentityProviderType string
|
||||
|
||||
const (
|
||||
// GrantHandlerAuto auto-approves client authorization grant requests
|
||||
GrantHandlerAuto GrantHandlerType = "auto"
|
||||
// GrantHandlerPrompt prompts the user to approve new client authorization grant requests
|
||||
GrantHandlerPrompt GrantHandlerType = "prompt"
|
||||
// GrantHandlerDeny auto-denies client authorization grant requests
|
||||
GrantHandlerDeny GrantHandlerType = "deny"
|
||||
// MappingMethodAuto The default value.
|
||||
// The user will automatically create and mapping when login successful.
|
||||
// Fails if a user with that username is already mapped to another identity.
|
||||
MappingMethodAuto MappingMethod = "auto"
|
||||
// MappingMethodLookup Looks up an existing identity, user identity mapping, and user, but does not automatically
|
||||
// provision users or identities. Using this method requires you to manually provision users.
|
||||
MappingMethodLookup MappingMethod = "lookup"
|
||||
// MappingMethodMixed A user entity can be mapped with multiple identifyProvider.
|
||||
// MappingMethodMixed A user entity can be mapped with multiple identifyProvider.
|
||||
// not supported yet.
|
||||
MappingMethodMixed MappingMethod = "mixed"
|
||||
|
||||
DefaultIssuer string = "kubesphere"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorClientNotFound = errors.New("the OAuth client was not found")
|
||||
ErrorProviderNotFound = errors.New("the identity provider was not found")
|
||||
ErrorRedirectURLNotAllowed = errors.New("redirect URL is not allowed")
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
// An Issuer Identifier is a case-sensitive URL using the https scheme that contains scheme,
|
||||
type IssuerOptions struct {
|
||||
// URL is a case-sensitive URL using the https scheme that contains scheme,
|
||||
// host, and optionally, port number and path components and no query or fragment components.
|
||||
Issuer string `json:"issuer,omitempty" yaml:"issuer,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
|
||||
// secret to sign jwt token
|
||||
JWTSecret string `json:"-" yaml:"jwtSecret"`
|
||||
|
||||
// RSA private key file used to sign the id token
|
||||
SignKey string `json:"signKey,omitempty" yaml:"signKey,omitempty"`
|
||||
@@ -68,14 +39,9 @@ type Options struct {
|
||||
// Raw RSA private key. Base64 encoded PEM file
|
||||
SignKeyData string `json:"-,omitempty" yaml:"signKeyData,omitempty"`
|
||||
|
||||
// Register identity providers.
|
||||
IdentityProviders []IdentityProviderOptions `json:"identityProviders,omitempty" yaml:"identityProviders,omitempty"`
|
||||
|
||||
// Register additional OAuth clients.
|
||||
Clients []Client `json:"clients,omitempty" yaml:"clients,omitempty"`
|
||||
|
||||
// AccessTokenMaxAgeSeconds control the lifetime of access tokens. The default lifetime is 24 hours.
|
||||
// 0 means no expiration.
|
||||
// AccessTokenMaxAgeSeconds control the lifetime of access tokens.
|
||||
// The default lifetime is 24 hours.
|
||||
// Zero means no expiration.
|
||||
AccessTokenMaxAge time.Duration `json:"accessTokenMaxAge" yaml:"accessTokenMaxAge"`
|
||||
|
||||
// Inactivity timeout for tokens
|
||||
@@ -89,26 +55,34 @@ type Options struct {
|
||||
// - X: Tokens time out if there is no activity
|
||||
// The current minimum allowed value for X is 5 minutes
|
||||
AccessTokenInactivityTimeout time.Duration `json:"accessTokenInactivityTimeout" yaml:"accessTokenInactivityTimeout"`
|
||||
|
||||
// Token verification maximum time difference, default to 10s.
|
||||
// You should consider allowing a clock skew when checking the time-based values.
|
||||
// This should be values of a few seconds, and we don’t recommend using more than 30 seconds for this purpose,
|
||||
// as this would rather indicate problems with the server, rather than a common clock skew.
|
||||
MaximumClockSkew time.Duration `json:"maximumClockSkew" yaml:"maximumClockSkew"`
|
||||
}
|
||||
|
||||
type IdentityProviderOptions struct {
|
||||
// The provider name.
|
||||
Name string `json:"name" yaml:"name"`
|
||||
|
||||
// Defines how new identities are mapped to users when they login. Allowed values are:
|
||||
// - auto: The default value.The user will automatically create and mapping when login successful.
|
||||
// Fails if a user with that user name is already mapped to another identity.
|
||||
// Defines how new identities are mapped to users when they login.
|
||||
// Allowed values are:
|
||||
// - auto: The default value.The user will automatically create and mapping when login is successful.
|
||||
// Fails if a user with that username is already mapped to another identity.
|
||||
// - lookup: Looks up an existing identity, user identity mapping, and user, but does not automatically
|
||||
// provision users or identities. Using this method requires you to manually provision users.
|
||||
// - mixed: A user entity can be mapped with multiple identifyProvider.
|
||||
// provision users or identities.
|
||||
// Using this method requires you to manually provision users.
|
||||
// - mixed: A user entity can be mapped with multiple identifyProvider.
|
||||
MappingMethod MappingMethod `json:"mappingMethod" yaml:"mappingMethod"`
|
||||
|
||||
// DisableLoginConfirmation means that when the user login successfully,
|
||||
// reconfirm the account information is not required.
|
||||
// DisableLoginConfirmation Skip the login confirmation screen, so user cannot change its username.
|
||||
// Username is provided from ID Token.
|
||||
// Username from IDP must math [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
|
||||
DisableLoginConfirmation bool `json:"disableLoginConfirmation" yaml:"disableLoginConfirmation"`
|
||||
|
||||
// The type of identify provider
|
||||
// The type of identity provider
|
||||
// OpenIDIdentityProvider LDAPIdentityProvider GitHubIdentityProvider
|
||||
Type string `json:"type" yaml:"type"`
|
||||
|
||||
@@ -125,7 +99,7 @@ type Token struct {
|
||||
// The Type method returns either this or "Bearer", the default.
|
||||
TokenType string `json:"token_type,omitempty"`
|
||||
|
||||
// RefreshToken is a token that's used by the application
|
||||
// RefreshToken is a token used by the application
|
||||
// (as opposed to the user) to refresh the access token
|
||||
// if it expires.
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
@@ -137,104 +111,10 @@ type Token struct {
|
||||
ExpiresIn int `json:"expires_in,omitempty"`
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
// The name of the OAuth client is used as the client_id parameter when making requests to <master>/oauth/authorize
|
||||
// and <master>/oauth/token.
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
|
||||
// Secret is the unique secret associated with a client
|
||||
Secret string `json:"-" yaml:"secret,omitempty"`
|
||||
|
||||
// RespondWithChallenges indicates whether the client wants authentication needed responses made
|
||||
// in the form of challenges instead of redirects
|
||||
RespondWithChallenges bool `json:"respondWithChallenges,omitempty" yaml:"respondWithChallenges,omitempty"`
|
||||
|
||||
// RedirectURIs is the valid redirection URIs associated with a client
|
||||
RedirectURIs []string `json:"redirectURIs,omitempty" yaml:"redirectURIs,omitempty"`
|
||||
|
||||
// GrantMethod determines how to handle grants for this client. If no method is provided, the
|
||||
// cluster default grant handling method will be used. Valid grant handling methods are:
|
||||
// - auto: always approves grant requests, useful for trusted clients
|
||||
// - prompt: prompts the end user for approval of grant requests, useful for third-party clients
|
||||
// - deny: always denies grant requests, useful for black-listed clients
|
||||
GrantMethod GrantHandlerType `json:"grantMethod,omitempty" yaml:"grantMethod,omitempty"`
|
||||
|
||||
// ScopeRestrictions describes which scopes this client can request. Each requested scope
|
||||
// is checked against each restriction. If any restriction matches, then the scope is allowed.
|
||||
// If no restriction matches, then the scope is denied.
|
||||
ScopeRestrictions []string `json:"scopeRestrictions,omitempty" yaml:"scopeRestrictions,omitempty"`
|
||||
|
||||
// AccessTokenMaxAge overrides the default access token max age for tokens granted to this client.
|
||||
AccessTokenMaxAge *time.Duration `json:"accessTokenMaxAge,omitempty" yaml:"accessTokenMaxAge,omitempty"`
|
||||
|
||||
// AccessTokenInactivityTimeout overrides the default token
|
||||
// inactivity timeout for tokens granted to this client.
|
||||
AccessTokenInactivityTimeout *time.Duration `json:"accessTokenInactivityTimeout,omitempty" yaml:"accessTokenInactivityTimeout,omitempty"`
|
||||
}
|
||||
|
||||
var (
|
||||
// AllowAllRedirectURI Allow any redirect URI if the redirectURI is defined in request
|
||||
AllowAllRedirectURI = "*"
|
||||
)
|
||||
|
||||
func (o *Options) OAuthClient(name string) (Client, error) {
|
||||
for _, found := range o.Clients {
|
||||
if found.Name == name {
|
||||
return found, nil
|
||||
}
|
||||
}
|
||||
return Client{}, ErrorClientNotFound
|
||||
}
|
||||
|
||||
func (o *Options) IdentityProviderOptions(name string) (*IdentityProviderOptions, error) {
|
||||
for _, found := range o.IdentityProviders {
|
||||
if found.Name == name {
|
||||
return &found, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrorProviderNotFound
|
||||
}
|
||||
|
||||
func (c Client) anyRedirectAbleURI() []string {
|
||||
uris := make([]string, 0)
|
||||
for _, uri := range c.RedirectURIs {
|
||||
_, err := url.Parse(uri)
|
||||
if err == nil {
|
||||
uris = append(uris, uri)
|
||||
}
|
||||
}
|
||||
return uris
|
||||
}
|
||||
|
||||
func (c Client) ResolveRedirectURL(expectURL string) (*url.URL, error) {
|
||||
// RedirectURIs is empty
|
||||
if len(c.RedirectURIs) == 0 {
|
||||
return nil, ErrorRedirectURLNotAllowed
|
||||
}
|
||||
allowAllRedirectURI := sliceutil.HasString(c.RedirectURIs, AllowAllRedirectURI)
|
||||
redirectAbleURIs := c.anyRedirectAbleURI()
|
||||
|
||||
if expectURL == "" {
|
||||
// Need to specify at least one RedirectURI
|
||||
if len(redirectAbleURIs) > 0 {
|
||||
return url.Parse(redirectAbleURIs[0])
|
||||
} else {
|
||||
return nil, ErrorRedirectURLNotAllowed
|
||||
}
|
||||
}
|
||||
if allowAllRedirectURI || sliceutil.HasString(redirectAbleURIs, expectURL) {
|
||||
return url.Parse(expectURL)
|
||||
}
|
||||
|
||||
return nil, ErrorRedirectURLNotAllowed
|
||||
}
|
||||
|
||||
func NewOptions() *Options {
|
||||
return &Options{
|
||||
Issuer: DefaultIssuer,
|
||||
IdentityProviders: make([]IdentityProviderOptions, 0),
|
||||
Clients: make([]Client, 0),
|
||||
func NewIssuerOptions() *IssuerOptions {
|
||||
return &IssuerOptions{
|
||||
AccessTokenMaxAge: time.Hour * 2,
|
||||
AccessTokenInactivityTimeout: time.Hour * 2,
|
||||
MaximumClockSkew: 10 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user