open-vault/audit/hashstructure_test.go
Jeff Mitchell 1c7157e632 Reintroduce the ability to look up obfuscated values in the audit log
with a new endpoint '/sys/audit-hash', which returns the given input
string hashed with the given audit backend's hash function and salt
(currently, always HMAC-SHA256 and a backend-specific salt).

In the process of adding the HTTP handler, this also removes the custom
HTTP handlers for the other audit endpoints, which were simply
forwarding to the logical system backend. This means that the various
audit functions will now redirect correctly from a standby to master.
(Tests all pass.)

Fixes #784
2015-11-18 20:26:03 -05:00

223 lines
4.6 KiB
Go

package audit
import (
"crypto/sha256"
"fmt"
"reflect"
"testing"
"time"
"github.com/hashicorp/vault/helper/salt"
"github.com/hashicorp/vault/logical"
"github.com/mitchellh/copystructure"
)
func TestCopy_auth(t *testing.T) {
// Make a non-pointer one so that it can't be modified directly
expected := logical.Auth{
LeaseOptions: logical.LeaseOptions{
TTL: 1 * time.Hour,
IssueTime: time.Now().UTC(),
},
ClientToken: "foo",
}
auth := expected
// Copy it
dup, err := copystructure.Copy(&auth)
if err != nil {
t.Fatalf("err: %s", err)
}
// Check equality
auth2 := dup.(*logical.Auth)
if !reflect.DeepEqual(*auth2, expected) {
t.Fatalf("bad:\n\n%#v\n\n%#v", *auth2, expected)
}
}
func TestCopy_request(t *testing.T) {
// Make a non-pointer one so that it can't be modified directly
expected := logical.Request{
Data: map[string]interface{}{
"foo": "bar",
},
}
arg := expected
// Copy it
dup, err := copystructure.Copy(&arg)
if err != nil {
t.Fatalf("err: %s", err)
}
// Check equality
arg2 := dup.(*logical.Request)
if !reflect.DeepEqual(*arg2, expected) {
t.Fatalf("bad:\n\n%#v\n\n%#v", *arg2, expected)
}
}
func TestCopy_response(t *testing.T) {
// Make a non-pointer one so that it can't be modified directly
expected := logical.Response{
Data: map[string]interface{}{
"foo": "bar",
},
}
arg := expected
// Copy it
dup, err := copystructure.Copy(&arg)
if err != nil {
t.Fatalf("err: %s", err)
}
// Check equality
arg2 := dup.(*logical.Response)
if !reflect.DeepEqual(*arg2, expected) {
t.Fatalf("bad:\n\n%#v\n\n%#v", *arg2, expected)
}
}
func TestHashString(t *testing.T) {
inmemStorage := &logical.InmemStorage{}
inmemStorage.Put(&logical.StorageEntry{
Key: "salt",
Value: []byte("foo"),
})
localSalt, err := salt.NewSalt(inmemStorage, &salt.Config{
HMAC: sha256.New,
HMACType: "hmac-sha256",
})
if err != nil {
t.Fatalf("Error instantiating salt: %s", err)
}
out := HashString(localSalt, "foo")
if out != "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a" {
t.Fatalf("err: HashString output did not match expected")
}
}
func TestHash(t *testing.T) {
now := time.Now().UTC()
cases := []struct {
Input interface{}
Output interface{}
}{
{
&logical.Auth{ClientToken: "foo"},
&logical.Auth{ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a"},
},
{
&logical.Request{
Data: map[string]interface{}{
"foo": "bar",
},
},
&logical.Request{
Data: map[string]interface{}{
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
},
},
},
{
&logical.Response{
Data: map[string]interface{}{
"foo": "bar",
},
},
&logical.Response{
Data: map[string]interface{}{
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
},
},
},
{
"foo",
"foo",
},
{
&logical.Auth{
LeaseOptions: logical.LeaseOptions{
TTL: 1 * time.Hour,
IssueTime: now,
},
ClientToken: "foo",
},
&logical.Auth{
LeaseOptions: logical.LeaseOptions{
TTL: 1 * time.Hour,
IssueTime: now,
},
ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
},
},
}
inmemStorage := &logical.InmemStorage{}
inmemStorage.Put(&logical.StorageEntry{
Key: "salt",
Value: []byte("foo"),
})
localSalt, err := salt.NewSalt(inmemStorage, &salt.Config{
HMAC: sha256.New,
HMACType: "hmac-sha256",
})
if err != nil {
t.Fatalf("Error instantiating salt: %s", err)
}
for _, tc := range cases {
input := fmt.Sprintf("%#v", tc.Input)
if err := Hash(localSalt, tc.Input); err != nil {
t.Fatalf("err: %s\n\n%s", err, input)
}
if !reflect.DeepEqual(tc.Input, tc.Output) {
t.Fatalf("bad:\n\n%s\n\n%#v\n\n%#v", input, tc.Input, tc.Output)
}
}
}
func TestHashWalker(t *testing.T) {
replaceText := "foo"
cases := []struct {
Input interface{}
Output interface{}
}{
{
map[string]interface{}{
"hello": "foo",
},
map[string]interface{}{
"hello": replaceText,
},
},
{
map[string]interface{}{
"hello": []interface{}{"world"},
},
map[string]interface{}{
"hello": []interface{}{replaceText},
},
},
}
for _, tc := range cases {
output, err := HashStructure(tc.Input, func(string) string {
return replaceText
})
if err != nil {
t.Fatalf("err: %s\n\n%#v", err, tc.Input)
}
if !reflect.DeepEqual(output, tc.Output) {
t.Fatalf("bad:\n\n%#v\n\n%#v", tc.Input, output)
}
}
}