2017-06-26 21:21:37 +00:00
|
|
|
package api_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/hashicorp/vault/api"
|
|
|
|
"github.com/hashicorp/vault/builtin/logical/database"
|
|
|
|
"github.com/hashicorp/vault/builtin/logical/pki"
|
|
|
|
"github.com/hashicorp/vault/builtin/logical/transit"
|
|
|
|
"github.com/hashicorp/vault/logical"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestRenewer_Renew(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
client, vaultDone := testVaultServerBackends(t, map[string]logical.Factory{
|
|
|
|
"database": database.Factory,
|
|
|
|
"pki": pki.Factory,
|
|
|
|
"transit": transit.Factory,
|
|
|
|
})
|
|
|
|
defer vaultDone()
|
|
|
|
|
|
|
|
pgURL, pgDone := testPostgresDB(t)
|
|
|
|
defer pgDone()
|
|
|
|
|
|
|
|
t.Run("group", func(t *testing.T) {
|
|
|
|
t.Run("generic", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
if _, err := client.Logical().Write("secret/value", map[string]interface{}{
|
|
|
|
"foo": "bar",
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secret, err := client.Logical().Read("secret/value")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := client.NewRenewer(&api.RenewerInput{
|
|
|
|
Secret: secret,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
go v.Renew()
|
|
|
|
defer v.Stop()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-v.DoneCh():
|
|
|
|
if err != api.ErrRenewerNotRenewable {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
case renew := <-v.RenewCh():
|
2017-06-27 00:56:00 +00:00
|
|
|
t.Errorf("received renew, but should have been nil: %#v", renew)
|
2017-06-26 21:21:37 +00:00
|
|
|
case <-time.After(500 * time.Millisecond):
|
|
|
|
t.Error("should have been non-renewable")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("transit", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
if err := client.Sys().Mount("transit", &api.MountInput{
|
|
|
|
Type: "transit",
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secret, err := client.Logical().Write("transit/encrypt/my-app", map[string]interface{}{
|
|
|
|
"plaintext": "Zm9vCg==",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := client.NewRenewer(&api.RenewerInput{
|
|
|
|
Secret: secret,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
go v.Renew()
|
|
|
|
defer v.Stop()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-v.DoneCh():
|
|
|
|
if err != api.ErrRenewerNotRenewable {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
case renew := <-v.RenewCh():
|
2017-06-27 00:56:00 +00:00
|
|
|
t.Errorf("received renew, but should have been nil: %#v", renew)
|
2017-06-26 21:21:37 +00:00
|
|
|
case <-time.After(500 * time.Millisecond):
|
|
|
|
t.Error("should have been non-renewable")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("database", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
if err := client.Sys().Mount("database", &api.MountInput{
|
|
|
|
Type: "database",
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if _, err := client.Logical().Write("database/config/postgresql", map[string]interface{}{
|
|
|
|
"plugin_name": "postgresql-database-plugin",
|
|
|
|
"connection_url": pgURL,
|
|
|
|
"allowed_roles": "readonly",
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if _, err := client.Logical().Write("database/roles/readonly", map[string]interface{}{
|
|
|
|
"db_name": "postgresql",
|
|
|
|
"creation_statements": `` +
|
|
|
|
`CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';` +
|
|
|
|
`GRANT SELECT ON ALL TABLES IN SCHEMA public TO "{{name}}";`,
|
|
|
|
"default_ttl": "1s",
|
|
|
|
"max_ttl": "3s",
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secret, err := client.Logical().Read("database/creds/readonly")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := client.NewRenewer(&api.RenewerInput{
|
|
|
|
Secret: secret,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
go v.Renew()
|
|
|
|
defer v.Stop()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-v.DoneCh():
|
|
|
|
t.Errorf("should have renewed once before returning: %s", err)
|
|
|
|
case renew := <-v.RenewCh():
|
|
|
|
if renew == nil {
|
|
|
|
t.Fatal("renew is nil")
|
|
|
|
}
|
|
|
|
if !renew.Secret.Renewable {
|
|
|
|
t.Errorf("expected lease to be renewable: %#v", renew)
|
|
|
|
}
|
|
|
|
if renew.Secret.LeaseDuration > 2 {
|
|
|
|
t.Errorf("expected lease to < 2s: %#v", renew)
|
|
|
|
}
|
|
|
|
case <-time.After(3 * time.Second):
|
|
|
|
t.Errorf("no renewal")
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-v.DoneCh():
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
case renew := <-v.RenewCh():
|
|
|
|
t.Fatalf("should not have renewed (lease should be up): %#v", renew)
|
|
|
|
case <-time.After(3 * time.Second):
|
|
|
|
t.Errorf("no data")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("auth", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
secret, err := client.Auth().Token().Create(&api.TokenCreateRequest{
|
|
|
|
Policies: []string{"default"},
|
|
|
|
TTL: "1s",
|
|
|
|
ExplicitMaxTTL: "3s",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := client.NewRenewer(&api.RenewerInput{
|
|
|
|
Secret: secret,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
go v.Renew()
|
|
|
|
defer v.Stop()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-v.DoneCh():
|
|
|
|
t.Errorf("should have renewed once before returning: %s", err)
|
|
|
|
case renew := <-v.RenewCh():
|
|
|
|
if renew == nil {
|
|
|
|
t.Fatal("renew is nil")
|
|
|
|
}
|
|
|
|
if renew.Secret.Auth == nil {
|
|
|
|
t.Fatal("renew auth is nil")
|
|
|
|
}
|
|
|
|
if !renew.Secret.Auth.Renewable {
|
|
|
|
t.Errorf("expected lease to be renewable: %#v", renew)
|
|
|
|
}
|
|
|
|
if renew.Secret.Auth.LeaseDuration > 2 {
|
|
|
|
t.Errorf("expected lease to < 2s: %#v", renew)
|
|
|
|
}
|
|
|
|
if renew.Secret.Auth.ClientToken == "" {
|
|
|
|
t.Error("expected a client token")
|
|
|
|
}
|
|
|
|
if renew.Secret.Auth.Accessor == "" {
|
|
|
|
t.Error("expected an accessor")
|
|
|
|
}
|
|
|
|
case <-time.After(3 * time.Second):
|
|
|
|
t.Errorf("no renewal")
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-v.DoneCh():
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
case renew := <-v.RenewCh():
|
|
|
|
t.Fatalf("should not have renewed (lease should be up): %#v", renew)
|
|
|
|
case <-time.After(3 * time.Second):
|
|
|
|
t.Errorf("no data")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|