Skip to content
This repository has been archived by the owner on Nov 18, 2024. It is now read-only.

Add refresh_interval config option #43

Merged
merged 6 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ $ vault write oauth2/bitbucket/self/my-machine-auth/config \
Success! Data written to: oauth2/bitbucket/self/my-machine-auth/config
```

### Automatic refresh checking

By default tokens are automatically checked for refresh every 60
seconds. You can change that interval by setting the
`tune_refresh_check_interval_seconds` config option to another number of
seconds. If set to zero, tokens will be refreshed only on demand.

## Tips

For some operations, you may find that you need to provide a map of data for a
Expand Down Expand Up @@ -184,6 +191,13 @@ configuration, so you must specify all required fields, even when updating.
| `provider` | The name of the provider to use. See [the list of providers](#providers). | String | None | Yes |
| `provider_options` | Options to configure the specified provider. | Map of String🠦String | None | No |

There is also an additional configuration option that may be set for
fine tuning.

| Name | Description | Type | Default |
|------|-------------|------|---------|
| `tune_refresh_check_interval_seconds` | Number of seconds between checking tokens for refresh. | Integer | 60 |

#### `DELETE` (`delete`)

Remove the current configuration. This does not invalidate any existing access
Expand Down
28 changes: 23 additions & 5 deletions pkg/backend/path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (
"github.com/puppetlabs/vault-plugin-secrets-oauthapp/pkg/provider"
)

const (
DefaultRefreshCheckIntervalSeconds = 60
)

func (b *backend) configReadOperation(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
c, err := b.getCache(ctx, req.Storage)
if err != nil {
Expand All @@ -22,11 +26,12 @@ func (b *backend) configReadOperation(ctx context.Context, req *logical.Request,

resp := &logical.Response{
Data: map[string]interface{}{
"client_id": c.Config.ClientID,
"auth_url_params": c.Config.AuthURLParams,
"provider": c.Config.ProviderName,
"provider_version": c.Config.ProviderVersion,
"provider_options": c.Config.ProviderOptions,
"client_id": c.Config.ClientID,
"auth_url_params": c.Config.AuthURLParams,
"provider": c.Config.ProviderName,
"provider_version": c.Config.ProviderVersion,
"provider_options": c.Config.ProviderOptions,
"tune_refresh_check_interval_seconds": c.Config.Tuning.RefreshCheckIntervalSeconds,
},
}
return resp, nil
Expand Down Expand Up @@ -54,13 +59,21 @@ func (b *backend) configUpdateOperation(ctx context.Context, req *logical.Reques
return nil, err
}

refresh_interval := data.Get("tune_refresh_check_interval_seconds").(int)
if refresh_interval < 0 || refresh_interval > 90*24*60*60 {
return logical.ErrorResponse("invalid tune_refresh_check_interval_seconds"), nil
}

c := &persistence.ConfigEntry{
ClientID: clientID.(string),
ClientSecret: data.Get("client_secret").(string),
AuthURLParams: data.Get("auth_url_params").(map[string]string),
ProviderName: providerName.(string),
ProviderVersion: p.Version(),
ProviderOptions: providerOptions,
Tuning: persistence.ConfigTuning{
RefreshCheckIntervalSeconds: refresh_interval,
},
}
if err := b.data.Managers(req.Storage).Config().WriteConfig(ctx, c); err != nil {
return nil, err
Expand Down Expand Up @@ -139,6 +152,11 @@ var configFields = map[string]*framework.FieldSchema{
Type: framework.TypeKVPairs,
Description: "Specifies any provider-specific options.",
},
"tune_refresh_check_interval_seconds": {
Type: framework.TypeInt,
Description: "Specifies the interval in seconds between credential refresh, disabled if 0.",
Default: DefaultRefreshCheckIntervalSeconds,
},
}

const configHelpSynopsis = `
Expand Down
48 changes: 29 additions & 19 deletions pkg/backend/token_authcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@ import (
"github.com/puppetlabs/vault-plugin-secrets-oauthapp/pkg/persistence"
)

const (
refreshInterval = time.Minute
)

type refreshProcess struct {
backend *backend
storage logical.Storage
keyer persistence.AuthCodeKeyer
seconds int
}

var _ scheduler.Process = &refreshProcess{}
Expand All @@ -29,7 +26,7 @@ func (rp *refreshProcess) Description() string {
}

func (rp *refreshProcess) Run(ctx context.Context) error {
_, err := rp.backend.getRefreshCredToken(ctx, rp.storage, rp.keyer, refreshInterval+10*time.Second)
_, err := rp.backend.getRefreshCredToken(ctx, rp.storage, rp.keyer, time.Duration(rp.seconds)*time.Second)
return err
}

Expand All @@ -41,24 +38,37 @@ type refreshDescriptor struct {
var _ scheduler.Descriptor = &refreshDescriptor{}

func (rd *refreshDescriptor) Run(ctx context.Context, pc chan<- scheduler.Process) error {
ticker := rd.backend.clock.NewTicker(refreshInterval)
defer ticker.Stop()
// start out checking once per minute
refreshInterval := DefaultRefreshCheckIntervalSeconds
ticker := rd.backend.clock.NewTicker(time.Duration(refreshInterval) * time.Second)
defer func() {
ticker.Stop()
}()

for {
err := rd.backend.data.Managers(rd.storage).AuthCode().ForEachAuthCodeKey(ctx, func(keyer persistence.AuthCodeKeyer) {
proc := &refreshProcess{
backend: rd.backend,
storage: rd.storage,
keyer: keyer,
c, err := rd.backend.getCache(ctx, rd.storage)
if err == nil && c != nil && c.Config.Tuning.RefreshCheckIntervalSeconds > 0 {
if c.Config.Tuning.RefreshCheckIntervalSeconds != refreshInterval {
refreshInterval = c.Config.Tuning.RefreshCheckIntervalSeconds
ticker.Stop()
ticker = rd.backend.clock.NewTicker(time.Duration(refreshInterval) * time.Second)
}

select {
case pc <- proc:
case <-ctx.Done():
err = rd.backend.data.Managers(rd.storage).AuthCode().ForEachAuthCodeKey(ctx, func(keyer persistence.AuthCodeKeyer) {
proc := &refreshProcess{
backend: rd.backend,
storage: rd.storage,
keyer: keyer,
seconds: refreshInterval + 10,
}

select {
case pc <- proc:
case <-ctx.Done():
}
})
if err != nil {
return err
}
})
if err != nil {
return err
}

select {
Expand Down
5 changes: 5 additions & 0 deletions pkg/persistence/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ const (
configKey = "config"
)

type ConfigTuning struct {
RefreshCheckIntervalSeconds int `json:"refresh_check_interval_seconds"`
}

type ConfigEntry struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
AuthURLParams map[string]string `json:"auth_url_params"`
ProviderName string `json:"provider_name"`
ProviderVersion int `json:"provider_version"`
ProviderOptions map[string]string `json:"provider_options"`
Tuning ConfigTuning `json:"tuning"`
}

type LockedConfigManager struct {
Expand Down