Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(authentication): Add cli args for specifying session length and renewal #13924

Merged
merged 5 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions cmd/influxd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ func buildLauncherCommand(l *Launcher, cmd *cobra.Command) {
Default: false,
Desc: "disable sending telemetry data to https://telemetry.influxdata.com every 8 hours",
},
{
DestP: &l.sessionLength,
Flag: "session-length",
Default: 60, // 60 minutes
Desc: "ttl in minutes for newly created sessions",
},
{
DestP: &l.sessionRenewDisabled,
Flag: "session-renew-disabled",
Default: false,
Desc: "disables automatically extending session ttl on request",
},
}

cli.BindOptions(cmd, opts)
Expand All @@ -186,9 +198,11 @@ type Launcher struct {
cancel func()
running bool

storeType string
assetsPath string
testing bool
storeType string
assetsPath string
testing bool
sessionLength int // in minutes
sessionRenewDisabled bool

logLevel string
tracingType string
Expand Down Expand Up @@ -382,18 +396,22 @@ func (m *Launcher) run(ctx context.Context) (err error) {
return err
}

serviceConfig := kv.ServiceConfig{
SessionLength: time.Duration(m.sessionLength) * time.Minute,
}

var flusher http.Flusher
switch m.storeType {
case BoltStore:
store := bolt.NewKVStore(m.boltPath)
store.WithDB(m.boltClient.DB())
m.kvService = kv.NewService(store)
m.kvService = kv.NewService(store, serviceConfig)
if m.testing {
flusher = store
}
case MemoryStore:
store := inmem.NewKVStore()
m.kvService = kv.NewService(store)
m.kvService = kv.NewService(store, serviceConfig)
if m.testing {
flusher = store
}
Expand Down Expand Up @@ -580,6 +598,7 @@ func (m *Launcher) run(ctx context.Context) (err error) {
m.apibackend = &http.APIBackend{
AssetsPath: m.assetsPath,
Logger: m.logger,
SessionRenewDisabled: m.sessionRenewDisabled,
NewBucketService: source.NewBucketService,
NewQueryService: source.NewQueryService,
PointsWriter: pointsWriter,
Expand Down
5 changes: 3 additions & 2 deletions http/api_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ type APIHandler struct {
// APIBackend is all services and associated parameters required to construct
// an APIHandler.
type APIBackend struct {
AssetsPath string // if empty then assets are served from bindata.
Logger *zap.Logger
AssetsPath string // if empty then assets are served from bindata.
Logger *zap.Logger
SessionRenewDisabled bool

NewBucketService func(*influxdb.Source) (influxdb.BucketService, error)
NewQueryService func(*influxdb.Source) (query.ProxyQueryService, error)
Expand Down
11 changes: 7 additions & 4 deletions http/authentication_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type AuthenticationHandler struct {

AuthorizationService platform.AuthorizationService
SessionService platform.SessionService
SessionRenewDisabled bool

// This is only really used for it's lookup method the specific http
// handler used to register routes does not matter.
Expand Down Expand Up @@ -123,10 +124,12 @@ func (h *AuthenticationHandler) extractSession(ctx context.Context, r *http.Requ
return ctx, e
}

// if the session is not expired, renew the session
e = h.SessionService.RenewSession(ctx, s, time.Now().Add(platform.RenewSessionTime))
if e != nil {
return ctx, e
if !h.SessionRenewDisabled {
// if the session is not expired, renew the session
e = h.SessionService.RenewSession(ctx, s, time.Now().Add(platform.RenewSessionTime))
if e != nil {
return ctx, e
}
}

return platcontext.SetAuthorizer(ctx, s), nil
Expand Down
1 change: 1 addition & 0 deletions http/platform_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func NewPlatformHandler(b *APIBackend) *PlatformHandler {
h.Handler = NewAPIHandler(b)
h.AuthorizationService = b.AuthorizationService
h.SessionService = b.SessionService
h.SessionRenewDisabled = b.SessionRenewDisabled

h.RegisterNoAuthRoute("GET", "/api/v2")
h.RegisterNoAuthRoute("POST", "/api/v2/signin")
Expand Down
18 changes: 16 additions & 2 deletions kv/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const OpPrefix = "kv/"
type Service struct {
kv Store
Logger *zap.Logger
Config ServiceConfig

IDGenerator influxdb.IDGenerator
TokenGenerator influxdb.TokenGenerator
Expand All @@ -31,15 +32,28 @@ type Service struct {
}

// NewService returns an instance of a Service.
func NewService(kv Store) *Service {
return &Service{
func NewService(kv Store, configs ...ServiceConfig) *Service {
s := &Service{
Logger: zap.NewNop(),
IDGenerator: snowflake.NewIDGenerator(),
TokenGenerator: rand.NewTokenGenerator(64),
Hash: &Bcrypt{},
kv: kv,
time: time.Now,
}

if len(configs) > 0 {
s.Config = configs[0]
} else {
s.Config.SessionLength = influxdb.DefaultSessionLength
}

return s
}

// ServiceConfig allows us to configure Services
type ServiceConfig struct {
SessionLength time.Duration
}

// Initialize creates Buckets needed.
Expand Down
39 changes: 39 additions & 0 deletions kv/service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package kv_test

import (
"context"
"testing"
"time"

"github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/kv"
)

type mockStore struct {
}

func (s mockStore) View(context.Context, func(kv.Tx) error) error {
return nil
}

func (s mockStore) Update(context.Context, func(kv.Tx) error) error {
return nil
}

func TestNewService(t *testing.T) {
s := kv.NewService(mockStore{})

if s.Config.SessionLength != influxdb.DefaultSessionLength {
t.Errorf("Service session length should use default length when not set")
}

config := kv.ServiceConfig{
SessionLength: time.Duration(time.Hour * 4),
}

s = kv.NewService(mockStore{}, config)

if s.Config != config {
t.Errorf("Service config not set by constructor")
}
}
3 changes: 1 addition & 2 deletions kv/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,7 @@ func (s *Service) createSession(ctx context.Context, tx Tx, user string) (*influ
sn.Key = k
sn.UserID = u.ID
sn.CreatedAt = time.Now()
// TODO(desa): make this configurable
sn.ExpiresAt = sn.CreatedAt.Add(time.Hour)
sn.ExpiresAt = sn.CreatedAt.Add(s.Config.SessionLength)
// TODO(desa): not totally sure what to do here. Possibly we should have a maximal privilege permission.
sn.Permissions = []influxdb.Permission{}

Expand Down
3 changes: 3 additions & 0 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const ErrSessionExpired = "session has expired"
// RenewSessionTime is the the time to extend session, currently set to 5min.
var RenewSessionTime = time.Duration(time.Second * 300)

// DefaultSessionLength is the default session length on initial creation.
var DefaultSessionLength = time.Hour

var (
// OpFindSession represents the operation that looks for sessions.
OpFindSession = "FindSession"
Expand Down