mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 04:05:40 +01:00
feat: support customize session timeout (#17767)
Add configuration session_timeout for API, then user can customize the timeout from system config page or API. The timeout is 60 minutes by default. Signed-off-by: chlins <chenyuzh@vmware.com> Signed-off-by: chlins <chenyuzh@vmware.com>
This commit is contained in:
parent
cf036df68b
commit
9c9aa58d6a
@ -8631,6 +8631,9 @@ definitions:
|
|||||||
type: integer
|
type: integer
|
||||||
description: 'The offset in seconds of UTC 0 o''clock, only valid when the policy type is "daily"'
|
description: 'The offset in seconds of UTC 0 o''clock, only valid when the policy type is "daily"'
|
||||||
description: 'The parameters of the policy, the values are dependent on the type of the policy.'
|
description: 'The parameters of the policy, the values are dependent on the type of the policy.'
|
||||||
|
session_timeout:
|
||||||
|
$ref: '#/definitions/IntegerConfigItem'
|
||||||
|
description: The session timeout in minutes
|
||||||
Configurations:
|
Configurations:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -8883,7 +8886,12 @@ definitions:
|
|||||||
type: boolean
|
type: boolean
|
||||||
description: Skip audit log database
|
description: Skip audit log database
|
||||||
x-omitempty: true
|
x-omitempty: true
|
||||||
x-isnullable: true
|
x-isnullable: true
|
||||||
|
session_timeout:
|
||||||
|
type: integer
|
||||||
|
description: The session timeout for harbor, in minutes.
|
||||||
|
x-omitempty: true
|
||||||
|
x-isnullable: true
|
||||||
StringConfigItem:
|
StringConfigItem:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -218,4 +218,7 @@ const (
|
|||||||
SkipAuditLogDatabase = "skip_audit_log_database"
|
SkipAuditLogDatabase = "skip_audit_log_database"
|
||||||
// MaxAuditRetentionHour allowed in audit log purge
|
// MaxAuditRetentionHour allowed in audit log purge
|
||||||
MaxAuditRetentionHour = 240000
|
MaxAuditRetentionHour = 240000
|
||||||
|
|
||||||
|
// SessionTimeout defines the web session timeout
|
||||||
|
SessionTimeout = "session_timeout"
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/goharbor/harbor/src/lib/cache"
|
"github.com/goharbor/harbor/src/lib/cache"
|
||||||
"github.com/goharbor/harbor/src/lib/cache/redis"
|
"github.com/goharbor/harbor/src/lib/cache/redis"
|
||||||
|
"github.com/goharbor/harbor/src/lib/config"
|
||||||
"github.com/goharbor/harbor/src/lib/log"
|
"github.com/goharbor/harbor/src/lib/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,8 +92,10 @@ func (rs *Store) SessionRelease(w http.ResponseWriter) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
maxlifetime := time.Duration(systemSessionTimeout(ctx, rs.maxlifetime))
|
||||||
if rdb, ok := rs.c.(*redis.Cache); ok {
|
if rdb, ok := rs.c.(*redis.Cache); ok {
|
||||||
cmd := rdb.Client.Set(context.TODO(), rs.sid, string(b), time.Duration(rs.maxlifetime))
|
cmd := rdb.Client.Set(ctx, rs.sid, string(b), maxlifetime)
|
||||||
if cmd.Err() != nil {
|
if cmd.Err() != nil {
|
||||||
log.Debugf("release session error: %v", err)
|
log.Debugf("release session error: %v", err)
|
||||||
}
|
}
|
||||||
@ -136,8 +139,9 @@ func (rp *Provider) SessionExist(sid string) bool {
|
|||||||
// SessionRegenerate generate new sid for redis session
|
// SessionRegenerate generate new sid for redis session
|
||||||
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
maxlifetime := time.Duration(systemSessionTimeout(ctx, rp.maxlifetime))
|
||||||
if !rp.SessionExist(oldsid) {
|
if !rp.SessionExist(oldsid) {
|
||||||
err := rp.c.Save(ctx, sid, "", time.Duration(rp.maxlifetime))
|
err := rp.c.Save(ctx, sid, "", maxlifetime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to save sid=%s, where oldsid=%s, error: %s", sid, oldsid, err)
|
log.Debugf("failed to save sid=%s, where oldsid=%s, error: %s", sid, oldsid, err)
|
||||||
}
|
}
|
||||||
@ -145,7 +149,7 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error)
|
|||||||
if rdb, ok := rp.c.(*redis.Cache); ok {
|
if rdb, ok := rp.c.(*redis.Cache); ok {
|
||||||
// redis has rename command
|
// redis has rename command
|
||||||
rdb.Rename(ctx, oldsid, sid)
|
rdb.Rename(ctx, oldsid, sid)
|
||||||
rdb.Expire(ctx, sid, time.Duration(rp.maxlifetime))
|
rdb.Expire(ctx, sid, maxlifetime)
|
||||||
} else {
|
} else {
|
||||||
kv := make(map[interface{}]interface{})
|
kv := make(map[interface{}]interface{})
|
||||||
err := rp.c.Fetch(ctx, sid, &kv)
|
err := rp.c.Fetch(ctx, sid, &kv)
|
||||||
@ -157,7 +161,7 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to delete oldsid=%s, error: %s", oldsid, err)
|
log.Debugf("failed to delete oldsid=%s, error: %s", oldsid, err)
|
||||||
}
|
}
|
||||||
err = rp.c.Save(ctx, sid, kv)
|
err = rp.c.Save(ctx, sid, kv, maxlifetime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to save sid=%s, error: %s", sid, err)
|
log.Debugf("failed to save sid=%s, error: %s", sid, err)
|
||||||
}
|
}
|
||||||
@ -181,6 +185,18 @@ func (rp *Provider) SessionAll() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// systemSessionTimeout return the system session timeout set by user.
|
||||||
|
func systemSessionTimeout(ctx context.Context, beegoTimeout int64) int64 {
|
||||||
|
// read from system config if it is meaningful to support change session timeout in runtime for user.
|
||||||
|
// otherwise, use parameters beegoTimeout which set from beego.
|
||||||
|
timeout := beegoTimeout
|
||||||
|
if sysTimeout := config.SessionTimeout(ctx); sysTimeout > 0 {
|
||||||
|
timeout = sysTimeout * int64(time.Minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeout
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
session.Register(HarborProviderName, harborpder)
|
session.Register(HarborProviderName, harborpder)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ import (
|
|||||||
|
|
||||||
"github.com/beego/beego/session"
|
"github.com/beego/beego/session"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/goharbor/harbor/src/lib/config"
|
||||||
|
_ "github.com/goharbor/harbor/src/pkg/config/db"
|
||||||
|
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sessionTestSuite struct {
|
type sessionTestSuite struct {
|
||||||
@ -27,7 +31,9 @@ type sessionTestSuite struct {
|
|||||||
provider session.Provider
|
provider session.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sessionTestSuite) SetupTest() {
|
func (s *sessionTestSuite) SetupSuite() {
|
||||||
|
config.Init()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
s.provider, err = session.GetProvider("harbor")
|
s.provider, err = session.GetProvider("harbor")
|
||||||
s.NoError(err, "should get harbor provider")
|
s.NoError(err, "should get harbor provider")
|
||||||
|
@ -183,5 +183,7 @@ var (
|
|||||||
|
|
||||||
{Name: common.AuditLogForwardEndpoint, Scope: UserScope, Group: BasicGroup, EnvKey: "AUDIT_LOG_FORWARD_ENDPOINT", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The endpoint to forward the audit log.`},
|
{Name: common.AuditLogForwardEndpoint, Scope: UserScope, Group: BasicGroup, EnvKey: "AUDIT_LOG_FORWARD_ENDPOINT", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The endpoint to forward the audit log.`},
|
||||||
{Name: common.SkipAuditLogDatabase, Scope: UserScope, Group: BasicGroup, EnvKey: "SKIP_LOG_AUDIT_DATABASE", DefaultValue: "false", ItemType: &BoolType{}, Editable: false, Description: `The option to skip audit log in database`},
|
{Name: common.SkipAuditLogDatabase, Scope: UserScope, Group: BasicGroup, EnvKey: "SKIP_LOG_AUDIT_DATABASE", DefaultValue: "false", ItemType: &BoolType{}, Editable: false, Description: `The option to skip audit log in database`},
|
||||||
|
|
||||||
|
{Name: common.SessionTimeout, Scope: UserScope, Group: BasicGroup, EnvKey: "SESSION_TIMEOUT", DefaultValue: "60", ItemType: &Int64Type{}, Editable: true, Description: `The session timeout in minutes`},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -84,6 +84,11 @@ func LDAPGroupConf(ctx context.Context) (*cfgModels.GroupConf, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SessionTimeout returns the session timeout for web (in minute).
|
||||||
|
func SessionTimeout(ctx context.Context) int64 {
|
||||||
|
return DefaultMgr().Get(ctx, common.SessionTimeout).GetInt64()
|
||||||
|
}
|
||||||
|
|
||||||
// TokenExpiration returns the token expiration time (in minute)
|
// TokenExpiration returns the token expiration time (in minute)
|
||||||
func TokenExpiration(ctx context.Context) (int, error) {
|
func TokenExpiration(ctx context.Context) (int, error) {
|
||||||
return DefaultMgr().Get(ctx, common.TokenExpiration).GetInt(), nil
|
return DefaultMgr().Get(ctx, common.TokenExpiration).GetInt(), nil
|
||||||
|
Loading…
Reference in New Issue
Block a user