mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 12:15:20 +01:00
"Skip verify cert" to "verify cert"
This commit tweaks the attribute for auth proxy mode and OIDC auth mode. To change it from "Skip verify cert" to "verify cert" so they are more consistent with other modes. Additionally it removes a workaround in `SearchUser` in auth proxy authenticator. Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
parent
72a42451b2
commit
f92bc8076d
@ -133,7 +133,7 @@ var (
|
|||||||
|
|
||||||
{Name: common.HTTPAuthProxyEndpoint, Scope: UserScope, Group: HTTPAuthGroup, ItemType: &StringType{}},
|
{Name: common.HTTPAuthProxyEndpoint, Scope: UserScope, Group: HTTPAuthGroup, ItemType: &StringType{}},
|
||||||
{Name: common.HTTPAuthProxyTokenReviewEndpoint, Scope: UserScope, Group: HTTPAuthGroup, ItemType: &StringType{}},
|
{Name: common.HTTPAuthProxyTokenReviewEndpoint, Scope: UserScope, Group: HTTPAuthGroup, ItemType: &StringType{}},
|
||||||
{Name: common.HTTPAuthProxySkipCertVerify, Scope: UserScope, Group: HTTPAuthGroup, DefaultValue: "false", ItemType: &BoolType{}},
|
{Name: common.HTTPAuthProxyVerifyCert, Scope: UserScope, Group: HTTPAuthGroup, DefaultValue: "true", ItemType: &BoolType{}},
|
||||||
{Name: common.HTTPAuthProxyAlwaysOnboard, Scope: UserScope, Group: HTTPAuthGroup, DefaultValue: "false", ItemType: &BoolType{}},
|
{Name: common.HTTPAuthProxyAlwaysOnboard, Scope: UserScope, Group: HTTPAuthGroup, DefaultValue: "false", ItemType: &BoolType{}},
|
||||||
|
|
||||||
{Name: common.OIDCName, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
|
{Name: common.OIDCName, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
|
||||||
@ -141,7 +141,7 @@ var (
|
|||||||
{Name: common.OIDCCLientID, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
|
{Name: common.OIDCCLientID, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
|
||||||
{Name: common.OIDCClientSecret, Scope: UserScope, Group: OIDCGroup, ItemType: &PasswordType{}},
|
{Name: common.OIDCClientSecret, Scope: UserScope, Group: OIDCGroup, ItemType: &PasswordType{}},
|
||||||
{Name: common.OIDCScope, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
|
{Name: common.OIDCScope, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
|
||||||
{Name: common.OIDCSkipCertVerify, Scope: UserScope, Group: OIDCGroup, DefaultValue: "false", ItemType: &BoolType{}},
|
{Name: common.OIDCVerifyCert, Scope: UserScope, Group: OIDCGroup, DefaultValue: "true", ItemType: &BoolType{}},
|
||||||
|
|
||||||
{Name: "with_chartmuseum", Scope: SystemScope, Group: BasicGroup, EnvKey: "WITH_CHARTMUSEUM", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},
|
{Name: "with_chartmuseum", Scope: SystemScope, Group: BasicGroup, EnvKey: "WITH_CHARTMUSEUM", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},
|
||||||
{Name: "with_clair", Scope: SystemScope, Group: BasicGroup, EnvKey: "WITH_CLAIR", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},
|
{Name: "with_clair", Scope: SystemScope, Group: BasicGroup, EnvKey: "WITH_CLAIR", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},
|
||||||
|
@ -98,13 +98,13 @@ const (
|
|||||||
UAAVerifyCert = "uaa_verify_cert"
|
UAAVerifyCert = "uaa_verify_cert"
|
||||||
HTTPAuthProxyEndpoint = "http_authproxy_endpoint"
|
HTTPAuthProxyEndpoint = "http_authproxy_endpoint"
|
||||||
HTTPAuthProxyTokenReviewEndpoint = "http_authproxy_tokenreview_endpoint"
|
HTTPAuthProxyTokenReviewEndpoint = "http_authproxy_tokenreview_endpoint"
|
||||||
HTTPAuthProxySkipCertVerify = "http_authproxy_skip_cert_verify"
|
HTTPAuthProxyVerifyCert = "http_authproxy_verify_cert"
|
||||||
HTTPAuthProxyAlwaysOnboard = "http_authproxy_always_onboard"
|
HTTPAuthProxyAlwaysOnboard = "http_authproxy_always_onboard"
|
||||||
OIDCName = "oidc_name"
|
OIDCName = "oidc_name"
|
||||||
OIDCEndpoint = "oidc_endpoint"
|
OIDCEndpoint = "oidc_endpoint"
|
||||||
OIDCCLientID = "oidc_client_id"
|
OIDCCLientID = "oidc_client_id"
|
||||||
OIDCClientSecret = "oidc_client_secret"
|
OIDCClientSecret = "oidc_client_secret"
|
||||||
OIDCSkipCertVerify = "oidc_skip_cert_verify"
|
OIDCVerifyCert = "oidc_verify_cert"
|
||||||
OIDCScope = "oidc_scope"
|
OIDCScope = "oidc_scope"
|
||||||
|
|
||||||
DefaultClairEndpoint = "http://clair:6060"
|
DefaultClairEndpoint = "http://clair:6060"
|
||||||
|
@ -69,19 +69,19 @@ type Email struct {
|
|||||||
type HTTPAuthProxy struct {
|
type HTTPAuthProxy struct {
|
||||||
Endpoint string `json:"endpoint"`
|
Endpoint string `json:"endpoint"`
|
||||||
TokenReviewEndpoint string `json:"tokenreivew_endpoint"`
|
TokenReviewEndpoint string `json:"tokenreivew_endpoint"`
|
||||||
SkipCertVerify bool `json:"skip_cert_verify"`
|
VerifyCert bool `json:"verify_cert"`
|
||||||
AlwaysOnBoard bool `json:"always_onboard"`
|
AlwaysOnBoard bool `json:"always_onboard"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCSetting wraps the settings for OIDC auth endpoint
|
// OIDCSetting wraps the settings for OIDC auth endpoint
|
||||||
type OIDCSetting struct {
|
type OIDCSetting struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Endpoint string `json:"endpoint"`
|
Endpoint string `json:"endpoint"`
|
||||||
SkipCertVerify bool `json:"skip_cert_verify"`
|
VerifyCert bool `json:"verify_cert"`
|
||||||
ClientID string `json:"client_id"`
|
ClientID string `json:"client_id"`
|
||||||
ClientSecret string `json:"client_secret"`
|
ClientSecret string `json:"client_secret"`
|
||||||
RedirectURL string `json:"redirect_url"`
|
RedirectURL string `json:"redirect_url"`
|
||||||
Scope []string `json:"scope"`
|
Scope []string `json:"scope"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigEntry ...
|
// ConfigEntry ...
|
||||||
|
@ -41,14 +41,14 @@ type providerHelper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type endpoint struct {
|
type endpoint struct {
|
||||||
url string
|
url string
|
||||||
skipCertVerify bool
|
VerifyCert bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *providerHelper) get() (*gooidc.Provider, error) {
|
func (p *providerHelper) get() (*gooidc.Provider, error) {
|
||||||
if p.instance.Load() != nil {
|
if p.instance.Load() != nil {
|
||||||
s := p.setting.Load().(models.OIDCSetting)
|
s := p.setting.Load().(models.OIDCSetting)
|
||||||
if s.Endpoint != p.ep.url || s.SkipCertVerify != p.ep.skipCertVerify { // relevant settings have changed, need to re-create provider.
|
if s.Endpoint != p.ep.url || s.VerifyCert != p.ep.VerifyCert { // relevant settings have changed, need to re-create provider.
|
||||||
if err := p.create(); err != nil {
|
if err := p.create(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -90,15 +90,15 @@ func (p *providerHelper) create() error {
|
|||||||
return errors.New("the configuration is not loaded")
|
return errors.New("the configuration is not loaded")
|
||||||
}
|
}
|
||||||
s := p.setting.Load().(models.OIDCSetting)
|
s := p.setting.Load().(models.OIDCSetting)
|
||||||
ctx := clientCtx(context.Background(), s.SkipCertVerify)
|
ctx := clientCtx(context.Background(), s.VerifyCert)
|
||||||
provider, err := gooidc.NewProvider(ctx, s.Endpoint)
|
provider, err := gooidc.NewProvider(ctx, s.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create OIDC provider, error: %v", err)
|
return fmt.Errorf("failed to create OIDC provider, error: %v", err)
|
||||||
}
|
}
|
||||||
p.instance.Store(provider)
|
p.instance.Store(provider)
|
||||||
p.ep = endpoint{
|
p.ep = endpoint{
|
||||||
url: s.Endpoint,
|
url: s.Endpoint,
|
||||||
skipCertVerify: s.SkipCertVerify,
|
VerifyCert: s.VerifyCert,
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ func ExchangeToken(ctx context.Context, code string) (*Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
setting := provider.setting.Load().(models.OIDCSetting)
|
setting := provider.setting.Load().(models.OIDCSetting)
|
||||||
ctx = clientCtx(ctx, setting.SkipCertVerify)
|
ctx = clientCtx(ctx, setting.VerifyCert)
|
||||||
oauthToken, err := oauth.Exchange(ctx, code)
|
oauthToken, err := oauth.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -178,13 +178,13 @@ func VerifyToken(ctx context.Context, rawIDToken string) (*gooidc.IDToken, error
|
|||||||
}
|
}
|
||||||
verifier := p.Verifier(&gooidc.Config{ClientID: provider.setting.Load().(models.OIDCSetting).ClientID})
|
verifier := p.Verifier(&gooidc.Config{ClientID: provider.setting.Load().(models.OIDCSetting).ClientID})
|
||||||
setting := provider.setting.Load().(models.OIDCSetting)
|
setting := provider.setting.Load().(models.OIDCSetting)
|
||||||
ctx = clientCtx(ctx, setting.SkipCertVerify)
|
ctx = clientCtx(ctx, setting.VerifyCert)
|
||||||
return verifier.Verify(ctx, rawIDToken)
|
return verifier.Verify(ctx, rawIDToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func clientCtx(ctx context.Context, skipCertVerify bool) context.Context {
|
func clientCtx(ctx context.Context, verifyCert bool) context.Context {
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
if skipCertVerify {
|
if !verifyCert {
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Transport: insecureTransport,
|
Transport: insecureTransport,
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ func RefreshToken(ctx context.Context, token *Token) (*Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
setting := provider.setting.Load().(models.OIDCSetting)
|
setting := provider.setting.Load().(models.OIDCSetting)
|
||||||
ctx = clientCtx(ctx, setting.SkipCertVerify)
|
ctx = clientCtx(ctx, setting.VerifyCert)
|
||||||
ts := oauth.TokenSource(ctx, token.Token)
|
ts := oauth.TokenSource(ctx, token.Token)
|
||||||
t, err := ts.Token()
|
t, err := ts.Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -29,13 +29,13 @@ import (
|
|||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
conf := map[string]interface{}{
|
conf := map[string]interface{}{
|
||||||
common.OIDCName: "test",
|
common.OIDCName: "test",
|
||||||
common.OIDCEndpoint: "https://accounts.google.com",
|
common.OIDCEndpoint: "https://accounts.google.com",
|
||||||
common.OIDCSkipCertVerify: "false",
|
common.OIDCVerifyCert: "true",
|
||||||
common.OIDCScope: "openid, profile, offline_access",
|
common.OIDCScope: "openid, profile, offline_access",
|
||||||
common.OIDCCLientID: "client",
|
common.OIDCCLientID: "client",
|
||||||
common.OIDCClientSecret: "secret",
|
common.OIDCClientSecret: "secret",
|
||||||
common.ExtEndpoint: "https://harbor.test",
|
common.ExtEndpoint: "https://harbor.test",
|
||||||
}
|
}
|
||||||
kp := &config2.PresetKeyProvider{Key: "naa4JtarA1Zsc3uY"}
|
kp := &config2.PresetKeyProvider{Key: "naa4JtarA1Zsc3uY"}
|
||||||
|
|
||||||
@ -73,13 +73,13 @@ func TestHelperGet(t *testing.T) {
|
|||||||
assert.Equal(t, "https://oauth2.googleapis.com/token", p.Endpoint().TokenURL)
|
assert.Equal(t, "https://oauth2.googleapis.com/token", p.Endpoint().TokenURL)
|
||||||
|
|
||||||
update := map[string]interface{}{
|
update := map[string]interface{}{
|
||||||
common.OIDCName: "test",
|
common.OIDCName: "test",
|
||||||
common.OIDCEndpoint: "https://accounts.google.com",
|
common.OIDCEndpoint: "https://accounts.google.com",
|
||||||
common.OIDCSkipCertVerify: "false",
|
common.OIDCVerifyCert: "true",
|
||||||
common.OIDCScope: "openid, profile, offline_access",
|
common.OIDCScope: "openid, profile, offline_access",
|
||||||
common.OIDCCLientID: "client",
|
common.OIDCCLientID: "client",
|
||||||
common.OIDCClientSecret: "new-secret",
|
common.OIDCClientSecret: "new-secret",
|
||||||
common.ExtEndpoint: "https://harbor.test",
|
common.ExtEndpoint: "https://harbor.test",
|
||||||
}
|
}
|
||||||
config.GetCfgManager().UpdateConfig(update)
|
config.GetCfgManager().UpdateConfig(update)
|
||||||
|
|
||||||
|
@ -94,18 +94,11 @@ func (a *Auth) PostAuthenticate(u *models.User) error {
|
|||||||
return a.OnBoardUser(u)
|
return a.OnBoardUser(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchUser - TODO: Remove this workaround when #6767 is fixed.
|
// SearchUser returns nil as authproxy does not have such capability.
|
||||||
// When the flag is set it always return the default model without searching
|
// When AlwaysOnboard is set it always return the default model.
|
||||||
func (a *Auth) SearchUser(username string) (*models.User, error) {
|
func (a *Auth) SearchUser(username string) (*models.User, error) {
|
||||||
a.ensure()
|
var u *models.User
|
||||||
var queryCondition = models.User{
|
if a.AlwaysOnboard {
|
||||||
Username: username,
|
|
||||||
}
|
|
||||||
u, err := dao.GetUser(queryCondition)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if a.AlwaysOnboard && u == nil {
|
|
||||||
u = &models.User{Username: username}
|
u = &models.User{Username: username}
|
||||||
if err := a.fillInModel(u); err != nil {
|
if err := a.fillInModel(u); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -138,7 +131,7 @@ func (a *Auth) ensure() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.Endpoint = setting.Endpoint
|
a.Endpoint = setting.Endpoint
|
||||||
a.SkipCertVerify = setting.SkipCertVerify
|
a.SkipCertVerify = !setting.VerifyCert
|
||||||
a.AlwaysOnboard = setting.AlwaysOnBoard
|
a.AlwaysOnboard = setting.AlwaysOnBoard
|
||||||
}
|
}
|
||||||
if a.client == nil {
|
if a.client == nil {
|
||||||
|
@ -476,7 +476,7 @@ func HTTPAuthProxySetting() (*models.HTTPAuthProxy, error) {
|
|||||||
return &models.HTTPAuthProxy{
|
return &models.HTTPAuthProxy{
|
||||||
Endpoint: cfgMgr.Get(common.HTTPAuthProxyEndpoint).GetString(),
|
Endpoint: cfgMgr.Get(common.HTTPAuthProxyEndpoint).GetString(),
|
||||||
TokenReviewEndpoint: cfgMgr.Get(common.HTTPAuthProxyTokenReviewEndpoint).GetString(),
|
TokenReviewEndpoint: cfgMgr.Get(common.HTTPAuthProxyTokenReviewEndpoint).GetString(),
|
||||||
SkipCertVerify: cfgMgr.Get(common.HTTPAuthProxySkipCertVerify).GetBool(),
|
VerifyCert: cfgMgr.Get(common.HTTPAuthProxyVerifyCert).GetBool(),
|
||||||
AlwaysOnBoard: cfgMgr.Get(common.HTTPAuthProxyAlwaysOnboard).GetBool(),
|
AlwaysOnBoard: cfgMgr.Get(common.HTTPAuthProxyAlwaysOnboard).GetBool(),
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -496,12 +496,12 @@ func OIDCSetting() (*models.OIDCSetting, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &models.OIDCSetting{
|
return &models.OIDCSetting{
|
||||||
Name: cfgMgr.Get(common.OIDCName).GetString(),
|
Name: cfgMgr.Get(common.OIDCName).GetString(),
|
||||||
Endpoint: cfgMgr.Get(common.OIDCEndpoint).GetString(),
|
Endpoint: cfgMgr.Get(common.OIDCEndpoint).GetString(),
|
||||||
SkipCertVerify: cfgMgr.Get(common.OIDCSkipCertVerify).GetBool(),
|
VerifyCert: cfgMgr.Get(common.OIDCVerifyCert).GetBool(),
|
||||||
ClientID: cfgMgr.Get(common.OIDCCLientID).GetString(),
|
ClientID: cfgMgr.Get(common.OIDCCLientID).GetString(),
|
||||||
ClientSecret: cfgMgr.Get(common.OIDCClientSecret).GetString(),
|
ClientSecret: cfgMgr.Get(common.OIDCClientSecret).GetString(),
|
||||||
RedirectURL: extEndpoint + common.OIDCCallbackPath,
|
RedirectURL: extEndpoint + common.OIDCCallbackPath,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -228,36 +228,36 @@ func TestConfigureValue_GetMap(t *testing.T) {
|
|||||||
|
|
||||||
func TestHTTPAuthProxySetting(t *testing.T) {
|
func TestHTTPAuthProxySetting(t *testing.T) {
|
||||||
m := map[string]interface{}{
|
m := map[string]interface{}{
|
||||||
common.HTTPAuthProxyAlwaysOnboard: "true",
|
common.HTTPAuthProxyAlwaysOnboard: "true",
|
||||||
common.HTTPAuthProxySkipCertVerify: "true",
|
common.HTTPAuthProxyVerifyCert: "true",
|
||||||
common.HTTPAuthProxyEndpoint: "https://auth.proxy/suffix",
|
common.HTTPAuthProxyEndpoint: "https://auth.proxy/suffix",
|
||||||
}
|
}
|
||||||
InitWithSettings(m)
|
InitWithSettings(m)
|
||||||
v, e := HTTPAuthProxySetting()
|
v, e := HTTPAuthProxySetting()
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, *v, models.HTTPAuthProxy{
|
assert.Equal(t, *v, models.HTTPAuthProxy{
|
||||||
Endpoint: "https://auth.proxy/suffix",
|
Endpoint: "https://auth.proxy/suffix",
|
||||||
AlwaysOnBoard: true,
|
AlwaysOnBoard: true,
|
||||||
SkipCertVerify: true,
|
VerifyCert: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOIDCSetting(t *testing.T) {
|
func TestOIDCSetting(t *testing.T) {
|
||||||
m := map[string]interface{}{
|
m := map[string]interface{}{
|
||||||
common.OIDCName: "test",
|
common.OIDCName: "test",
|
||||||
common.OIDCEndpoint: "https://oidc.test",
|
common.OIDCEndpoint: "https://oidc.test",
|
||||||
common.OIDCSkipCertVerify: "true",
|
common.OIDCVerifyCert: "true",
|
||||||
common.OIDCScope: "openid, profile",
|
common.OIDCScope: "openid, profile",
|
||||||
common.OIDCCLientID: "client",
|
common.OIDCCLientID: "client",
|
||||||
common.OIDCClientSecret: "secret",
|
common.OIDCClientSecret: "secret",
|
||||||
common.ExtEndpoint: "https://harbor.test",
|
common.ExtEndpoint: "https://harbor.test",
|
||||||
}
|
}
|
||||||
InitWithSettings(m)
|
InitWithSettings(m)
|
||||||
v, e := OIDCSetting()
|
v, e := OIDCSetting()
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, "test", v.Name)
|
assert.Equal(t, "test", v.Name)
|
||||||
assert.Equal(t, "https://oidc.test", v.Endpoint)
|
assert.Equal(t, "https://oidc.test", v.Endpoint)
|
||||||
assert.True(t, v.SkipCertVerify)
|
assert.True(t, v.VerifyCert)
|
||||||
assert.Equal(t, "client", v.ClientID)
|
assert.Equal(t, "client", v.ClientID)
|
||||||
assert.Equal(t, "secret", v.ClientSecret)
|
assert.Equal(t, "secret", v.ClientSecret)
|
||||||
assert.Equal(t, "https://harbor.test/c/oidc/callback", v.RedirectURL)
|
assert.Equal(t, "https://harbor.test/c/oidc/callback", v.RedirectURL)
|
||||||
|
@ -292,7 +292,7 @@ func (ap *authProxyReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
|||||||
},
|
},
|
||||||
BearerToken: proxyPwd,
|
BearerToken: proxyPwd,
|
||||||
TLSClientConfig: rest.TLSClientConfig{
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
Insecure: httpAuthProxyConf.SkipCertVerify,
|
Insecure: !httpAuthProxyConf.VerifyCert,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
authClient, err := rest.RESTClientFor(authClientCfg)
|
authClient, err := rest.RESTClientFor(authClientCfg)
|
||||||
|
@ -123,14 +123,14 @@ func TestSecretReqCtxModifier(t *testing.T) {
|
|||||||
|
|
||||||
func TestOIDCCliReqCtxModifier(t *testing.T) {
|
func TestOIDCCliReqCtxModifier(t *testing.T) {
|
||||||
conf := map[string]interface{}{
|
conf := map[string]interface{}{
|
||||||
common.AUTHMode: common.OIDCAuth,
|
common.AUTHMode: common.OIDCAuth,
|
||||||
common.OIDCName: "test",
|
common.OIDCName: "test",
|
||||||
common.OIDCEndpoint: "https://accounts.google.com",
|
common.OIDCEndpoint: "https://accounts.google.com",
|
||||||
common.OIDCSkipCertVerify: "false",
|
common.OIDCVerifyCert: "true",
|
||||||
common.OIDCScope: "openid, profile, offline_access",
|
common.OIDCScope: "openid, profile, offline_access",
|
||||||
common.OIDCCLientID: "client",
|
common.OIDCCLientID: "client",
|
||||||
common.OIDCClientSecret: "secret",
|
common.OIDCClientSecret: "secret",
|
||||||
common.ExtEndpoint: "https://harbor.test",
|
common.ExtEndpoint: "https://harbor.test",
|
||||||
}
|
}
|
||||||
|
|
||||||
kp := &config2.PresetKeyProvider{Key: "naa4JtarA1Zsc3uY"}
|
kp := &config2.PresetKeyProvider{Key: "naa4JtarA1Zsc3uY"}
|
||||||
@ -193,7 +193,7 @@ func TestAuthProxyReqCtxModifier(t *testing.T) {
|
|||||||
|
|
||||||
c := map[string]interface{}{
|
c := map[string]interface{}{
|
||||||
common.HTTPAuthProxyAlwaysOnboard: "true",
|
common.HTTPAuthProxyAlwaysOnboard: "true",
|
||||||
common.HTTPAuthProxySkipCertVerify: "true",
|
common.HTTPAuthProxyVerifyCert: "false",
|
||||||
common.HTTPAuthProxyEndpoint: "https://auth.proxy/suffix",
|
common.HTTPAuthProxyEndpoint: "https://auth.proxy/suffix",
|
||||||
common.HTTPAuthProxyTokenReviewEndpoint: server.URL,
|
common.HTTPAuthProxyTokenReviewEndpoint: server.URL,
|
||||||
common.AUTHMode: common.HTTPAuth,
|
common.AUTHMode: common.HTTPAuth,
|
||||||
@ -205,7 +205,7 @@ func TestAuthProxyReqCtxModifier(t *testing.T) {
|
|||||||
assert.Equal(t, *v, models.HTTPAuthProxy{
|
assert.Equal(t, *v, models.HTTPAuthProxy{
|
||||||
Endpoint: "https://auth.proxy/suffix",
|
Endpoint: "https://auth.proxy/suffix",
|
||||||
AlwaysOnBoard: true,
|
AlwaysOnBoard: true,
|
||||||
SkipCertVerify: true,
|
VerifyCert: false,
|
||||||
TokenReviewEndpoint: server.URL,
|
TokenReviewEndpoint: server.URL,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -90,13 +90,13 @@ export class Configuration {
|
|||||||
read_only: BoolValueItem;
|
read_only: BoolValueItem;
|
||||||
http_authproxy_endpoint?: StringValueItem;
|
http_authproxy_endpoint?: StringValueItem;
|
||||||
http_authproxy_tokenreview_endpoint?: StringValueItem;
|
http_authproxy_tokenreview_endpoint?: StringValueItem;
|
||||||
http_authproxy_skip_cert_verify?: BoolValueItem;
|
http_authproxy_verify_cert?: BoolValueItem;
|
||||||
http_authproxy_always_onboard?: BoolValueItem;
|
http_authproxy_always_onboard?: BoolValueItem;
|
||||||
oidc_name?: StringValueItem;
|
oidc_name?: StringValueItem;
|
||||||
oidc_endpoint?: StringValueItem;
|
oidc_endpoint?: StringValueItem;
|
||||||
oidc_client_id?: StringValueItem;
|
oidc_client_id?: StringValueItem;
|
||||||
oidc_client_secret?: StringValueItem;
|
oidc_client_secret?: StringValueItem;
|
||||||
oidc_skip_cert_verify?: BoolValueItem;
|
oidc_verify_cert?: BoolValueItem;
|
||||||
oidc_scope?: StringValueItem;
|
oidc_scope?: StringValueItem;
|
||||||
public constructor() {
|
public constructor() {
|
||||||
this.auth_mode = new StringValueItem("db_auth", true);
|
this.auth_mode = new StringValueItem("db_auth", true);
|
||||||
@ -141,13 +141,13 @@ export class Configuration {
|
|||||||
this.read_only = new BoolValueItem(false, true);
|
this.read_only = new BoolValueItem(false, true);
|
||||||
this.http_authproxy_endpoint = new StringValueItem("", true);
|
this.http_authproxy_endpoint = new StringValueItem("", true);
|
||||||
this.http_authproxy_tokenreview_endpoint = new StringValueItem("", true);
|
this.http_authproxy_tokenreview_endpoint = new StringValueItem("", true);
|
||||||
this.http_authproxy_skip_cert_verify = new BoolValueItem(false, true);
|
this.http_authproxy_verify_cert = new BoolValueItem(false, true);
|
||||||
this.http_authproxy_always_onboard = new BoolValueItem(false, true);
|
this.http_authproxy_always_onboard = new BoolValueItem(false, true);
|
||||||
this.oidc_name = new StringValueItem('', true);
|
this.oidc_name = new StringValueItem('', true);
|
||||||
this.oidc_endpoint = new StringValueItem('', true);
|
this.oidc_endpoint = new StringValueItem('', true);
|
||||||
this.oidc_client_id = new StringValueItem('', true);
|
this.oidc_client_id = new StringValueItem('', true);
|
||||||
this.oidc_client_secret = new StringValueItem('', true);
|
this.oidc_client_secret = new StringValueItem('', true);
|
||||||
this.oidc_skip_cert_verify = new BoolValueItem(false, true);
|
this.oidc_verify_cert = new BoolValueItem(false, true);
|
||||||
this.oidc_scope = new StringValueItem('', true);
|
this.oidc_scope = new StringValueItem('', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,13 +300,13 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="http_authproxy_skip_cert_verify"
|
<label for="http_authproxy_verify_cert"
|
||||||
class="required">{{'CONFIG.HTTP_AUTH.VERIFY_CERT' | translate}}</label>
|
class="required">{{'CONFIG.HTTP_AUTH.VERIFY_CERT' | translate}}</label>
|
||||||
<clr-checkbox-wrapper>
|
<clr-checkbox-wrapper>
|
||||||
<input type="checkbox" clrCheckbox name="http_authproxy_skip_cert_verify"
|
<input type="checkbox" clrCheckbox name="http_authproxy_verify_cert"
|
||||||
id="http_authproxy_skip_cert_verify"
|
id="http_authproxy_verify_cert"
|
||||||
[(ngModel)]="currentConfig.http_authproxy_skip_cert_verify.value"
|
[(ngModel)]="currentConfig.http_authproxy_verify_cert.value"
|
||||||
[disabled]="!currentConfig.http_authproxy_skip_cert_verify.editable" />
|
[disabled]="!currentConfig.http_authproxy_verify_cert.editable" />
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -403,16 +403,16 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="oidc_skip_cert_verify">{{'CONFIG.OIDC.OIDCSKIPCERTVERIFY' | translate}}</label>
|
<label for="oidc_verify_cert">{{'CONFIG.OIDC.OIDC_VERIFYCERT' | translate}}</label>
|
||||||
<clr-checkbox-wrapper>
|
<clr-checkbox-wrapper>
|
||||||
<input type="checkbox" clrCheckbox name="oidc_skip_cert_verify" id="oidc_skip_cert_verify"
|
<input type="checkbox" clrCheckbox name="oidc_verify_cert" id="oidc_verify_cert"
|
||||||
[disabled]="disabled(currentConfig.oidc_skip_cert_verify)"
|
[disabled]="disabled(currentConfig.oidc_verify_cert)"
|
||||||
[(ngModel)]="currentConfig.oidc_skip_cert_verify.value" />
|
[(ngModel)]="currentConfig.oidc_verify_cert.value" />
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper>
|
||||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true"
|
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true"
|
||||||
class="tooltip tooltip-lg tooltip-top-right top-1px">
|
class="tooltip tooltip-lg tooltip-top-right top-1px">
|
||||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||||
<span class="tooltip-content">{{'TOOLTIP.OIDC_SKIPCERTVERIFY' | translate}}</span>
|
<span class="tooltip-content">{{'TOOLTIP.OIDC_VERIFYCERT' | translate}}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -425,4 +425,4 @@
|
|||||||
<button type="button" class="btn btn-outline" (click)="testLDAPServer()" *ngIf="showLdapServerBtn"
|
<button type="button" class="btn btn-outline" (click)="testLDAPServer()" *ngIf="showLdapServerBtn"
|
||||||
[disabled]="!isLDAPConfigValid()">{{'BUTTON.TEST_LDAP' | translate}}</button>
|
[disabled]="!isLDAPConfigValid()">{{'BUTTON.TEST_LDAP' | translate}}</button>
|
||||||
<span id="forTestingLDAP" class="spinner spinner-inline" [hidden]="hideLDAPTestingSpinner"></span>
|
<span id="forTestingLDAP" class="spinner spinner-inline" [hidden]="hideLDAPTestingSpinner"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
"OIDC_NAME": "The name of the OIDC provider.",
|
"OIDC_NAME": "The name of the OIDC provider.",
|
||||||
"OIDC_ENDPOINT": "The URL of an OIDC-complaint server.",
|
"OIDC_ENDPOINT": "The URL of an OIDC-complaint server.",
|
||||||
"OIDC_SCOPE": "The scope sent to OIDC server during authentication. It has to contain “openid”, and “offline_access”. If you are using google, please remove “offline_access” from this field.",
|
"OIDC_SCOPE": "The scope sent to OIDC server during authentication. It has to contain “openid”, and “offline_access”. If you are using google, please remove “offline_access” from this field.",
|
||||||
"OIDC_SKIPCERTVERIFY": "Check this box if your OIDC server is hosted via self-signed certificate."
|
"OIDC_VERIFYCERT": "Uncheck this box if your OIDC server is hosted via self-signed certificate."
|
||||||
},
|
},
|
||||||
"PLACEHOLDER": {
|
"PLACEHOLDER": {
|
||||||
"CURRENT_PWD": "Enter current password",
|
"CURRENT_PWD": "Enter current password",
|
||||||
@ -673,7 +673,7 @@
|
|||||||
"FILTER": "LDAP Filter",
|
"FILTER": "LDAP Filter",
|
||||||
"UID": "LDAP UID",
|
"UID": "LDAP UID",
|
||||||
"SCOPE": "LDAP Scope",
|
"SCOPE": "LDAP Scope",
|
||||||
"VERIFY_CERT": "LDAP Verify Cert",
|
"VERIFY_CERT": "LDAP Verify Certificate",
|
||||||
"LDAP_GROUP_BASE_DN": "LDAP Group Base DN",
|
"LDAP_GROUP_BASE_DN": "LDAP Group Base DN",
|
||||||
"LDAP_GROUP_BASE_DN_INFO": "The base DN from which to look up a group in LDAP/AD.",
|
"LDAP_GROUP_BASE_DN_INFO": "The base DN from which to look up a group in LDAP/AD.",
|
||||||
"LDAP_GROUP_FILTER": "LDAP Group Filter",
|
"LDAP_GROUP_FILTER": "LDAP Group Filter",
|
||||||
@ -698,15 +698,15 @@
|
|||||||
"ENDPOINT": "Server Endpoint",
|
"ENDPOINT": "Server Endpoint",
|
||||||
"TOKEN_REVIEW": "Token Review Endpoint",
|
"TOKEN_REVIEW": "Token Review Endpoint",
|
||||||
"ALWAYS_ONBOARD": "Always Onboard",
|
"ALWAYS_ONBOARD": "Always Onboard",
|
||||||
"VERIFY_CERT": "Authentication Verify Cert"
|
"VERIFY_CERT": "Verify Certificate"
|
||||||
},
|
},
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
"OIDC_PROVIDER": "OIDC Provider",
|
"OIDC_PROVIDER": "OIDC Provider Name",
|
||||||
"ENDPOINT": "OIDC Endpoint",
|
"ENDPOINT": "OIDC Endpoint",
|
||||||
"CLIENT_ID": "OIDC Client ID",
|
"CLIENT_ID": "OIDC Client ID",
|
||||||
"CLIENTSECRET": "OIDC Client Secret",
|
"CLIENTSECRET": "OIDC Client Secret",
|
||||||
"SCOPE": "OIDC Scope",
|
"SCOPE": "OIDC Scope",
|
||||||
"OIDCSKIPCERTVERIFY": "OIDC Skip Verifying Certificate",
|
"OIDC_VERIFYCERT": "Verify Certificate",
|
||||||
"OIDC_SETNAME": "Set OIDC Username",
|
"OIDC_SETNAME": "Set OIDC Username",
|
||||||
"OIDC_SETNAMECONTENT": "You must create a Harbor username the first time when authenticating via a third party(OIDC).This will be used within Harbor to be associated with projects, roles, etc.",
|
"OIDC_SETNAMECONTENT": "You must create a Harbor username the first time when authenticating via a third party(OIDC).This will be used within Harbor to be associated with projects, roles, etc.",
|
||||||
"OIDC_USERNAME": "Username"
|
"OIDC_USERNAME": "Username"
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
"OIDC_NAME": "El nombre de la OIDC proveedor.",
|
"OIDC_NAME": "El nombre de la OIDC proveedor.",
|
||||||
"OIDC_ENDPOINT": "La dirección URL de un servidor OIDC denuncia.",
|
"OIDC_ENDPOINT": "La dirección URL de un servidor OIDC denuncia.",
|
||||||
"OIDC_SCOPE": "El ámbito de aplicación enviada a OIDC Server durante la autenticación.Tiene que contener 'Openid', y 'offline_access'.Si usted esta usando Google, por favor quitar 'offline_access' de este campo",
|
"OIDC_SCOPE": "El ámbito de aplicación enviada a OIDC Server durante la autenticación.Tiene que contener 'Openid', y 'offline_access'.Si usted esta usando Google, por favor quitar 'offline_access' de este campo",
|
||||||
"OIDC_SKIPCERTVERIFY": "Marque esta casilla si tu OIDC servidor está alojado a través de certificado autofirmado."
|
"OIDC_VERIFYCERT": "Desmarque esta casilla si tu OIDC servidor está alojado a través de certificado autofirmado."
|
||||||
},
|
},
|
||||||
"PLACEHOLDER": {
|
"PLACEHOLDER": {
|
||||||
"CURRENT_PWD": "Introduzca la contraseña actual",
|
"CURRENT_PWD": "Introduzca la contraseña actual",
|
||||||
@ -704,7 +704,7 @@
|
|||||||
"CLIENT_ID": "ID de cliente OIDC",
|
"CLIENT_ID": "ID de cliente OIDC",
|
||||||
"CLIENTSECRET": "OIDC Client Secret",
|
"CLIENTSECRET": "OIDC Client Secret",
|
||||||
"SCOPE": "OIDC Ámbito",
|
"SCOPE": "OIDC Ámbito",
|
||||||
"OIDCSKIPCERTVERIFY": "OIDC Skip Verificar certificado",
|
"OIDC_VERIFYCERT": "Verificar certificado",
|
||||||
"OIDC_SETNAME": "Set OIDC nombre de usuario",
|
"OIDC_SETNAME": "Set OIDC nombre de usuario",
|
||||||
"OIDC_SETNAMECONTENT": "Usted debe crear un Harbor nombre de usuario la primera vez cuando la autenticación a través de un tercero (OIDC). Esta será usada en Harbor para ser asociados con proyectos, funciones, etc.",
|
"OIDC_SETNAMECONTENT": "Usted debe crear un Harbor nombre de usuario la primera vez cuando la autenticación a través de un tercero (OIDC). Esta será usada en Harbor para ser asociados con proyectos, funciones, etc.",
|
||||||
"OIDC_USERNAME": "Usuario"
|
"OIDC_USERNAME": "Usuario"
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
"OIDC_NAME": "le nom du fournisseur de oidc.",
|
"OIDC_NAME": "le nom du fournisseur de oidc.",
|
||||||
"OIDC_ENDPOINT": "l'url d'un serveur oidc plainte.",
|
"OIDC_ENDPOINT": "l'url d'un serveur oidc plainte.",
|
||||||
"OIDC_SCOPE": "le champ envoyés au serveur au cours oidc l'authentification.il doit contenir 'openid', et 'offline_access'.si vous utilisez google, veuillez supprimer 'offline_access' dans ce domaine",
|
"OIDC_SCOPE": "le champ envoyés au serveur au cours oidc l'authentification.il doit contenir 'openid', et 'offline_access'.si vous utilisez google, veuillez supprimer 'offline_access' dans ce domaine",
|
||||||
"OIDC_SKIPCERTVERIFY": "cocher cette case si votre oidc serveur est accueilli par auto - certificat signé."
|
"OIDC_VERIFYCERT": "décocher cette case si votre oidc serveur est accueilli par auto - certificat signé."
|
||||||
},
|
},
|
||||||
"PLACEHOLDER": {
|
"PLACEHOLDER": {
|
||||||
"CURRENT_PWD": "Entrez le mot de passe actuel",
|
"CURRENT_PWD": "Entrez le mot de passe actuel",
|
||||||
@ -669,7 +669,7 @@
|
|||||||
"CLIENT_ID": "no d'identification du client OIDC",
|
"CLIENT_ID": "no d'identification du client OIDC",
|
||||||
"CLIENTSECRET": "OIDC Client Secret",
|
"CLIENTSECRET": "OIDC Client Secret",
|
||||||
"SCOPE": "OIDC Scope",
|
"SCOPE": "OIDC Scope",
|
||||||
"OIDCSKIPCERTVERIFY": "Certificat OIDC skip vérifier",
|
"OIDC_VERIFYCERT": "Certificat vérifier",
|
||||||
"OIDC_SETNAME": "Ensemble OIDC nom d'utilisateur",
|
"OIDC_SETNAME": "Ensemble OIDC nom d'utilisateur",
|
||||||
"OIDC_SETNAMECONTENT": "vous devez créer un Harbor identifiant la première fois lors de la vérification par une tierce partie (oidc). il sera utilisé au sein de port à être associés aux projets, des rôles, etc.",
|
"OIDC_SETNAMECONTENT": "vous devez créer un Harbor identifiant la première fois lors de la vérification par une tierce partie (oidc). il sera utilisé au sein de port à être associés aux projets, des rôles, etc.",
|
||||||
"OIDC_USERNAME": "d'utilisateur"
|
"OIDC_USERNAME": "d'utilisateur"
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
"OIDC_NAME": "O Nome do prestador de oidc.",
|
"OIDC_NAME": "O Nome do prestador de oidc.",
|
||||||
"OIDC_ENDPOINT": "A URL de um servidor oidc denúncia.",
|
"OIDC_ENDPOINT": "A URL de um servidor oidc denúncia.",
|
||||||
"OIDC_SCOPE": "O âmbito de aplicação enviada Ao servidor oidc Durante a autenticação.TEM que conter 'openid' e 'offline_access'.Se você está usando o Google, por favor remova 'offline_access' desse Campo.",
|
"OIDC_SCOPE": "O âmbito de aplicação enviada Ao servidor oidc Durante a autenticação.TEM que conter 'openid' e 'offline_access'.Se você está usando o Google, por favor remova 'offline_access' desse Campo.",
|
||||||
"OIDC_SKIPCERTVERIFY": "Assinale esta opção se o SEU servidor está hospedado oidc via self - signed certificate."
|
"OIDC_VERIFYCERT": "Desmarque esta opção se o SEU servidor está hospedado oidc via self - signed certificate."
|
||||||
},
|
},
|
||||||
"PLACEHOLDER": {
|
"PLACEHOLDER": {
|
||||||
"CURRENT_PWD": "Insira a senha atual",
|
"CURRENT_PWD": "Insira a senha atual",
|
||||||
@ -698,7 +698,7 @@
|
|||||||
"CLIENT_ID": "ID de cliente OIDC",
|
"CLIENT_ID": "ID de cliente OIDC",
|
||||||
"CLIENTSECRET": "OIDC Client Secret",
|
"CLIENTSECRET": "OIDC Client Secret",
|
||||||
"SCOPE": "Escopo OIDC",
|
"SCOPE": "Escopo OIDC",
|
||||||
"OIDCSKIPCERTVERIFY": "OIDC Skip Verificar Certificado",
|
"OIDC_VERIFYCERT": "Verificar Certificado",
|
||||||
"OIDC_SETNAME": "Definir o Utilizador OIDC",
|
"OIDC_SETNAME": "Definir o Utilizador OIDC",
|
||||||
"OIDC_SETNAMECONTENT": "Você deve Criar um Nome de usuário do Porto a primeira vez que autenticar através de um terceiro (OIDC). Isto será usado Dentro de Harbor para ser associado a projetos, papéis, etc.",
|
"OIDC_SETNAMECONTENT": "Você deve Criar um Nome de usuário do Porto a primeira vez que autenticar através de um terceiro (OIDC). Isto será usado Dentro de Harbor para ser associado a projetos, papéis, etc.",
|
||||||
"OIDC_USERNAME": "Utilizador"
|
"OIDC_USERNAME": "Utilizador"
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
"OIDC_NAME": "OIDC提供商的名称.",
|
"OIDC_NAME": "OIDC提供商的名称.",
|
||||||
"OIDC_ENDPOINT": "OIDC服务器的地址.",
|
"OIDC_ENDPOINT": "OIDC服务器的地址.",
|
||||||
"OIDC_SCOPE": "在身份验证期间发送到OIDC服务器的scope。它必须包含“openid”和“offline_access”。如果您使用Google,请从此字段中删除“脱机访问”。",
|
"OIDC_SCOPE": "在身份验证期间发送到OIDC服务器的scope。它必须包含“openid”和“offline_access”。如果您使用Google,请从此字段中删除“脱机访问”。",
|
||||||
"OIDC_SKIPCERTVERIFY": "如果您的OIDC服务器是通过自签名证书托管的,请选中此框。"
|
"OIDC_VERIFYCERT": "如果您的OIDC服务器是通过自签名证书托管的,请取消选中此框。"
|
||||||
},
|
},
|
||||||
"PLACEHOLDER": {
|
"PLACEHOLDER": {
|
||||||
"CURRENT_PWD": "输入当前密码",
|
"CURRENT_PWD": "输入当前密码",
|
||||||
@ -703,7 +703,7 @@
|
|||||||
"CLIENT_ID": "OIDC 客户端标识",
|
"CLIENT_ID": "OIDC 客户端标识",
|
||||||
"CLIENTSECRET": "OIDC 客户端密码",
|
"CLIENTSECRET": "OIDC 客户端密码",
|
||||||
"SCOPE": "OIDC Scope",
|
"SCOPE": "OIDC Scope",
|
||||||
"OIDCSKIPCERTVERIFY": "OIDC 验证证书",
|
"OIDC_VERIFYCERT": "验证证书",
|
||||||
"OIDC_SETNAME": "设置OIDC用户名",
|
"OIDC_SETNAME": "设置OIDC用户名",
|
||||||
"OIDC_SETNAMECONTENT": "在通过第三方(OIDC)进行身份验证时,您必须第一次创建一个Harbor用户名。这将在端口中用于与项目、角色等关联。",
|
"OIDC_SETNAMECONTENT": "在通过第三方(OIDC)进行身份验证时,您必须第一次创建一个Harbor用户名。这将在端口中用于与项目、角色等关联。",
|
||||||
"OIDC_USERNAME": "用户名"
|
"OIDC_USERNAME": "用户名"
|
||||||
|
Loading…
Reference in New Issue
Block a user