-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Add API helper for renewing a secret #2886
Changes from all commits
bf61690
46fa7be
dcbd729
42354ae
7e08052
320d764
f9465a8
de0250a
91a255b
47260ed
a8fe164
3d74752
437b8e7
c0b2d41
8cdc037
b2b9cdf
ce43621
54224b0
dfb6166
da9d57f
8f97e9b
21a17b6
c29e851
6034c9a
2fbb192
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package api_test | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/vault/api" | ||
"github.com/hashicorp/vault/builtin/logical/pki" | ||
"github.com/hashicorp/vault/builtin/logical/transit" | ||
"github.com/hashicorp/vault/logical" | ||
"github.com/hashicorp/vault/vault" | ||
|
||
vaulthttp "github.com/hashicorp/vault/http" | ||
logxi "github.com/mgutz/logxi/v1" | ||
dockertest "gopkg.in/ory-am/dockertest.v3" | ||
) | ||
|
||
var testVaultServerDefaultBackends = map[string]logical.Factory{ | ||
"transit": transit.Factory, | ||
"pki": pki.Factory, | ||
} | ||
|
||
func testVaultServer(t testing.TB) (*api.Client, func()) { | ||
return testVaultServerBackends(t, testVaultServerDefaultBackends) | ||
} | ||
|
||
func testVaultServerBackends(t testing.TB, backends map[string]logical.Factory) (*api.Client, func()) { | ||
coreConfig := &vault.CoreConfig{ | ||
DisableMlock: true, | ||
DisableCache: true, | ||
Logger: logxi.NullLog, | ||
LogicalBackends: backends, | ||
} | ||
|
||
cluster := vault.NewTestCluster(t, coreConfig, true) | ||
cluster.StartListeners() | ||
for _, core := range cluster.Cores { | ||
core.Handler.Handle("/", vaulthttp.Handler(core.Core)) | ||
} | ||
|
||
// make it easy to get access to the active | ||
core := cluster.Cores[0].Core | ||
vault.TestWaitActive(t, core) | ||
|
||
// Grab the root token | ||
rootToken := cluster.Cores[0].Root | ||
|
||
client := cluster.Cores[0].Client | ||
client.SetToken(rootToken) | ||
|
||
// Sanity check | ||
secret, err := client.Auth().Token().LookupSelf() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if secret == nil || secret.Data["id"].(string) != rootToken { | ||
t.Fatalf("token mismatch: %#v vs %q", secret, rootToken) | ||
} | ||
return client, func() { defer cluster.CloseListeners() } | ||
} | ||
|
||
// testPostgresDB creates a testing postgres database in a Docker container, | ||
// returning the connection URL and the associated closer function. | ||
func testPostgresDB(t testing.TB) (string, func()) { | ||
pool, err := dockertest.NewPool("") | ||
if err != nil { | ||
t.Fatalf("postgresdb: failed to connect to docker: %s", err) | ||
} | ||
|
||
resource, err := pool.Run("postgres", "latest", []string{ | ||
"POSTGRES_PASSWORD=secret", | ||
"POSTGRES_DB=database", | ||
}) | ||
if err != nil { | ||
t.Fatalf("postgresdb: could not start container: %s", err) | ||
} | ||
|
||
addr := fmt.Sprintf("postgres://postgres:secret@localhost:%s/database?sslmode=disable", resource.GetPort("5432/tcp")) | ||
|
||
if err := pool.Retry(func() error { | ||
db, err := sql.Open("postgres", addr) | ||
if err != nil { | ||
return err | ||
} | ||
return db.Ping() | ||
}); err != nil { | ||
t.Fatalf("postgresdb: could not connect: %s", err) | ||
} | ||
|
||
return addr, func() { | ||
if err := pool.Purge(resource); err != nil { | ||
t.Fatalf("postgresdb: failed to cleanup container: %s", err) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,6 +135,26 @@ func (c *TokenAuth) RenewSelf(increment int) (*Secret, error) { | |
return ParseSecret(resp.Body) | ||
} | ||
|
||
// RenewTokenAsSelf behaves like renew-self, but authenticates using a provided | ||
// token instead of the token attached to the client. | ||
func (c *TokenAuth) RenewTokenAsSelf(token string, increment int) (*Secret, error) { | ||
r := c.c.NewRequest("PUT", "/v1/auth/token/renew-self") | ||
r.ClientToken = token | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will make the client not thread safe, since any call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying the client is really challenging due to the way we setup the underlying TLS and connection stuff 😦 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also note this is setting the token on the request, not the client (it's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sethvargo Yes, I believe that should be fine. FYI there is a tls.Config.Clone() method (https://golang.org/pkg/crypto/tls/#Config.Clone) but it's only semi-safe in that underlying pointers are copied as-is so you can't use that and then say modify the CA pools without affecting other clients. |
||
|
||
body := map[string]interface{}{"increment": increment} | ||
if err := r.SetJSONBody(body); err != nil { | ||
return nil, err | ||
} | ||
|
||
resp, err := c.c.RawRequest(r) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
return ParseSecret(resp.Body) | ||
} | ||
|
||
// RevokeAccessor revokes a token associated with the given accessor | ||
// along with all the child tokens. | ||
func (c *TokenAuth) RevokeAccessor(accessor string) error { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to discuss pulling the functions in this file into a testing package which other Go tools that leverage Vault can use to stand up a Vault cluster and client in tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm +1 for this, I would definitely use it. Consul has a similar thing in its
testutil
package. I'm not married to thetestutil
name but a dedicated package with all of the test helpers exported (public) would be huge. For reference, the consul test server stuff is here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also vote for tackling this in a separate PR though to minimize scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vault already has a bunch of these. I would suggest not adding such a PR right now as you're likely to duplicate work.