| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package plugin |
| |
| import ( |
| "context" |
| "reflect" |
| "testing" |
| "time" |
| |
| "github.com/hashicorp/go-plugin" |
| "github.com/hashicorp/vault/sdk/helper/consts" |
| "github.com/hashicorp/vault/sdk/logical" |
| "github.com/hashicorp/vault/sdk/plugin/pb" |
| "google.golang.org/grpc" |
| "google.golang.org/protobuf/proto" |
| ) |
| |
| func TestSystem_GRPC_ReturnsErrIfSystemViewNil(t *testing.T) { |
| _, err := new(gRPCSystemViewServer).ReplicationState(context.Background(), nil) |
| if err == nil { |
| t.Error("Expected error when using server with no impl") |
| } |
| } |
| |
| func TestSystem_GRPC_GRPC_impl(t *testing.T) { |
| var _ logical.SystemView = new(gRPCSystemViewClient) |
| } |
| |
| func TestSystem_GRPC_defaultLeaseTTL(t *testing.T) { |
| sys := logical.TestSystemView() |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| expected := sys.DefaultLeaseTTL() |
| actual := testSystemView.DefaultLeaseTTL() |
| if !reflect.DeepEqual(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_maxLeaseTTL(t *testing.T) { |
| sys := logical.TestSystemView() |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| expected := sys.MaxLeaseTTL() |
| actual := testSystemView.MaxLeaseTTL() |
| if !reflect.DeepEqual(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_tainted(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.TaintedVal = true |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| expected := sys.Tainted() |
| actual := testSystemView.Tainted() |
| if !reflect.DeepEqual(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_cachingDisabled(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.CachingDisabledVal = true |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| expected := sys.CachingDisabled() |
| actual := testSystemView.CachingDisabled() |
| if !reflect.DeepEqual(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_replicationState(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.ReplicationStateVal = consts.ReplicationPerformancePrimary |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| expected := sys.ReplicationState() |
| actual := testSystemView.ReplicationState() |
| if !reflect.DeepEqual(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_lookupPlugin(t *testing.T) { |
| sys := logical.TestSystemView() |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| |
| testSystemView := newGRPCSystemView(client) |
| |
| if _, err := testSystemView.LookupPlugin(context.Background(), "foo", consts.PluginTypeDatabase); err == nil { |
| t.Fatal("LookPlugin(): expected error on due to unsupported call from plugin") |
| } |
| } |
| |
| func TestSystem_GRPC_mlockEnabled(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.EnableMlock = true |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| |
| testSystemView := newGRPCSystemView(client) |
| |
| expected := sys.MlockEnabled() |
| actual := testSystemView.MlockEnabled() |
| if !reflect.DeepEqual(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_entityInfo(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.EntityVal = &logical.Entity{ |
| ID: "id", |
| Name: "name", |
| Metadata: map[string]string{ |
| "foo": "bar", |
| }, |
| Aliases: []*logical.Alias{ |
| { |
| MountType: "logical", |
| MountAccessor: "accessor", |
| Name: "name", |
| Metadata: map[string]string{ |
| "zip": "zap", |
| }, |
| }, |
| }, |
| Disabled: true, |
| } |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| actual, err := testSystemView.EntityInfo("") |
| if err != nil { |
| t.Fatal(err) |
| } |
| if !proto.Equal(sys.EntityVal, actual) { |
| t.Fatalf("expected: %v, got: %v", sys.EntityVal, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_groupsForEntity(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.GroupsVal = []*logical.Group{ |
| { |
| ID: "group1-id", |
| Name: "group1", |
| Metadata: map[string]string{ |
| "group-metadata": "metadata-value", |
| }, |
| }, |
| } |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| testSystemView := newGRPCSystemView(client) |
| |
| actual, err := testSystemView.GroupsForEntity("") |
| if err != nil { |
| t.Fatal(err) |
| } |
| if !proto.Equal(sys.GroupsVal[0], actual[0]) { |
| t.Fatalf("expected: %v, got: %v", sys.GroupsVal, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_pluginEnv(t *testing.T) { |
| sys := logical.TestSystemView() |
| sys.PluginEnvironment = &logical.PluginEnvironment{ |
| VaultVersion: "0.10.42", |
| VaultVersionPrerelease: "dev", |
| VaultVersionMetadata: "ent", |
| } |
| client, _ := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer client.Close() |
| |
| testSystemView := newGRPCSystemView(client) |
| |
| expected, err := sys.PluginEnv(context.Background()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| actual, err := testSystemView.PluginEnv(context.Background()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| if !proto.Equal(expected, actual) { |
| t.Fatalf("expected: %v, got: %v", expected, actual) |
| } |
| } |
| |
| func TestSystem_GRPC_GeneratePasswordFromPolicy(t *testing.T) { |
| policyName := "testpolicy" |
| expectedPassword := "87354qtnjgrehiogd9u0t43" |
| passGen := func() (password string, err error) { |
| return expectedPassword, nil |
| } |
| sys := &logical.StaticSystemView{ |
| PasswordPolicies: map[string]logical.PasswordGenerator{ |
| policyName: passGen, |
| }, |
| } |
| |
| client, server := plugin.TestGRPCConn(t, func(s *grpc.Server) { |
| pb.RegisterSystemViewServer(s, &gRPCSystemViewServer{ |
| impl: sys, |
| }) |
| }) |
| defer server.Stop() |
| defer client.Close() |
| |
| testSystemView := newGRPCSystemView(client) |
| |
| ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) |
| defer cancel() |
| |
| password, err := testSystemView.GeneratePasswordFromPolicy(ctx, policyName) |
| if err != nil { |
| t.Fatalf("no error expected, got: %s", err) |
| } |
| |
| if password != expectedPassword { |
| t.Fatalf("Actual password: %s\nExpected password: %s", password, expectedPassword) |
| } |
| } |