Skip to content

Commit

Permalink
feat(authentication): Add cli args for specifying session length and …
Browse files Browse the repository at this point in the history
…renewal (#13924)

Co-authored-by: Jade McGough <jade@influxdata.com>

* Add session renew option to launcher and use in middlewhere
* pass session options to services
* Update SessionAutoRenew to SessionRenewDisabled
* Add test for service constructor defaults
* Update changelog
  • Loading branch information
ischolten authored May 15, 2019
1 parent eac269d commit 2e26f23
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Features

1. [13850](https://github.com/influxdata/influxdb/pull/13850): Add description field to Tasks.
1. [13924](https://github.com/influxdata/influxdb/pull/13924): Add CLI arguments for configuring session length and renewal.

### Bug Fixes

Expand Down
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

0 comments on commit 2e26f23

Please sign in to comment.