2018-07-25 02:02:27 +00:00
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-02-11 14:36:03 +00:00
|
|
|
"encoding/json"
|
2020-09-30 01:03:09 +00:00
|
|
|
"errors"
|
2018-07-25 02:02:27 +00:00
|
|
|
"math/rand"
|
2020-01-09 22:56:34 +00:00
|
|
|
"net/http"
|
2018-07-25 02:02:27 +00:00
|
|
|
"time"
|
|
|
|
|
2021-02-23 20:04:21 +00:00
|
|
|
"github.com/hashicorp/go-hclog"
|
2018-07-25 02:02:27 +00:00
|
|
|
"github.com/hashicorp/vault/api"
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
2018-07-25 02:02:27 +00:00
|
|
|
)
|
|
|
|
|
2021-02-23 20:04:21 +00:00
|
|
|
const (
|
|
|
|
initialBackoff = 1 * time.Second
|
|
|
|
defaultMaxBackoff = 5 * time.Minute
|
|
|
|
)
|
|
|
|
|
2020-08-25 21:26:06 +00:00
|
|
|
// AuthMethod is the interface that auto-auth methods implement for the agent
|
|
|
|
// to use.
|
2018-07-25 02:02:27 +00:00
|
|
|
type AuthMethod interface {
|
2020-01-09 22:56:34 +00:00
|
|
|
// Authenticate returns a mount path, header, request body, and error.
|
|
|
|
// The header may be nil if no special header is needed.
|
|
|
|
Authenticate(context.Context, *api.Client) (string, http.Header, map[string]interface{}, error)
|
2018-07-25 02:02:27 +00:00
|
|
|
NewCreds() chan struct{}
|
|
|
|
CredSuccess()
|
|
|
|
Shutdown()
|
|
|
|
}
|
|
|
|
|
2020-08-25 21:26:06 +00:00
|
|
|
// AuthMethodWithClient is an extended interface that can return an API client
|
|
|
|
// for use during the authentication call.
|
|
|
|
type AuthMethodWithClient interface {
|
|
|
|
AuthMethod
|
|
|
|
AuthClient(client *api.Client) (*api.Client, error)
|
|
|
|
}
|
|
|
|
|
2018-07-25 02:02:27 +00:00
|
|
|
type AuthConfig struct {
|
|
|
|
Logger hclog.Logger
|
|
|
|
MountPath string
|
|
|
|
WrapTTL time.Duration
|
|
|
|
Config map[string]interface{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AuthHandler is responsible for keeping a token alive and renewed and passing
|
|
|
|
// new tokens to the sink server
|
|
|
|
type AuthHandler struct {
|
2018-10-27 17:45:55 +00:00
|
|
|
OutputCh chan string
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
TemplateTokenCh chan string
|
2021-02-11 14:36:03 +00:00
|
|
|
token string
|
2018-10-27 17:45:55 +00:00
|
|
|
logger hclog.Logger
|
|
|
|
client *api.Client
|
|
|
|
random *rand.Rand
|
|
|
|
wrapTTL time.Duration
|
2021-02-23 20:04:21 +00:00
|
|
|
maxBackoff time.Duration
|
2018-10-27 17:45:55 +00:00
|
|
|
enableReauthOnNewCredentials bool
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
enableTemplateTokenCh bool
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type AuthHandlerConfig struct {
|
2018-10-27 17:45:55 +00:00
|
|
|
Logger hclog.Logger
|
|
|
|
Client *api.Client
|
|
|
|
WrapTTL time.Duration
|
2021-02-23 20:04:21 +00:00
|
|
|
MaxBackoff time.Duration
|
2021-02-11 14:36:03 +00:00
|
|
|
Token string
|
2018-10-27 17:45:55 +00:00
|
|
|
EnableReauthOnNewCredentials bool
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
EnableTemplateTokenCh bool
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewAuthHandler(conf *AuthHandlerConfig) *AuthHandler {
|
|
|
|
ah := &AuthHandler{
|
2018-10-15 15:02:53 +00:00
|
|
|
// This is buffered so that if we try to output after the sink server
|
|
|
|
// has been shut down, during agent shutdown, we won't block
|
2018-10-27 17:45:55 +00:00
|
|
|
OutputCh: make(chan string, 1),
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
TemplateTokenCh: make(chan string, 1),
|
2021-02-11 14:36:03 +00:00
|
|
|
token: conf.Token,
|
2018-10-27 17:45:55 +00:00
|
|
|
logger: conf.Logger,
|
|
|
|
client: conf.Client,
|
|
|
|
random: rand.New(rand.NewSource(int64(time.Now().Nanosecond()))),
|
|
|
|
wrapTTL: conf.WrapTTL,
|
2021-02-23 20:04:21 +00:00
|
|
|
maxBackoff: conf.MaxBackoff,
|
2018-10-27 17:45:55 +00:00
|
|
|
enableReauthOnNewCredentials: conf.EnableReauthOnNewCredentials,
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
enableTemplateTokenCh: conf.EnableTemplateTokenCh,
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ah
|
|
|
|
}
|
|
|
|
|
2021-03-03 22:15:18 +00:00
|
|
|
func backoffOrQuit(ctx context.Context, backoff *agentBackoff) {
|
2018-07-25 02:02:27 +00:00
|
|
|
select {
|
2021-03-03 22:15:18 +00:00
|
|
|
case <-time.After(backoff.current):
|
2018-07-25 02:02:27 +00:00
|
|
|
case <-ctx.Done():
|
|
|
|
}
|
2021-03-03 22:15:18 +00:00
|
|
|
|
|
|
|
// Increase exponential backoff for the next time if we don't
|
|
|
|
// successfully auth/renew/etc.
|
|
|
|
backoff.next()
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
2020-09-30 01:03:09 +00:00
|
|
|
func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
|
2018-07-25 02:02:27 +00:00
|
|
|
if am == nil {
|
2020-09-30 01:03:09 +00:00
|
|
|
return errors.New("auth handler: nil auth method")
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
2021-03-03 22:15:18 +00:00
|
|
|
backoff := newAgentBackoff(ah.maxBackoff)
|
2021-02-23 20:04:21 +00:00
|
|
|
|
2018-07-25 02:02:27 +00:00
|
|
|
ah.logger.Info("starting auth handler")
|
|
|
|
defer func() {
|
2018-08-24 13:17:14 +00:00
|
|
|
am.Shutdown()
|
|
|
|
close(ah.OutputCh)
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
close(ah.TemplateTokenCh)
|
2018-08-24 13:17:14 +00:00
|
|
|
ah.logger.Info("auth handler stopped")
|
2018-07-25 02:02:27 +00:00
|
|
|
}()
|
|
|
|
|
|
|
|
credCh := am.NewCreds()
|
2018-10-27 17:45:55 +00:00
|
|
|
if !ah.enableReauthOnNewCredentials {
|
|
|
|
realCredCh := credCh
|
|
|
|
credCh = nil
|
|
|
|
if realCredCh != nil {
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return
|
|
|
|
case <-realCredCh:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
2018-07-25 02:02:27 +00:00
|
|
|
if credCh == nil {
|
|
|
|
credCh = make(chan struct{})
|
|
|
|
}
|
|
|
|
|
2019-10-29 00:28:59 +00:00
|
|
|
var watcher *api.LifetimeWatcher
|
2021-02-11 14:36:03 +00:00
|
|
|
first := true
|
2018-07-25 02:02:27 +00:00
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
2020-09-30 01:03:09 +00:00
|
|
|
return nil
|
2018-07-25 02:02:27 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
2020-08-25 21:26:06 +00:00
|
|
|
var clientToUse *api.Client
|
2021-02-11 14:36:03 +00:00
|
|
|
var err error
|
|
|
|
var path string
|
|
|
|
var data map[string]interface{}
|
|
|
|
var header http.Header
|
2020-08-25 21:26:06 +00:00
|
|
|
|
|
|
|
switch am.(type) {
|
|
|
|
case AuthMethodWithClient:
|
|
|
|
clientToUse, err = am.(AuthMethodWithClient).AuthClient(ah.client)
|
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("error creating client for authentication call", "error", err, "backoff", backoff)
|
2020-08-25 21:26:06 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
clientToUse = ah.client
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:36:03 +00:00
|
|
|
var secret *api.Secret = new(api.Secret)
|
|
|
|
if first && ah.token != "" {
|
|
|
|
ah.logger.Debug("using preloaded token")
|
|
|
|
|
|
|
|
first = false
|
|
|
|
ah.logger.Debug("lookup-self with preloaded token")
|
|
|
|
clientToUse.SetToken(ah.token)
|
|
|
|
|
|
|
|
secret, err = clientToUse.Logical().Read("auth/token/lookup-self")
|
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("could not look up token", "err", err, "backoff", backoff)
|
2021-02-11 14:36:03 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
duration, _ := secret.Data["ttl"].(json.Number).Int64()
|
|
|
|
secret.Auth = &api.SecretAuth{
|
|
|
|
ClientToken: secret.Data["id"].(string),
|
|
|
|
LeaseDuration: int(duration),
|
|
|
|
Renewable: secret.Data["renewable"].(bool),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ah.logger.Info("authenticating")
|
|
|
|
|
|
|
|
path, header, data, err = am.Authenticate(ctx, ah.client)
|
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("error getting path or data from method", "error", err, "backoff", backoff)
|
2021-02-11 14:36:03 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-25 02:02:27 +00:00
|
|
|
if ah.wrapTTL > 0 {
|
2020-08-25 21:26:06 +00:00
|
|
|
wrapClient, err := clientToUse.Clone()
|
2018-07-25 02:02:27 +00:00
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("error creating client for wrapped call", "error", err, "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wrapClient.SetWrappingLookupFunc(func(string, string) string {
|
|
|
|
return ah.wrapTTL.String()
|
|
|
|
})
|
|
|
|
clientToUse = wrapClient
|
|
|
|
}
|
2020-01-09 22:56:34 +00:00
|
|
|
for key, values := range header {
|
|
|
|
for _, value := range values {
|
|
|
|
clientToUse.AddHeader(key, value)
|
|
|
|
}
|
|
|
|
}
|
2018-07-25 02:02:27 +00:00
|
|
|
|
2021-02-11 14:36:03 +00:00
|
|
|
// This should only happen if there's no preloaded token (regular auto-auth login)
|
|
|
|
// or if a preloaded token has expired and is now switching to auto-auth.
|
|
|
|
if secret.Auth == nil {
|
|
|
|
secret, err = clientToUse.Logical().Write(path, data)
|
|
|
|
// Check errors/sanity
|
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("error authenticating", "error", err, "backoff", backoff)
|
2021-02-11 14:36:03 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case ah.wrapTTL > 0:
|
|
|
|
if secret.WrapInfo == nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("authentication returned nil wrap info", "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if secret.WrapInfo.Token == "" {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("authentication returned empty wrapped client token", "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wrappedResp, err := jsonutil.EncodeJSON(secret.WrapInfo)
|
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("failed to encode wrapinfo", "error", err, "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ah.logger.Info("authentication successful, sending wrapped token to sinks and pausing")
|
|
|
|
ah.OutputCh <- string(wrappedResp)
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
if ah.enableTemplateTokenCh {
|
|
|
|
ah.TemplateTokenCh <- string(wrappedResp)
|
|
|
|
}
|
2018-07-25 02:02:27 +00:00
|
|
|
|
|
|
|
am.CredSuccess()
|
2021-03-03 22:15:18 +00:00
|
|
|
backoff.reset()
|
2018-07-25 02:02:27 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
ah.logger.Info("shutdown triggered")
|
2018-08-24 13:17:14 +00:00
|
|
|
continue
|
2018-07-25 02:02:27 +00:00
|
|
|
|
|
|
|
case <-credCh:
|
|
|
|
ah.logger.Info("auth method found new credentials, re-authenticating")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2018-11-19 23:50:42 +00:00
|
|
|
if secret == nil || secret.Auth == nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("authentication returned nil auth info", "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if secret.Auth.ClientToken == "" {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("authentication returned empty client token", "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ah.logger.Info("authentication successful, sending token to sinks")
|
|
|
|
ah.OutputCh <- secret.Auth.ClientToken
|
Vault Agent Template (#7652)
* Vault Agent Template: parse templates (#7540)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* Update command/agent/config/config.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* return the decode error instead of swallowing it
* Update command/agent/config/config_test.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* go mod tidy
* change error checking style
* Add agent template doc
* TemplateServer: render secrets with Consul Template (#7621)
* add template config parsing, but it's wrong b/c it's not using mapstructure
* parsing consul templates in agent config
* add additional test to configuration parsing, to cover basics
* another test fixture, rework simple test into table
* refactor into table test
* rename test
* remove flattenKeys and add other test fixture
* add template package
* WIP: add runner
* fix panic, actually copy templates, etc
* rework how the config.Vault is created and enable reading from the environment
* this was supposed to be a part of the prior commit
* move/add methods to testhelpers for converting some values to pointers
* use new methods in testhelpers
* add an unblock channel to block agent until a template has been rendered
* add note
* unblock if there are no templates
* cleanups
* go mod tidy
* remove dead code
* simple test to starT
* add simple, empty templates test
* Update package doc, error logs, and add missing close() on channel
* update code comment to be clear what I'm referring to
* have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only
* Update command/agent.go
Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com>
* update with test
* Add README and doc.go to the command/agent directory (#7503)
* Add README and doc.go to the command/agent directory
* Add link to website
* address feedback for agent.go
* updated with feedback from Calvin
* Rework template.Server to export the unblock channel, and remove it from the NewServer function
* apply feedback from Nick
* fix/restructure rendering test
* Add pointerutil package for converting types to their pointers
* Remove pointer helper methods; use sdk/helper/pointerutil instead
* update newRunnerConfig to use pointerutil and empty strings
* only wait for unblock if template server is initialized
* drain the token channel in this test
* conditionally send on channel
2019-10-18 21:21:46 +00:00
|
|
|
if ah.enableTemplateTokenCh {
|
|
|
|
ah.TemplateTokenCh <- secret.Auth.ClientToken
|
|
|
|
}
|
2018-07-25 02:02:27 +00:00
|
|
|
|
|
|
|
am.CredSuccess()
|
2021-03-03 22:15:18 +00:00
|
|
|
backoff.reset()
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 00:28:59 +00:00
|
|
|
if watcher != nil {
|
|
|
|
watcher.Stop()
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
|
2020-08-25 21:26:06 +00:00
|
|
|
watcher, err = clientToUse.NewLifetimeWatcher(&api.LifetimeWatcherInput{
|
2018-07-25 02:02:27 +00:00
|
|
|
Secret: secret,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2021-03-03 22:15:18 +00:00
|
|
|
ah.logger.Error("error creating lifetime watcher, backing off and retrying", "error", err, "backoff", backoff)
|
2018-07-25 02:02:27 +00:00
|
|
|
backoffOrQuit(ctx, backoff)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start the renewal process
|
|
|
|
ah.logger.Info("starting renewal process")
|
2019-10-29 00:28:59 +00:00
|
|
|
go watcher.Renew()
|
2018-07-25 02:02:27 +00:00
|
|
|
|
2019-10-29 00:28:59 +00:00
|
|
|
LifetimeWatcherLoop:
|
2018-07-25 02:02:27 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
2019-10-29 00:28:59 +00:00
|
|
|
ah.logger.Info("shutdown triggered, stopping lifetime watcher")
|
|
|
|
watcher.Stop()
|
|
|
|
break LifetimeWatcherLoop
|
2018-07-25 02:02:27 +00:00
|
|
|
|
2019-10-29 00:28:59 +00:00
|
|
|
case err := <-watcher.DoneCh():
|
|
|
|
ah.logger.Info("lifetime watcher done channel triggered")
|
2018-07-25 02:02:27 +00:00
|
|
|
if err != nil {
|
|
|
|
ah.logger.Error("error renewing token", "error", err)
|
|
|
|
}
|
2019-10-29 00:28:59 +00:00
|
|
|
break LifetimeWatcherLoop
|
2018-07-25 02:02:27 +00:00
|
|
|
|
2019-10-29 00:28:59 +00:00
|
|
|
case <-watcher.RenewCh():
|
2018-07-25 02:02:27 +00:00
|
|
|
ah.logger.Info("renewed auth token")
|
|
|
|
|
|
|
|
case <-credCh:
|
|
|
|
ah.logger.Info("auth method found new credentials, re-authenticating")
|
2019-10-29 00:28:59 +00:00
|
|
|
break LifetimeWatcherLoop
|
2018-07-25 02:02:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 20:04:21 +00:00
|
|
|
|
2021-03-03 22:15:18 +00:00
|
|
|
// agentBackoff tracks exponential backoff state.
|
|
|
|
type agentBackoff struct {
|
|
|
|
max time.Duration
|
|
|
|
current time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
func newAgentBackoff(max time.Duration) *agentBackoff {
|
|
|
|
if max <= 0 {
|
|
|
|
max = defaultMaxBackoff
|
|
|
|
}
|
|
|
|
|
|
|
|
return &agentBackoff{
|
|
|
|
max: max,
|
|
|
|
current: initialBackoff,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// next determines the next backoff duration that is roughly twice
|
|
|
|
// the current value, capped to a max value, with a measure of randomness.
|
|
|
|
func (b *agentBackoff) next() {
|
|
|
|
maxBackoff := 2 * b.current
|
|
|
|
|
|
|
|
if maxBackoff > b.max {
|
|
|
|
maxBackoff = b.max
|
2021-02-23 20:04:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Trim a random amount (0-25%) off the doubled duration
|
|
|
|
trim := rand.Int63n(int64(maxBackoff) / 4)
|
2021-03-03 22:15:18 +00:00
|
|
|
b.current = maxBackoff - time.Duration(trim)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *agentBackoff) reset() {
|
|
|
|
b.current = initialBackoff
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b agentBackoff) String() string {
|
|
|
|
return b.current.Truncate(10 * time.Millisecond).String()
|
2021-02-23 20:04:21 +00:00
|
|
|
}
|