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,18 +1,7 @@
|
||||
/*
|
||||
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 aliyunidaas
|
||||
|
||||
@@ -23,7 +12,6 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider"
|
||||
@@ -31,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
identityprovider.RegisterOAuthProvider(&idaasProviderFactory{})
|
||||
identityprovider.RegisterOAuthProviderFactory(&idaasProviderFactory{})
|
||||
}
|
||||
|
||||
type aliyunIDaaS struct {
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 aliyunidaas
|
||||
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 cas
|
||||
|
||||
@@ -30,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
identityprovider.RegisterOAuthProvider(&casProviderFactory{})
|
||||
identityprovider.RegisterOAuthProviderFactory(&casProviderFactory{})
|
||||
}
|
||||
|
||||
type cas struct {
|
||||
|
||||
120
pkg/apiserver/authentication/identityprovider/configuration.go
Normal file
120
pkg/apiserver/authentication/identityprovider/configuration.go
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package identityprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
)
|
||||
|
||||
const (
|
||||
MappingMethodManual MappingMethod = "manual"
|
||||
|
||||
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"
|
||||
|
||||
ConfigTypeIdentityProvider = "identityprovider"
|
||||
SecretTypeIdentityProvider = "config.kubesphere.io/" + ConfigTypeIdentityProvider
|
||||
|
||||
SecretDataKey = "configuration.yaml"
|
||||
)
|
||||
|
||||
var ErrorIdentityProviderNotFound = errors.New("the Identity provider was not found")
|
||||
|
||||
type MappingMethod string
|
||||
|
||||
type Configuration struct {
|
||||
// The provider name.
|
||||
Name string `json:"name" yaml:"name"`
|
||||
|
||||
// Defines how new identities are mapped to users when they login. Allowed values are:
|
||||
// - manual: The user needs to confirm the mapped username on the onboarding page.
|
||||
// - auto: Skip the onboarding screen, so the user cannot change its username.
|
||||
// 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.
|
||||
MappingMethod MappingMethod `json:"mappingMethod" yaml:"mappingMethod"`
|
||||
|
||||
// The type of identity provider
|
||||
Type string `json:"type" yaml:"type"`
|
||||
|
||||
// The options of identify provider
|
||||
ProviderOptions options.DynamicOptions `json:"provider" yaml:"provider"`
|
||||
}
|
||||
|
||||
type ConfigurationGetter interface {
|
||||
GetConfiguration(ctx context.Context, name string) (*Configuration, error)
|
||||
ListConfigurations(ctx context.Context) ([]*Configuration, error)
|
||||
}
|
||||
|
||||
func NewConfigurationGetter(client client.Client) ConfigurationGetter {
|
||||
return &configurationGetter{client}
|
||||
}
|
||||
|
||||
type configurationGetter struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (o *configurationGetter) ListConfigurations(ctx context.Context) ([]*Configuration, error) {
|
||||
configurations := make([]*Configuration, 0)
|
||||
secrets := &v1.SecretList{}
|
||||
if err := o.List(ctx, secrets, client.InNamespace(constants.KubeSphereNamespace), client.MatchingLabels{constants.GenericConfigTypeLabel: ConfigTypeIdentityProvider}); err != nil {
|
||||
klog.Errorf("failed to list secrets: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
for _, secret := range secrets.Items {
|
||||
if secret.Type != SecretTypeIdentityProvider {
|
||||
continue
|
||||
}
|
||||
if c, err := UnmarshalFrom(&secret); err != nil {
|
||||
klog.Errorf("failed to unmarshal secret data: %s", err)
|
||||
continue
|
||||
} else {
|
||||
configurations = append(configurations, c)
|
||||
}
|
||||
}
|
||||
return configurations, nil
|
||||
}
|
||||
|
||||
func (o *configurationGetter) GetConfiguration(ctx context.Context, name string) (*Configuration, error) {
|
||||
configurations, err := o.ListConfigurations(ctx)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to list identity providers: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range configurations {
|
||||
if c.Name == name {
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrorIdentityProviderNotFound
|
||||
}
|
||||
|
||||
func UnmarshalFrom(secret *v1.Secret) (*Configuration, error) {
|
||||
c := &Configuration{}
|
||||
if err := yaml.Unmarshal(secret.Data[SecretDataKey], c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func IsIdentityProviderConfiguration(secret *v1.Secret) bool {
|
||||
if secret.Namespace != constants.KubeSphereNamespace {
|
||||
return false
|
||||
}
|
||||
return secret.Type == SecretTypeIdentityProvider
|
||||
}
|
||||
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
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 identityprovider
|
||||
|
||||
@@ -30,6 +17,6 @@ type GenericProvider interface {
|
||||
type GenericProviderFactory interface {
|
||||
// Type unique type of the provider
|
||||
Type() string
|
||||
// Apply the dynamic options from kubesphere-config
|
||||
// Create generic identity provider
|
||||
Create(options options.DynamicOptions) (GenericProvider, error)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 github
|
||||
|
||||
@@ -38,7 +27,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
identityprovider.RegisterOAuthProvider(&ldapProviderFactory{})
|
||||
identityprovider.RegisterOAuthProviderFactory(&ldapProviderFactory{})
|
||||
}
|
||||
|
||||
type github struct {
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
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 github
|
||||
|
||||
@@ -29,7 +16,7 @@ import (
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
"golang.org/x/oauth2"
|
||||
@@ -45,7 +32,7 @@ func TestGithub(t *testing.T) {
|
||||
RunSpecs(t, "GitHub Identity Provider Suite")
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func(done Done) {
|
||||
var _ = BeforeSuite(func() {
|
||||
githubServer = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var data map[string]interface{}
|
||||
switch r.RequestURI {
|
||||
@@ -69,8 +56,7 @@ var _ = BeforeSuite(func(done Done) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(data)
|
||||
}))
|
||||
close(done)
|
||||
}, 60)
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
By("tearing down the test environment")
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
package gitlab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider"
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
)
|
||||
|
||||
const (
|
||||
userInfoURL = "https://gitlab.com/api/v4/user"
|
||||
authURL = "https://gitlab.com/oauth/authorize"
|
||||
tokenURL = "https://gitlab.com/oauth/token"
|
||||
)
|
||||
|
||||
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 sso.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:"-"`
|
||||
}
|
||||
|
||||
// endpoint represents an OAuth 2.0 provider's authorization and token
|
||||
// endpoint URLs.
|
||||
type endpoint struct {
|
||||
AuthURL string `json:"authURL" yaml:"authURL"`
|
||||
TokenURL string `json:"tokenURL" yaml:"tokenURL"`
|
||||
UserInfoURL string `json:"userInfoURL" yaml:"userInfoURL"`
|
||||
}
|
||||
|
||||
type gitlabIdentity struct {
|
||||
ID int64 `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"`
|
||||
}
|
||||
|
||||
type gitlabProviderFactory struct {
|
||||
}
|
||||
|
||||
func (g *gitlabProviderFactory) Type() string {
|
||||
return "GitlabIdentityProvider"
|
||||
}
|
||||
|
||||
func (g *gitlabProviderFactory) Create(opts options.DynamicOptions) (identityprovider.OAuthProvider, error) {
|
||||
var gitlab gitlab
|
||||
if err := mapstructure.Decode(opts, &gitlab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if gitlab.Endpoint.AuthURL == "" {
|
||||
gitlab.Endpoint.AuthURL = authURL
|
||||
}
|
||||
if gitlab.Endpoint.TokenURL == "" {
|
||||
gitlab.Endpoint.TokenURL = tokenURL
|
||||
}
|
||||
if gitlab.Endpoint.UserInfoURL == "" {
|
||||
gitlab.Endpoint.UserInfoURL = userInfoURL
|
||||
}
|
||||
// fixed options
|
||||
opts["endpoint"] = options.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 strconv.FormatInt(g.ID, 10)
|
||||
}
|
||||
|
||||
func (g gitlabIdentity) GetUsername() string {
|
||||
return g.Username
|
||||
}
|
||||
|
||||
func (g gitlabIdentity) GetEmail() string {
|
||||
return g.Email
|
||||
}
|
||||
|
||||
func (g *gitlab) IdentityExchangeCallback(req *http.Request) (identityprovider.Identity, error) {
|
||||
// OAuth2 callback, see also https://tools.ietf.org/html/rfc6749#section-4.1.2
|
||||
code := req.URL.Query().Get("code")
|
||||
ctx := req.Context()
|
||||
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 := io.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
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package gitlab
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider"
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
)
|
||||
|
||||
func Test_gitlabProviderFactory_Create(t *testing.T) {
|
||||
type args struct {
|
||||
opts options.DynamicOptions
|
||||
}
|
||||
|
||||
mustUnmarshalYAML := func(data string) options.DynamicOptions {
|
||||
var dynamicOptions options.DynamicOptions
|
||||
_ = yaml.Unmarshal([]byte(data), &dynamicOptions)
|
||||
return dynamicOptions
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want identityprovider.OAuthProvider
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "should create successfully",
|
||||
args: args{opts: mustUnmarshalYAML(`
|
||||
clientID: 035c18fc229c686e4652d7034
|
||||
clientSecret: 75c82b42e54aaf25186140f5
|
||||
endpoint:
|
||||
userInfoUrl: "https://gitlab.com/api/v4/user"
|
||||
authURL: "https://gitlab.com/oauth/authorize"
|
||||
tokenURL: "https://gitlab.com/oauth/token"
|
||||
redirectURL: "https://ks-console.kubesphere-system.svc/oauth/redirect/gitlab"
|
||||
scopes:
|
||||
- read
|
||||
`)},
|
||||
want: &gitlab{
|
||||
ClientID: "035c18fc229c686e4652d7034",
|
||||
ClientSecret: "75c82b42e54aaf25186140f5",
|
||||
Endpoint: endpoint{
|
||||
AuthURL: "https://gitlab.com/oauth/authorize",
|
||||
TokenURL: "https://gitlab.com/oauth/token",
|
||||
UserInfoURL: "https://gitlab.com/api/v4/user",
|
||||
},
|
||||
RedirectURL: "https://ks-console.kubesphere-system.svc/oauth/redirect/gitlab",
|
||||
Scopes: []string{"read"},
|
||||
Config: &oauth2.Config{
|
||||
ClientID: "035c18fc229c686e4652d7034",
|
||||
ClientSecret: "75c82b42e54aaf25186140f5",
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: "https://gitlab.com/oauth/authorize",
|
||||
TokenURL: "https://gitlab.com/oauth/token",
|
||||
AuthStyle: oauth2.AuthStyleAutoDetect,
|
||||
},
|
||||
RedirectURL: "https://ks-console.kubesphere-system.svc/oauth/redirect/gitlab",
|
||||
Scopes: []string{"read"},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := &gitlabProviderFactory{}
|
||||
got, err := g.Create(tt.args.opts)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Create() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Create() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
18
pkg/apiserver/authentication/identityprovider/identity.go
Normal file
18
pkg/apiserver/authentication/identityprovider/identity.go
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package identityprovider
|
||||
|
||||
// Identity represents the account mapped to kubesphere
|
||||
type Identity interface {
|
||||
// GetUserID required
|
||||
// Identifier for the End-User at the Issuer.
|
||||
GetUserID() string
|
||||
// GetUsername optional
|
||||
// The username which the End-User wishes to be referred to kubesphere.
|
||||
GetUsername() string
|
||||
// GetEmail optional
|
||||
GetEmail() string
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
package identityprovider
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/oauth"
|
||||
)
|
||||
|
||||
var (
|
||||
oauthProviderFactories = make(map[string]OAuthProviderFactory)
|
||||
genericProviderFactories = make(map[string]GenericProviderFactory)
|
||||
identityProviderNotFound = errors.New("identity provider not found")
|
||||
oauthProviders = make(map[string]OAuthProvider)
|
||||
genericProviders = make(map[string]GenericProvider)
|
||||
)
|
||||
|
||||
// Identity represents the account mapped to kubesphere
|
||||
type Identity interface {
|
||||
// GetUserID required
|
||||
// Identifier for the End-User at the Issuer.
|
||||
GetUserID() string
|
||||
// GetUsername optional
|
||||
// The username which the End-User wishes to be referred to kubesphere.
|
||||
GetUsername() string
|
||||
// GetEmail optional
|
||||
GetEmail() string
|
||||
}
|
||||
|
||||
// SetupWithOptions will verify the configuration and initialize the identityProviders
|
||||
func SetupWithOptions(options []oauth.IdentityProviderOptions) error {
|
||||
// Clear all providers when reloading configuration
|
||||
oauthProviders = make(map[string]OAuthProvider)
|
||||
genericProviders = make(map[string]GenericProvider)
|
||||
|
||||
for _, o := range options {
|
||||
if oauthProviders[o.Name] != nil || genericProviders[o.Name] != nil {
|
||||
err := fmt.Errorf("duplicate identity provider found: %s, name must be unique", o.Name)
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
if genericProviderFactories[o.Type] == nil && oauthProviderFactories[o.Type] == nil {
|
||||
err := fmt.Errorf("identity provider %s with type %s is not supported", o.Name, o.Type)
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
if factory, ok := oauthProviderFactories[o.Type]; ok {
|
||||
if provider, err := factory.Create(o.Provider); err != nil {
|
||||
// don’t return errors, decoupling external dependencies
|
||||
klog.Error(fmt.Sprintf("failed to create identity provider %s: %s", o.Name, err))
|
||||
} else {
|
||||
oauthProviders[o.Name] = provider
|
||||
klog.V(4).Infof("create identity provider %s successfully", o.Name)
|
||||
}
|
||||
}
|
||||
if factory, ok := genericProviderFactories[o.Type]; ok {
|
||||
if provider, err := factory.Create(o.Provider); err != nil {
|
||||
klog.Error(fmt.Sprintf("failed to create identity provider %s: %s", o.Name, err))
|
||||
} else {
|
||||
genericProviders[o.Name] = provider
|
||||
klog.V(4).Infof("create identity provider %s successfully", o.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGenericProvider returns GenericProvider with given name
|
||||
func GetGenericProvider(providerName string) (GenericProvider, error) {
|
||||
if provider, ok := genericProviders[providerName]; ok {
|
||||
return provider, nil
|
||||
}
|
||||
return nil, identityProviderNotFound
|
||||
}
|
||||
|
||||
// GetOAuthProvider returns OAuthProvider with given name
|
||||
func GetOAuthProvider(providerName string) (OAuthProvider, error) {
|
||||
if provider, ok := oauthProviders[providerName]; ok {
|
||||
return provider, nil
|
||||
}
|
||||
return nil, identityProviderNotFound
|
||||
}
|
||||
|
||||
// RegisterOAuthProvider register OAuthProviderFactory with the specified type
|
||||
func RegisterOAuthProvider(factory OAuthProviderFactory) {
|
||||
oauthProviderFactories[factory.Type()] = factory
|
||||
}
|
||||
|
||||
// RegisterGenericProvider registers GenericProviderFactory with the specified type
|
||||
func RegisterGenericProvider(factory GenericProviderFactory) {
|
||||
genericProviderFactories[factory.Type()] = factory
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package identityprovider
|
||||
|
||||
var (
|
||||
oauthProviderFactories = make(map[string]OAuthProviderFactory)
|
||||
genericProviderFactories = make(map[string]GenericProviderFactory)
|
||||
)
|
||||
|
||||
// RegisterOAuthProviderFactory register OAuthProviderFactory with the specified type
|
||||
func RegisterOAuthProviderFactory(factory OAuthProviderFactory) {
|
||||
oauthProviderFactories[factory.Type()] = factory
|
||||
}
|
||||
|
||||
// RegisterGenericProviderFactory registers GenericProviderFactory with the specified type
|
||||
func RegisterGenericProviderFactory(factory GenericProviderFactory) {
|
||||
genericProviderFactories[factory.Type()] = factory
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
package identityprovider
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/oauth"
|
||||
)
|
||||
|
||||
type emptyOAuthProviderFactory struct {
|
||||
typeName string
|
||||
}
|
||||
|
||||
func (e emptyOAuthProviderFactory) Type() string {
|
||||
return e.typeName
|
||||
}
|
||||
|
||||
type emptyOAuthProvider struct {
|
||||
}
|
||||
|
||||
type emptyIdentity struct {
|
||||
}
|
||||
|
||||
func (e emptyIdentity) GetUserID() string {
|
||||
return "test"
|
||||
}
|
||||
|
||||
func (e emptyIdentity) GetUsername() string {
|
||||
return "test"
|
||||
}
|
||||
|
||||
func (e emptyIdentity) GetEmail() string {
|
||||
return "test@test.com"
|
||||
}
|
||||
|
||||
func (e emptyOAuthProvider) IdentityExchangeCallback(req *http.Request) (Identity, error) {
|
||||
return emptyIdentity{}, nil
|
||||
}
|
||||
|
||||
func (e emptyOAuthProviderFactory) Create(options options.DynamicOptions) (OAuthProvider, error) {
|
||||
return emptyOAuthProvider{}, nil
|
||||
}
|
||||
|
||||
type emptyGenericProviderFactory struct {
|
||||
typeName string
|
||||
}
|
||||
|
||||
func (e emptyGenericProviderFactory) Type() string {
|
||||
return e.typeName
|
||||
}
|
||||
|
||||
type emptyGenericProvider struct {
|
||||
}
|
||||
|
||||
func (e emptyGenericProvider) Authenticate(username string, password string) (Identity, error) {
|
||||
return emptyIdentity{}, nil
|
||||
}
|
||||
|
||||
func (e emptyGenericProviderFactory) Create(options options.DynamicOptions) (GenericProvider, error) {
|
||||
return emptyGenericProvider{}, nil
|
||||
}
|
||||
|
||||
func TestSetupWith(t *testing.T) {
|
||||
RegisterOAuthProvider(emptyOAuthProviderFactory{typeName: "GitHubIdentityProvider"})
|
||||
RegisterOAuthProvider(emptyOAuthProviderFactory{typeName: "OIDCIdentityProvider"})
|
||||
RegisterGenericProvider(emptyGenericProviderFactory{typeName: "LDAPIdentityProvider"})
|
||||
type args struct {
|
||||
options []oauth.IdentityProviderOptions
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "ldap",
|
||||
args: args{options: []oauth.IdentityProviderOptions{
|
||||
{
|
||||
Name: "ldap",
|
||||
MappingMethod: "auto",
|
||||
Type: "LDAPIdentityProvider",
|
||||
Provider: options.DynamicOptions{},
|
||||
},
|
||||
}},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "conflict",
|
||||
args: args{options: []oauth.IdentityProviderOptions{
|
||||
{
|
||||
Name: "ldap",
|
||||
MappingMethod: "auto",
|
||||
Type: "LDAPIdentityProvider",
|
||||
Provider: options.DynamicOptions{},
|
||||
},
|
||||
{
|
||||
Name: "ldap",
|
||||
MappingMethod: "auto",
|
||||
Type: "LDAPIdentityProvider",
|
||||
Provider: options.DynamicOptions{},
|
||||
},
|
||||
}},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "not supported",
|
||||
args: args{options: []oauth.IdentityProviderOptions{
|
||||
{
|
||||
Name: "test",
|
||||
MappingMethod: "auto",
|
||||
Type: "NotSupported",
|
||||
Provider: options.DynamicOptions{},
|
||||
},
|
||||
}},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := SetupWithOptions(tt.args.options); (err != nil) != tt.wantErr {
|
||||
t.Errorf("SetupWithOptions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package identityprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
toolscache "k8s.io/client-go/tools/cache"
|
||||
"k8s.io/klog/v2"
|
||||
runtimecache "sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
)
|
||||
|
||||
var SharedIdentityProviderController = NewController()
|
||||
|
||||
type Controller struct {
|
||||
identityProviders *sync.Map
|
||||
identityProviderConfigs *sync.Map
|
||||
}
|
||||
|
||||
func NewController() *Controller {
|
||||
return &Controller{identityProviders: &sync.Map{}, identityProviderConfigs: &sync.Map{}}
|
||||
}
|
||||
|
||||
func (c *Controller) WatchConfigurationChanges(ctx context.Context, cache runtimecache.Cache) error {
|
||||
informer, err := cache.GetInformer(ctx, &v1.Secret{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("get informer failed: %w", err)
|
||||
}
|
||||
|
||||
_, err = informer.AddEventHandler(toolscache.FilteringResourceEventHandler{
|
||||
FilterFunc: func(obj interface{}) bool {
|
||||
return IsIdentityProviderConfiguration(obj.(*v1.Secret))
|
||||
},
|
||||
Handler: &toolscache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
c.OnConfigurationChange(obj.(*v1.Secret))
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
c.OnConfigurationChange(new.(*v1.Secret))
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
c.OnConfigurationDelete(obj.(*v1.Secret))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("add event handler failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) OnConfigurationDelete(secret *v1.Secret) {
|
||||
configuration, err := UnmarshalFrom(secret)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to unmarshal secret data: %s", err)
|
||||
return
|
||||
}
|
||||
c.identityProviders.Delete(configuration.Name)
|
||||
c.identityProviderConfigs.Delete(configuration.Name)
|
||||
}
|
||||
|
||||
func (c *Controller) OnConfigurationChange(secret *v1.Secret) {
|
||||
configuration, err := UnmarshalFrom(secret)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to unmarshal secret data: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if genericProviderFactories[configuration.Type] == nil && oauthProviderFactories[configuration.Type] == nil {
|
||||
klog.Errorf("identity provider %s with type %s is not supported", configuration.Name, configuration.Type)
|
||||
return
|
||||
}
|
||||
|
||||
if factory, ok := oauthProviderFactories[configuration.Type]; ok {
|
||||
if provider, err := factory.Create(configuration.ProviderOptions); err != nil {
|
||||
// don’t return errors, decoupling external dependencies
|
||||
klog.Error(fmt.Sprintf("failed to create identity provider %s: %s", configuration.Name, err))
|
||||
} else {
|
||||
c.identityProviders.Store(configuration.Name, provider)
|
||||
c.identityProviderConfigs.Store(configuration.Name, configuration)
|
||||
klog.Infof("create identity provider %s successfully", configuration.Name)
|
||||
}
|
||||
}
|
||||
if factory, ok := genericProviderFactories[configuration.Type]; ok {
|
||||
if provider, err := factory.Create(configuration.ProviderOptions); err != nil {
|
||||
klog.Error(fmt.Sprintf("failed to create identity provider %s: %s", configuration.Name, err))
|
||||
} else {
|
||||
c.identityProviders.Store(configuration.Name, provider)
|
||||
c.identityProviderConfigs.Store(configuration.Name, configuration)
|
||||
klog.V(4).Infof("create identity provider %s successfully", configuration.Name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Controller) GetGenericProvider(providerName string) (GenericProvider, bool) {
|
||||
if obj, ok := c.identityProviders.Load(providerName); ok {
|
||||
if provider, ok := obj.(GenericProvider); ok {
|
||||
return provider, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (c *Controller) GetOAuthProvider(providerName string) (OAuthProvider, bool) {
|
||||
if obj, ok := c.identityProviders.Load(providerName); ok {
|
||||
if provider, ok := obj.(OAuthProvider); ok {
|
||||
return provider, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (c *Controller) ListConfigurations() []*Configuration {
|
||||
configurations := make([]*Configuration, 0)
|
||||
c.identityProviderConfigs.Range(func(key, value any) bool {
|
||||
if configuration, ok := value.(*Configuration); ok {
|
||||
configurations = append(configurations, configuration)
|
||||
}
|
||||
return true
|
||||
})
|
||||
return configurations
|
||||
}
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 ldap
|
||||
|
||||
@@ -39,7 +28,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
identityprovider.RegisterGenericProvider(&ldapProviderFactory{})
|
||||
identityprovider.RegisterGenericProviderFactory(&ldapProviderFactory{})
|
||||
}
|
||||
|
||||
type ldapProvider struct {
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 ldap
|
||||
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 identityprovider
|
||||
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
/*
|
||||
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 oidc
|
||||
|
||||
@@ -36,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
identityprovider.RegisterOAuthProvider(&oidcProviderFactory{})
|
||||
identityprovider.RegisterOAuthProviderFactory(&oidcProviderFactory{})
|
||||
}
|
||||
|
||||
type oidcProvider struct {
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
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 oidc
|
||||
|
||||
@@ -36,7 +23,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/server/options"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
@@ -53,7 +40,7 @@ func TestOIDC(t *testing.T) {
|
||||
RunSpecs(t, "OIDC Identity Provider Suite")
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func(done Done) {
|
||||
var _ = BeforeSuite(func() {
|
||||
privateKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
|
||||
Expect(err).Should(BeNil())
|
||||
jwk := jose.JSONWebKey{
|
||||
@@ -152,8 +139,7 @@ var _ = BeforeSuite(func(done Done) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(data)
|
||||
}))
|
||||
close(done)
|
||||
}, 60)
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
By("tearing down the test environment")
|
||||
|
||||
Reference in New Issue
Block a user