To reduce administrative costs, consider using oAuth2 protocol to implement single sign-on functions of Kubepshere and in-house GitLab

Kubesphere3.1 supports oAuth2 login function, and has built-in github and Alicloud IDaas plug-in, just need to make a slight change in kS-Apiserver configuration file, you can achieve; However, if you need to support other third-party authentication systems based on OAuth2, you need to develop the corresponding plug-in, to develop separately, seems to defeat the original purpose of convenient and quick implementation

On second thought, since GitLab and Github share the same name, can github’s configuration also be applied to GitLab? As a result, I used github’s configuration to replace it opportunely. After several twists and turns, I finally failed. It seems that I can only develop plug-ins honestly

Download kubesphere source, authentication plug-in directory location/PKG/apiserver/authentication/identityprovider /

The interface definition


Kubesphere has officially abstracted and encapsulated the OAuth2 authentication logic. According to the official guidelines, the provider only needs to implement several specified interfaces

Interface implementation


Specific implementation of the github plug-in reference source

There are no major changes, but the major change is the need to redefine a structure called gitlabIdentity to deserialize user information from the Gitlab User API

package gitlab import ( "context" "crypto/tls" "encoding/json" "io/ioutil" "net/http" "time" "github.com/mitchellh/mapstructure" "golang.org/x/oauth2" "kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider" "kubesphere.io/kubesphere/pkg/apiserver/authentication/oauth" ) func init() { identityprovider.RegisterOAuthProvider(&gitlabProviderFactory{}) } type gitlab struct { // ClientID is the application's  ID. ClientID string `json:"clientID" yaml:"clientID"` // ClientSecret is the application's secret. ClientSecret string `json:"-" yaml:"clientSecret"` // Endpoint contains the resource server's token endpoint // URLs. These are constants specific to each server and are // often available via site-specific packages, such as // google.Endpoint or gitlab.endpoint. Endpoint endpoint `json:"endpoint" yaml:"endpoint"` // RedirectURL is the  URL to redirect users going through // the OAuth flow, after the resource owner's URLs. RedirectURL string `json:"redirectURL" yaml:"redirectURL"` // Used to turn off TLS certificate checks InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify"` // Scope specifies optional requested permissions. Scopes []string `json:"scopes" yaml:"scopes"` Config *oauth2.Config `json:"-" yaml:"-"` Type Endpoint struct {Log into the directory where the user resides. AuthURL string `json:"authURL" yaml:"authURL"` TokenURL string `json:"tokenURL" yaml:"tokenURL"` UserInfoURL string `json:"userInfoURL" yaml:"userInfoURL"` } type Identity struct { Provider string `json:"provider"` ExternUid string 'json:"extern_uid"'} type gitlabIdentity struct {ID int 'json:" ID "' UserName string `json:"username"` Email string `json:"email"` Name string `json:"name"` State string `json:"state"` AvatarURL string `json:"avatar_url"` WEBURL string `json:"web_url"` CreatedAt time.Time `json:"created_at"` IsAdmin bool `json:"is_admin"` Bio string `json:"bio"` Location string `json:"location"` Skype string `json:"skype"` LINKEDIN string `json:"linkedin"` TWITTER string `json:"twitter"` WebsiteURL string `json:"website_url"` ORGANIZATION string `json:"organization"` LastSignInAt time.Time `json:"last_sign_in_at"` ConfirmedAt time.Time `json:"confirmed_at"` ThemeID int `json:"theme_id"` ColorSchemeID int `json:"color_scheme_id"` ProjectsLimits int `json:"projects_limit"` CurrentSignInAt time.Time `json:"current_sign_in_at"` CanCreateGroup bool `json:"can_create_group"` CanCreateProject bool `json:"can_create_project"` TwoFactorEnabled bool `json:"two_factor_enabled"` External bool `json:"external"` Identities []Identity `json:"identities"` } type gitlabProviderFactory struct { } func (g *gitlabProviderFactory) Type()  string { return "GitLabIdentityProvider" } func (g *gitlabProviderFactory) Create(options oauth.DynamicOptions) (identityprovider.OAuthProvider, error) { var gitlab gitlab if err := mapstructure.Decode(options, &gitlab); err ! = nil { return nil, err } // fixed options options["endpoint"] = oauth.DynamicOptions{ "authURL": gitlab.Endpoint.AuthURL, "tokenURL": gitlab.Endpoint.TokenURL, "userInfoURL": gitlab.Endpoint.UserInfoURL, } gitlab.Config = &oauth2.Config{ ClientID: gitlab.ClientID, ClientSecret: gitlab.ClientSecret, Endpoint: oauth2.Endpoint{ AuthURL: gitlab.Endpoint.AuthURL, TokenURL: gitlab.Endpoint.TokenURL, }, RedirectURL: gitlab.RedirectURL, Scopes: gitlab.Scopes, } return &gitlab, nil } func (g gitlabIdentity) GetUserID() string { return g.UserName } func (g gitlabIdentity) GetUsername() string { Return g.userName} func (g gitlabIdentity) GetEmail() string {return g.mail} // Request oauth2 server, deserialize user information func (g *gitlab) IdentityExchange(code string) (identityprovider.Identity, error) { ctx := context.TODO() if g.InsecureSkipVerify { client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, } ctx = context.WithValue(ctx, oauth2.HTTPClient, client) } token, err := g.Config.Exchange(ctx, code) if err ! = nil { return nil, err } resp, err := oauth2.NewClient(ctx, oauth2.StaticTokenSource(token)).Get(g.Endpoint.UserInfoURL) if err ! = nil { return nil, err } data, err := ioutil.ReadAll(resp.Body) if err ! = nil { return nil, err } defer resp.Body.Close() var gitlabIdentity gitlabIdentity err = json.Unmarshal(data, &gitlabIdentity) if err ! = nil { return nil, err } return gitlabIdentity, nil }Copy the code

After changing the source code, recompile the image and deploy it according to kubesphere’s secondary development document

The configuration file


Accordingly, the configuration file kubesphere-config of Ks-Apiserver also needs to be configured accordingly

kubesphere.yaml: | authentication: authenticateRateLimiterMaxTries: 10 authenticateRateLimiterDuration: 10m0s jwtSecret: "xxxxxxxxxxxxxxxxx" oauthOptions: accessTokenMaxAge: 1h accessTokenInactivityTimeout: 30m identityProviders: - name: gitlab type: GitLabIdentityProvider mappingMethod: auto provider: clientID: 'XXXXXXXXXXXXXXXX' clientSecret: 'XXXXXXXXXXXX' endpoint: # XXX 'http://xxx/oauth/authorize' tokenURL: 'http://xxx/oauth/token' userInfoURL: 'http://xxx/api/v4/user' redirectURL: 'http://xxx/oauth/redirect/gitlab' scopes: - read_userCopy the code