open-vault/api/renewer_test.go
2017-07-07 17:14:44 -04:00

252 lines
4.5 KiB
Go

package api
import (
"fmt"
"reflect"
"testing"
"time"
)
func TestRenewer_NewRenewer(t *testing.T) {
t.Parallel()
client, err := NewClient(DefaultConfig())
if err != nil {
t.Fatal(err)
}
cases := []struct {
name string
i *RenewerInput
e *Renewer
err bool
}{
{
"nil",
nil,
nil,
true,
},
{
"missing_secret",
&RenewerInput{
Secret: nil,
},
nil,
true,
},
{
"default_grace",
&RenewerInput{
Secret: &Secret{},
},
&Renewer{
secret: &Secret{},
grace: DefaultRenewerGrace,
},
false,
},
{
"custom_grace",
&RenewerInput{
Secret: &Secret{},
Grace: 30,
},
&Renewer{
secret: &Secret{},
grace: 30,
},
false,
},
}
for i, tc := range cases {
t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) {
v, err := client.NewRenewer(tc.i)
if (err != nil) != tc.err {
t.Fatal(err)
}
if v == nil {
return
}
// Zero-out channels because reflect
v.client = nil
v.doneCh = nil
v.tickCh = nil
v.stopCh = nil
if !reflect.DeepEqual(tc.e, v) {
t.Errorf("not equal\nexp: %#v\nact: %#v", tc.e, v)
}
})
}
}
func TestRenewer_Renew(t *testing.T) {
client, vaultDone := testVaultServer(t)
defer vaultDone()
pgURL, pgDone := testPostgresDatabase(t)
defer pgDone()
// Generic
if _, err := client.Logical().Write("secret/value", map[string]interface{}{
"foo": "bar",
}); err != nil {
t.Fatal(err)
}
// Transit
if err := client.Sys().Mount("transit", &MountInput{
Type: "transit",
}); err != nil {
t.Fatal(err)
}
// PostgreSQL
if err := client.Sys().Mount("database", &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": "2s",
"max_ttl": "5s",
}); err != nil {
t.Fatal(err)
}
t.Run("generic", func(t *testing.T) {
secret, err := client.Logical().Read("secret/value")
if err != nil {
t.Fatal(err)
}
v, err := client.NewRenewer(&RenewerInput{
Secret: secret,
})
if err != nil {
t.Fatal(err)
}
go v.Renew()
defer v.Stop()
select {
case err := <-v.DoneCh():
if err != ErrRenewerNotRenewable {
t.Fatal(err)
}
}
})
t.Run("transit", func(t *testing.T) {
secret, err := client.Logical().Write("transit/encrypt/my-app", map[string]interface{}{
"plaintext": "Zm9vCg==",
})
if err != nil {
t.Fatal(err)
}
v, err := client.NewRenewer(&RenewerInput{
Secret: secret,
})
if err != nil {
t.Fatal(err)
}
go v.Renew()
defer v.Stop()
select {
case err := <-v.DoneCh():
if err != ErrRenewerNotRenewable {
t.Fatal(err)
}
}
})
t.Run("dynamic", func(t *testing.T) {
secret, err := client.Logical().Read("database/creds/readonly")
if err != nil {
t.Fatal(err)
}
v, err := client.NewRenewer(&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 <-v.TickCh():
// Received a renewal
case <-time.After(5 * time.Second):
t.Errorf("no data in 5s")
}
select {
case err := <-v.DoneCh():
if err != nil {
t.Fatal(err)
}
case <-time.After(5 * time.Second):
t.Errorf("no data in 5s")
}
})
t.Run("auth", func(t *testing.T) {
secret, err := client.Auth().Token().Create(&TokenCreateRequest{
Policies: []string{"default"},
TTL: "2s",
ExplicitMaxTTL: "5s",
})
if err != nil {
t.Fatal(err)
}
v, err := client.NewRenewer(&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 <-v.TickCh():
// Received a renewal
case <-time.After(5 * time.Second):
t.Errorf("no data in 5s")
}
select {
case err := <-v.DoneCh():
if err != nil {
t.Fatal(err)
}
case <-time.After(5 * time.Second):
t.Errorf("no data in 5s")
}
})
}