99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package awsauth
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/request"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/iam"
|
|
"github.com/aws/aws-sdk-go/service/iam/iamiface"
|
|
"github.com/hashicorp/go-secure-stdlib/awsutil"
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
)
|
|
|
|
type mockIAMClient awsutil.MockIAM
|
|
|
|
func (m *mockIAMClient) GetUserWithContext(_ aws.Context, input *iam.GetUserInput, _ ...request.Option) (*iam.GetUserOutput, error) {
|
|
return (*awsutil.MockIAM)(m).GetUser(input)
|
|
}
|
|
|
|
func (m *mockIAMClient) CreateAccessKeyWithContext(_ aws.Context, input *iam.CreateAccessKeyInput, _ ...request.Option) (*iam.CreateAccessKeyOutput, error) {
|
|
return (*awsutil.MockIAM)(m).CreateAccessKey(input)
|
|
}
|
|
|
|
func (m *mockIAMClient) DeleteAccessKeyWithContext(_ aws.Context, input *iam.DeleteAccessKeyInput, _ ...request.Option) (*iam.DeleteAccessKeyOutput, error) {
|
|
return (*awsutil.MockIAM)(m).DeleteAccessKey(input)
|
|
}
|
|
|
|
func TestPathConfigRotateRoot(t *testing.T) {
|
|
getIAMClient = func(sess *session.Session) iamiface.IAMAPI {
|
|
return &mockIAMClient{
|
|
CreateAccessKeyOutput: &iam.CreateAccessKeyOutput{
|
|
AccessKey: &iam.AccessKey{
|
|
AccessKeyId: aws.String("fizz2"),
|
|
SecretAccessKey: aws.String("buzz2"),
|
|
},
|
|
},
|
|
GetUserOutput: &iam.GetUserOutput{
|
|
User: &iam.User{
|
|
UserName: aws.String("ellen"),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
ctx := context.Background()
|
|
config := logical.TestBackendConfig()
|
|
logical.TestBackendConfig()
|
|
storage := &logical.InmemStorage{}
|
|
config.StorageView = storage
|
|
|
|
b, err := Backend(config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
clientConf := &clientConfig{
|
|
AccessKey: "fizz1",
|
|
SecretKey: "buzz1",
|
|
}
|
|
entry, err := logical.StorageEntryJSON("config/client", clientConf)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := storage.Put(ctx, entry); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "config/rotate-root",
|
|
Storage: storage,
|
|
}
|
|
resp, err := b.HandleRequest(ctx, req)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: resp: %#v\nerr:%v", resp, err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected nil response to represent a 204")
|
|
}
|
|
if resp.Data == nil {
|
|
t.Fatal("expected resp.Data")
|
|
}
|
|
if resp.Data["access_key"].(string) != "fizz2" {
|
|
t.Fatalf("expected new access key buzz2 but received %s", resp.Data["access_key"])
|
|
}
|
|
newClientConf, err := b.nonLockedClientConfigEntry(ctx, req.Storage)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp.Data["access_key"].(string) != newClientConf.AccessKey {
|
|
t.Fatalf("expected new access key buzz2 to be saved to storage but receieved %s", clientConf.AccessKey)
|
|
}
|
|
}
|