mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 11:08:10 +00:00
Run all builtins as plugins (#5536)
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/hashicorp/vault/builtin/logical/database"
|
"github.com/hashicorp/vault/builtin/logical/database"
|
||||||
"github.com/hashicorp/vault/builtin/logical/pki"
|
"github.com/hashicorp/vault/builtin/logical/pki"
|
||||||
"github.com/hashicorp/vault/builtin/logical/transit"
|
"github.com/hashicorp/vault/builtin/logical/transit"
|
||||||
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ func testVaultServerUnseal(t testing.TB) (*api.Client, []string, func()) {
|
|||||||
"pki": pki.Factory,
|
"pki": pki.Factory,
|
||||||
"transit": transit.Factory,
|
"transit": transit.Factory,
|
||||||
},
|
},
|
||||||
|
BuiltinRegistry: builtinplugins.Registry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
"github.com/hashicorp/go-retryablehttp"
|
||||||
"github.com/hashicorp/go-rootcerts"
|
"github.com/hashicorp/go-rootcerts"
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/parseutil"
|
"github.com/hashicorp/vault/helper/parseutil"
|
||||||
|
|||||||
@@ -133,7 +133,6 @@ type MountInput struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Config MountConfigInput `json:"config"`
|
Config MountConfigInput `json:"config"`
|
||||||
Local bool `json:"local"`
|
Local bool `json:"local"`
|
||||||
PluginName string `json:"plugin_name,omitempty"`
|
|
||||||
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
|
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
|
||||||
Options map[string]string `json:"options"`
|
Options map[string]string `json:"options"`
|
||||||
}
|
}
|
||||||
@@ -144,7 +143,6 @@ type MountConfigInput struct {
|
|||||||
Description *string `json:"description,omitempty" mapstructure:"description"`
|
Description *string `json:"description,omitempty" mapstructure:"description"`
|
||||||
MaxLeaseTTL string `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
MaxLeaseTTL string `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
||||||
ForceNoCache bool `json:"force_no_cache" mapstructure:"force_no_cache"`
|
ForceNoCache bool `json:"force_no_cache" mapstructure:"force_no_cache"`
|
||||||
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
|
||||||
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
|
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
|
||||||
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
|
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
|
||||||
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
|
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
|
||||||
@@ -166,7 +164,6 @@ type MountConfigOutput struct {
|
|||||||
DefaultLeaseTTL int `json:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
DefaultLeaseTTL int `json:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
||||||
MaxLeaseTTL int `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
MaxLeaseTTL int `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
||||||
ForceNoCache bool `json:"force_no_cache" mapstructure:"force_no_cache"`
|
ForceNoCache bool `json:"force_no_cache" mapstructure:"force_no_cache"`
|
||||||
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
|
||||||
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
|
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
|
||||||
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
|
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
|
||||||
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
|
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
|
||||||
|
|||||||
@@ -2,24 +2,43 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListPluginsInput is used as input to the ListPlugins function.
|
// ListPluginsInput is used as input to the ListPlugins function.
|
||||||
type ListPluginsInput struct{}
|
type ListPluginsInput struct {
|
||||||
|
// Type of the plugin. Required.
|
||||||
|
Type consts.PluginType `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListPluginsResponse is the response from the ListPlugins call.
|
// ListPluginsResponse is the response from the ListPlugins call.
|
||||||
type ListPluginsResponse struct {
|
type ListPluginsResponse struct {
|
||||||
// Names is the list of names of the plugins.
|
// PluginsByType is the list of plugins by type.
|
||||||
Names []string `json:"names"`
|
PluginsByType map[consts.PluginType][]string `json:"types"`
|
||||||
|
|
||||||
|
// NamesDeprecated is the list of names of the plugins.
|
||||||
|
NamesDeprecated []string `json:"names"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPlugins lists all plugins in the catalog and returns their names as a
|
// ListPlugins lists all plugins in the catalog and returns their names as a
|
||||||
// list of strings.
|
// list of strings.
|
||||||
func (c *Sys) ListPlugins(i *ListPluginsInput) (*ListPluginsResponse, error) {
|
func (c *Sys) ListPlugins(i *ListPluginsInput) (*ListPluginsResponse, error) {
|
||||||
path := "/v1/sys/plugins/catalog"
|
path := ""
|
||||||
req := c.c.NewRequest("LIST", path)
|
method := ""
|
||||||
|
if i.Type == consts.PluginTypeUnknown {
|
||||||
|
path = "/v1/sys/plugins/catalog"
|
||||||
|
method = "GET"
|
||||||
|
} else {
|
||||||
|
path = fmt.Sprintf("/v1/sys/plugins/catalog/%s", i.Type)
|
||||||
|
method = "LIST"
|
||||||
|
}
|
||||||
|
|
||||||
|
req := c.c.NewRequest(method, path)
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
@@ -29,21 +48,76 @@ func (c *Sys) ListPlugins(i *ListPluginsInput) (*ListPluginsResponse, error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var result struct {
|
secret, err := ParseSecret(resp.Body)
|
||||||
Data struct {
|
if err != nil {
|
||||||
Keys []string `json:"keys"`
|
|
||||||
} `json:"data"`
|
|
||||||
}
|
|
||||||
if err := resp.DecodeJSON(&result); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if secret == nil || secret.Data == nil {
|
||||||
|
return nil, errors.New("data from server response is empty")
|
||||||
|
}
|
||||||
|
|
||||||
return &ListPluginsResponse{Names: result.Data.Keys}, nil
|
if resp.StatusCode == 405 && req.Method == "GET" {
|
||||||
|
// We received an Unsupported Operation response from Vault, indicating
|
||||||
|
// Vault of an older version that doesn't support the READ method yet.
|
||||||
|
req.Method = "LIST"
|
||||||
|
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
var result struct {
|
||||||
|
Data struct {
|
||||||
|
Keys []string `json:"keys"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
if err := resp.DecodeJSON(&result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ListPluginsResponse{NamesDeprecated: result.Data.Keys}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &ListPluginsResponse{
|
||||||
|
PluginsByType: make(map[consts.PluginType][]string),
|
||||||
|
}
|
||||||
|
if i.Type == consts.PluginTypeUnknown {
|
||||||
|
for pluginTypeStr, pluginsRaw := range secret.Data {
|
||||||
|
pluginType, err := consts.ParsePluginType(pluginTypeStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginsIfc, ok := pluginsRaw.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unable to parse plugins for %q type", pluginTypeStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins := make([]string, len(pluginsIfc))
|
||||||
|
for i, nameIfc := range pluginsIfc {
|
||||||
|
name, ok := nameIfc.(string)
|
||||||
|
if !ok {
|
||||||
|
|
||||||
|
}
|
||||||
|
plugins[i] = name
|
||||||
|
}
|
||||||
|
result.PluginsByType[pluginType] = plugins
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var respKeys []string
|
||||||
|
if err := mapstructure.Decode(secret.Data["keys"], &respKeys); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.PluginsByType[i.Type] = respKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPluginInput is used as input to the GetPlugin function.
|
// GetPluginInput is used as input to the GetPlugin function.
|
||||||
type GetPluginInput struct {
|
type GetPluginInput struct {
|
||||||
Name string `json:"-"`
|
Name string `json:"-"`
|
||||||
|
|
||||||
|
// Type of the plugin. Required.
|
||||||
|
Type consts.PluginType `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPluginResponse is the response from the GetPlugin call.
|
// GetPluginResponse is the response from the GetPlugin call.
|
||||||
@@ -56,7 +130,7 @@ type GetPluginResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Sys) GetPlugin(i *GetPluginInput) (*GetPluginResponse, error) {
|
func (c *Sys) GetPlugin(i *GetPluginInput) (*GetPluginResponse, error) {
|
||||||
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s", i.Name)
|
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s/%s", i.Type, i.Name)
|
||||||
req := c.c.NewRequest(http.MethodGet, path)
|
req := c.c.NewRequest(http.MethodGet, path)
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
@@ -82,6 +156,9 @@ type RegisterPluginInput struct {
|
|||||||
// Name is the name of the plugin. Required.
|
// Name is the name of the plugin. Required.
|
||||||
Name string `json:"-"`
|
Name string `json:"-"`
|
||||||
|
|
||||||
|
// Type of the plugin. Required.
|
||||||
|
Type consts.PluginType `json:"type"`
|
||||||
|
|
||||||
// Args is the list of args to spawn the process with.
|
// Args is the list of args to spawn the process with.
|
||||||
Args []string `json:"args,omitempty"`
|
Args []string `json:"args,omitempty"`
|
||||||
|
|
||||||
@@ -94,7 +171,7 @@ type RegisterPluginInput struct {
|
|||||||
|
|
||||||
// RegisterPlugin registers the plugin with the given information.
|
// RegisterPlugin registers the plugin with the given information.
|
||||||
func (c *Sys) RegisterPlugin(i *RegisterPluginInput) error {
|
func (c *Sys) RegisterPlugin(i *RegisterPluginInput) error {
|
||||||
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s", i.Name)
|
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s/%s", i.Type, i.Name)
|
||||||
req := c.c.NewRequest(http.MethodPut, path)
|
req := c.c.NewRequest(http.MethodPut, path)
|
||||||
if err := req.SetJSONBody(i); err != nil {
|
if err := req.SetJSONBody(i); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -113,12 +190,15 @@ func (c *Sys) RegisterPlugin(i *RegisterPluginInput) error {
|
|||||||
type DeregisterPluginInput struct {
|
type DeregisterPluginInput struct {
|
||||||
// Name is the name of the plugin. Required.
|
// Name is the name of the plugin. Required.
|
||||||
Name string `json:"-"`
|
Name string `json:"-"`
|
||||||
|
|
||||||
|
// Type of the plugin. Required.
|
||||||
|
Type consts.PluginType `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeregisterPlugin removes the plugin with the given name from the plugin
|
// DeregisterPlugin removes the plugin with the given name from the plugin
|
||||||
// catalog.
|
// catalog.
|
||||||
func (c *Sys) DeregisterPlugin(i *DeregisterPluginInput) error {
|
func (c *Sys) DeregisterPlugin(i *DeregisterPluginInput) error {
|
||||||
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s", i.Name)
|
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s/%s", i.Type, i.Name)
|
||||||
req := c.c.NewRequest(http.MethodDelete, path)
|
req := c.c.NewRequest(http.MethodDelete, path)
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: factory,
|
CredentialFactory: factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepMapAppId(t),
|
testAccStepMapAppId(t),
|
||||||
testAccStepMapUserId(t),
|
testAccStepMapUserId(t),
|
||||||
@@ -65,7 +65,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
|
|
||||||
func TestBackend_cidr(t *testing.T) {
|
func TestBackend_cidr(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
CredentialFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepMapAppIdDisplayName(t),
|
testAccStepMapAppIdDisplayName(t),
|
||||||
testAccStepMapUserIdCidr(t, "192.168.1.0/16"),
|
testAccStepMapUserIdCidr(t, "192.168.1.0/16"),
|
||||||
@@ -78,7 +78,7 @@ func TestBackend_cidr(t *testing.T) {
|
|||||||
|
|
||||||
func TestBackend_displayName(t *testing.T) {
|
func TestBackend_displayName(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
CredentialFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepMapAppIdDisplayName(t),
|
testAccStepMapAppIdDisplayName(t),
|
||||||
testAccStepMapUserId(t),
|
testAccStepMapUserId(t),
|
||||||
|
|||||||
@@ -508,8 +508,8 @@ func TestBackend_ConfigClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: false,
|
AcceptanceTest: false,
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
stepCreate,
|
stepCreate,
|
||||||
stepInvalidAccessKey,
|
stepInvalidAccessKey,
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ func TestBackend_PermittedDNSDomainsIntermediateCA(t *testing.T) {
|
|||||||
// Sign the intermediate CSR using /pki
|
// Sign the intermediate CSR using /pki
|
||||||
secret, err = client.Logical().Write("pki/root/sign-intermediate", map[string]interface{}{
|
secret, err = client.Logical().Write("pki/root/sign-intermediate", map[string]interface{}{
|
||||||
"permitted_dns_domains": ".myvault.com",
|
"permitted_dns_domains": ".myvault.com",
|
||||||
"csr": intermediateCSR,
|
"csr": intermediateCSR,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -840,7 +840,7 @@ func TestBackend_CertWrites(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tc := logicaltest.TestCase{
|
tc := logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "aaa", ca1, "foo", allowed{}, false),
|
testAccStepCert(t, "aaa", ca1, "foo", allowed{}, false),
|
||||||
testAccStepCert(t, "bbb", ca2, "foo", allowed{}, false),
|
testAccStepCert(t, "bbb", ca2, "foo", allowed{}, false),
|
||||||
@@ -863,7 +863,7 @@ func TestBackend_basic_CA(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -898,7 +898,7 @@ func TestBackend_Basic_CRLs(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCertNoLease(t, "web", ca, "foo"),
|
testAccStepCertNoLease(t, "web", ca, "foo"),
|
||||||
testAccStepLoginDefaultLease(t, connState),
|
testAccStepLoginDefaultLease(t, connState),
|
||||||
@@ -923,7 +923,7 @@ func TestBackend_basic_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -948,7 +948,7 @@ func TestBackend_common_name_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -977,7 +977,7 @@ func TestBackend_ext_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:A UTF8String Extension"}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:A UTF8String Extension"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -1032,7 +1032,7 @@ func TestBackend_dns_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{dns: "example.com"}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{dns: "example.com"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -1063,7 +1063,7 @@ func TestBackend_email_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{emails: "valid@example.com"}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{emails: "valid@example.com"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -1094,7 +1094,7 @@ func TestBackend_organizationalUnit_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{organizational_units: "engineering"}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{organizational_units: "engineering"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -1123,7 +1123,7 @@ func TestBackend_uri_singleCert(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/*"}, false),
|
testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/*"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
@@ -1151,7 +1151,7 @@ func TestBackend_mixed_constraints(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "1unconstrained", ca, "foo", allowed{}, false),
|
testAccStepCert(t, "1unconstrained", ca, "foo", allowed{}, false),
|
||||||
testAccStepCert(t, "2matching", ca, "foo", allowed{names: "*.example.com,whatever"}, false),
|
testAccStepCert(t, "2matching", ca, "foo", allowed{names: "*.example.com,whatever"}, false),
|
||||||
@@ -1172,7 +1172,7 @@ func TestBackend_untrusted(t *testing.T) {
|
|||||||
t.Fatalf("error testing connection state: %v", err)
|
t.Fatalf("error testing connection state: %v", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
CredentialBackend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ func TestBackend_Config(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testConfigWrite(t, config_data1),
|
testConfigWrite(t, config_data1),
|
||||||
testLoginWrite(t, login_data, expectedTTL1.Nanoseconds(), false),
|
testLoginWrite(t, login_data, expectedTTL1.Nanoseconds(), false),
|
||||||
@@ -105,8 +105,8 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, false),
|
testAccStepConfig(t, false),
|
||||||
testAccMap(t, "default", "fakepol"),
|
testAccMap(t, "default", "fakepol"),
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
b := factory(t)
|
b := factory(t)
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigUrl(t),
|
testAccStepConfigUrl(t),
|
||||||
// Map Scientists group (from LDAP server) with foo policy
|
// Map Scientists group (from LDAP server) with foo policy
|
||||||
@@ -429,7 +429,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
func TestBackend_basic_noPolicies(t *testing.T) {
|
func TestBackend_basic_noPolicies(t *testing.T) {
|
||||||
b := factory(t)
|
b := factory(t)
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigUrl(t),
|
testAccStepConfigUrl(t),
|
||||||
// Create LDAP user
|
// Create LDAP user
|
||||||
@@ -444,7 +444,7 @@ func TestBackend_basic_noPolicies(t *testing.T) {
|
|||||||
func TestBackend_basic_group_noPolicies(t *testing.T) {
|
func TestBackend_basic_group_noPolicies(t *testing.T) {
|
||||||
b := factory(t)
|
b := factory(t)
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigUrl(t),
|
testAccStepConfigUrl(t),
|
||||||
// Create engineers group with no policies
|
// Create engineers group with no policies
|
||||||
@@ -463,7 +463,7 @@ func TestBackend_basic_authbind(t *testing.T) {
|
|||||||
b := factory(t)
|
b := factory(t)
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigUrlWithAuthBind(t),
|
testAccStepConfigUrlWithAuthBind(t),
|
||||||
testAccStepGroup(t, "Scientists", "foo"),
|
testAccStepGroup(t, "Scientists", "foo"),
|
||||||
@@ -478,7 +478,7 @@ func TestBackend_basic_discover(t *testing.T) {
|
|||||||
b := factory(t)
|
b := factory(t)
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigUrlWithDiscover(t),
|
testAccStepConfigUrlWithDiscover(t),
|
||||||
testAccStepGroup(t, "Scientists", "foo"),
|
testAccStepGroup(t, "Scientists", "foo"),
|
||||||
@@ -493,7 +493,7 @@ func TestBackend_basic_nogroupdn(t *testing.T) {
|
|||||||
b := factory(t)
|
b := factory(t)
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigUrlNoGroupDN(t),
|
testAccStepConfigUrlNoGroupDN(t),
|
||||||
testAccStepGroup(t, "Scientists", "foo"),
|
testAccStepGroup(t, "Scientists", "foo"),
|
||||||
@@ -508,7 +508,7 @@ func TestBackend_groupCrud(t *testing.T) {
|
|||||||
b := factory(t)
|
b := factory(t)
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepGroup(t, "g1", "foo"),
|
testAccStepGroup(t, "g1", "foo"),
|
||||||
testAccStepReadGroup(t, "g1", "foo"),
|
testAccStepReadGroup(t, "g1", "foo"),
|
||||||
@@ -525,7 +525,7 @@ func TestBackend_configDefaultsAfterUpdate(t *testing.T) {
|
|||||||
b := factory(t)
|
b := factory(t)
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
logicaltest.TestStep{
|
logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
@@ -687,7 +687,7 @@ func TestBackend_userCrud(t *testing.T) {
|
|||||||
b := Backend()
|
b := Backend()
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepUser(t, "g1", "bar"),
|
testAccStepUser(t, "g1", "bar"),
|
||||||
testAccStepReadUser(t, "g1", "bar"),
|
testAccStepReadUser(t, "g1", "bar"),
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func TestBackend_Config(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testConfigCreate(t, configData),
|
testConfigCreate(t, configData),
|
||||||
testLoginWrite(t, username, "wrong", "E0000004", 0, nil),
|
testLoginWrite(t, username, "wrong", "E0000004", 0, nil),
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ func TestBackend_Config(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: false,
|
AcceptanceTest: false,
|
||||||
// PreCheck: func() { testAccPreCheck(t) },
|
// PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testConfigWrite(t, configDataBasic, false),
|
testConfigWrite(t, configDataBasic, false),
|
||||||
testConfigWrite(t, configDataMissingRequired, true),
|
testConfigWrite(t, configDataMissingRequired, true),
|
||||||
@@ -135,7 +135,7 @@ func TestBackend_users(t *testing.T) {
|
|||||||
t.Fatalf("Unable to create backend: %s", err)
|
t.Fatalf("Unable to create backend: %s", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testStepUpdateUser(t, "web", "foo"),
|
testStepUpdateUser(t, "web", "foo"),
|
||||||
testStepUpdateUser(t, "web2", "foo"),
|
testStepUpdateUser(t, "web2", "foo"),
|
||||||
@@ -210,9 +210,9 @@ func TestBackend_acceptance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
PreCheck: testAccPreCheck(t, host, port),
|
PreCheck: testAccPreCheck(t, host, port),
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
// Login with valid but unknown user will fail because unregistered_user_policies is emtpy
|
// Login with valid but unknown user will fail because unregistered_user_policies is emtpy
|
||||||
testConfigWrite(t, configDataAcceptanceNoAllowUnreg, false),
|
testConfigWrite(t, configDataAcceptanceNoAllowUnreg, false),
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
t.Fatalf("Unable to create backend: %s", err)
|
t.Fatalf("Unable to create backend: %s", err)
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepUser(t, "web", "password", "foo"),
|
testAccStepUser(t, "web", "password", "foo"),
|
||||||
testAccStepUser(t, "web2", "password", "foo"),
|
testAccStepUser(t, "web2", "password", "foo"),
|
||||||
@@ -125,7 +125,7 @@ func TestBackend_userCrud(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepUser(t, "web", "password", "foo"),
|
testAccStepUser(t, "web", "password", "foo"),
|
||||||
testAccStepReadUser(t, "web", "foo"),
|
testAccStepReadUser(t, "web", "foo"),
|
||||||
@@ -148,7 +148,7 @@ func TestBackend_userCreateOperation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testUserCreateOperation(t, "web", "password", "foo"),
|
testUserCreateOperation(t, "web", "password", "foo"),
|
||||||
testAccStepLogin(t, "web", "password", []string{"default", "foo"}),
|
testAccStepLogin(t, "web", "password", []string{"default", "foo"}),
|
||||||
@@ -169,7 +169,7 @@ func TestBackend_passwordUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepUser(t, "web", "password", "foo"),
|
testAccStepUser(t, "web", "password", "foo"),
|
||||||
testAccStepReadUser(t, "web", "foo"),
|
testAccStepReadUser(t, "web", "foo"),
|
||||||
@@ -194,7 +194,7 @@ func TestBackend_policiesUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
CredentialBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepUser(t, "web", "password", "foo"),
|
testAccStepUser(t, "web", "password", "foo"),
|
||||||
testAccStepReadUser(t, "web", "foo"),
|
testAccStepReadUser(t, "web", "foo"),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWritePolicy(t, "test", testDynamoPolicy),
|
testAccStepWritePolicy(t, "test", testDynamoPolicy),
|
||||||
@@ -77,7 +77,7 @@ func TestBackend_basicSTS(t *testing.T) {
|
|||||||
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
|
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
},
|
},
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfigWithCreds(t, accessKey),
|
testAccStepConfigWithCreds(t, accessKey),
|
||||||
testAccStepRotateRoot(accessKey),
|
testAccStepRotateRoot(accessKey),
|
||||||
@@ -103,7 +103,7 @@ func TestBackend_policyCrud(t *testing.T) {
|
|||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWritePolicy(t, "test", testDynamoPolicy),
|
testAccStepWritePolicy(t, "test", testDynamoPolicy),
|
||||||
@@ -724,7 +724,7 @@ func TestBackend_basicPolicyArnRef(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWriteArnPolicyRef(t, "test", ec2PolicyArn),
|
testAccStepWriteArnPolicyRef(t, "test", ec2PolicyArn),
|
||||||
@@ -755,7 +755,7 @@ func TestBackend_iamUserManagedInlinePolicies(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWriteRole(t, "test", roleData),
|
testAccStepWriteRole(t, "test", roleData),
|
||||||
@@ -804,7 +804,7 @@ func TestBackend_AssumedRoleWithPolicyDoc(t *testing.T) {
|
|||||||
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
|
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
},
|
},
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWriteRole(t, "test", roleData),
|
testAccStepWriteRole(t, "test", roleData),
|
||||||
@@ -840,7 +840,7 @@ func TestBackend_RoleDefaultSTSTTL(t *testing.T) {
|
|||||||
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
|
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
},
|
},
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWriteRole(t, "test", roleData),
|
testAccStepWriteRole(t, "test", roleData),
|
||||||
@@ -856,7 +856,7 @@ func TestBackend_policyArnCrud(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Backend: getBackend(t),
|
LogicalBackend: getBackend(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t),
|
testAccStepConfig(t),
|
||||||
testAccStepWriteArnPolicyRef(t, "test", ec2PolicyArn),
|
testAccStepWriteArnPolicyRef(t, "test", ec2PolicyArn),
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, hostname),
|
testAccStepConfig(t, hostname),
|
||||||
testAccStepRole(t),
|
testAccStepRole(t),
|
||||||
@@ -116,7 +116,7 @@ func TestBackend_roleCrud(t *testing.T) {
|
|||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, hostname),
|
testAccStepConfig(t, hostname),
|
||||||
testAccStepRole(t),
|
testAccStepRole(t),
|
||||||
|
|||||||
@@ -564,7 +564,7 @@ func testBackendManagement(t *testing.T, version string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData),
|
testAccStepConfig(t, connData),
|
||||||
testAccStepWriteManagementPolicy(t, "test", ""),
|
testAccStepWriteManagementPolicy(t, "test", ""),
|
||||||
@@ -608,7 +608,7 @@ func testBackendBasic(t *testing.T, version string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData),
|
testAccStepConfig(t, connData),
|
||||||
testAccStepWritePolicy(t, "test", testPolicy, ""),
|
testAccStepWritePolicy(t, "test", testPolicy, ""),
|
||||||
@@ -620,7 +620,7 @@ func testBackendBasic(t *testing.T, version string) {
|
|||||||
func TestBackend_crud(t *testing.T) {
|
func TestBackend_crud(t *testing.T) {
|
||||||
b, _ := Factory(context.Background(), logical.TestBackendConfig())
|
b, _ := Factory(context.Background(), logical.TestBackendConfig())
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepWritePolicy(t, "test", testPolicy, ""),
|
testAccStepWritePolicy(t, "test", testPolicy, ""),
|
||||||
testAccStepWritePolicy(t, "test2", testPolicy, ""),
|
testAccStepWritePolicy(t, "test2", testPolicy, ""),
|
||||||
@@ -635,7 +635,7 @@ func TestBackend_crud(t *testing.T) {
|
|||||||
func TestBackend_role_lease(t *testing.T) {
|
func TestBackend_role_lease(t *testing.T) {
|
||||||
b, _ := Factory(context.Background(), logical.TestBackendConfig())
|
b, _ := Factory(context.Background(), logical.TestBackendConfig())
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepWritePolicy(t, "test", testPolicy, "6h"),
|
testAccStepWritePolicy(t, "test", testPolicy, "6h"),
|
||||||
testAccStepReadPolicy(t, "test", testPolicy, 6*time.Hour),
|
testAccStepReadPolicy(t, "test", testPolicy, 6*time.Hour),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-test/deep"
|
"github.com/go-test/deep"
|
||||||
"github.com/hashicorp/vault/builtin/logical/database/dbplugin"
|
"github.com/hashicorp/vault/builtin/logical/database/dbplugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
vaulthttp "github.com/hashicorp/vault/http"
|
vaulthttp "github.com/hashicorp/vault/http"
|
||||||
@@ -101,7 +102,7 @@ func getCluster(t *testing.T) (*vault.TestCluster, logical.SystemView) {
|
|||||||
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
||||||
|
|
||||||
sys := vault.TestDynamicSystemView(cores[0].Core)
|
sys := vault.TestDynamicSystemView(cores[0].Core)
|
||||||
vault.TestAddTestPlugin(t, cores[0].Core, "postgresql-database-plugin", "TestBackend_PluginMain", []string{}, "")
|
vault.TestAddTestPlugin(t, cores[0].Core, "postgresql-database-plugin", consts.PluginTypeDatabase, "TestBackend_PluginMain", []string{}, "")
|
||||||
|
|
||||||
return cluster, sys
|
return cluster, sys
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ func (dc *DatabasePluginClient) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPluginClient returns a databaseRPCClient with a connection to a running
|
// NewPluginClient returns a databaseRPCClient with a connection to a running
|
||||||
// plugin. The client is wrapped in a DatabasePluginClient object to ensure the
|
// plugin. The client is wrapped in a DatabasePluginClient object to ensure the
|
||||||
// plugin is killed on call of Close().
|
// plugin is killed on call of Close().
|
||||||
func newPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger) (Database, error) {
|
func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger, isMetadataMode bool) (Database, error) {
|
||||||
|
|
||||||
// pluginSets is the map of plugins we can dispense.
|
// pluginSets is the map of plugins we can dispense.
|
||||||
pluginSets := map[int]plugin.PluginSet{
|
pluginSets := map[int]plugin.PluginSet{
|
||||||
// Version 3 supports both protocols
|
// Version 3 supports both protocols
|
||||||
@@ -46,7 +47,13 @@ func newPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunne
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := pluginRunner.Run(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
var client *plugin.Client
|
||||||
|
var err error
|
||||||
|
if isMetadataMode {
|
||||||
|
client, err = pluginRunner.RunMetadataMode(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
||||||
|
} else {
|
||||||
|
client, err = pluginRunner.Run(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ type Database interface {
|
|||||||
// object in a logging and metrics middleware.
|
// object in a logging and metrics middleware.
|
||||||
func PluginFactory(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger) (Database, error) {
|
func PluginFactory(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger) (Database, error) {
|
||||||
// Look for plugin in the plugin catalog
|
// Look for plugin in the plugin catalog
|
||||||
pluginRunner, err := sys.LookupPlugin(ctx, pluginName)
|
pluginRunner, err := sys.LookupPlugin(ctx, pluginName, consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,7 @@ func PluginFactory(ctx context.Context, pluginName string, sys pluginutil.LookRu
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// create a DatabasePluginClient instance
|
// create a DatabasePluginClient instance
|
||||||
db, err = newPluginClient(ctx, sys, pluginRunner, namedLogger)
|
db, err = NewPluginClient(ctx, sys, pluginRunner, namedLogger, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/vault/builtin/logical/database/dbplugin"
|
"github.com/hashicorp/vault/builtin/logical/database/dbplugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
vaulthttp "github.com/hashicorp/vault/http"
|
vaulthttp "github.com/hashicorp/vault/http"
|
||||||
@@ -94,8 +95,8 @@ func getCluster(t *testing.T) (*vault.TestCluster, logical.SystemView) {
|
|||||||
cores := cluster.Cores
|
cores := cluster.Cores
|
||||||
|
|
||||||
sys := vault.TestDynamicSystemView(cores[0].Core)
|
sys := vault.TestDynamicSystemView(cores[0].Core)
|
||||||
vault.TestAddTestPlugin(t, cores[0].Core, "test-plugin", "TestPlugin_GRPC_Main", []string{}, "")
|
vault.TestAddTestPlugin(t, cores[0].Core, "test-plugin", consts.PluginTypeDatabase, "TestPlugin_GRPC_Main", []string{}, "")
|
||||||
vault.TestAddTestPlugin(t, cores[0].Core, "test-plugin-netRPC", "TestPlugin_NetRPC_Main", []string{}, "")
|
vault.TestAddTestPlugin(t, cores[0].Core, "test-plugin-netRPC", consts.PluginTypeDatabase, "TestPlugin_NetRPC_Main", []string{}, "")
|
||||||
|
|
||||||
return cluster, sys
|
return cluster, sys
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(connData, false),
|
testAccStepConfig(connData, false),
|
||||||
testAccStepRole(),
|
testAccStepRole(),
|
||||||
@@ -147,7 +147,7 @@ func TestBackend_roleCrud(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(connData, false),
|
testAccStepConfig(connData, false),
|
||||||
testAccStepRole(),
|
testAccStepRole(),
|
||||||
@@ -175,7 +175,7 @@ func TestBackend_leaseWriteRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(connData, false),
|
testAccStepConfig(connData, false),
|
||||||
testAccStepWriteLease(),
|
testAccStepWriteLease(),
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: testAccPreCheckFunc(t, connURL),
|
PreCheck: testAccPreCheckFunc(t, connURL),
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connURL),
|
testAccStepConfig(t, connURL),
|
||||||
testAccStepRole(t),
|
testAccStepRole(t),
|
||||||
@@ -138,7 +138,7 @@ func TestBackend_roleCrud(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: testAccPreCheckFunc(t, connURL),
|
PreCheck: testAccPreCheckFunc(t, connURL),
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connURL),
|
testAccStepConfig(t, connURL),
|
||||||
testAccStepRole(t),
|
testAccStepRole(t),
|
||||||
@@ -162,7 +162,7 @@ func TestBackend_leaseWriteRead(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
PreCheck: testAccPreCheckFunc(t, connURL),
|
PreCheck: testAccPreCheckFunc(t, connURL),
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connURL),
|
testAccStepConfig(t, connURL),
|
||||||
testAccStepWriteLease(t),
|
testAccStepWriteLease(t),
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
|
|
||||||
// for wildcard based mysql user
|
// for wildcard based mysql user
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepRole(t, true),
|
testAccStepRole(t, true),
|
||||||
@@ -141,7 +141,7 @@ func TestBackend_basicHostRevoke(t *testing.T) {
|
|||||||
|
|
||||||
// for host based mysql user
|
// for host based mysql user
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepRole(t, false),
|
testAccStepRole(t, false),
|
||||||
@@ -166,7 +166,7 @@ func TestBackend_roleCrud(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
// test SQL with wildcard based user
|
// test SQL with wildcard based user
|
||||||
@@ -197,7 +197,7 @@ func TestBackend_leaseWriteRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepWriteLease(t),
|
testAccStepWriteLease(t),
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ func TestBackend_CSRValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{},
|
Steps: []logicaltest.TestStep{},
|
||||||
}
|
}
|
||||||
|
|
||||||
intdata := map[string]interface{}{}
|
intdata := map[string]interface{}{}
|
||||||
@@ -178,8 +178,8 @@ func TestBackend_URLsCRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{},
|
Steps: []logicaltest.TestStep{},
|
||||||
}
|
}
|
||||||
|
|
||||||
intdata := map[string]interface{}{}
|
intdata := map[string]interface{}{}
|
||||||
@@ -208,7 +208,7 @@ func TestBackend_RSARoles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
logicaltest.TestStep{
|
logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
@@ -249,7 +249,7 @@ func TestBackend_RSARoles_CSR(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
logicaltest.TestStep{
|
logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
@@ -290,7 +290,7 @@ func TestBackend_ECRoles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
logicaltest.TestStep{
|
logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
@@ -331,7 +331,7 @@ func TestBackend_ECRoles_CSR(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
logicaltest.TestStep{
|
logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
@@ -1986,8 +1986,8 @@ func TestBackend_SignSelfIssued(t *testing.T) {
|
|||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "foo.bar.com",
|
CommonName: "foo.bar.com",
|
||||||
},
|
},
|
||||||
SerialNumber: big.NewInt(1234),
|
SerialNumber: big.NewInt(1234),
|
||||||
IsCA: false,
|
IsCA: false,
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2017,8 +2017,8 @@ func TestBackend_SignSelfIssued(t *testing.T) {
|
|||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "bar.foo.com",
|
CommonName: "bar.foo.com",
|
||||||
},
|
},
|
||||||
SerialNumber: big.NewInt(2345),
|
SerialNumber: big.NewInt(2345),
|
||||||
IsCA: true,
|
IsCA: true,
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
}
|
}
|
||||||
ss, ssCert := getSelfSigned(template, issuer)
|
ss, ssCert := getSelfSigned(template, issuer)
|
||||||
@@ -2600,7 +2600,7 @@ func setCerts() {
|
|||||||
SerialNumber: big.NewInt(mathrand.Int63()),
|
SerialNumber: big.NewInt(mathrand.Int63()),
|
||||||
NotAfter: time.Now().Add(262980 * time.Hour),
|
NotAfter: time.Now().Add(262980 * time.Hour),
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
IsCA: true,
|
IsCA: true,
|
||||||
}
|
}
|
||||||
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, cak.Public(), cak)
|
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, cak.Public(), cak)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
"connection_url": connURL,
|
"connection_url": connURL,
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepCreateRole(t, "web", testRole, false),
|
testAccStepCreateRole(t, "web", testRole, false),
|
||||||
@@ -140,7 +140,7 @@ func TestBackend_roleCrud(t *testing.T) {
|
|||||||
"connection_url": connURL,
|
"connection_url": connURL,
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepCreateRole(t, "web", testRole, false),
|
testAccStepCreateRole(t, "web", testRole, false),
|
||||||
@@ -171,7 +171,7 @@ func TestBackend_BlockStatements(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
// This will also validate the query
|
// This will also validate the query
|
||||||
@@ -196,7 +196,7 @@ func TestBackend_roleReadOnly(t *testing.T) {
|
|||||||
"connection_url": connURL,
|
"connection_url": connURL,
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepCreateRole(t, "web", testRole, false),
|
testAccStepCreateRole(t, "web", testRole, false),
|
||||||
@@ -227,7 +227,7 @@ func TestBackend_roleReadOnly_revocationSQL(t *testing.T) {
|
|||||||
"connection_url": connURL,
|
"connection_url": connURL,
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, connData, false),
|
testAccStepConfig(t, connData, false),
|
||||||
testAccStepCreateRoleWithRevocationSQL(t, "web", testRole, defaultRevocationSQL, false),
|
testAccStepCreateRoleWithRevocationSQL(t, "web", testRole, defaultRevocationSQL, false),
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
PreCheck: testAccPreCheckFunc(t, uri),
|
PreCheck: testAccPreCheckFunc(t, uri),
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, uri),
|
testAccStepConfig(t, uri),
|
||||||
testAccStepRole(t),
|
testAccStepRole(t),
|
||||||
@@ -104,8 +104,8 @@ func TestBackend_roleCrud(t *testing.T) {
|
|||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
PreCheck: testAccPreCheckFunc(t, uri),
|
PreCheck: testAccPreCheckFunc(t, uri),
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepConfig(t, uri),
|
testAccStepConfig(t, uri),
|
||||||
testAccStepRole(t),
|
testAccStepRole(t),
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ func TestSSHBackend_Lookup(t *testing.T) {
|
|||||||
resp4 := []string{testDynamicRoleName}
|
resp4 := []string{testDynamicRoleName}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testLookupRead(t, data, resp1),
|
testLookupRead(t, data, resp1),
|
||||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||||
@@ -285,7 +285,7 @@ func TestSSHBackend_RoleList(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testRoleList(t, resp1),
|
testRoleList(t, resp1),
|
||||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||||
@@ -309,7 +309,7 @@ func TestSSHBackend_DynamicKeyCreate(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
PreCheck: testAccUserPrecheckFunc(t),
|
PreCheck: testAccUserPrecheckFunc(t),
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||||
@@ -332,7 +332,7 @@ func TestSSHBackend_OTPRoleCrud(t *testing.T) {
|
|||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||||
testRoleRead(t, testOTPRoleName, respOTPRoleData),
|
testRoleRead(t, testOTPRoleName, respOTPRoleData),
|
||||||
@@ -362,7 +362,7 @@ func TestSSHBackend_DynamicRoleCrud(t *testing.T) {
|
|||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||||
@@ -376,7 +376,7 @@ func TestSSHBackend_DynamicRoleCrud(t *testing.T) {
|
|||||||
func TestSSHBackend_NamedKeysCrud(t *testing.T) {
|
func TestSSHBackend_NamedKeysCrud(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||||
testNamedKeysDelete(t),
|
testNamedKeysDelete(t),
|
||||||
@@ -396,7 +396,7 @@ func TestSSHBackend_OTPCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||||
testCredsWrite(t, testOTPRoleName, data, false),
|
testCredsWrite(t, testOTPRoleName, data, false),
|
||||||
@@ -413,7 +413,7 @@ func TestSSHBackend_VerifyEcho(t *testing.T) {
|
|||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testVerifyWrite(t, verifyData, expectedData),
|
testVerifyWrite(t, verifyData, expectedData),
|
||||||
},
|
},
|
||||||
@@ -451,7 +451,7 @@ func TestSSHBackend_ConfigZeroAddressCRUD(t *testing.T) {
|
|||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||||
testConfigZeroAddressWrite(t, req1),
|
testConfigZeroAddressWrite(t, req1),
|
||||||
@@ -483,7 +483,7 @@ func TestSSHBackend_CredsForZeroAddressRoles_otp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testRoleWrite(t, testOTPRoleName, otpRoleData),
|
testRoleWrite(t, testOTPRoleName, otpRoleData),
|
||||||
testCredsWrite(t, testOTPRoleName, data, true),
|
testCredsWrite(t, testOTPRoleName, data, true),
|
||||||
@@ -512,7 +512,7 @@ func TestSSHBackend_CredsForZeroAddressRoles_dynamic(t *testing.T) {
|
|||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
PreCheck: testAccUserPrecheckFunc(t),
|
PreCheck: testAccUserPrecheckFunc(t),
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Factory: testingFactory,
|
LogicalFactory: testingFactory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||||
testRoleWrite(t, testDynamicRoleName, dynamicRoleData),
|
testRoleWrite(t, testDynamicRoleName, dynamicRoleData),
|
||||||
@@ -535,7 +535,7 @@ func TestBackend_AbleToRetrievePublicKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
configCaStep(),
|
configCaStep(),
|
||||||
|
|
||||||
@@ -571,7 +571,7 @@ func TestBackend_AbleToAutoGenerateSigningKeys(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
logicaltest.TestStep{
|
logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
@@ -609,7 +609,7 @@ func TestBackend_ValidPrincipalsValidatedForHostCertificates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
configCaStep(),
|
configCaStep(),
|
||||||
|
|
||||||
@@ -652,7 +652,7 @@ func TestBackend_OptionsOverrideDefaults(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
configCaStep(),
|
configCaStep(),
|
||||||
|
|
||||||
@@ -700,7 +700,7 @@ func TestBackend_CustomKeyIDFormat(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
configCaStep(),
|
configCaStep(),
|
||||||
|
|
||||||
@@ -749,7 +749,7 @@ func TestBackend_DisallowUserProvidedKeyIDs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCase := logicaltest.TestCase{
|
testCase := logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
configCaStep(),
|
configCaStep(),
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ func TestBackend_readCredentialsDefaultValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -176,7 +176,7 @@ func TestBackend_readCredentialsEightDigitsThirtySecondPeriod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -214,7 +214,7 @@ func TestBackend_readCredentialsSixDigitsNinetySecondPeriod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -252,7 +252,7 @@ func TestBackend_readCredentialsSHA256(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -290,7 +290,7 @@ func TestBackend_readCredentialsSHA512(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -329,7 +329,7 @@ func TestBackend_keyCrudDefaultValues(t *testing.T) {
|
|||||||
invalidCode := "12345678"
|
invalidCode := "12345678"
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -358,7 +358,7 @@ func TestBackend_createKeyMissingKeyValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -382,7 +382,7 @@ func TestBackend_createKeyInvalidKeyValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -410,7 +410,7 @@ func TestBackend_createKeyInvalidAlgorithm(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -438,7 +438,7 @@ func TestBackend_createKeyInvalidPeriod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -466,7 +466,7 @@ func TestBackend_createKeyInvalidDigits(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -500,7 +500,7 @@ func TestBackend_generatedKeyDefaultValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -526,7 +526,7 @@ func TestBackend_generatedKeyDefaultValuesNoQR(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
},
|
},
|
||||||
@@ -559,7 +559,7 @@ func TestBackend_generatedKeyNonDefaultKeySize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -583,7 +583,7 @@ func TestBackend_urlPassedNonGeneratedKeyInvalidPeriod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -607,7 +607,7 @@ func TestBackend_urlPassedNonGeneratedKeyInvalidDigits(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -640,7 +640,7 @@ func TestBackend_urlPassedNonGeneratedKeyIssuerInFirstPosition(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -674,7 +674,7 @@ func TestBackend_urlPassedNonGeneratedKeyIssuerInQueryString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -708,7 +708,7 @@ func TestBackend_urlPassedNonGeneratedKeyMissingIssuer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -742,7 +742,7 @@ func TestBackend_urlPassedNonGeneratedKeyMissingAccountName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -776,7 +776,7 @@ func TestBackend_urlPassedNonGeneratedKeyMissingAccountNameandIssuer(t *testing.
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
@@ -801,7 +801,7 @@ func TestBackend_generatedKeyInvalidSkew(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -825,7 +825,7 @@ func TestBackend_generatedKeyInvalidQRSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -849,7 +849,7 @@ func TestBackend_generatedKeyInvalidKeySize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -871,7 +871,7 @@ func TestBackend_generatedKeyMissingAccountName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -893,7 +893,7 @@ func TestBackend_generatedKeyMissingIssuer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -915,7 +915,7 @@ func TestBackend_invalidURLValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -937,7 +937,7 @@ func TestBackend_urlAndGenerateTrue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -959,7 +959,7 @@ func TestBackend_keyAndGenerateTrue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, true),
|
testAccStepCreateKey(t, "test", keyData, true),
|
||||||
testAccStepReadKey(t, "test", nil),
|
testAccStepReadKey(t, "test", nil),
|
||||||
@@ -991,7 +991,7 @@ func TestBackend_generatedKeyExportedFalse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCreateKey(t, "test", keyData, false),
|
testAccStepCreateKey(t, "test", keyData, false),
|
||||||
testAccStepReadKey(t, "test", expected),
|
testAccStepReadKey(t, "test", expected),
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ func testTransit_RSA(t *testing.T, keyType string) {
|
|||||||
func TestBackend_basic(t *testing.T) {
|
func TestBackend_basic(t *testing.T) {
|
||||||
decryptData := make(map[string]interface{})
|
decryptData := make(map[string]interface{})
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
LogicalFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepListPolicy(t, "test", true),
|
testAccStepListPolicy(t, "test", true),
|
||||||
testAccStepWritePolicy(t, "test", false),
|
testAccStepWritePolicy(t, "test", false),
|
||||||
@@ -278,7 +278,7 @@ func TestBackend_basic(t *testing.T) {
|
|||||||
func TestBackend_upsert(t *testing.T) {
|
func TestBackend_upsert(t *testing.T) {
|
||||||
decryptData := make(map[string]interface{})
|
decryptData := make(map[string]interface{})
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
LogicalFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepReadPolicy(t, "test", true, false),
|
testAccStepReadPolicy(t, "test", true, false),
|
||||||
testAccStepListPolicy(t, "test", true),
|
testAccStepListPolicy(t, "test", true),
|
||||||
@@ -293,7 +293,7 @@ func TestBackend_upsert(t *testing.T) {
|
|||||||
func TestBackend_datakey(t *testing.T) {
|
func TestBackend_datakey(t *testing.T) {
|
||||||
dataKeyInfo := make(map[string]interface{})
|
dataKeyInfo := make(map[string]interface{})
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
LogicalFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepListPolicy(t, "test", true),
|
testAccStepListPolicy(t, "test", true),
|
||||||
testAccStepWritePolicy(t, "test", false),
|
testAccStepWritePolicy(t, "test", false),
|
||||||
@@ -317,7 +317,7 @@ func testBackendRotation(t *testing.T) {
|
|||||||
decryptData := make(map[string]interface{})
|
decryptData := make(map[string]interface{})
|
||||||
encryptHistory := make(map[int]map[string]interface{})
|
encryptHistory := make(map[int]map[string]interface{})
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
LogicalFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepListPolicy(t, "test", true),
|
testAccStepListPolicy(t, "test", true),
|
||||||
testAccStepWritePolicy(t, "test", false),
|
testAccStepWritePolicy(t, "test", false),
|
||||||
@@ -380,7 +380,7 @@ func testBackendRotation(t *testing.T) {
|
|||||||
func TestBackend_basic_derived(t *testing.T) {
|
func TestBackend_basic_derived(t *testing.T) {
|
||||||
decryptData := make(map[string]interface{})
|
decryptData := make(map[string]interface{})
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Factory: Factory,
|
LogicalFactory: Factory,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepListPolicy(t, "test", true),
|
testAccStepListPolicy(t, "test", true),
|
||||||
testAccStepWritePolicy(t, "test", true),
|
testAccStepWritePolicy(t, "test", true),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
bplugin "github.com/hashicorp/vault/logical/plugin"
|
bplugin "github.com/hashicorp/vault/logical/plugin"
|
||||||
@@ -38,13 +39,18 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
|
|||||||
// Backend returns an instance of the backend, either as a plugin if external
|
// Backend returns an instance of the backend, either as a plugin if external
|
||||||
// or as a concrete implementation if builtin, casted as logical.Backend.
|
// or as a concrete implementation if builtin, casted as logical.Backend.
|
||||||
func Backend(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
func Backend(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
||||||
var b backend
|
var b PluginBackend
|
||||||
|
|
||||||
name := conf.Config["plugin_name"]
|
name := conf.Config["plugin_name"]
|
||||||
|
pluginType, err := consts.ParsePluginType(conf.Config["plugin_type"])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
sys := conf.System
|
sys := conf.System
|
||||||
|
|
||||||
// NewBackend with isMetadataMode set to true
|
// NewBackend with isMetadataMode set to true
|
||||||
raw, err := bplugin.NewBackend(ctx, name, sys, conf.Logger, true)
|
raw, err := bplugin.NewBackend(ctx, name, pluginType, sys, conf, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -71,8 +77,8 @@ func Backend(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
|
|||||||
return &b, nil
|
return &b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// backend is a thin wrapper around plugin.BackendPluginClient
|
// PluginBackend is a thin wrapper around plugin.BackendPluginClient
|
||||||
type backend struct {
|
type PluginBackend struct {
|
||||||
logical.Backend
|
logical.Backend
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
@@ -85,19 +91,23 @@ type backend struct {
|
|||||||
loaded bool
|
loaded bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) reloadBackend(ctx context.Context) error {
|
func (b *PluginBackend) reloadBackend(ctx context.Context) error {
|
||||||
b.Logger().Debug("reloading plugin backend", "plugin", b.config.Config["plugin_name"])
|
b.Logger().Debug("reloading plugin backend", "plugin", b.config.Config["plugin_name"])
|
||||||
return b.startBackend(ctx)
|
return b.startBackend(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// startBackend starts a plugin backend
|
// startBackend starts a plugin backend
|
||||||
func (b *backend) startBackend(ctx context.Context) error {
|
func (b *PluginBackend) startBackend(ctx context.Context) error {
|
||||||
pluginName := b.config.Config["plugin_name"]
|
pluginName := b.config.Config["plugin_name"]
|
||||||
|
pluginType, err := consts.ParsePluginType(b.config.Config["plugin_type"])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure proper cleanup of the backend (i.e. call client.Kill())
|
// Ensure proper cleanup of the backend (i.e. call client.Kill())
|
||||||
b.Backend.Cleanup(ctx)
|
b.Backend.Cleanup(ctx)
|
||||||
|
|
||||||
nb, err := bplugin.NewBackend(ctx, pluginName, b.config.System, b.config.Logger, false)
|
nb, err := bplugin.NewBackend(ctx, pluginName, pluginType, b.config.System, b.config, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -128,7 +138,7 @@ func (b *backend) startBackend(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleRequest is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
|
// HandleRequest is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
|
||||||
func (b *backend) HandleRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
func (b *PluginBackend) HandleRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
||||||
b.RLock()
|
b.RLock()
|
||||||
canary := b.canary
|
canary := b.canary
|
||||||
|
|
||||||
@@ -179,7 +189,7 @@ func (b *backend) HandleRequest(ctx context.Context, req *logical.Request) (*log
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleExistenceCheck is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
|
// HandleExistenceCheck is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
|
||||||
func (b *backend) HandleExistenceCheck(ctx context.Context, req *logical.Request) (bool, bool, error) {
|
func (b *PluginBackend) HandleExistenceCheck(ctx context.Context, req *logical.Request) (bool, bool, error) {
|
||||||
b.RLock()
|
b.RLock()
|
||||||
canary := b.canary
|
canary := b.canary
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package plugin
|
package plugin_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,24 +7,26 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/hashicorp/vault/builtin/plugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/logging"
|
"github.com/hashicorp/vault/helper/logging"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
vaulthttp "github.com/hashicorp/vault/http"
|
vaulthttp "github.com/hashicorp/vault/http"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/plugin"
|
logicalPlugin "github.com/hashicorp/vault/logical/plugin"
|
||||||
"github.com/hashicorp/vault/logical/plugin/mock"
|
"github.com/hashicorp/vault/logical/plugin/mock"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBackend_impl(t *testing.T) {
|
func TestBackend_impl(t *testing.T) {
|
||||||
var _ logical.Backend = &backend{}
|
var _ logical.Backend = &plugin.PluginBackend{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackend(t *testing.T) {
|
func TestBackend(t *testing.T) {
|
||||||
config, cleanup := testConfig(t)
|
config, cleanup := testConfig(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
_, err := Backend(context.Background(), config)
|
_, err := plugin.Backend(context.Background(), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -34,7 +36,7 @@ func TestBackend_Factory(t *testing.T) {
|
|||||||
config, cleanup := testConfig(t)
|
config, cleanup := testConfig(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
_, err := Factory(context.Background(), config)
|
_, err := plugin.Factory(context.Background(), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,7 @@ func TestBackend_PluginMain(t *testing.T) {
|
|||||||
tlsConfig := apiClientMeta.GetTLSConfig()
|
tlsConfig := apiClientMeta.GetTLSConfig()
|
||||||
tlsProviderFunc := pluginutil.VaultPluginTLSProvider(tlsConfig)
|
tlsProviderFunc := pluginutil.VaultPluginTLSProvider(tlsConfig)
|
||||||
|
|
||||||
err := plugin.Serve(&plugin.ServeOpts{
|
err := logicalPlugin.Serve(&logicalPlugin.ServeOpts{
|
||||||
BackendFactoryFunc: mock.Factory,
|
BackendFactoryFunc: mock.Factory,
|
||||||
TLSProviderFunc: tlsProviderFunc,
|
TLSProviderFunc: tlsProviderFunc,
|
||||||
})
|
})
|
||||||
@@ -84,12 +86,13 @@ func testConfig(t *testing.T) (*logical.BackendConfig, func()) {
|
|||||||
System: sys,
|
System: sys,
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"plugin_name": "mock-plugin",
|
"plugin_name": "mock-plugin",
|
||||||
|
"plugin_type": "database",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
||||||
|
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMain", []string{}, "")
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeDatabase, "TestBackend_PluginMain", []string{}, "")
|
||||||
|
|
||||||
return config, func() {
|
return config, func() {
|
||||||
cluster.Cleanup()
|
cluster.Cleanup()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@@ -58,6 +59,10 @@ Usage: vault auth enable [options] TYPE
|
|||||||
|
|
||||||
$ vault auth enable -path=my-auth -plugin-name=my-auth-plugin plugin
|
$ vault auth enable -path=my-auth -plugin-name=my-auth-plugin plugin
|
||||||
|
|
||||||
|
OR (preferred way):
|
||||||
|
|
||||||
|
$ vault auth enable -path=my-auth my-auth-plugin
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
@@ -135,7 +140,7 @@ func (c *AuthEnableCommand) Flags() *FlagSets {
|
|||||||
f.StringVar(&StringVar{
|
f.StringVar(&StringVar{
|
||||||
Name: "plugin-name",
|
Name: "plugin-name",
|
||||||
Target: &c.flagPluginName,
|
Target: &c.flagPluginName,
|
||||||
Completion: c.PredictVaultPlugins(),
|
Completion: c.PredictVaultPlugins(consts.PluginTypeCredential),
|
||||||
Usage: "Name of the auth method plugin. This plugin name must already " +
|
Usage: "Name of the auth method plugin. This plugin name must already " +
|
||||||
"exist in the Vault server's plugin catalog.",
|
"exist in the Vault server's plugin catalog.",
|
||||||
})
|
})
|
||||||
@@ -212,6 +217,9 @@ func (c *AuthEnableCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
authType := strings.TrimSpace(args[0])
|
authType := strings.TrimSpace(args[0])
|
||||||
|
if authType == "plugin" {
|
||||||
|
authType = c.flagPluginName
|
||||||
|
}
|
||||||
|
|
||||||
// If no path is specified, we default the path to the backend type
|
// If no path is specified, we default the path to the backend type
|
||||||
// or use the plugin name if it's a plugin backend
|
// or use the plugin name if it's a plugin backend
|
||||||
@@ -242,7 +250,6 @@ func (c *AuthEnableCommand) Run(args []string) int {
|
|||||||
Config: api.AuthConfigInput{
|
Config: api.AuthConfigInput{
|
||||||
DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(),
|
DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(),
|
||||||
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),
|
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),
|
||||||
PluginName: c.flagPluginName,
|
|
||||||
},
|
},
|
||||||
Options: c.flagOptions,
|
Options: c.flagOptions,
|
||||||
}
|
}
|
||||||
@@ -279,7 +286,6 @@ func (c *AuthEnableCommand) Run(args []string) int {
|
|||||||
if authType == "plugin" {
|
if authType == "plugin" {
|
||||||
authThing = c.flagPluginName + " plugin"
|
authThing = c.flagPluginName + " plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
c.UI.Output(fmt.Sprintf("Success! Enabled %s at: %s", authThing, authPath))
|
c.UI.Output(fmt.Sprintf("Success! Enabled %s at: %s", authThing, authPath))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -171,8 +173,11 @@ func TestAuthEnableCommand_Run(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(backends) != len(credentialBackends) {
|
// Add 1 to account for the "token" backend, which is visible when you walk the filesystem but
|
||||||
t.Fatalf("expected %d credential backends, got %d", len(credentialBackends), len(backends))
|
// is treated as special and excluded from the registry.
|
||||||
|
expected := len(builtinplugins.Registry.Keys(consts.PluginTypeCredential)) + 1
|
||||||
|
if len(backends) != expected {
|
||||||
|
t.Fatalf("expected %d credential backends, got %d", expected, len(backends))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, b := range backends {
|
for _, b := range backends {
|
||||||
|
|||||||
@@ -155,11 +155,10 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
|
|||||||
replication = "local"
|
replication = "local"
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %s | %t | %v | %s",
|
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s",
|
||||||
path,
|
path,
|
||||||
mount.Type,
|
mount.Type,
|
||||||
mount.Accessor,
|
mount.Accessor,
|
||||||
mount.Config.PluginName,
|
|
||||||
defaultTTL,
|
defaultTTL,
|
||||||
maxTTL,
|
maxTTL,
|
||||||
mount.Config.TokenType,
|
mount.Config.TokenType,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -146,8 +147,8 @@ func (b *BaseCommand) PredictVaultAuths() complete.Predictor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PredictVaultPlugins returns a predictor for installed plugins.
|
// PredictVaultPlugins returns a predictor for installed plugins.
|
||||||
func (b *BaseCommand) PredictVaultPlugins() complete.Predictor {
|
func (b *BaseCommand) PredictVaultPlugins(pluginTypes ...consts.PluginType) complete.Predictor {
|
||||||
return NewPredict().VaultPlugins()
|
return NewPredict().VaultPlugins(pluginTypes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PredictVaultPolicies returns a predictor for "folders". See PredictVaultFiles
|
// PredictVaultPolicies returns a predictor for "folders". See PredictVaultFiles
|
||||||
@@ -191,8 +192,11 @@ func (p *Predict) VaultAuths() complete.Predictor {
|
|||||||
// VaultPlugins returns a predictor for Vault's plugin catalog. This is a public
|
// VaultPlugins returns a predictor for Vault's plugin catalog. This is a public
|
||||||
// API for consumers, but you probably want BaseCommand.PredictVaultPlugins
|
// API for consumers, but you probably want BaseCommand.PredictVaultPlugins
|
||||||
// instead.
|
// instead.
|
||||||
func (p *Predict) VaultPlugins() complete.Predictor {
|
func (p *Predict) VaultPlugins(pluginTypes ...consts.PluginType) complete.Predictor {
|
||||||
return p.filterFunc(p.plugins)
|
filterFunc := func() []string {
|
||||||
|
return p.plugins(pluginTypes...)
|
||||||
|
}
|
||||||
|
return p.filterFunc(filterFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VaultPolicies returns a predictor for Vault "folders". This is a public API for
|
// VaultPolicies returns a predictor for Vault "folders". This is a public API for
|
||||||
@@ -329,17 +333,35 @@ func (p *Predict) auths() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// plugins returns a sorted list of the plugins in the catalog.
|
// plugins returns a sorted list of the plugins in the catalog.
|
||||||
func (p *Predict) plugins() []string {
|
func (p *Predict) plugins(pluginTypes ...consts.PluginType) []string {
|
||||||
|
// This method's signature doesn't enforce that a pluginType must be passed in.
|
||||||
|
// If it's not, it's likely the caller's intent is go get a list of all of them,
|
||||||
|
// so let's help them out.
|
||||||
|
if len(pluginTypes) == 0 {
|
||||||
|
pluginTypes = append(pluginTypes, consts.PluginTypeUnknown)
|
||||||
|
}
|
||||||
|
|
||||||
client := p.Client()
|
client := p.Client()
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := client.Sys().ListPlugins(nil)
|
var plugins []string
|
||||||
if err != nil {
|
pluginsAdded := make(map[string]bool)
|
||||||
return nil
|
for _, pluginType := range pluginTypes {
|
||||||
|
result, err := client.Sys().ListPlugins(&api.ListPluginsInput{Type: pluginType})
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, names := range result.PluginsByType {
|
||||||
|
for _, name := range names {
|
||||||
|
if _, ok := pluginsAdded[name]; !ok {
|
||||||
|
plugins = append(plugins, name)
|
||||||
|
pluginsAdded[name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
plugins := result.Names
|
|
||||||
sort.Strings(plugins)
|
sort.Strings(plugins)
|
||||||
return plugins
|
return plugins
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,15 +322,45 @@ func TestPredict_Plugins(t *testing.T) {
|
|||||||
"good_path",
|
"good_path",
|
||||||
client,
|
client,
|
||||||
[]string{
|
[]string{
|
||||||
|
"ad",
|
||||||
|
"alicloud",
|
||||||
|
"app-id",
|
||||||
|
"approle",
|
||||||
|
"aws",
|
||||||
|
"azure",
|
||||||
|
"cassandra",
|
||||||
"cassandra-database-plugin",
|
"cassandra-database-plugin",
|
||||||
|
"centrify",
|
||||||
|
"cert",
|
||||||
|
"consul",
|
||||||
|
"gcp",
|
||||||
|
"gcpkms",
|
||||||
|
"github",
|
||||||
"hana-database-plugin",
|
"hana-database-plugin",
|
||||||
|
"jwt",
|
||||||
|
"kubernetes",
|
||||||
|
"kv",
|
||||||
|
"ldap",
|
||||||
|
"mongodb",
|
||||||
"mongodb-database-plugin",
|
"mongodb-database-plugin",
|
||||||
|
"mssql",
|
||||||
"mssql-database-plugin",
|
"mssql-database-plugin",
|
||||||
|
"mysql",
|
||||||
"mysql-aurora-database-plugin",
|
"mysql-aurora-database-plugin",
|
||||||
"mysql-database-plugin",
|
"mysql-database-plugin",
|
||||||
"mysql-legacy-database-plugin",
|
"mysql-legacy-database-plugin",
|
||||||
"mysql-rds-database-plugin",
|
"mysql-rds-database-plugin",
|
||||||
|
"nomad",
|
||||||
|
"okta",
|
||||||
|
"pki",
|
||||||
|
"postgresql",
|
||||||
"postgresql-database-plugin",
|
"postgresql-database-plugin",
|
||||||
|
"rabbitmq",
|
||||||
|
"radius",
|
||||||
|
"ssh",
|
||||||
|
"totp",
|
||||||
|
"transit",
|
||||||
|
"userpass",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
kv "github.com/hashicorp/vault-plugin-secrets-kv"
|
"github.com/hashicorp/vault-plugin-secrets-kv"
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/audit"
|
"github.com/hashicorp/vault/audit"
|
||||||
"github.com/hashicorp/vault/builtin/logical/pki"
|
"github.com/hashicorp/vault/builtin/logical/pki"
|
||||||
"github.com/hashicorp/vault/builtin/logical/ssh"
|
"github.com/hashicorp/vault/builtin/logical/ssh"
|
||||||
"github.com/hashicorp/vault/builtin/logical/transit"
|
"github.com/hashicorp/vault/builtin/logical/transit"
|
||||||
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/physical/inmem"
|
"github.com/hashicorp/vault/physical/inmem"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
@@ -74,6 +75,7 @@ func testVaultServerAllBackends(tb testing.TB) (*api.Client, func()) {
|
|||||||
CredentialBackends: credentialBackends,
|
CredentialBackends: credentialBackends,
|
||||||
AuditBackends: auditBackends,
|
AuditBackends: auditBackends,
|
||||||
LogicalBackends: logicalBackends,
|
LogicalBackends: logicalBackends,
|
||||||
|
BuiltinRegistry: builtinplugins.Registry,
|
||||||
})
|
})
|
||||||
return client, closer
|
return client, closer
|
||||||
}
|
}
|
||||||
@@ -90,6 +92,7 @@ func testVaultServerUnseal(tb testing.TB) (*api.Client, []string, func()) {
|
|||||||
CredentialBackends: defaultVaultCredentialBackends,
|
CredentialBackends: defaultVaultCredentialBackends,
|
||||||
AuditBackends: defaultVaultAuditBackends,
|
AuditBackends: defaultVaultAuditBackends,
|
||||||
LogicalBackends: defaultVaultLogicalBackends,
|
LogicalBackends: defaultVaultLogicalBackends,
|
||||||
|
BuiltinRegistry: builtinplugins.Registry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +110,7 @@ func testVaultServerPluginDir(tb testing.TB, pluginDir string) (*api.Client, []s
|
|||||||
AuditBackends: defaultVaultAuditBackends,
|
AuditBackends: defaultVaultAuditBackends,
|
||||||
LogicalBackends: defaultVaultLogicalBackends,
|
LogicalBackends: defaultVaultLogicalBackends,
|
||||||
PluginDirectory: pluginDir,
|
PluginDirectory: pluginDir,
|
||||||
|
BuiltinRegistry: builtinplugins.Registry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,6 +160,7 @@ func testVaultServerUninit(tb testing.TB) (*api.Client, func()) {
|
|||||||
CredentialBackends: defaultVaultCredentialBackends,
|
CredentialBackends: defaultVaultCredentialBackends,
|
||||||
AuditBackends: defaultVaultAuditBackends,
|
AuditBackends: defaultVaultAuditBackends,
|
||||||
LogicalBackends: defaultVaultLogicalBackends,
|
LogicalBackends: defaultVaultLogicalBackends,
|
||||||
|
BuiltinRegistry: builtinplugins.Registry,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tb.Fatal(err)
|
tb.Fatal(err)
|
||||||
|
|||||||
@@ -6,55 +6,38 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
ad "github.com/hashicorp/vault-plugin-secrets-ad/plugin"
|
|
||||||
alicloud "github.com/hashicorp/vault-plugin-secrets-alicloud"
|
|
||||||
azure "github.com/hashicorp/vault-plugin-secrets-azure"
|
|
||||||
gcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
|
|
||||||
gcpkms "github.com/hashicorp/vault-plugin-secrets-gcpkms"
|
|
||||||
kv "github.com/hashicorp/vault-plugin-secrets-kv"
|
|
||||||
"github.com/hashicorp/vault/audit"
|
"github.com/hashicorp/vault/audit"
|
||||||
|
"github.com/hashicorp/vault/builtin/plugin"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/physical"
|
"github.com/hashicorp/vault/physical"
|
||||||
"github.com/hashicorp/vault/version"
|
"github.com/hashicorp/vault/version"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/aws"
|
/*
|
||||||
"github.com/hashicorp/vault/builtin/logical/cassandra"
|
The builtinplugins package is initialized here because it, in turn,
|
||||||
"github.com/hashicorp/vault/builtin/logical/consul"
|
initializes the database plugins.
|
||||||
"github.com/hashicorp/vault/builtin/logical/database"
|
They register multiple database drivers for the "database/sql" package.
|
||||||
"github.com/hashicorp/vault/builtin/logical/mongodb"
|
*/
|
||||||
"github.com/hashicorp/vault/builtin/logical/mssql"
|
_ "github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
"github.com/hashicorp/vault/builtin/logical/mysql"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/nomad"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/pki"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/postgresql"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/rabbitmq"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/ssh"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/totp"
|
|
||||||
"github.com/hashicorp/vault/builtin/logical/transit"
|
|
||||||
"github.com/hashicorp/vault/builtin/plugin"
|
|
||||||
|
|
||||||
auditFile "github.com/hashicorp/vault/builtin/audit/file"
|
auditFile "github.com/hashicorp/vault/builtin/audit/file"
|
||||||
auditSocket "github.com/hashicorp/vault/builtin/audit/socket"
|
auditSocket "github.com/hashicorp/vault/builtin/audit/socket"
|
||||||
auditSyslog "github.com/hashicorp/vault/builtin/audit/syslog"
|
auditSyslog "github.com/hashicorp/vault/builtin/audit/syslog"
|
||||||
|
|
||||||
credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
|
credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
|
||||||
credAzure "github.com/hashicorp/vault-plugin-auth-azure"
|
|
||||||
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
||||||
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||||
credJWT "github.com/hashicorp/vault-plugin-auth-jwt"
|
|
||||||
credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
|
|
||||||
credAppId "github.com/hashicorp/vault/builtin/credential/app-id"
|
|
||||||
credAppRole "github.com/hashicorp/vault/builtin/credential/approle"
|
|
||||||
credAws "github.com/hashicorp/vault/builtin/credential/aws"
|
credAws "github.com/hashicorp/vault/builtin/credential/aws"
|
||||||
credCert "github.com/hashicorp/vault/builtin/credential/cert"
|
credCert "github.com/hashicorp/vault/builtin/credential/cert"
|
||||||
credGitHub "github.com/hashicorp/vault/builtin/credential/github"
|
credGitHub "github.com/hashicorp/vault/builtin/credential/github"
|
||||||
credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
|
credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
|
||||||
credOkta "github.com/hashicorp/vault/builtin/credential/okta"
|
credOkta "github.com/hashicorp/vault/builtin/credential/okta"
|
||||||
credRadius "github.com/hashicorp/vault/builtin/credential/radius"
|
|
||||||
credToken "github.com/hashicorp/vault/builtin/credential/token"
|
credToken "github.com/hashicorp/vault/builtin/credential/token"
|
||||||
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
|
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
|
||||||
|
|
||||||
|
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
|
||||||
|
logicalDb "github.com/hashicorp/vault/builtin/logical/database"
|
||||||
|
|
||||||
physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss"
|
physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss"
|
||||||
physAzure "github.com/hashicorp/vault/physical/azure"
|
physAzure "github.com/hashicorp/vault/physical/azure"
|
||||||
physCassandra "github.com/hashicorp/vault/physical/cassandra"
|
physCassandra "github.com/hashicorp/vault/physical/cassandra"
|
||||||
@@ -105,46 +88,15 @@ var (
|
|||||||
}
|
}
|
||||||
|
|
||||||
credentialBackends = map[string]logical.Factory{
|
credentialBackends = map[string]logical.Factory{
|
||||||
"alicloud": credAliCloud.Factory,
|
"plugin": plugin.Factory,
|
||||||
"app-id": credAppId.Factory,
|
|
||||||
"approle": credAppRole.Factory,
|
|
||||||
"aws": credAws.Factory,
|
|
||||||
"azure": credAzure.Factory,
|
|
||||||
"centrify": credCentrify.Factory,
|
|
||||||
"cert": credCert.Factory,
|
|
||||||
"gcp": credGcp.Factory,
|
|
||||||
"github": credGitHub.Factory,
|
|
||||||
"jwt": credJWT.Factory,
|
|
||||||
"kubernetes": credKube.Factory,
|
|
||||||
"ldap": credLdap.Factory,
|
|
||||||
"okta": credOkta.Factory,
|
|
||||||
"plugin": plugin.Factory,
|
|
||||||
"radius": credRadius.Factory,
|
|
||||||
"userpass": credUserpass.Factory,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logicalBackends = map[string]logical.Factory{
|
logicalBackends = map[string]logical.Factory{
|
||||||
"ad": ad.Factory,
|
"plugin": plugin.Factory,
|
||||||
"alicloud": alicloud.Factory,
|
"database": logicalDb.Factory,
|
||||||
"aws": aws.Factory,
|
// This is also available in the plugin catalog, but is here due to the need to
|
||||||
"azure": azure.Factory,
|
// automatically mount it.
|
||||||
"cassandra": cassandra.Factory,
|
"kv": logicalKv.Factory,
|
||||||
"consul": consul.Factory,
|
|
||||||
"database": database.Factory,
|
|
||||||
"gcp": gcp.Factory,
|
|
||||||
"gcpkms": gcpkms.Factory,
|
|
||||||
"kv": kv.Factory,
|
|
||||||
"mongodb": mongodb.Factory,
|
|
||||||
"mssql": mssql.Factory,
|
|
||||||
"mysql": mysql.Factory,
|
|
||||||
"nomad": nomad.Factory,
|
|
||||||
"pki": pki.Factory,
|
|
||||||
"plugin": plugin.Factory,
|
|
||||||
"postgresql": postgresql.Factory,
|
|
||||||
"rabbitmq": rabbitmq.Factory,
|
|
||||||
"ssh": ssh.Factory,
|
|
||||||
"totp": totp.Factory,
|
|
||||||
"transit": transit.Factory,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
physicalBackends = map[string]physical.Factory{
|
physicalBackends = map[string]physical.Factory{
|
||||||
|
|||||||
@@ -21,19 +21,21 @@ func (c *PluginCommand) Help() string {
|
|||||||
Usage: vault plugin <subcommand> [options] [args]
|
Usage: vault plugin <subcommand> [options] [args]
|
||||||
|
|
||||||
This command groups subcommands for interacting with Vault's plugins and the
|
This command groups subcommands for interacting with Vault's plugins and the
|
||||||
plugin catalog. Here are a few examples of the plugin commands:
|
plugin catalog. The plugin catalog is divided into three types: "auth",
|
||||||
|
"database", and "secret" plugins. A type must be specified on each call. Here
|
||||||
|
are a few examples of the plugin commands.
|
||||||
|
|
||||||
List all available plugins in the catalog:
|
List all available plugins in the catalog of a particular type:
|
||||||
|
|
||||||
$ vault plugin list
|
$ vault plugin list database
|
||||||
|
|
||||||
Register a new plugin to the catalog:
|
Register a new plugin to the catalog as a particular type:
|
||||||
|
|
||||||
$ vault plugin register -sha256=d3f0a8b... my-custom-plugin
|
$ vault plugin register -sha256=d3f0a8b... auth my-custom-plugin
|
||||||
|
|
||||||
Get information about a plugin in the catalog:
|
Get information about a plugin in the catalog listed under a particular type:
|
||||||
|
|
||||||
$ vault plugin info my-custom-plugin
|
$ vault plugin info auth my-custom-plugin
|
||||||
|
|
||||||
Please see the individual subcommand help for detailed usage information.
|
Please see the individual subcommand help for detailed usage information.
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@@ -22,14 +23,15 @@ func (c *PluginDeregisterCommand) Synopsis() string {
|
|||||||
|
|
||||||
func (c *PluginDeregisterCommand) Help() string {
|
func (c *PluginDeregisterCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: vault plugin deregister [options] NAME
|
Usage: vault plugin deregister [options] TYPE NAME
|
||||||
|
|
||||||
Deregister an existing plugin in the catalog. If the plugin does not exist,
|
Deregister an existing plugin in the catalog. If the plugin does not exist,
|
||||||
no action is taken (the command is idempotent).
|
no action is taken (the command is idempotent). The argument of type
|
||||||
|
takes "auth", "database", or "secret".
|
||||||
|
|
||||||
Deregister the plugin named my-custom-plugin:
|
Deregister the plugin named my-custom-plugin:
|
||||||
|
|
||||||
$ vault plugin deregister my-custom-plugin
|
$ vault plugin deregister auth my-custom-plugin
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ func (c *PluginDeregisterCommand) Flags() *FlagSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *PluginDeregisterCommand) AutocompleteArgs() complete.Predictor {
|
func (c *PluginDeregisterCommand) AutocompleteArgs() complete.Predictor {
|
||||||
return c.PredictVaultPlugins()
|
return c.PredictVaultPlugins(consts.PluginTypeUnknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PluginDeregisterCommand) AutocompleteFlags() complete.Flags {
|
func (c *PluginDeregisterCommand) AutocompleteFlags() complete.Flags {
|
||||||
@@ -58,11 +60,11 @@ func (c *PluginDeregisterCommand) Run(args []string) int {
|
|||||||
|
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
switch {
|
switch {
|
||||||
case len(args) < 1:
|
case len(args) < 2:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) > 1:
|
case len(args) > 2:
|
||||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,10 +74,16 @@ func (c *PluginDeregisterCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginName := strings.TrimSpace(args[0])
|
pluginType, err := consts.ParsePluginType(strings.TrimSpace(args[0]))
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
pluginName := strings.TrimSpace(args[1])
|
||||||
|
|
||||||
if err := client.Sys().DeregisterPlugin(&api.DeregisterPluginInput{
|
if err := client.Sys().DeregisterPlugin(&api.DeregisterPluginInput{
|
||||||
Name: pluginName,
|
Name: pluginName,
|
||||||
|
Type: pluginType,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
c.UI.Error(fmt.Sprintf("Error deregistering plugin named %s: %s", pluginName, err))
|
c.UI.Error(fmt.Sprintf("Error deregistering plugin named %s: %s", pluginName, err))
|
||||||
return 2
|
return 2
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,13 +37,13 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"too_many_args",
|
"too_many_args",
|
||||||
[]string{"foo", "bar"},
|
[]string{"foo", "bar", "fizz"},
|
||||||
"Too many arguments",
|
"Too many arguments",
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"not_a_plugin",
|
"not_a_plugin",
|
||||||
[]string{"nope_definitely_never_a_plugin_nope"},
|
[]string{consts.PluginTypeCredential.String(), "nope_definitely_never_a_plugin_nope"},
|
||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
@@ -82,13 +83,14 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
|
|||||||
defer closer()
|
defer closer()
|
||||||
|
|
||||||
pluginName := "my-plugin"
|
pluginName := "my-plugin"
|
||||||
_, sha256Sum := testPluginCreateAndRegister(t, client, pluginDir, pluginName)
|
_, sha256Sum := testPluginCreateAndRegister(t, client, pluginDir, pluginName, consts.PluginTypeCredential)
|
||||||
|
|
||||||
ui, cmd := testPluginDeregisterCommand(t)
|
ui, cmd := testPluginDeregisterCommand(t)
|
||||||
cmd.client = client
|
cmd.client = client
|
||||||
|
|
||||||
if err := client.Sys().RegisterPlugin(&api.RegisterPluginInput{
|
if err := client.Sys().RegisterPlugin(&api.RegisterPluginInput{
|
||||||
Name: pluginName,
|
Name: pluginName,
|
||||||
|
Type: consts.PluginTypeCredential,
|
||||||
Command: pluginName,
|
Command: pluginName,
|
||||||
SHA256: sha256Sum,
|
SHA256: sha256Sum,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@@ -96,6 +98,7 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
|
consts.PluginTypeCredential.String(),
|
||||||
pluginName,
|
pluginName,
|
||||||
})
|
})
|
||||||
if exp := 0; code != exp {
|
if exp := 0; code != exp {
|
||||||
@@ -108,19 +111,23 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
|
|||||||
t.Errorf("expected %q to contain %q", combined, expected)
|
t.Errorf("expected %q to contain %q", combined, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Sys().ListPlugins(&api.ListPluginsInput{})
|
resp, err := client.Sys().ListPlugins(&api.ListPluginsInput{
|
||||||
|
Type: consts.PluginTypeCredential,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
found := false
|
found := false
|
||||||
for _, p := range resp.Names {
|
for _, plugins := range resp.PluginsByType {
|
||||||
if p == pluginName {
|
for _, p := range plugins {
|
||||||
found = true
|
if p == pluginName {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if found {
|
if found {
|
||||||
t.Errorf("expected %q to not be in %q", pluginName, resp.Names)
|
t.Errorf("expected %q to not be in %q", pluginName, resp.PluginsByType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -134,6 +141,7 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
|
|||||||
cmd.client = client
|
cmd.client = client
|
||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
|
consts.PluginTypeCredential.String(),
|
||||||
"my-plugin",
|
"my-plugin",
|
||||||
})
|
})
|
||||||
if exp := 2; code != exp {
|
if exp := 2; code != exp {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@@ -22,14 +23,15 @@ func (c *PluginInfoCommand) Synopsis() string {
|
|||||||
|
|
||||||
func (c *PluginInfoCommand) Help() string {
|
func (c *PluginInfoCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: vault plugin info [options] NAME
|
Usage: vault plugin info [options] TYPE NAME
|
||||||
|
|
||||||
Displays information about a plugin in the catalog with the given name. If
|
Displays information about a plugin in the catalog with the given name. If
|
||||||
the plugin does not exist, an error is returned.
|
the plugin does not exist, an error is returned. The argument of type
|
||||||
|
takes "auth", "database", or "secret".
|
||||||
|
|
||||||
Get info about a plugin:
|
Get info about a plugin:
|
||||||
|
|
||||||
$ vault plugin info mysql-database-plugin
|
$ vault plugin info database mysql-database-plugin
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ func (c *PluginInfoCommand) Flags() *FlagSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *PluginInfoCommand) AutocompleteArgs() complete.Predictor {
|
func (c *PluginInfoCommand) AutocompleteArgs() complete.Predictor {
|
||||||
return c.PredictVaultPlugins()
|
return c.PredictVaultPlugins(consts.PluginTypeUnknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PluginInfoCommand) AutocompleteFlags() complete.Flags {
|
func (c *PluginInfoCommand) AutocompleteFlags() complete.Flags {
|
||||||
@@ -58,10 +60,10 @@ func (c *PluginInfoCommand) Run(args []string) int {
|
|||||||
|
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
switch {
|
switch {
|
||||||
case len(args) < 1:
|
case len(args) < 2:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) > 1:
|
case len(args) > 2:
|
||||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@@ -72,10 +74,16 @@ func (c *PluginInfoCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginName := strings.TrimSpace(args[0])
|
pluginType, err := consts.ParsePluginType(strings.TrimSpace(args[0]))
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
pluginName := strings.TrimSpace(args[1])
|
||||||
|
|
||||||
resp, err := client.Sys().GetPlugin(&api.GetPluginInput{
|
resp, err := client.Sys().GetPlugin(&api.GetPluginInput{
|
||||||
Name: pluginName,
|
Name: pluginName,
|
||||||
|
Type: pluginType,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(fmt.Sprintf("Error reading plugin named %s: %s", pluginName, err))
|
c.UI.Error(fmt.Sprintf("Error reading plugin named %s: %s", pluginName, err))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,13 +30,13 @@ func TestPluginInfoCommand_Run(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"too_many_args",
|
"too_many_args",
|
||||||
[]string{"foo", "bar"},
|
[]string{"foo", "bar", "fizz"},
|
||||||
"Too many arguments",
|
"Too many arguments",
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"no_plugin_exist",
|
"no_plugin_exist",
|
||||||
[]string{"not-a-real-plugin-like-ever"},
|
[]string{consts.PluginTypeCredential.String(), "not-a-real-plugin-like-ever"},
|
||||||
"Error reading plugin",
|
"Error reading plugin",
|
||||||
2,
|
2,
|
||||||
},
|
},
|
||||||
@@ -79,13 +80,13 @@ func TestPluginInfoCommand_Run(t *testing.T) {
|
|||||||
defer closer()
|
defer closer()
|
||||||
|
|
||||||
pluginName := "my-plugin"
|
pluginName := "my-plugin"
|
||||||
_, sha256Sum := testPluginCreateAndRegister(t, client, pluginDir, pluginName)
|
_, sha256Sum := testPluginCreateAndRegister(t, client, pluginDir, pluginName, consts.PluginTypeCredential)
|
||||||
|
|
||||||
ui, cmd := testPluginInfoCommand(t)
|
ui, cmd := testPluginInfoCommand(t)
|
||||||
cmd.client = client
|
cmd.client = client
|
||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
pluginName,
|
consts.PluginTypeCredential.String(), pluginName,
|
||||||
})
|
})
|
||||||
if exp := 0; code != exp {
|
if exp := 0; code != exp {
|
||||||
t.Errorf("expected %d to be %d", code, exp)
|
t.Errorf("expected %d to be %d", code, exp)
|
||||||
@@ -110,14 +111,14 @@ func TestPluginInfoCommand_Run(t *testing.T) {
|
|||||||
defer closer()
|
defer closer()
|
||||||
|
|
||||||
pluginName := "my-plugin"
|
pluginName := "my-plugin"
|
||||||
testPluginCreateAndRegister(t, client, pluginDir, pluginName)
|
testPluginCreateAndRegister(t, client, pluginDir, pluginName, consts.PluginTypeCredential)
|
||||||
|
|
||||||
ui, cmd := testPluginInfoCommand(t)
|
ui, cmd := testPluginInfoCommand(t)
|
||||||
cmd.client = client
|
cmd.client = client
|
||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
"-field", "builtin",
|
"-field", "builtin",
|
||||||
pluginName,
|
consts.PluginTypeCredential.String(), pluginName,
|
||||||
})
|
})
|
||||||
if exp := 0; code != exp {
|
if exp := 0; code != exp {
|
||||||
t.Errorf("expected %d to be %d", code, exp)
|
t.Errorf("expected %d to be %d", code, exp)
|
||||||
@@ -139,7 +140,7 @@ func TestPluginInfoCommand_Run(t *testing.T) {
|
|||||||
cmd.client = client
|
cmd.client = client
|
||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
"my-plugin",
|
consts.PluginTypeCredential.String(), "my-plugin",
|
||||||
})
|
})
|
||||||
if exp := 2; code != exp {
|
if exp := 2; code != exp {
|
||||||
t.Errorf("expected %d to be %d", code, exp)
|
t.Errorf("expected %d to be %d", code, exp)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@@ -23,15 +24,20 @@ func (c *PluginListCommand) Synopsis() string {
|
|||||||
|
|
||||||
func (c *PluginListCommand) Help() string {
|
func (c *PluginListCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: vault plugin list [options]
|
Usage: vault plugin list [options] [TYPE]
|
||||||
|
|
||||||
Lists available plugins registered in the catalog. This does not list whether
|
Lists available plugins registered in the catalog. This does not list whether
|
||||||
plugins are in use, but rather just their availability.
|
plugins are in use, but rather just their availability. The last argument of
|
||||||
|
type takes "auth", "database", or "secret".
|
||||||
|
|
||||||
List all available plugins in the catalog:
|
List all available plugins in the catalog:
|
||||||
|
|
||||||
$ vault plugin list
|
$ vault plugin list
|
||||||
|
|
||||||
|
List all available database plugins in the catalog:
|
||||||
|
|
||||||
|
$ vault plugin list database
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
@@ -58,32 +64,60 @@ func (c *PluginListCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
if len(args) > 0 {
|
switch {
|
||||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 0, got %d)", len(args)))
|
case len(args) > 1:
|
||||||
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 0 or 1, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginType := consts.PluginTypeUnknown
|
||||||
|
if len(args) > 0 {
|
||||||
|
pluginTypeStr := strings.TrimSpace(args[0])
|
||||||
|
if pluginTypeStr != "" {
|
||||||
|
var err error
|
||||||
|
pluginType, err = consts.ParsePluginType(pluginTypeStr)
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error parsing type: %s", err))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
client, err := c.Client()
|
client, err := c.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(err.Error())
|
c.UI.Error(err.Error())
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Sys().ListPlugins(&api.ListPluginsInput{})
|
resp, err := client.Sys().ListPlugins(&api.ListPluginsInput{
|
||||||
|
Type: pluginType,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(fmt.Sprintf("Error listing available plugins: %s", err))
|
c.UI.Error(fmt.Sprintf("Error listing available plugins: %s", err))
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginNames := resp.Names
|
|
||||||
sort.Strings(pluginNames)
|
|
||||||
|
|
||||||
switch Format(c.UI) {
|
switch Format(c.UI) {
|
||||||
case "table":
|
case "table":
|
||||||
list := append([]string{"Plugins"}, pluginNames...)
|
var flattenedNames []string
|
||||||
|
namesAdded := make(map[string]bool)
|
||||||
|
for _, names := range resp.PluginsByType {
|
||||||
|
for _, name := range names {
|
||||||
|
if ok := namesAdded[name]; !ok {
|
||||||
|
flattenedNames = append(flattenedNames, name)
|
||||||
|
namesAdded[name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(flattenedNames)
|
||||||
|
}
|
||||||
|
list := append([]string{"Plugins"}, flattenedNames...)
|
||||||
c.UI.Output(tableOutput(list, nil))
|
c.UI.Output(tableOutput(list, nil))
|
||||||
return 0
|
return 0
|
||||||
default:
|
default:
|
||||||
return OutputData(c.UI, pluginNames)
|
res := make(map[string]interface{})
|
||||||
|
for k, v := range resp.PluginsByType {
|
||||||
|
res[k.String()] = v
|
||||||
|
}
|
||||||
|
return OutputData(c.UI, res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func TestPluginListCommand_Run(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"too_many_args",
|
"too_many_args",
|
||||||
[]string{"foo"},
|
[]string{"foo", "fizz"},
|
||||||
"Too many arguments",
|
"Too many arguments",
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
@@ -78,7 +78,7 @@ func TestPluginListCommand_Run(t *testing.T) {
|
|||||||
ui, cmd := testPluginListCommand(t)
|
ui, cmd := testPluginListCommand(t)
|
||||||
cmd.client = client
|
cmd.client = client
|
||||||
|
|
||||||
code := cmd.Run([]string{})
|
code := cmd.Run([]string{"database"})
|
||||||
if exp := 2; code != exp {
|
if exp := 2; code != exp {
|
||||||
t.Errorf("expected %d to be %d", code, exp)
|
t.Errorf("expected %d to be %d", code, exp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@@ -26,21 +27,22 @@ func (c *PluginRegisterCommand) Synopsis() string {
|
|||||||
|
|
||||||
func (c *PluginRegisterCommand) Help() string {
|
func (c *PluginRegisterCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: vault plugin register [options] NAME
|
Usage: vault plugin register [options] TYPE NAME
|
||||||
|
|
||||||
Registers a new plugin in the catalog. The plugin binary must exist in Vault's
|
Registers a new plugin in the catalog. The plugin binary must exist in Vault's
|
||||||
configured plugin directory.
|
configured plugin directory. The argument of type takes "auth", "database",
|
||||||
|
or "secret".
|
||||||
|
|
||||||
Register the plugin named my-custom-plugin:
|
Register the plugin named my-custom-plugin:
|
||||||
|
|
||||||
$ vault plugin register -sha256=d3f0a8b... my-custom-plugin
|
$ vault plugin register -sha256=d3f0a8b... auth my-custom-plugin
|
||||||
|
|
||||||
Register a plugin with custom arguments:
|
Register a plugin with custom arguments:
|
||||||
|
|
||||||
$ vault plugin register \
|
$ vault plugin register \
|
||||||
-sha256=d3f0a8b... \
|
-sha256=d3f0a8b... \
|
||||||
-args=--with-glibc,--with-cgo \
|
-args=--with-glibc,--with-cgo \
|
||||||
my-custom-plugin
|
auth my-custom-plugin
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
|
||||||
@@ -79,7 +81,7 @@ func (c *PluginRegisterCommand) Flags() *FlagSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *PluginRegisterCommand) AutocompleteArgs() complete.Predictor {
|
func (c *PluginRegisterCommand) AutocompleteArgs() complete.Predictor {
|
||||||
return c.PredictVaultPlugins()
|
return c.PredictVaultPlugins(consts.PluginTypeUnknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PluginRegisterCommand) AutocompleteFlags() complete.Flags {
|
func (c *PluginRegisterCommand) AutocompleteFlags() complete.Flags {
|
||||||
@@ -96,11 +98,11 @@ func (c *PluginRegisterCommand) Run(args []string) int {
|
|||||||
|
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
switch {
|
switch {
|
||||||
case len(args) < 1:
|
case len(args) < 2:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) > 1:
|
case len(args) > 2:
|
||||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case c.flagSHA256 == "":
|
case c.flagSHA256 == "":
|
||||||
c.UI.Error("SHA256 is required for all plugins, please provide -sha256")
|
c.UI.Error("SHA256 is required for all plugins, please provide -sha256")
|
||||||
@@ -113,7 +115,12 @@ func (c *PluginRegisterCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginName := strings.TrimSpace(args[0])
|
pluginType, err := consts.ParsePluginType(strings.TrimSpace(args[0]))
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
pluginName := strings.TrimSpace(args[1])
|
||||||
|
|
||||||
command := c.flagCommand
|
command := c.flagCommand
|
||||||
if command == "" {
|
if command == "" {
|
||||||
@@ -122,6 +129,7 @@ func (c *PluginRegisterCommand) Run(args []string) int {
|
|||||||
|
|
||||||
if err := client.Sys().RegisterPlugin(&api.RegisterPluginInput{
|
if err := client.Sys().RegisterPlugin(&api.RegisterPluginInput{
|
||||||
Name: pluginName,
|
Name: pluginName,
|
||||||
|
Type: pluginType,
|
||||||
Args: c.flagArgs,
|
Args: c.flagArgs,
|
||||||
Command: command,
|
Command: command,
|
||||||
SHA256: c.flagSHA256,
|
SHA256: c.flagSHA256,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,13 +37,13 @@ func TestPluginRegisterCommand_Run(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"too_many_args",
|
"too_many_args",
|
||||||
[]string{"foo", "bar"},
|
[]string{"foo", "bar", "fizz"},
|
||||||
"Too many arguments",
|
"Too many arguments",
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"not_a_plugin",
|
"not_a_plugin",
|
||||||
[]string{"nope_definitely_never_a_plugin_nope"},
|
[]string{consts.PluginTypeCredential.String(), "nope_definitely_never_a_plugin_nope"},
|
||||||
"",
|
"",
|
||||||
2,
|
2,
|
||||||
},
|
},
|
||||||
@@ -90,7 +91,7 @@ func TestPluginRegisterCommand_Run(t *testing.T) {
|
|||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
"-sha256", sha256Sum,
|
"-sha256", sha256Sum,
|
||||||
pluginName,
|
consts.PluginTypeCredential.String(), pluginName,
|
||||||
})
|
})
|
||||||
if exp := 0; code != exp {
|
if exp := 0; code != exp {
|
||||||
t.Errorf("expected %d to be %d", code, exp)
|
t.Errorf("expected %d to be %d", code, exp)
|
||||||
@@ -102,19 +103,23 @@ func TestPluginRegisterCommand_Run(t *testing.T) {
|
|||||||
t.Errorf("expected %q to contain %q", combined, expected)
|
t.Errorf("expected %q to contain %q", combined, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Sys().ListPlugins(&api.ListPluginsInput{})
|
resp, err := client.Sys().ListPlugins(&api.ListPluginsInput{
|
||||||
|
Type: consts.PluginTypeCredential,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
found := false
|
found := false
|
||||||
for _, p := range resp.Names {
|
for _, plugins := range resp.PluginsByType {
|
||||||
if p == pluginName {
|
for _, p := range plugins {
|
||||||
found = true
|
if p == pluginName {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected %q to be in %q", pluginName, resp.Names)
|
t.Errorf("expected %q to be in %q", pluginName, resp.PluginsByType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -129,7 +134,7 @@ func TestPluginRegisterCommand_Run(t *testing.T) {
|
|||||||
|
|
||||||
code := cmd.Run([]string{
|
code := cmd.Run([]string{
|
||||||
"-sha256", "abcd1234",
|
"-sha256", "abcd1234",
|
||||||
"my-plugin",
|
consts.PluginTypeCredential.String(), "my-plugin",
|
||||||
})
|
})
|
||||||
if exp := 2; code != exp {
|
if exp := 2; code != exp {
|
||||||
t.Errorf("expected %d to be %d", code, exp)
|
t.Errorf("expected %d to be %d", code, exp)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testPluginDir creates a temporary directory suitable for holding plugins.
|
// testPluginDir creates a temporary directory suitable for holding plugins.
|
||||||
@@ -61,13 +62,14 @@ func testPluginCreate(tb testing.TB, dir, name string) (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// testPluginCreateAndRegister creates a plugin and registers it in the catalog.
|
// testPluginCreateAndRegister creates a plugin and registers it in the catalog.
|
||||||
func testPluginCreateAndRegister(tb testing.TB, client *api.Client, dir, name string) (string, string) {
|
func testPluginCreateAndRegister(tb testing.TB, client *api.Client, dir, name string, pluginType consts.PluginType) (string, string) {
|
||||||
tb.Helper()
|
tb.Helper()
|
||||||
|
|
||||||
pth, sha256Sum := testPluginCreate(tb, dir, name)
|
pth, sha256Sum := testPluginCreate(tb, dir, name)
|
||||||
|
|
||||||
if err := client.Sys().RegisterPlugin(&api.RegisterPluginInput{
|
if err := client.Sys().RegisterPlugin(&api.RegisterPluginInput{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Type: pluginType,
|
||||||
Command: name,
|
Command: name,
|
||||||
SHA256: sha256Sum,
|
SHA256: sha256Sum,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@@ -65,6 +66,10 @@ Usage: vault secrets enable [options] TYPE
|
|||||||
|
|
||||||
$ vault secrets enable -path=my-secrets -plugin-name=my-plugin plugin
|
$ vault secrets enable -path=my-secrets -plugin-name=my-plugin plugin
|
||||||
|
|
||||||
|
OR (preferred way):
|
||||||
|
|
||||||
|
$ vault secrets enable -path=my-secrets my-plugin
|
||||||
|
|
||||||
For a full list of secrets engines and examples, please see the documentation.
|
For a full list of secrets engines and examples, please see the documentation.
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
@@ -151,7 +156,7 @@ func (c *SecretsEnableCommand) Flags() *FlagSets {
|
|||||||
f.StringVar(&StringVar{
|
f.StringVar(&StringVar{
|
||||||
Name: "plugin-name",
|
Name: "plugin-name",
|
||||||
Target: &c.flagPluginName,
|
Target: &c.flagPluginName,
|
||||||
Completion: c.PredictVaultPlugins(),
|
Completion: c.PredictVaultPlugins(consts.PluginTypeSecrets, consts.PluginTypeDatabase),
|
||||||
Usage: "Name of the secrets engine plugin. This plugin name must already " +
|
Usage: "Name of the secrets engine plugin. This plugin name must already " +
|
||||||
"exist in Vault's plugin catalog.",
|
"exist in Vault's plugin catalog.",
|
||||||
})
|
})
|
||||||
@@ -223,6 +228,9 @@ func (c *SecretsEnableCommand) Run(args []string) int {
|
|||||||
|
|
||||||
// Get the engine type type (first arg)
|
// Get the engine type type (first arg)
|
||||||
engineType := strings.TrimSpace(args[0])
|
engineType := strings.TrimSpace(args[0])
|
||||||
|
if engineType == "plugin" {
|
||||||
|
engineType = c.flagPluginName
|
||||||
|
}
|
||||||
|
|
||||||
// If no path is specified, we default the path to the backend type
|
// If no path is specified, we default the path to the backend type
|
||||||
// or use the plugin name if it's a plugin backend
|
// or use the plugin name if it's a plugin backend
|
||||||
@@ -255,7 +263,6 @@ func (c *SecretsEnableCommand) Run(args []string) int {
|
|||||||
DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(),
|
DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(),
|
||||||
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),
|
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),
|
||||||
ForceNoCache: c.flagForceNoCache,
|
ForceNoCache: c.flagForceNoCache,
|
||||||
PluginName: c.flagPluginName,
|
|
||||||
},
|
},
|
||||||
Options: c.flagOptions,
|
Options: c.flagOptions,
|
||||||
}
|
}
|
||||||
@@ -288,7 +295,6 @@ func (c *SecretsEnableCommand) Run(args []string) int {
|
|||||||
if engineType == "plugin" {
|
if engineType == "plugin" {
|
||||||
thing = c.flagPluginName + " plugin"
|
thing = c.flagPluginName + " plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
c.UI.Output(fmt.Sprintf("Success! Enabled the %s at: %s", thing, mountPath))
|
c.UI.Output(fmt.Sprintf("Success! Enabled the %s at: %s", thing, mountPath))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -201,9 +203,10 @@ func TestSecretsEnableCommand_Run(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removing one from logical list since plugin is a virtual backend
|
// backends are found by walking the directory, which includes the database backend,
|
||||||
if len(backends) != len(logicalBackends)-1 {
|
// however, the plugins registry omits that one
|
||||||
t.Fatalf("expected %d logical backends, got %d", len(logicalBackends)-1, len(backends))
|
if len(backends) != len(builtinplugins.Registry.Keys(consts.PluginTypeSecrets))+1 {
|
||||||
|
t.Fatalf("expected %d logical backends, got %d", len(builtinplugins.Registry.Keys(consts.PluginTypeSecrets))+1, len(backends))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, b := range backends {
|
for _, b := range backends {
|
||||||
|
|||||||
@@ -155,11 +155,10 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
|
|||||||
replication = "local"
|
replication = "local"
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %t | %s | %t | %v | %s",
|
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s",
|
||||||
path,
|
path,
|
||||||
mount.Type,
|
mount.Type,
|
||||||
mount.Accessor,
|
mount.Accessor,
|
||||||
mount.Config.PluginName,
|
|
||||||
defaultTTL,
|
defaultTTL,
|
||||||
maxTTL,
|
maxTTL,
|
||||||
mount.Config.ForceNoCache,
|
mount.Config.ForceNoCache,
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ import (
|
|||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
sockaddr "github.com/hashicorp/go-sockaddr"
|
"github.com/hashicorp/go-sockaddr"
|
||||||
"github.com/hashicorp/vault/audit"
|
"github.com/hashicorp/vault/audit"
|
||||||
"github.com/hashicorp/vault/command/server"
|
"github.com/hashicorp/vault/command/server"
|
||||||
serverseal "github.com/hashicorp/vault/command/server/seal"
|
serverseal "github.com/hashicorp/vault/command/server/seal"
|
||||||
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
"github.com/hashicorp/vault/helper/gated-writer"
|
"github.com/hashicorp/vault/helper/gated-writer"
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
"github.com/hashicorp/vault/helper/jsonutil"
|
||||||
"github.com/hashicorp/vault/helper/logging"
|
"github.com/hashicorp/vault/helper/logging"
|
||||||
@@ -550,6 +551,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
DisablePerformanceStandby: config.DisablePerformanceStandby,
|
DisablePerformanceStandby: config.DisablePerformanceStandby,
|
||||||
DisableIndexing: config.DisableIndexing,
|
DisableIndexing: config.DisableIndexing,
|
||||||
AllLoggers: allLoggers,
|
AllLoggers: allLoggers,
|
||||||
|
BuiltinRegistry: builtinplugins.Registry,
|
||||||
}
|
}
|
||||||
if c.flagDev {
|
if c.flagDev {
|
||||||
coreConfig.DevToken = c.flagDevRootTokenID
|
coreConfig.DevToken = c.flagDevRootTokenID
|
||||||
@@ -967,6 +969,7 @@ CLUSTER_SYNTHESIS_COMPLETE:
|
|||||||
|
|
||||||
var plugins []string
|
var plugins []string
|
||||||
if c.flagDevPluginDir != "" && c.flagDevPluginInit {
|
if c.flagDevPluginDir != "" && c.flagDevPluginInit {
|
||||||
|
|
||||||
f, err := os.Open(c.flagDevPluginDir)
|
f, err := os.Open(c.flagDevPluginDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(fmt.Sprintf("Error reading plugin dir: %s", err))
|
c.UI.Error(fmt.Sprintf("Error reading plugin dir: %s", err))
|
||||||
@@ -1553,7 +1556,7 @@ func (c *ServerCommand) addPlugin(path, token string, core *vault.Core) error {
|
|||||||
req := &logical.Request{
|
req := &logical.Request{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
ClientToken: token,
|
ClientToken: token,
|
||||||
Path: "sys/plugins/catalog/" + name,
|
Path: fmt.Sprintf("sys/plugins/catalog/%s", name),
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"sha256": sha256sum,
|
"sha256": sha256sum,
|
||||||
"command": name,
|
"command": name,
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package builtinplugins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/hashicorp/vault/plugins/database/cassandra"
|
|
||||||
"github.com/hashicorp/vault/plugins/database/hana"
|
|
||||||
"github.com/hashicorp/vault/plugins/database/mongodb"
|
|
||||||
"github.com/hashicorp/vault/plugins/database/mssql"
|
|
||||||
"github.com/hashicorp/vault/plugins/database/mysql"
|
|
||||||
"github.com/hashicorp/vault/plugins/database/postgresql"
|
|
||||||
"github.com/hashicorp/vault/plugins/helper/database/credsutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BuiltinFactory is the func signature that should be returned by
|
|
||||||
// the plugin's New() func.
|
|
||||||
type BuiltinFactory func() (interface{}, error)
|
|
||||||
|
|
||||||
var plugins = map[string]BuiltinFactory{
|
|
||||||
// These four plugins all use the same mysql implementation but with
|
|
||||||
// different username settings passed by the constructor.
|
|
||||||
"mysql-database-plugin": mysql.New(mysql.MetadataLen, mysql.MetadataLen, mysql.UsernameLen),
|
|
||||||
"mysql-aurora-database-plugin": mysql.New(credsutil.NoneLength, mysql.LegacyMetadataLen, mysql.LegacyUsernameLen),
|
|
||||||
"mysql-rds-database-plugin": mysql.New(credsutil.NoneLength, mysql.LegacyMetadataLen, mysql.LegacyUsernameLen),
|
|
||||||
"mysql-legacy-database-plugin": mysql.New(credsutil.NoneLength, mysql.LegacyMetadataLen, mysql.LegacyUsernameLen),
|
|
||||||
|
|
||||||
"postgresql-database-plugin": postgresql.New,
|
|
||||||
"mssql-database-plugin": mssql.New,
|
|
||||||
"cassandra-database-plugin": cassandra.New,
|
|
||||||
"mongodb-database-plugin": mongodb.New,
|
|
||||||
"hana-database-plugin": hana.New,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the BuiltinFactory func for a particular backend plugin
|
|
||||||
// from the plugins map.
|
|
||||||
func Get(name string) (BuiltinFactory, bool) {
|
|
||||||
f, ok := plugins[name]
|
|
||||||
return f, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys returns the list of plugin names that are considered builtin plugins.
|
|
||||||
func Keys() []string {
|
|
||||||
keys := make([]string, len(plugins))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for k := range plugins {
|
|
||||||
keys[i] = k
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
174
helper/builtinplugins/registry.go
Normal file
174
helper/builtinplugins/registry.go
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
package builtinplugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
|
"github.com/hashicorp/vault/logical"
|
||||||
|
"github.com/hashicorp/vault/plugins/helper/database/credsutil"
|
||||||
|
|
||||||
|
credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
|
||||||
|
credAzure "github.com/hashicorp/vault-plugin-auth-azure"
|
||||||
|
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
||||||
|
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||||
|
credJWT "github.com/hashicorp/vault-plugin-auth-jwt"
|
||||||
|
credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
|
||||||
|
credAppId "github.com/hashicorp/vault/builtin/credential/app-id"
|
||||||
|
credAppRole "github.com/hashicorp/vault/builtin/credential/approle"
|
||||||
|
credAws "github.com/hashicorp/vault/builtin/credential/aws"
|
||||||
|
credCert "github.com/hashicorp/vault/builtin/credential/cert"
|
||||||
|
credGitHub "github.com/hashicorp/vault/builtin/credential/github"
|
||||||
|
credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
|
||||||
|
credOkta "github.com/hashicorp/vault/builtin/credential/okta"
|
||||||
|
credRadius "github.com/hashicorp/vault/builtin/credential/radius"
|
||||||
|
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
|
||||||
|
|
||||||
|
dbCass "github.com/hashicorp/vault/plugins/database/cassandra"
|
||||||
|
dbHana "github.com/hashicorp/vault/plugins/database/hana"
|
||||||
|
dbMongo "github.com/hashicorp/vault/plugins/database/mongodb"
|
||||||
|
dbMssql "github.com/hashicorp/vault/plugins/database/mssql"
|
||||||
|
dbMysql "github.com/hashicorp/vault/plugins/database/mysql"
|
||||||
|
dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql"
|
||||||
|
|
||||||
|
logicalAd "github.com/hashicorp/vault-plugin-secrets-ad/plugin"
|
||||||
|
logicalAlicloud "github.com/hashicorp/vault-plugin-secrets-alicloud"
|
||||||
|
logicalAzure "github.com/hashicorp/vault-plugin-secrets-azure"
|
||||||
|
logicalGcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
|
||||||
|
logicalGcpKms "github.com/hashicorp/vault-plugin-secrets-gcpkms"
|
||||||
|
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
|
||||||
|
logicalAws "github.com/hashicorp/vault/builtin/logical/aws"
|
||||||
|
logicalCass "github.com/hashicorp/vault/builtin/logical/cassandra"
|
||||||
|
logicalConsul "github.com/hashicorp/vault/builtin/logical/consul"
|
||||||
|
logicalMongo "github.com/hashicorp/vault/builtin/logical/mongodb"
|
||||||
|
logicalMssql "github.com/hashicorp/vault/builtin/logical/mssql"
|
||||||
|
logicalMysql "github.com/hashicorp/vault/builtin/logical/mysql"
|
||||||
|
logicalNomad "github.com/hashicorp/vault/builtin/logical/nomad"
|
||||||
|
logicalPki "github.com/hashicorp/vault/builtin/logical/pki"
|
||||||
|
logicalPostgres "github.com/hashicorp/vault/builtin/logical/postgresql"
|
||||||
|
logicalRabbit "github.com/hashicorp/vault/builtin/logical/rabbitmq"
|
||||||
|
logicalSsh "github.com/hashicorp/vault/builtin/logical/ssh"
|
||||||
|
logicalTotp "github.com/hashicorp/vault/builtin/logical/totp"
|
||||||
|
logicalTransit "github.com/hashicorp/vault/builtin/logical/transit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Registry is inherently thread-safe because it's immutable.
|
||||||
|
// Thus, rather than creating multiple instances of it, we only need one.
|
||||||
|
var Registry = newRegistry()
|
||||||
|
|
||||||
|
// BuiltinFactory is the func signature that should be returned by
|
||||||
|
// the plugin's New() func.
|
||||||
|
type BuiltinFactory func() (interface{}, error)
|
||||||
|
|
||||||
|
func newRegistry() *registry {
|
||||||
|
return ®istry{
|
||||||
|
credentialBackends: map[string]logical.Factory{
|
||||||
|
"alicloud": credAliCloud.Factory,
|
||||||
|
"app-id": credAppId.Factory,
|
||||||
|
"approle": credAppRole.Factory,
|
||||||
|
"aws": credAws.Factory,
|
||||||
|
"azure": credAzure.Factory,
|
||||||
|
"centrify": credCentrify.Factory,
|
||||||
|
"cert": credCert.Factory,
|
||||||
|
"gcp": credGcp.Factory,
|
||||||
|
"github": credGitHub.Factory,
|
||||||
|
"jwt": credJWT.Factory,
|
||||||
|
"kubernetes": credKube.Factory,
|
||||||
|
"ldap": credLdap.Factory,
|
||||||
|
"okta": credOkta.Factory,
|
||||||
|
"radius": credRadius.Factory,
|
||||||
|
"userpass": credUserpass.Factory,
|
||||||
|
},
|
||||||
|
databasePlugins: map[string]BuiltinFactory{
|
||||||
|
// These four plugins all use the same mysql implementation but with
|
||||||
|
// different username settings passed by the constructor.
|
||||||
|
"mysql-database-plugin": dbMysql.New(dbMysql.MetadataLen, dbMysql.MetadataLen, dbMysql.UsernameLen),
|
||||||
|
"mysql-aurora-database-plugin": dbMysql.New(credsutil.NoneLength, dbMysql.LegacyMetadataLen, dbMysql.LegacyUsernameLen),
|
||||||
|
"mysql-rds-database-plugin": dbMysql.New(credsutil.NoneLength, dbMysql.LegacyMetadataLen, dbMysql.LegacyUsernameLen),
|
||||||
|
"mysql-legacy-database-plugin": dbMysql.New(credsutil.NoneLength, dbMysql.LegacyMetadataLen, dbMysql.LegacyUsernameLen),
|
||||||
|
|
||||||
|
"postgresql-database-plugin": dbPostgres.New,
|
||||||
|
"mssql-database-plugin": dbMssql.New,
|
||||||
|
"cassandra-database-plugin": dbCass.New,
|
||||||
|
"mongodb-database-plugin": dbMongo.New,
|
||||||
|
"hana-database-plugin": dbHana.New,
|
||||||
|
},
|
||||||
|
logicalBackends: map[string]logical.Factory{
|
||||||
|
"ad": logicalAd.Factory,
|
||||||
|
"alicloud": logicalAlicloud.Factory,
|
||||||
|
"aws": logicalAws.Factory,
|
||||||
|
"azure": logicalAzure.Factory,
|
||||||
|
"cassandra": logicalCass.Factory,
|
||||||
|
"consul": logicalConsul.Factory,
|
||||||
|
"gcp": logicalGcp.Factory,
|
||||||
|
"gcpkms": logicalGcpKms.Factory,
|
||||||
|
"kv": logicalKv.Factory,
|
||||||
|
"mongodb": logicalMongo.Factory,
|
||||||
|
"mssql": logicalMssql.Factory,
|
||||||
|
"mysql": logicalMysql.Factory,
|
||||||
|
"nomad": logicalNomad.Factory,
|
||||||
|
"pki": logicalPki.Factory,
|
||||||
|
"postgresql": logicalPostgres.Factory,
|
||||||
|
"rabbitmq": logicalRabbit.Factory,
|
||||||
|
"ssh": logicalSsh.Factory,
|
||||||
|
"totp": logicalTotp.Factory,
|
||||||
|
"transit": logicalTransit.Factory,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type registry struct {
|
||||||
|
credentialBackends map[string]logical.Factory
|
||||||
|
databasePlugins map[string]BuiltinFactory
|
||||||
|
logicalBackends map[string]logical.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the BuiltinFactory func for a particular backend plugin
|
||||||
|
// from the plugins map.
|
||||||
|
func (r *registry) Get(name string, pluginType consts.PluginType) (func() (interface{}, error), bool) {
|
||||||
|
switch pluginType {
|
||||||
|
case consts.PluginTypeCredential:
|
||||||
|
f, ok := r.credentialBackends[name]
|
||||||
|
return toFunc(f), ok
|
||||||
|
case consts.PluginTypeSecrets:
|
||||||
|
f, ok := r.logicalBackends[name]
|
||||||
|
return toFunc(f), ok
|
||||||
|
case consts.PluginTypeDatabase:
|
||||||
|
f, ok := r.databasePlugins[name]
|
||||||
|
return f, ok
|
||||||
|
default:
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns the list of plugin names that are considered builtin plugins.
|
||||||
|
func (r *registry) Keys(pluginType consts.PluginType) []string {
|
||||||
|
var keys []string
|
||||||
|
switch pluginType {
|
||||||
|
case consts.PluginTypeDatabase:
|
||||||
|
for key := range r.databasePlugins {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
case consts.PluginTypeCredential:
|
||||||
|
for key := range r.credentialBackends {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
case consts.PluginTypeSecrets:
|
||||||
|
for key := range r.logicalBackends {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *registry) Contains(name string, pluginType consts.PluginType) bool {
|
||||||
|
for _, key := range r.Keys(pluginType) {
|
||||||
|
if key == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func toFunc(ifc interface{}) func() (interface{}, error) {
|
||||||
|
return func() (interface{}, error) {
|
||||||
|
return ifc, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
59
helper/consts/plugin_types.go
Normal file
59
helper/consts/plugin_types.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
var PluginTypes = []PluginType{
|
||||||
|
PluginTypeUnknown,
|
||||||
|
PluginTypeCredential,
|
||||||
|
PluginTypeDatabase,
|
||||||
|
PluginTypeSecrets,
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginType uint32
|
||||||
|
|
||||||
|
// This is a list of PluginTypes used by Vault.
|
||||||
|
// If we need to add any in the future, it would
|
||||||
|
// be best to add them to the _end_ of the list below
|
||||||
|
// because they resolve to incrementing numbers,
|
||||||
|
// which may be saved in state somewhere. Thus if
|
||||||
|
// the name for one of those numbers changed because
|
||||||
|
// a value were added to the middle, that could cause
|
||||||
|
// the wrong plugin types to be read from storage
|
||||||
|
// for a given underlying number. Example of the problem
|
||||||
|
// here: https://play.golang.org/p/YAaPw5ww3er
|
||||||
|
const (
|
||||||
|
PluginTypeUnknown PluginType = iota
|
||||||
|
PluginTypeCredential
|
||||||
|
PluginTypeDatabase
|
||||||
|
PluginTypeSecrets
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p PluginType) String() string {
|
||||||
|
switch p {
|
||||||
|
case PluginTypeUnknown:
|
||||||
|
return "unknown"
|
||||||
|
case PluginTypeCredential:
|
||||||
|
return "auth"
|
||||||
|
case PluginTypeDatabase:
|
||||||
|
return "database"
|
||||||
|
case PluginTypeSecrets:
|
||||||
|
return "secret"
|
||||||
|
default:
|
||||||
|
return "unsupported"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePluginType(pluginType string) (PluginType, error) {
|
||||||
|
switch pluginType {
|
||||||
|
case "unknown":
|
||||||
|
return PluginTypeUnknown, nil
|
||||||
|
case "auth":
|
||||||
|
return PluginTypeCredential, nil
|
||||||
|
case "database":
|
||||||
|
return PluginTypeDatabase, nil
|
||||||
|
case "secret":
|
||||||
|
return PluginTypeSecrets, nil
|
||||||
|
default:
|
||||||
|
return PluginTypeUnknown, fmt.Errorf("%s is not a supported plugin type", pluginType)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,7 +71,7 @@ func TestMFALogin(t *testing.T) {
|
|||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepEnableMFA(t),
|
testAccStepEnableMFA(t),
|
||||||
testAccStepLogin(t, "user"),
|
testAccStepLogin(t, "user"),
|
||||||
@@ -84,7 +84,7 @@ func TestMFALoginDenied(t *testing.T) {
|
|||||||
|
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
AcceptanceTest: true,
|
AcceptanceTest: true,
|
||||||
Backend: b,
|
LogicalBackend: b,
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepEnableMFA(t),
|
testAccStepEnableMFA(t),
|
||||||
testAccStepLoginDenied(t, "user"),
|
testAccStepLoginDenied(t, "user"),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/wrapping"
|
"github.com/hashicorp/vault/helper/wrapping"
|
||||||
"github.com/hashicorp/vault/version"
|
"github.com/hashicorp/vault/version"
|
||||||
)
|
)
|
||||||
@@ -19,7 +20,7 @@ import (
|
|||||||
// Looker defines the plugin Lookup function that looks into the plugin catalog
|
// Looker defines the plugin Lookup function that looks into the plugin catalog
|
||||||
// for available plugins and returns a PluginRunner
|
// for available plugins and returns a PluginRunner
|
||||||
type Looker interface {
|
type Looker interface {
|
||||||
LookupPlugin(context.Context, string) (*PluginRunner, error)
|
LookupPlugin(context.Context, string, consts.PluginType) (*PluginRunner, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunnerUtil interface defines the functions needed by the runner to wrap the
|
// RunnerUtil interface defines the functions needed by the runner to wrap the
|
||||||
@@ -41,6 +42,7 @@ type LookRunnerUtil interface {
|
|||||||
// go-plugin.
|
// go-plugin.
|
||||||
type PluginRunner struct {
|
type PluginRunner struct {
|
||||||
Name string `json:"name" structs:"name"`
|
Name string `json:"name" structs:"name"`
|
||||||
|
Type consts.PluginType `json:"type" structs:"type"`
|
||||||
Command string `json:"command" structs:"command"`
|
Command string `json:"command" structs:"command"`
|
||||||
Args []string `json:"args" structs:"args"`
|
Args []string `json:"args" structs:"args"`
|
||||||
Env []string `json:"env" structs:"env"`
|
Env []string `json:"env" structs:"env"`
|
||||||
@@ -73,7 +75,7 @@ func (r *PluginRunner) runCommon(ctx context.Context, wrapper RunnerUtil, plugin
|
|||||||
cmd.Env = append(cmd.Env, env...)
|
cmd.Env = append(cmd.Env, env...)
|
||||||
|
|
||||||
// Add the mlock setting to the ENV of the plugin
|
// Add the mlock setting to the ENV of the plugin
|
||||||
if wrapper.MlockEnabled() {
|
if wrapper != nil && wrapper.MlockEnabled() {
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true"))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true"))
|
||||||
}
|
}
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version))
|
||||||
|
|||||||
@@ -11,10 +11,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
)
|
)
|
||||||
@@ -274,7 +273,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -287,7 +285,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -300,7 +297,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -313,7 +309,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -327,7 +322,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -340,7 +334,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -353,7 +346,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -366,7 +358,6 @@ func TestSysMounts_headerAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
bplugin "github.com/hashicorp/vault/builtin/plugin"
|
bplugin "github.com/hashicorp/vault/builtin/plugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/plugin"
|
"github.com/hashicorp/vault/logical/plugin"
|
||||||
@@ -50,12 +51,11 @@ func getPluginClusterAndCore(t testing.TB, logger log.Logger) (*vault.TestCluste
|
|||||||
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
||||||
|
|
||||||
vault.TestWaitActive(t, core.Core)
|
vault.TestWaitActive(t, core.Core)
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestPlugin_PluginMain", []string{}, "")
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "TestPlugin_PluginMain", []string{}, "")
|
||||||
|
|
||||||
// Mount the mock plugin
|
// Mount the mock plugin
|
||||||
err = core.Client.Sys().Mount("mock", &api.MountInput{
|
err = core.Client.Sys().Mount("mock", &api.MountInput{
|
||||||
Type: "plugin",
|
Type: "mock-plugin",
|
||||||
PluginName: "mock-plugin",
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ func TestSysAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
@@ -47,7 +46,6 @@ func TestSysAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
@@ -102,7 +100,6 @@ func TestSysEnableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
@@ -116,7 +113,6 @@ func TestSysEnableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
},
|
},
|
||||||
@@ -131,7 +127,6 @@ func TestSysEnableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
@@ -145,7 +140,6 @@ func TestSysEnableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
@@ -201,7 +195,6 @@ func TestSysDisableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
@@ -216,7 +209,6 @@ func TestSysDisableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -46,7 +45,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -59,7 +57,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -72,7 +69,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -86,7 +82,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -99,7 +94,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -112,7 +106,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -125,7 +118,6 @@ func TestSysMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -181,7 +173,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -194,7 +185,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -207,7 +197,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -220,7 +209,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -233,7 +221,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -247,7 +234,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -260,7 +246,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -273,7 +258,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -286,7 +270,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -299,7 +282,6 @@ func TestSysMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -374,7 +356,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -387,7 +368,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -400,7 +380,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -413,7 +392,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -426,7 +404,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -440,7 +417,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -453,7 +429,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -466,7 +441,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -479,7 +453,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -492,7 +465,6 @@ func TestSysRemount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -548,7 +520,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -561,7 +532,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -574,7 +544,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -587,7 +556,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -601,7 +569,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -614,7 +581,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -627,7 +593,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -640,7 +605,6 @@ func TestSysUnmount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -778,7 +742,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -791,7 +754,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -804,7 +766,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -817,7 +778,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -830,7 +790,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -844,7 +803,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -857,7 +815,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -870,7 +827,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -883,7 +839,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -896,7 +851,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -978,7 +932,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("259196400"),
|
"default_lease_ttl": json.Number("259196400"),
|
||||||
"max_lease_ttl": json.Number("259200000"),
|
"max_lease_ttl": json.Number("259200000"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -991,7 +944,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1004,7 +956,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1017,7 +968,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1030,7 +980,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1044,7 +993,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("259196400"),
|
"default_lease_ttl": json.Number("259196400"),
|
||||||
"max_lease_ttl": json.Number("259200000"),
|
"max_lease_ttl": json.Number("259200000"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1057,7 +1005,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1070,7 +1017,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1083,7 +1029,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
@@ -1096,7 +1041,6 @@ func TestSysTuneMount(t *testing.T) {
|
|||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
"seal_wrap": false,
|
"seal_wrap": false,
|
||||||
|
|||||||
@@ -4,11 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/license"
|
"github.com/hashicorp/vault/helper/license"
|
||||||
@@ -16,6 +13,7 @@ import (
|
|||||||
"github.com/hashicorp/vault/helper/wrapping"
|
"github.com/hashicorp/vault/helper/wrapping"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/plugin/pb"
|
"github.com/hashicorp/vault/logical/plugin/pb"
|
||||||
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newGRPCSystemView(conn *grpc.ClientConn) *gRPCSystemViewClient {
|
func newGRPCSystemView(conn *grpc.ClientConn) *gRPCSystemViewClient {
|
||||||
@@ -111,7 +109,7 @@ func (s *gRPCSystemViewClient) ResponseWrapData(ctx context.Context, data map[st
|
|||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *gRPCSystemViewClient) LookupPlugin(ctx context.Context, name string) (*pluginutil.PluginRunner, error) {
|
func (s *gRPCSystemViewClient) LookupPlugin(_ context.Context, _ string, _ consts.PluginType) (*pluginutil.PluginRunner, error) {
|
||||||
return nil, fmt.Errorf("cannot call LookupPlugin from a plugin backend")
|
return nil, fmt.Errorf("cannot call LookupPlugin from a plugin backend")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ func TestSystem_GRPC_lookupPlugin(t *testing.T) {
|
|||||||
|
|
||||||
testSystemView := newGRPCSystemView(client)
|
testSystemView := newGRPCSystemView(client)
|
||||||
|
|
||||||
if _, err := testSystemView.LookupPlugin(context.Background(), "foo"); err == nil {
|
if _, err := testSystemView.LookupPlugin(context.Background(), "foo", consts.PluginTypeDatabase); err == nil {
|
||||||
t.Fatal("LookPlugin(): expected error on due to unsupported call from plugin")
|
t.Fatal("LookPlugin(): expected error on due to unsupported call from plugin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import (
|
|||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
)
|
)
|
||||||
@@ -61,9 +61,9 @@ func (b *BackendPluginClient) Cleanup(ctx context.Context) {
|
|||||||
// external plugins, or a concrete implementation of the backend if it is a builtin backend.
|
// external plugins, or a concrete implementation of the backend if it is a builtin backend.
|
||||||
// The backend is returned as a logical.Backend interface. The isMetadataMode param determines whether
|
// The backend is returned as a logical.Backend interface. The isMetadataMode param determines whether
|
||||||
// the plugin should run in metadata mode.
|
// the plugin should run in metadata mode.
|
||||||
func NewBackend(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger, isMetadataMode bool) (logical.Backend, error) {
|
func NewBackend(ctx context.Context, pluginName string, pluginType consts.PluginType, sys pluginutil.LookRunnerUtil, conf *logical.BackendConfig, isMetadataMode bool) (logical.Backend, error) {
|
||||||
// Look for plugin in the plugin catalog
|
// Look for plugin in the plugin catalog
|
||||||
pluginRunner, err := sys.LookupPlugin(ctx, pluginName)
|
pluginRunner, err := sys.LookupPlugin(ctx, pluginName, pluginType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -71,21 +71,22 @@ func NewBackend(ctx context.Context, pluginName string, sys pluginutil.LookRunne
|
|||||||
var backend logical.Backend
|
var backend logical.Backend
|
||||||
if pluginRunner.Builtin {
|
if pluginRunner.Builtin {
|
||||||
// Plugin is builtin so we can retrieve an instance of the interface
|
// Plugin is builtin so we can retrieve an instance of the interface
|
||||||
// from the pluginRunner. Then cast it to logical.Backend.
|
// from the pluginRunner. Then cast it to logical.Factory.
|
||||||
backendRaw, err := pluginRunner.BuiltinFactory()
|
rawFactory, err := pluginRunner.BuiltinFactory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errwrap.Wrapf("error getting plugin type: {{err}}", err)
|
return nil, errwrap.Wrapf("error getting plugin type: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok bool
|
if factory, ok := rawFactory.(logical.Factory); !ok {
|
||||||
backend, ok = backendRaw.(logical.Backend)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unsupported backend type: %q", pluginName)
|
return nil, fmt.Errorf("unsupported backend type: %q", pluginName)
|
||||||
|
} else {
|
||||||
|
if backend, err = factory(ctx, conf); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// create a backendPluginClient instance
|
// create a backendPluginClient instance
|
||||||
backend, err = newPluginClient(ctx, sys, pluginRunner, logger, isMetadataMode)
|
backend, err = NewPluginClient(ctx, sys, pluginRunner, conf.Logger, isMetadataMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -94,7 +95,7 @@ func NewBackend(ctx context.Context, pluginName string, sys pluginutil.LookRunne
|
|||||||
return backend, nil
|
return backend, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger, isMetadataMode bool) (logical.Backend, error) {
|
func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger, isMetadataMode bool) (logical.Backend, error) {
|
||||||
// pluginMap is the map of plugins we can dispense.
|
// pluginMap is the map of plugins we can dispense.
|
||||||
pluginSet := map[int]plugin.PluginSet{
|
pluginSet := map[int]plugin.PluginSet{
|
||||||
3: plugin.PluginSet{
|
3: plugin.PluginSet{
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func (s *SystemViewClient) ResponseWrapData(ctx context.Context, data map[string
|
|||||||
return reply.ResponseWrapInfo, nil
|
return reply.ResponseWrapInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SystemViewClient) LookupPlugin(ctx context.Context, name string) (*pluginutil.PluginRunner, error) {
|
func (s *SystemViewClient) LookupPlugin(_ context.Context, _ string, _ consts.PluginType) (*pluginutil.PluginRunner, error) {
|
||||||
return nil, fmt.Errorf("cannot call LookupPlugin from a plugin backend")
|
return nil, fmt.Errorf("cannot call LookupPlugin from a plugin backend")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ func TestSystem_lookupPlugin(t *testing.T) {
|
|||||||
|
|
||||||
testSystemView := &SystemViewClient{client: client}
|
testSystemView := &SystemViewClient{client: client}
|
||||||
|
|
||||||
if _, err := testSystemView.LookupPlugin(context.Background(), "foo"); err == nil {
|
if _, err := testSystemView.LookupPlugin(context.Background(), "foo", consts.PluginTypeDatabase); err == nil {
|
||||||
t.Fatal("LookPlugin(): expected error on due to unsupported call from plugin")
|
t.Fatal("LookPlugin(): expected error on due to unsupported call from plugin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ type SystemView interface {
|
|||||||
|
|
||||||
// LookupPlugin looks into the plugin catalog for a plugin with the given
|
// LookupPlugin looks into the plugin catalog for a plugin with the given
|
||||||
// name. Returns a PluginRunner or an error if a plugin can not be found.
|
// name. Returns a PluginRunner or an error if a plugin can not be found.
|
||||||
LookupPlugin(context.Context, string) (*pluginutil.PluginRunner, error)
|
LookupPlugin(context.Context, string, consts.PluginType) (*pluginutil.PluginRunner, error)
|
||||||
|
|
||||||
// MlockEnabled returns the configuration setting for enabling mlock on
|
// MlockEnabled returns the configuration setting for enabling mlock on
|
||||||
// plugins.
|
// plugins.
|
||||||
@@ -118,7 +118,7 @@ func (d StaticSystemView) ResponseWrapData(_ context.Context, data map[string]in
|
|||||||
return nil, errors.New("ResponseWrapData is not implemented in StaticSystemView")
|
return nil, errors.New("ResponseWrapData is not implemented in StaticSystemView")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d StaticSystemView) LookupPlugin(_ context.Context, name string) (*pluginutil.PluginRunner, error) {
|
func (d StaticSystemView) LookupPlugin(_ context.Context, _ string, _ consts.PluginType) (*pluginutil.PluginRunner, error) {
|
||||||
return nil, errors.New("LookupPlugin is not implemented in StaticSystemView")
|
return nil, errors.New("LookupPlugin is not implemented in StaticSystemView")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,19 @@ type TestCase struct {
|
|||||||
// test running.
|
// test running.
|
||||||
PreCheck func()
|
PreCheck func()
|
||||||
|
|
||||||
// Backend is the backend that will be mounted.
|
// LogicalBackend is the backend that will be mounted.
|
||||||
Backend logical.Backend
|
LogicalBackend logical.Backend
|
||||||
|
|
||||||
// Factory can be used instead of Backend if the
|
// LogicalFactory can be used instead of LogicalBackend if the
|
||||||
// backend requires more construction
|
// backend requires more construction
|
||||||
Factory logical.Factory
|
LogicalFactory logical.Factory
|
||||||
|
|
||||||
|
// CredentialBackend is the backend that will be mounted.
|
||||||
|
CredentialBackend logical.Backend
|
||||||
|
|
||||||
|
// CredentialFactory can be used instead of CredentialBackend if the
|
||||||
|
// backend requires more construction
|
||||||
|
CredentialFactory logical.Factory
|
||||||
|
|
||||||
// Steps are the set of operations that are run for this test case.
|
// Steps are the set of operations that are run for this test case.
|
||||||
Steps []TestStep
|
Steps []TestStep
|
||||||
@@ -135,8 +142,15 @@ func Test(tt TestT, c TestCase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that something is provided
|
// Check that something is provided
|
||||||
if c.Backend == nil && c.Factory == nil {
|
if c.LogicalBackend == nil && c.LogicalFactory == nil {
|
||||||
tt.Fatal("Must provide either Backend or Factory")
|
if c.CredentialBackend == nil && c.CredentialFactory == nil {
|
||||||
|
tt.Fatal("Must provide either Backend or Factory")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We currently only support doing one logical OR one credential test at a time.
|
||||||
|
if (c.LogicalFactory != nil || c.LogicalBackend != nil) && (c.CredentialFactory != nil || c.CredentialBackend != nil) {
|
||||||
|
tt.Fatal("Must provide only one backend or factory")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,18 +163,34 @@ func Test(tt TestT, c TestCase) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core, err := vault.NewCore(&vault.CoreConfig{
|
config := &vault.CoreConfig{
|
||||||
Physical: phys,
|
Physical: phys,
|
||||||
LogicalBackends: map[string]logical.Factory{
|
DisableMlock: true,
|
||||||
|
BuiltinRegistry: vault.NewMockBuiltinRegistry(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.LogicalBackend != nil || c.LogicalFactory != nil {
|
||||||
|
config.LogicalBackends = map[string]logical.Factory{
|
||||||
"test": func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
"test": func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
||||||
if c.Backend != nil {
|
if c.LogicalBackend != nil {
|
||||||
return c.Backend, nil
|
return c.LogicalBackend, nil
|
||||||
}
|
}
|
||||||
return c.Factory(ctx, conf)
|
return c.LogicalFactory(ctx, conf)
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
DisableMlock: true,
|
}
|
||||||
})
|
if c.CredentialBackend != nil || c.CredentialFactory != nil {
|
||||||
|
config.CredentialBackends = map[string]logical.Factory{
|
||||||
|
"test": func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
||||||
|
if c.CredentialBackend != nil {
|
||||||
|
return c.CredentialBackend, nil
|
||||||
|
}
|
||||||
|
return c.CredentialFactory(ctx, conf)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core, err := vault.NewCore(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tt.Fatal("error initializing core: ", err)
|
tt.Fatal("error initializing core: ", err)
|
||||||
return
|
return
|
||||||
@@ -202,15 +232,31 @@ func Test(tt TestT, c TestCase) {
|
|||||||
// Set the token so we're authenticated
|
// Set the token so we're authenticated
|
||||||
client.SetToken(init.RootToken)
|
client.SetToken(init.RootToken)
|
||||||
|
|
||||||
// Mount the backend
|
|
||||||
prefix := "mnt"
|
prefix := "mnt"
|
||||||
mountInfo := &api.MountInput{
|
if c.LogicalBackend != nil || c.LogicalFactory != nil {
|
||||||
Type: "test",
|
// Mount the backend
|
||||||
Description: "acceptance test",
|
mountInfo := &api.MountInput{
|
||||||
|
Type: "test",
|
||||||
|
Description: "acceptance test",
|
||||||
|
}
|
||||||
|
if err := client.Sys().Mount(prefix, mountInfo); err != nil {
|
||||||
|
tt.Fatal("error mounting backend: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := client.Sys().Mount(prefix, mountInfo); err != nil {
|
|
||||||
tt.Fatal("error mounting backend: ", err)
|
isAuthBackend := false
|
||||||
return
|
if c.CredentialBackend != nil || c.CredentialFactory != nil {
|
||||||
|
isAuthBackend = true
|
||||||
|
|
||||||
|
// Enable the test auth method
|
||||||
|
opts := &api.EnableAuthOptions{
|
||||||
|
Type: "test",
|
||||||
|
}
|
||||||
|
if err := client.Sys().EnableAuthWithOptions(prefix, opts); err != nil {
|
||||||
|
tt.Fatal("error enabling backend: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenInfo, err := client.Auth().Token().LookupSelf()
|
tokenInfo, err := client.Auth().Token().LookupSelf()
|
||||||
@@ -269,6 +315,11 @@ func Test(tt TestT, c TestCase) {
|
|||||||
// Make sure to prefix the path with where we mounted the thing
|
// Make sure to prefix the path with where we mounted the thing
|
||||||
req.Path = fmt.Sprintf("%s/%s", prefix, req.Path)
|
req.Path = fmt.Sprintf("%s/%s", prefix, req.Path)
|
||||||
|
|
||||||
|
if isAuthBackend {
|
||||||
|
// Prepend the path with "auth"
|
||||||
|
req.Path = "auth/" + req.Path
|
||||||
|
}
|
||||||
|
|
||||||
// Make the request
|
// Make the request
|
||||||
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if resp != nil && resp.Secret != nil {
|
if resp != nil && resp.Secret != nil {
|
||||||
@@ -338,7 +389,11 @@ func Test(tt TestT, c TestCase) {
|
|||||||
// We set the "immediate" flag here that any backend can pick up on
|
// We set the "immediate" flag here that any backend can pick up on
|
||||||
// to do all rollbacks immediately even if the WAL entries are new.
|
// to do all rollbacks immediately even if the WAL entries are new.
|
||||||
logger.Warn("Requesting RollbackOperation")
|
logger.Warn("Requesting RollbackOperation")
|
||||||
req := logical.RollbackRequest(prefix + "/")
|
rollbackPath := prefix + "/"
|
||||||
|
if c.CredentialFactory != nil || c.CredentialBackend != nil {
|
||||||
|
rollbackPath = "auth/" + rollbackPath
|
||||||
|
}
|
||||||
|
req := logical.RollbackRequest(rollbackPath)
|
||||||
req.Data["immediate"] = true
|
req.Data["immediate"] = true
|
||||||
req.ClientToken = client.Token()
|
req.ClientToken = client.Token()
|
||||||
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
|
"github.com/hashicorp/vault/builtin/plugin"
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
"github.com/hashicorp/vault/helper/jsonutil"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
@@ -141,11 +142,6 @@ func (c *Core) enableCredentialInternal(ctx context.Context, entry *MountEntry,
|
|||||||
var backend logical.Backend
|
var backend logical.Backend
|
||||||
// Create the new backend
|
// Create the new backend
|
||||||
sysView := c.mountEntrySysView(entry)
|
sysView := c.mountEntrySysView(entry)
|
||||||
conf := make(map[string]string)
|
|
||||||
if entry.Config.PluginName != "" {
|
|
||||||
conf["plugin_name"] = entry.Config.PluginName
|
|
||||||
}
|
|
||||||
// Create the new backend
|
|
||||||
backend, err = c.newCredentialBackend(ctx, entry, sysView, view)
|
backend, err = c.newCredentialBackend(ctx, entry, sysView, view)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -156,8 +152,8 @@ func (c *Core) enableCredentialInternal(ctx context.Context, entry *MountEntry,
|
|||||||
|
|
||||||
// Check for the correct backend type
|
// Check for the correct backend type
|
||||||
backendType := backend.Type()
|
backendType := backend.Type()
|
||||||
if entry.Type == "plugin" && backendType != logical.TypeCredential {
|
if backendType != logical.TypeCredential {
|
||||||
return fmt.Errorf("cannot mount %q of type %q as an auth backend", entry.Config.PluginName, backendType)
|
return fmt.Errorf("cannot mount %q of type %q as an auth backend", entry.Type, backendType)
|
||||||
}
|
}
|
||||||
|
|
||||||
addPathCheckers(c, entry, backend, viewPath)
|
addPathCheckers(c, entry, backend, viewPath)
|
||||||
@@ -600,15 +596,11 @@ func (c *Core) setupCredentials(ctx context.Context) error {
|
|||||||
|
|
||||||
// Initialize the backend
|
// Initialize the backend
|
||||||
sysView := c.mountEntrySysView(entry)
|
sysView := c.mountEntrySysView(entry)
|
||||||
conf := make(map[string]string)
|
|
||||||
if entry.Config.PluginName != "" {
|
|
||||||
conf["plugin_name"] = entry.Config.PluginName
|
|
||||||
}
|
|
||||||
|
|
||||||
backend, err = c.newCredentialBackend(ctx, entry, sysView, view)
|
backend, err = c.newCredentialBackend(ctx, entry, sysView, view)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Error("failed to create credential entry", "path", entry.Path, "error", err)
|
c.logger.Error("failed to create credential entry", "path", entry.Path, "error", err)
|
||||||
if entry.Type == "plugin" {
|
if !c.builtinRegistry.Contains(entry.Type, consts.PluginTypeCredential) {
|
||||||
// If we encounter an error instantiating the backend due to an error,
|
// If we encounter an error instantiating the backend due to an error,
|
||||||
// skip backend initialization but register the entry to the mount table
|
// skip backend initialization but register the entry to the mount table
|
||||||
// to preserve storage and path.
|
// to preserve storage and path.
|
||||||
@@ -624,8 +616,8 @@ func (c *Core) setupCredentials(ctx context.Context) error {
|
|||||||
{
|
{
|
||||||
// Check for the correct backend type
|
// Check for the correct backend type
|
||||||
backendType := backend.Type()
|
backendType := backend.Type()
|
||||||
if entry.Type == "plugin" && backendType != logical.TypeCredential {
|
if backendType != logical.TypeCredential {
|
||||||
return fmt.Errorf("cannot mount %q of type %q as an auth backend", entry.Config.PluginName, backendType)
|
return fmt.Errorf("cannot mount %q of type %q as an auth backend", entry.Type, backendType)
|
||||||
}
|
}
|
||||||
|
|
||||||
addPathCheckers(c, entry, backend, viewPath)
|
addPathCheckers(c, entry, backend, viewPath)
|
||||||
@@ -717,7 +709,7 @@ func (c *Core) newCredentialBackend(ctx context.Context, entry *MountEntry, sysV
|
|||||||
|
|
||||||
f, ok := c.credentialBackends[t]
|
f, ok := c.credentialBackends[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unknown backend type: %q", t)
|
f = plugin.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up conf to pass in plugin_name
|
// Set up conf to pass in plugin_name
|
||||||
@@ -725,10 +717,16 @@ func (c *Core) newCredentialBackend(ctx context.Context, entry *MountEntry, sysV
|
|||||||
for k, v := range entry.Options {
|
for k, v := range entry.Options {
|
||||||
conf[k] = v
|
conf[k] = v
|
||||||
}
|
}
|
||||||
if entry.Config.PluginName != "" {
|
|
||||||
conf["plugin_name"] = entry.Config.PluginName
|
switch {
|
||||||
|
case entry.Type == "plugin":
|
||||||
|
conf["plugin_name"] = entry.Config.PluginNameDeprecated
|
||||||
|
default:
|
||||||
|
conf["plugin_name"] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf["plugin_type"] = consts.PluginTypeCredential.String()
|
||||||
|
|
||||||
authLogger := c.baseLogger.Named(fmt.Sprintf("auth.%s.%s", t, entry.Accessor))
|
authLogger := c.baseLogger.Named(fmt.Sprintf("auth.%s.%s", t, entry.Accessor))
|
||||||
c.AddLogger(authLogger)
|
c.AddLogger(authLogger)
|
||||||
config := &logical.BackendConfig{
|
config := &logical.BackendConfig{
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ func TestAuth_ReadOnlyViewDuringMount(t *testing.T) {
|
|||||||
if err == nil || !strings.Contains(err.Error(), logical.ErrSetupReadOnly.Error()) {
|
if err == nil || !strings.Contains(err.Error(), logical.ErrSetupReadOnly.Error()) {
|
||||||
t.Fatalf("expected a read-only error")
|
t.Fatalf("expected a read-only error")
|
||||||
}
|
}
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
me := &MountEntry{
|
me := &MountEntry{
|
||||||
@@ -67,7 +69,9 @@ func TestCore_DefaultAuthTable(t *testing.T) {
|
|||||||
func TestCore_EnableCredential(t *testing.T) {
|
func TestCore_EnableCredential(t *testing.T) {
|
||||||
c, keys, _ := TestCoreUnsealed(t)
|
c, keys, _ := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
me := &MountEntry{
|
me := &MountEntry{
|
||||||
@@ -94,7 +98,9 @@ func TestCore_EnableCredential(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
c2.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c2.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
unseal, err := TestCoreUnseal(c2, key)
|
unseal, err := TestCoreUnseal(c2, key)
|
||||||
@@ -118,7 +124,9 @@ func TestCore_EnableCredential(t *testing.T) {
|
|||||||
func TestCore_EnableCredential_Local(t *testing.T) {
|
func TestCore_EnableCredential_Local(t *testing.T) {
|
||||||
c, _, _ := TestCoreUnsealed(t)
|
c, _, _ := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.auth = &MountTable{
|
c.auth = &MountTable{
|
||||||
@@ -205,7 +213,9 @@ func TestCore_EnableCredential_Local(t *testing.T) {
|
|||||||
func TestCore_EnableCredential_twice_409(t *testing.T) {
|
func TestCore_EnableCredential_twice_409(t *testing.T) {
|
||||||
c, _, _ := TestCoreUnsealed(t)
|
c, _, _ := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
me := &MountEntry{
|
me := &MountEntry{
|
||||||
@@ -246,7 +256,9 @@ func TestCore_EnableCredential_Token(t *testing.T) {
|
|||||||
func TestCore_DisableCredential(t *testing.T) {
|
func TestCore_DisableCredential(t *testing.T) {
|
||||||
c, keys, _ := TestCoreUnsealed(t)
|
c, keys, _ := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := c.disableCredential(namespace.RootContext(nil), "foo")
|
err := c.disableCredential(namespace.RootContext(nil), "foo")
|
||||||
@@ -308,7 +320,8 @@ func TestCore_DisableCredential_Protected(t *testing.T) {
|
|||||||
|
|
||||||
func TestCore_DisableCredential_Cleanup(t *testing.T) {
|
func TestCore_DisableCredential_Cleanup(t *testing.T) {
|
||||||
noop := &NoopBackend{
|
noop := &NoopBackend{
|
||||||
Login: []string{"login"},
|
Login: []string{"login"},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
c, _, _ := TestCoreUnsealed(t)
|
c, _, _ := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
"github.com/armon/go-metrics"
|
"github.com/armon/go-metrics"
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
cache "github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
@@ -137,6 +137,10 @@ type unlockInformation struct {
|
|||||||
type Core struct {
|
type Core struct {
|
||||||
entCore
|
entCore
|
||||||
|
|
||||||
|
// The registry of builtin plugins is passed in here as an interface because
|
||||||
|
// if it's used directly, it results in import cycles.
|
||||||
|
builtinRegistry BuiltinRegistry
|
||||||
|
|
||||||
// N.B.: This is used to populate a dev token down replication, as
|
// N.B.: This is used to populate a dev token down replication, as
|
||||||
// otherwise, after replication is started, a dev would have to go through
|
// otherwise, after replication is started, a dev would have to go through
|
||||||
// the generate-root process simply to talk to the new follower cluster.
|
// the generate-root process simply to talk to the new follower cluster.
|
||||||
@@ -403,6 +407,8 @@ type Core struct {
|
|||||||
type CoreConfig struct {
|
type CoreConfig struct {
|
||||||
DevToken string `json:"dev_token" structs:"dev_token" mapstructure:"dev_token"`
|
DevToken string `json:"dev_token" structs:"dev_token" mapstructure:"dev_token"`
|
||||||
|
|
||||||
|
BuiltinRegistry BuiltinRegistry `json:"builtin_registry" structs:"builtin_registry" mapstructure:"builtin_registry"`
|
||||||
|
|
||||||
LogicalBackends map[string]logical.Factory `json:"logical_backends" structs:"logical_backends" mapstructure:"logical_backends"`
|
LogicalBackends map[string]logical.Factory `json:"logical_backends" structs:"logical_backends" mapstructure:"logical_backends"`
|
||||||
|
|
||||||
CredentialBackends map[string]logical.Factory `json:"credential_backends" structs:"credential_backends" mapstructure:"credential_backends"`
|
CredentialBackends map[string]logical.Factory `json:"credential_backends" structs:"credential_backends" mapstructure:"credential_backends"`
|
||||||
@@ -567,6 +573,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
|
|||||||
disablePerfStandby: true,
|
disablePerfStandby: true,
|
||||||
activeContextCancelFunc: new(atomic.Value),
|
activeContextCancelFunc: new(atomic.Value),
|
||||||
allLoggers: conf.AllLoggers,
|
allLoggers: conf.AllLoggers,
|
||||||
|
builtinRegistry: conf.BuiltinRegistry,
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic.StoreUint32(c.sealed, 1)
|
atomic.StoreUint32(c.sealed, 1)
|
||||||
@@ -619,7 +626,6 @@ func NewCore(conf *CoreConfig) (*Core, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var ok bool
|
|
||||||
|
|
||||||
if conf.PluginDirectory != "" {
|
if conf.PluginDirectory != "" {
|
||||||
c.pluginDirectory, err = filepath.Abs(conf.PluginDirectory)
|
c.pluginDirectory, err = filepath.Abs(conf.PluginDirectory)
|
||||||
@@ -648,15 +654,15 @@ func NewCore(conf *CoreConfig) (*Core, error) {
|
|||||||
c.reloadFuncsLock.Unlock()
|
c.reloadFuncsLock.Unlock()
|
||||||
conf.ReloadFuncs = &c.reloadFuncs
|
conf.ReloadFuncs = &c.reloadFuncs
|
||||||
|
|
||||||
// Setup the backends
|
|
||||||
logicalBackends := make(map[string]logical.Factory)
|
logicalBackends := make(map[string]logical.Factory)
|
||||||
for k, f := range conf.LogicalBackends {
|
for k, f := range conf.LogicalBackends {
|
||||||
logicalBackends[k] = f
|
logicalBackends[k] = f
|
||||||
}
|
}
|
||||||
_, ok = logicalBackends["kv"]
|
_, ok := logicalBackends["kv"]
|
||||||
if !ok {
|
if !ok {
|
||||||
logicalBackends["kv"] = PassthroughBackendFactory
|
logicalBackends["kv"] = PassthroughBackendFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
logicalBackends["cubbyhole"] = CubbyholeBackendFactory
|
logicalBackends["cubbyhole"] = CubbyholeBackendFactory
|
||||||
logicalBackends[systemMountType] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
|
logicalBackends[systemMountType] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
|
||||||
sysBackendLogger := conf.Logger.Named("system")
|
sysBackendLogger := conf.Logger.Named("system")
|
||||||
@@ -1382,7 +1388,7 @@ func (s standardUnsealStrategy) unseal(ctx context.Context, logger log.Logger, c
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := c.setupPluginCatalog(); err != nil {
|
if err := c.setupPluginCatalog(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := c.loadMounts(ctx); err != nil {
|
if err := c.loadMounts(ctx); err != nil {
|
||||||
@@ -1695,3 +1701,12 @@ func (c *Core) SetLogLevel(level log.Level) {
|
|||||||
logger.SetLevel(level)
|
logger.SetLevel(level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuiltinRegistry is an interface that allows the "vault" package to use
|
||||||
|
// the registry of builtin plugins without getting an import cycle. It
|
||||||
|
// also allows for mocking the registry easily.
|
||||||
|
type BuiltinRegistry interface {
|
||||||
|
Contains(name string, pluginType consts.PluginType) bool
|
||||||
|
Get(name string, pluginType consts.PluginType) (func() (interface{}, error), bool)
|
||||||
|
Keys(pluginType consts.PluginType) []string
|
||||||
|
}
|
||||||
|
|||||||
@@ -632,8 +632,9 @@ func TestCore_HandleRequest_NoClientToken(t *testing.T) {
|
|||||||
|
|
||||||
func TestCore_HandleRequest_ConnOnLogin(t *testing.T) {
|
func TestCore_HandleRequest_ConnOnLogin(t *testing.T) {
|
||||||
noop := &NoopBackend{
|
noop := &NoopBackend{
|
||||||
Login: []string{"login"},
|
Login: []string{"login"},
|
||||||
Response: &logical.Response{},
|
Response: &logical.Response{},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
c, _, root := TestCoreUnsealed(t)
|
c, _, root := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
@@ -675,6 +676,7 @@ func TestCore_HandleLogin_Token(t *testing.T) {
|
|||||||
DisplayName: "armon",
|
DisplayName: "armon",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
c, _, root := TestCoreUnsealed(t)
|
c, _, root := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
||||||
@@ -919,6 +921,7 @@ func TestCore_HandleLogin_AuditTrail(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
c, _, root := TestCoreUnsealed(t)
|
c, _, root := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
@@ -1782,6 +1785,7 @@ func TestCore_HandleRequest_Login_InternalData(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
|
|
||||||
c, _, root := TestCoreUnsealed(t)
|
c, _, root := TestCoreUnsealed(t)
|
||||||
@@ -1871,6 +1875,7 @@ func TestCore_HandleLogin_ReturnSecret(t *testing.T) {
|
|||||||
Policies: []string{"foo", "bar"},
|
Policies: []string{"foo", "bar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
c, _, root := TestCoreUnsealed(t)
|
c, _, root := TestCoreUnsealed(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
@@ -2022,6 +2027,7 @@ func TestCore_EnableDisableCred_WithLease(t *testing.T) {
|
|||||||
Policies: []string{"root"},
|
Policies: []string{"root"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
|
|
||||||
c, _, root := TestCoreUnsealed(t)
|
c, _, root := TestCoreUnsealed(t)
|
||||||
|
|||||||
@@ -164,14 +164,14 @@ func (d dynamicSystemView) ResponseWrapData(ctx context.Context, data map[string
|
|||||||
|
|
||||||
// LookupPlugin looks for a plugin with the given name in the plugin catalog. It
|
// LookupPlugin looks for a plugin with the given name in the plugin catalog. It
|
||||||
// returns a PluginRunner or an error if no plugin was found.
|
// returns a PluginRunner or an error if no plugin was found.
|
||||||
func (d dynamicSystemView) LookupPlugin(ctx context.Context, name string) (*pluginutil.PluginRunner, error) {
|
func (d dynamicSystemView) LookupPlugin(ctx context.Context, name string, pluginType consts.PluginType) (*pluginutil.PluginRunner, error) {
|
||||||
if d.core == nil {
|
if d.core == nil {
|
||||||
return nil, fmt.Errorf("system view core is nil")
|
return nil, fmt.Errorf("system view core is nil")
|
||||||
}
|
}
|
||||||
if d.core.pluginCatalog == nil {
|
if d.core.pluginCatalog == nil {
|
||||||
return nil, fmt.Errorf("system view core plugin catalog is nil")
|
return nil, fmt.Errorf("system view core plugin catalog is nil")
|
||||||
}
|
}
|
||||||
r, err := d.core.pluginCatalog.Get(ctx, name)
|
r, err := d.core.pluginCatalog.Get(ctx, name, pluginType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1943,6 +1943,7 @@ func badRenewFactory(ctx context.Context, conf *logical.BackendConfig) (logical.
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeLogical,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := be.Setup(namespace.RootContext(nil), conf)
|
err := be.Setup(namespace.RootContext(nil), conf)
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ func LeaseSwitchedPassthroughBackend(ctx context.Context, conf *logical.BackendC
|
|||||||
HelpDescription: strings.TrimSpace(passthroughHelpDescription),
|
HelpDescription: strings.TrimSpace(passthroughHelpDescription),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeLogical,
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Backend.Secrets = []*framework.Secret{
|
b.Backend.Secrets = []*framework.Secret{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"hash"
|
"hash"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -19,8 +20,8 @@ import (
|
|||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
memdb "github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/vault/helper/compressutil"
|
"github.com/hashicorp/vault/helper/compressutil"
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/identity"
|
"github.com/hashicorp/vault/helper/identity"
|
||||||
@@ -131,8 +132,7 @@ func NewSystemBackend(core *Core, logger log.Logger) *SystemBackend {
|
|||||||
b.Backend.Paths = append(b.Backend.Paths, b.configPaths()...)
|
b.Backend.Paths = append(b.Backend.Paths, b.configPaths()...)
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.rekeyPaths()...)
|
b.Backend.Paths = append(b.Backend.Paths, b.rekeyPaths()...)
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.sealPaths()...)
|
b.Backend.Paths = append(b.Backend.Paths, b.sealPaths()...)
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.pluginsCatalogPath())
|
b.Backend.Paths = append(b.Backend.Paths, b.pluginsCatalogPaths()...)
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.pluginsCatalogListPath())
|
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.pluginsReloadPath())
|
b.Backend.Paths = append(b.Backend.Paths, b.pluginsReloadPath())
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.auditPaths()...)
|
b.Backend.Paths = append(b.Backend.Paths, b.auditPaths()...)
|
||||||
b.Backend.Paths = append(b.Backend.Paths, b.mountPaths()...)
|
b.Backend.Paths = append(b.Backend.Paths, b.mountPaths()...)
|
||||||
@@ -255,21 +255,53 @@ func (b *SystemBackend) handleTidyLeases(ctx context.Context, req *logical.Reque
|
|||||||
return logical.RespondWithStatusCode(resp, req, http.StatusAccepted)
|
return logical.RespondWithStatusCode(resp, req, http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handlePluginCatalogList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handlePluginCatalogTypedList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
plugins, err := b.Core.pluginCatalog.List(ctx)
|
pluginType, err := consts.ParsePluginType(d.Get("type").(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins, err := b.Core.pluginCatalog.List(ctx, pluginType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return logical.ListResponse(plugins), nil
|
return logical.ListResponse(plugins), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *SystemBackend) handlePluginCatalogUntypedList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
|
pluginsByType := make(map[string]interface{})
|
||||||
|
for _, pluginType := range consts.PluginTypes {
|
||||||
|
plugins, err := b.Core.pluginCatalog.List(ctx, pluginType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(plugins) > 0 {
|
||||||
|
sort.Strings(plugins)
|
||||||
|
pluginsByType[pluginType.String()] = plugins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &logical.Response{
|
||||||
|
Data: pluginsByType,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handlePluginCatalogUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handlePluginCatalogUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
pluginName := d.Get("name").(string)
|
pluginName := d.Get("name").(string)
|
||||||
if pluginName == "" {
|
if pluginName == "" {
|
||||||
return logical.ErrorResponse("missing plugin name"), nil
|
return logical.ErrorResponse("missing plugin name"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginTypeStr := d.Get("type").(string)
|
||||||
|
if pluginTypeStr == "" {
|
||||||
|
// If the plugin type is not provided, list it as unknown so that we
|
||||||
|
// add it to the catalog and UpdatePlugins later will sort it.
|
||||||
|
pluginTypeStr = "unknown"
|
||||||
|
}
|
||||||
|
pluginType, err := consts.ParsePluginType(pluginTypeStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
sha256 := d.Get("sha256").(string)
|
sha256 := d.Get("sha256").(string)
|
||||||
if sha256 == "" {
|
if sha256 == "" {
|
||||||
sha256 = d.Get("sha_256").(string)
|
sha256 = d.Get("sha_256").(string)
|
||||||
@@ -302,7 +334,7 @@ func (b *SystemBackend) handlePluginCatalogUpdate(ctx context.Context, req *logi
|
|||||||
return logical.ErrorResponse("Could not decode SHA-256 value from Hex"), err
|
return logical.ErrorResponse("Could not decode SHA-256 value from Hex"), err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.Core.pluginCatalog.Set(ctx, pluginName, parts[0], args, env, sha256Bytes)
|
err = b.Core.pluginCatalog.Set(ctx, pluginName, pluginType, parts[0], args, env, sha256Bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -315,7 +347,13 @@ func (b *SystemBackend) handlePluginCatalogRead(ctx context.Context, req *logica
|
|||||||
if pluginName == "" {
|
if pluginName == "" {
|
||||||
return logical.ErrorResponse("missing plugin name"), nil
|
return logical.ErrorResponse("missing plugin name"), nil
|
||||||
}
|
}
|
||||||
plugin, err := b.Core.pluginCatalog.Get(ctx, pluginName)
|
|
||||||
|
pluginType, err := consts.ParsePluginType(d.Get("type").(string))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin, err := b.Core.pluginCatalog.Get(ctx, pluginName, pluginType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -349,10 +387,13 @@ func (b *SystemBackend) handlePluginCatalogDelete(ctx context.Context, req *logi
|
|||||||
if pluginName == "" {
|
if pluginName == "" {
|
||||||
return logical.ErrorResponse("missing plugin name"), nil
|
return logical.ErrorResponse("missing plugin name"), nil
|
||||||
}
|
}
|
||||||
err := b.Core.pluginCatalog.Delete(ctx, pluginName)
|
pluginType, err := consts.ParsePluginType(d.Get("type").(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := b.Core.pluginCatalog.Delete(ctx, pluginName, pluginType); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -599,7 +640,6 @@ func mountInfo(entry *MountEntry) map[string]interface{} {
|
|||||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||||
"force_no_cache": entry.Config.ForceNoCache,
|
"force_no_cache": entry.Config.ForceNoCache,
|
||||||
"plugin_name": entry.Config.PluginName,
|
|
||||||
}
|
}
|
||||||
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
||||||
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
|
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
|
||||||
@@ -735,15 +775,14 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
|
|||||||
return logical.ErrorResponse(
|
return logical.ErrorResponse(
|
||||||
"backend type must be specified as a string"),
|
"backend type must be specified as a string"),
|
||||||
logical.ErrInvalidRequest
|
logical.ErrInvalidRequest
|
||||||
|
|
||||||
case "plugin":
|
case "plugin":
|
||||||
// Only set plugin-name if mount is of type plugin, with apiConfig.PluginName
|
// Only set plugin-name if mount is of type plugin, with apiConfig.PluginNameDeprecated
|
||||||
// option taking precedence.
|
// option taking precedence.
|
||||||
switch {
|
switch {
|
||||||
case apiConfig.PluginName != "":
|
case apiConfig.PluginNameDeprecated != "":
|
||||||
config.PluginName = apiConfig.PluginName
|
logicalType = apiConfig.PluginNameDeprecated
|
||||||
case pluginName != "":
|
case pluginName != "":
|
||||||
config.PluginName = pluginName
|
logicalType = pluginName
|
||||||
default:
|
default:
|
||||||
return logical.ErrorResponse(
|
return logical.ErrorResponse(
|
||||||
"plugin_name must be provided for plugin backend"),
|
"plugin_name must be provided for plugin backend"),
|
||||||
@@ -1620,15 +1659,14 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
|
|||||||
return logical.ErrorResponse(
|
return logical.ErrorResponse(
|
||||||
"backend type must be specified as a string"),
|
"backend type must be specified as a string"),
|
||||||
logical.ErrInvalidRequest
|
logical.ErrInvalidRequest
|
||||||
|
|
||||||
case "plugin":
|
case "plugin":
|
||||||
// Only set plugin name if mount is of type plugin, with apiConfig.PluginName
|
// Only set plugin name if mount is of type plugin, with apiConfig.PluginNameDeprecated
|
||||||
// option taking precedence.
|
// option taking precedence.
|
||||||
switch {
|
switch {
|
||||||
case apiConfig.PluginName != "":
|
case apiConfig.PluginNameDeprecated != "":
|
||||||
config.PluginName = apiConfig.PluginName
|
logicalType = apiConfig.PluginNameDeprecated
|
||||||
case pluginName != "":
|
case pluginName != "":
|
||||||
config.PluginName = pluginName
|
logicalType = pluginName
|
||||||
default:
|
default:
|
||||||
return logical.ErrorResponse(
|
return logical.ErrorResponse(
|
||||||
"plugin_name must be provided for plugin backend"),
|
"plugin_name must be provided for plugin backend"),
|
||||||
@@ -3642,8 +3680,16 @@ This path responds to the following HTTP methods.
|
|||||||
"Lists the headers configured to be audited.",
|
"Lists the headers configured to be audited.",
|
||||||
`Returns a list of headers that have been configured to be audited.`,
|
`Returns a list of headers that have been configured to be audited.`,
|
||||||
},
|
},
|
||||||
|
"plugin-catalog-list-all": {
|
||||||
|
"Lists all the plugins known to Vault",
|
||||||
|
`
|
||||||
|
This path responds to the following HTTP methods.
|
||||||
|
LIST /
|
||||||
|
Returns a list of names of configured plugins.
|
||||||
|
`,
|
||||||
|
},
|
||||||
"plugin-catalog": {
|
"plugin-catalog": {
|
||||||
"Configures the plugins known to vault",
|
"Configures the plugins known to Vault",
|
||||||
`
|
`
|
||||||
This path responds to the following HTTP methods.
|
This path responds to the following HTTP methods.
|
||||||
LIST /
|
LIST /
|
||||||
@@ -3663,6 +3709,10 @@ This path responds to the following HTTP methods.
|
|||||||
"The name of the plugin",
|
"The name of the plugin",
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
"plugin-catalog_type": {
|
||||||
|
"The type of the plugin, may be auth, secret, or database",
|
||||||
|
"",
|
||||||
|
},
|
||||||
"plugin-catalog_sha-256": {
|
"plugin-catalog_sha-256": {
|
||||||
`The SHA256 sum of the executable used in the
|
`The SHA256 sum of the executable used in the
|
||||||
command field. This should be HEX encoded.`,
|
command field. This should be HEX encoded.`,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/go-test/deep"
|
"github.com/go-test/deep"
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/builtin/plugin"
|
"github.com/hashicorp/vault/builtin/plugin"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
vaulthttp "github.com/hashicorp/vault/http"
|
vaulthttp "github.com/hashicorp/vault/http"
|
||||||
@@ -107,16 +108,16 @@ func TestSystemBackend_Plugin_MismatchType(t *testing.T) {
|
|||||||
|
|
||||||
core := cluster.Cores[0]
|
core := cluster.Cores[0]
|
||||||
|
|
||||||
// Replace the plugin with a credential backend
|
// Add a credential backend with the same name
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainCredentials", []string{}, "")
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeCredential, "TestBackend_PluginMainCredentials", []string{}, "")
|
||||||
|
|
||||||
// Make a request to lazy load the now-credential plugin
|
// Make a request to lazy load the now-credential plugin
|
||||||
// and expect an error
|
// and expect an error
|
||||||
req := logical.TestRequest(t, logical.ReadOperation, "mock-0/internal")
|
req := logical.TestRequest(t, logical.ReadOperation, "mock-0/internal")
|
||||||
req.ClientToken = core.Client.Token()
|
req.ClientToken = core.Client.Token()
|
||||||
_, err := core.HandleRequest(namespace.RootContext(nil), req)
|
_, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
t.Fatalf("expected error due to mismatch on error type: %s", err)
|
t.Fatalf("adding a same-named plugin of a different type should be no problem: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep a bit before cleanup is called
|
// Sleep a bit before cleanup is called
|
||||||
@@ -148,7 +149,7 @@ func testPlugin_CatalogRemoved(t *testing.T, btype logical.BackendType, testMoun
|
|||||||
core := cluster.Cores[0]
|
core := cluster.Cores[0]
|
||||||
|
|
||||||
// Remove the plugin from the catalog
|
// Remove the plugin from the catalog
|
||||||
req := logical.TestRequest(t, logical.DeleteOperation, "sys/plugins/catalog/mock-plugin")
|
req := logical.TestRequest(t, logical.DeleteOperation, "sys/plugins/catalog/database/mock-plugin")
|
||||||
req.ClientToken = core.Client.Token()
|
req.ClientToken = core.Client.Token()
|
||||||
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err != nil || (resp != nil && resp.IsError()) {
|
if err != nil || (resp != nil && resp.IsError()) {
|
||||||
@@ -183,19 +184,15 @@ func testPlugin_CatalogRemoved(t *testing.T, btype logical.BackendType, testMoun
|
|||||||
switch btype {
|
switch btype {
|
||||||
case logical.TypeLogical:
|
case logical.TypeLogical:
|
||||||
// Add plugin back to the catalog
|
// Add plugin back to the catalog
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainLogical", []string{}, "")
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "TestBackend_PluginMainLogical", []string{}, "")
|
||||||
_, err = core.Client.Logical().Write("sys/mounts/mock-0", map[string]interface{}{
|
_, err = core.Client.Logical().Write("sys/mounts/mock-0", map[string]interface{}{
|
||||||
"type": "plugin",
|
"type": "test",
|
||||||
"config": map[string]interface{}{
|
|
||||||
"plugin_name": "mock-plugin",
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
case logical.TypeCredential:
|
case logical.TypeCredential:
|
||||||
// Add plugin back to the catalog
|
// Add plugin back to the catalog
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainCredentials", []string{}, "")
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeCredential, "TestBackend_PluginMainCredentials", []string{}, "")
|
||||||
_, err = core.Client.Logical().Write("sys/auth/mock-0", map[string]interface{}{
|
_, err = core.Client.Logical().Write("sys/auth/mock-0", map[string]interface{}{
|
||||||
"type": "plugin",
|
"type": "test",
|
||||||
"plugin_name": "mock-plugin",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -207,33 +204,33 @@ func testPlugin_CatalogRemoved(t *testing.T, btype logical.BackendType, testMoun
|
|||||||
func TestSystemBackend_Plugin_continueOnError(t *testing.T) {
|
func TestSystemBackend_Plugin_continueOnError(t *testing.T) {
|
||||||
t.Run("secret", func(t *testing.T) {
|
t.Run("secret", func(t *testing.T) {
|
||||||
t.Run("sha256_mismatch", func(t *testing.T) {
|
t.Run("sha256_mismatch", func(t *testing.T) {
|
||||||
testPlugin_continueOnError(t, logical.TypeLogical, true)
|
testPlugin_continueOnError(t, logical.TypeLogical, true, consts.PluginTypeSecrets)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing_plugin", func(t *testing.T) {
|
t.Run("missing_plugin", func(t *testing.T) {
|
||||||
testPlugin_continueOnError(t, logical.TypeLogical, false)
|
testPlugin_continueOnError(t, logical.TypeLogical, false, consts.PluginTypeSecrets)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("auth", func(t *testing.T) {
|
t.Run("auth", func(t *testing.T) {
|
||||||
t.Run("sha256_mismatch", func(t *testing.T) {
|
t.Run("sha256_mismatch", func(t *testing.T) {
|
||||||
testPlugin_continueOnError(t, logical.TypeCredential, true)
|
testPlugin_continueOnError(t, logical.TypeCredential, true, consts.PluginTypeCredential)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing_plugin", func(t *testing.T) {
|
t.Run("missing_plugin", func(t *testing.T) {
|
||||||
testPlugin_continueOnError(t, logical.TypeCredential, false)
|
testPlugin_continueOnError(t, logical.TypeCredential, false, consts.PluginTypeCredential)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPlugin_continueOnError(t *testing.T, btype logical.BackendType, mismatch bool) {
|
func testPlugin_continueOnError(t *testing.T, btype logical.BackendType, mismatch bool, pluginType consts.PluginType) {
|
||||||
cluster := testSystemBackendMock(t, 1, 1, btype)
|
cluster := testSystemBackendMock(t, 1, 1, btype)
|
||||||
defer cluster.Cleanup()
|
defer cluster.Cleanup()
|
||||||
|
|
||||||
core := cluster.Cores[0]
|
core := cluster.Cores[0]
|
||||||
|
|
||||||
// Get the registered plugin
|
// Get the registered plugin
|
||||||
req := logical.TestRequest(t, logical.ReadOperation, "sys/plugins/catalog/mock-plugin")
|
req := logical.TestRequest(t, logical.ReadOperation, fmt.Sprintf("sys/plugins/catalog/%s/mock-plugin", pluginType))
|
||||||
req.ClientToken = core.Client.Token()
|
req.ClientToken = core.Client.Token()
|
||||||
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err != nil || resp == nil || (resp != nil && resp.IsError()) {
|
if err != nil || resp == nil || (resp != nil && resp.IsError()) {
|
||||||
@@ -247,7 +244,7 @@ func testPlugin_continueOnError(t *testing.T, btype logical.BackendType, mismatc
|
|||||||
|
|
||||||
// Trigger a sha256 mismatch or missing plugin error
|
// Trigger a sha256 mismatch or missing plugin error
|
||||||
if mismatch {
|
if mismatch {
|
||||||
req = logical.TestRequest(t, logical.UpdateOperation, "sys/plugins/catalog/mock-plugin")
|
req = logical.TestRequest(t, logical.UpdateOperation, "sys/plugins/catalog/database/mock-plugin")
|
||||||
req.Data = map[string]interface{}{
|
req.Data = map[string]interface{}{
|
||||||
"sha256": "d17bd7334758e53e6fbab15745d2520765c06e296f2ce8e25b7919effa0ac216",
|
"sha256": "d17bd7334758e53e6fbab15745d2520765c06e296f2ce8e25b7919effa0ac216",
|
||||||
"command": filepath.Base(command),
|
"command": filepath.Base(command),
|
||||||
@@ -288,9 +285,9 @@ func testPlugin_continueOnError(t *testing.T, btype logical.BackendType, mismatc
|
|||||||
// Re-add the plugin to the catalog
|
// Re-add the plugin to the catalog
|
||||||
switch btype {
|
switch btype {
|
||||||
case logical.TypeLogical:
|
case logical.TypeLogical:
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainLogical", []string{}, cluster.TempDir)
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "TestBackend_PluginMainLogical", []string{}, cluster.TempDir)
|
||||||
case logical.TypeCredential:
|
case logical.TypeCredential:
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainCredentials", []string{}, cluster.TempDir)
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeCredential, "TestBackend_PluginMainCredentials", []string{}, cluster.TempDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload the plugin
|
// Reload the plugin
|
||||||
@@ -485,18 +482,11 @@ func testSystemBackendMock(t *testing.T, numCores, numMounts int, backendType lo
|
|||||||
|
|
||||||
switch backendType {
|
switch backendType {
|
||||||
case logical.TypeLogical:
|
case logical.TypeLogical:
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainLogical", []string{}, tempDir)
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "TestBackend_PluginMainLogical", []string{}, tempDir)
|
||||||
for i := 0; i < numMounts; i++ {
|
for i := 0; i < numMounts; i++ {
|
||||||
// Alternate input styles for plugin_name on every other mount
|
// Alternate input styles for plugin_name on every other mount
|
||||||
options := map[string]interface{}{
|
options := map[string]interface{}{
|
||||||
"type": "plugin",
|
"type": "mock-plugin",
|
||||||
}
|
|
||||||
if (i+1)%2 == 0 {
|
|
||||||
options["config"] = map[string]interface{}{
|
|
||||||
"plugin_name": "mock-plugin",
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
options["plugin_name"] = "mock-plugin"
|
|
||||||
}
|
}
|
||||||
resp, err := client.Logical().Write(fmt.Sprintf("sys/mounts/mock-%d", i), options)
|
resp, err := client.Logical().Write(fmt.Sprintf("sys/mounts/mock-%d", i), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -507,18 +497,11 @@ func testSystemBackendMock(t *testing.T, numCores, numMounts int, backendType lo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case logical.TypeCredential:
|
case logical.TypeCredential:
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainCredentials", []string{}, tempDir)
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeCredential, "TestBackend_PluginMainCredentials", []string{}, tempDir)
|
||||||
for i := 0; i < numMounts; i++ {
|
for i := 0; i < numMounts; i++ {
|
||||||
// Alternate input styles for plugin_name on every other mount
|
// Alternate input styles for plugin_name on every other mount
|
||||||
options := map[string]interface{}{
|
options := map[string]interface{}{
|
||||||
"type": "plugin",
|
"type": "mock-plugin",
|
||||||
}
|
|
||||||
if (i+1)%2 == 0 {
|
|
||||||
options["config"] = map[string]interface{}{
|
|
||||||
"plugin_name": "mock-plugin",
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
options["plugin_name"] = "mock-plugin"
|
|
||||||
}
|
}
|
||||||
resp, err := client.Logical().Write(fmt.Sprintf("sys/auth/mock-%d", i), options)
|
resp, err := client.Logical().Write(fmt.Sprintf("sys/auth/mock-%d", i), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -546,7 +529,7 @@ func TestSystemBackend_Plugin_Env(t *testing.T) {
|
|||||||
func testSystemBackend_SingleCluster_Env(t *testing.T, env []string) *vault.TestCluster {
|
func testSystemBackend_SingleCluster_Env(t *testing.T, env []string) *vault.TestCluster {
|
||||||
coreConfig := &vault.CoreConfig{
|
coreConfig := &vault.CoreConfig{
|
||||||
LogicalBackends: map[string]logical.Factory{
|
LogicalBackends: map[string]logical.Factory{
|
||||||
"plugin": plugin.Factory,
|
"test": plugin.Factory,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,10 +553,9 @@ func testSystemBackend_SingleCluster_Env(t *testing.T, env []string) *vault.Test
|
|||||||
|
|
||||||
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
os.Setenv(pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)
|
||||||
|
|
||||||
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", "TestBackend_PluginMainEnv", env, tempDir)
|
vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "TestBackend_PluginMainEnv", env, tempDir)
|
||||||
options := map[string]interface{}{
|
options := map[string]interface{}{
|
||||||
"type": "plugin",
|
"type": "mock-plugin",
|
||||||
"plugin_name": "mock-plugin",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Logical().Write("sys/mounts/mock", options)
|
resp, err := client.Logical().Write("sys/mounts/mock", options)
|
||||||
|
|||||||
@@ -558,54 +558,90 @@ func (b *SystemBackend) sealPaths() []*framework.Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) pluginsCatalogPath() *framework.Path {
|
func (b *SystemBackend) pluginsCatalogPaths() []*framework.Path {
|
||||||
return &framework.Path{
|
return []*framework.Path{
|
||||||
Pattern: "plugins/catalog/(?P<name>.+)",
|
{
|
||||||
|
Pattern: "plugins/catalog/(?P<type>auth|database|secret)/?$",
|
||||||
|
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
"name": &framework.FieldSchema{
|
"type": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
Description: strings.TrimSpace(sysHelp["plugin-catalog_name"][0]),
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_type"][0]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"sha256": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
Operations: map[logical.Operation]framework.OperationHandler{
|
||||||
Description: strings.TrimSpace(sysHelp["plugin-catalog_sha-256"][0]),
|
logical.ListOperation: &framework.PathOperation{
|
||||||
},
|
Callback: b.handlePluginCatalogTypedList,
|
||||||
"sha_256": &framework.FieldSchema{
|
Summary: "List the plugins in the catalog.",
|
||||||
Type: framework.TypeString,
|
},
|
||||||
Description: strings.TrimSpace(sysHelp["plugin-catalog_sha-256"][0]),
|
|
||||||
},
|
|
||||||
"command": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: strings.TrimSpace(sysHelp["plugin-catalog_command"][0]),
|
|
||||||
},
|
|
||||||
"args": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeStringSlice,
|
|
||||||
Description: strings.TrimSpace(sysHelp["plugin-catalog_args"][0]),
|
|
||||||
},
|
|
||||||
"env": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeStringSlice,
|
|
||||||
Description: strings.TrimSpace(sysHelp["plugin-catalog_env"][0]),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog"][0]),
|
||||||
|
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog"][1]),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Pattern: "plugins/catalog(/(?P<type>auth|database|secret))?/(?P<name>.+)",
|
||||||
|
|
||||||
Operations: map[logical.Operation]framework.OperationHandler{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
logical.UpdateOperation: &framework.PathOperation{
|
"name": &framework.FieldSchema{
|
||||||
Callback: b.handlePluginCatalogUpdate,
|
Type: framework.TypeString,
|
||||||
Summary: "Register a new plugin, or updates an existing one with the supplied name.",
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_name"][0]),
|
||||||
|
},
|
||||||
|
"type": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_type"][0]),
|
||||||
|
},
|
||||||
|
"sha256": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_sha-256"][0]),
|
||||||
|
},
|
||||||
|
"sha_256": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_sha-256"][0]),
|
||||||
|
},
|
||||||
|
"command": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_command"][0]),
|
||||||
|
},
|
||||||
|
"args": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeStringSlice,
|
||||||
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_args"][0]),
|
||||||
|
},
|
||||||
|
"env": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeStringSlice,
|
||||||
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_env"][0]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
logical.DeleteOperation: &framework.PathOperation{
|
|
||||||
Callback: b.handlePluginCatalogDelete,
|
Operations: map[logical.Operation]framework.OperationHandler{
|
||||||
Summary: "Remove the plugin with the given name.",
|
logical.UpdateOperation: &framework.PathOperation{
|
||||||
},
|
Callback: b.handlePluginCatalogUpdate,
|
||||||
logical.ReadOperation: &framework.PathOperation{
|
Summary: "Register a new plugin, or updates an existing one with the supplied name.",
|
||||||
Callback: b.handlePluginCatalogRead,
|
},
|
||||||
Summary: "Return the configuration data for the plugin with the given name.",
|
logical.DeleteOperation: &framework.PathOperation{
|
||||||
|
Callback: b.handlePluginCatalogDelete,
|
||||||
|
Summary: "Remove the plugin with the given name.",
|
||||||
|
},
|
||||||
|
logical.ReadOperation: &framework.PathOperation{
|
||||||
|
Callback: b.handlePluginCatalogRead,
|
||||||
|
Summary: "Return the configuration data for the plugin with the given name.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog"][0]),
|
||||||
|
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog"][1]),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Pattern: "plugins/catalog/?$",
|
||||||
|
|
||||||
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog"][0]),
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog"][1]),
|
logical.ReadOperation: b.handlePluginCatalogUntypedList,
|
||||||
|
},
|
||||||
|
|
||||||
|
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog-list-all"][0]),
|
||||||
|
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog-list-all"][1]),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,24 +673,6 @@ func (b *SystemBackend) pluginsReloadPath() *framework.Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) pluginsCatalogListPath() *framework.Path {
|
|
||||||
return &framework.Path{
|
|
||||||
Pattern: "plugins/catalog/?$",
|
|
||||||
|
|
||||||
Fields: map[string]*framework.FieldSchema{},
|
|
||||||
|
|
||||||
Operations: map[logical.Operation]framework.OperationHandler{
|
|
||||||
logical.ListOperation: &framework.PathOperation{
|
|
||||||
Callback: b.handlePluginCatalogList,
|
|
||||||
Summary: "List the plugins in the catalog.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog"][0]),
|
|
||||||
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog"][1]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *SystemBackend) toolsPaths() []*framework.Path {
|
func (b *SystemBackend) toolsPaths() []*framework.Path {
|
||||||
return []*framework.Path{
|
return []*framework.Path{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
hclog "github.com/hashicorp/go-hclog"
|
hclog "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/vault/audit"
|
"github.com/hashicorp/vault/audit"
|
||||||
"github.com/hashicorp/vault/helper/builtinplugins"
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
"github.com/hashicorp/vault/helper/jsonutil"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
"github.com/hashicorp/vault/helper/salt"
|
"github.com/hashicorp/vault/helper/salt"
|
||||||
@@ -135,7 +136,6 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -151,7 +151,6 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -165,7 +164,6 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
@@ -179,7 +177,6 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -231,7 +228,6 @@ func TestSystemBackend_mount(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -247,7 +243,6 @@ func TestSystemBackend_mount(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -261,7 +256,6 @@ func TestSystemBackend_mount(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
@@ -275,7 +269,6 @@ func TestSystemBackend_mount(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -289,7 +282,6 @@ func TestSystemBackend_mount(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": int64(2100),
|
"default_lease_ttl": int64(2100),
|
||||||
"max_lease_ttl": int64(2700),
|
"max_lease_ttl": int64(2700),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
@@ -340,7 +332,7 @@ func TestSystemBackend_mount_invalid(t *testing.T) {
|
|||||||
if err != logical.ErrInvalidRequest {
|
if err != logical.ErrInvalidRequest {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if resp.Data["error"] != `unknown backend type: "nope"` {
|
if resp.Data["error"] != `plugin not found in the catalog: nope` {
|
||||||
t.Fatalf("bad: %v", resp)
|
t.Fatalf("bad: %v", resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1430,7 +1422,6 @@ func TestSystemBackend_authTable(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": int64(0),
|
"default_lease_ttl": int64(0),
|
||||||
"max_lease_ttl": int64(0),
|
"max_lease_ttl": int64(0),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
},
|
},
|
||||||
@@ -1447,7 +1438,7 @@ func TestSystemBackend_authTable(t *testing.T) {
|
|||||||
func TestSystemBackend_enableAuth(t *testing.T) {
|
func TestSystemBackend_enableAuth(t *testing.T) {
|
||||||
c, b, _ := testCoreSystemBackend(t)
|
c, b, _ := testCoreSystemBackend(t)
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{BackendType: logical.TypeCredential}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
req := logical.TestRequest(t, logical.UpdateOperation, "auth/foo")
|
req := logical.TestRequest(t, logical.UpdateOperation, "auth/foo")
|
||||||
@@ -1485,7 +1476,6 @@ func TestSystemBackend_enableAuth(t *testing.T) {
|
|||||||
"default_lease_ttl": int64(2100),
|
"default_lease_ttl": int64(2100),
|
||||||
"max_lease_ttl": int64(2700),
|
"max_lease_ttl": int64(2700),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
@@ -1499,7 +1489,6 @@ func TestSystemBackend_enableAuth(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": int64(0),
|
"default_lease_ttl": int64(0),
|
||||||
"max_lease_ttl": int64(0),
|
"max_lease_ttl": int64(0),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
},
|
},
|
||||||
@@ -1521,7 +1510,7 @@ func TestSystemBackend_enableAuth_invalid(t *testing.T) {
|
|||||||
if err != logical.ErrInvalidRequest {
|
if err != logical.ErrInvalidRequest {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if resp.Data["error"] != `unknown backend type: "nope"` {
|
if resp.Data["error"] != `plugin not found in the catalog: nope` {
|
||||||
t.Fatalf("bad: %v", resp)
|
t.Fatalf("bad: %v", resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1987,17 +1976,17 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
c.pluginCatalog.directory = sym
|
c.pluginCatalog.directory = sym
|
||||||
|
|
||||||
req := logical.TestRequest(t, logical.ListOperation, "plugins/catalog/")
|
req := logical.TestRequest(t, logical.ListOperation, "plugins/catalog/database")
|
||||||
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
|
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(resp.Data["keys"].([]string)) != len(builtinplugins.Keys()) {
|
if len(resp.Data["keys"].([]string)) != len(c.builtinRegistry.Keys(consts.PluginTypeDatabase)) {
|
||||||
t.Fatalf("Wrong number of plugins, got %d, expected %d", len(resp.Data["keys"].([]string)), len(builtinplugins.Keys()))
|
t.Fatalf("Wrong number of plugins, got %d, expected %d", len(resp.Data["keys"].([]string)), len(builtinplugins.Registry.Keys(consts.PluginTypeDatabase)))
|
||||||
}
|
}
|
||||||
|
|
||||||
req = logical.TestRequest(t, logical.ReadOperation, "plugins/catalog/mysql-database-plugin")
|
req = logical.TestRequest(t, logical.ReadOperation, "plugins/catalog/database/mysql-database-plugin")
|
||||||
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
@@ -2024,7 +2013,7 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) {
|
|||||||
|
|
||||||
// Check we can only specify args in one of command or args.
|
// Check we can only specify args in one of command or args.
|
||||||
command := fmt.Sprintf("%s --test", filepath.Base(file.Name()))
|
command := fmt.Sprintf("%s --test", filepath.Base(file.Name()))
|
||||||
req = logical.TestRequest(t, logical.UpdateOperation, "plugins/catalog/test-plugin")
|
req = logical.TestRequest(t, logical.UpdateOperation, "plugins/catalog/database/test-plugin")
|
||||||
req.Data["args"] = []string{"--foo"}
|
req.Data["args"] = []string{"--foo"}
|
||||||
req.Data["sha_256"] = hex.EncodeToString([]byte{'1'})
|
req.Data["sha_256"] = hex.EncodeToString([]byte{'1'})
|
||||||
req.Data["command"] = command
|
req.Data["command"] = command
|
||||||
@@ -2042,7 +2031,7 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) {
|
|||||||
t.Fatalf("err: %v %v", err, resp.Error())
|
t.Fatalf("err: %v %v", err, resp.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
req = logical.TestRequest(t, logical.ReadOperation, "plugins/catalog/test-plugin")
|
req = logical.TestRequest(t, logical.ReadOperation, "plugins/catalog/database/test-plugin")
|
||||||
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
@@ -2061,13 +2050,13 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete plugin
|
// Delete plugin
|
||||||
req = logical.TestRequest(t, logical.DeleteOperation, "plugins/catalog/test-plugin")
|
req = logical.TestRequest(t, logical.DeleteOperation, "plugins/catalog/database/test-plugin")
|
||||||
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req = logical.TestRequest(t, logical.ReadOperation, "plugins/catalog/test-plugin")
|
req = logical.TestRequest(t, logical.ReadOperation, "plugins/catalog/database/test-plugin")
|
||||||
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
||||||
if resp != nil || err != nil {
|
if resp != nil || err != nil {
|
||||||
t.Fatalf("expected nil response, plugin not deleted correctly got resp: %v, err: %v", resp, err)
|
t.Fatalf("expected nil response, plugin not deleted correctly got resp: %v, err: %v", resp, err)
|
||||||
@@ -2262,7 +2251,6 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -2278,7 +2266,6 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -2292,7 +2279,6 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": true,
|
"local": true,
|
||||||
@@ -2306,7 +2292,6 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
|
|||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
"plugin_name": "",
|
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
},
|
},
|
||||||
"local": false,
|
"local": false,
|
||||||
@@ -2321,7 +2306,6 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
|
|||||||
"default_lease_ttl": int64(0),
|
"default_lease_ttl": int64(0),
|
||||||
"max_lease_ttl": int64(0),
|
"max_lease_ttl": int64(0),
|
||||||
"force_no_cache": false,
|
"force_no_cache": false,
|
||||||
"plugin_name": "",
|
|
||||||
"token_type": "default-service",
|
"token_type": "default-service",
|
||||||
},
|
},
|
||||||
"type": "token",
|
"type": "token",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
|
"github.com/hashicorp/vault/builtin/plugin"
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
"github.com/hashicorp/vault/helper/jsonutil"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
@@ -60,6 +61,7 @@ const (
|
|||||||
systemMountType = "system"
|
systemMountType = "system"
|
||||||
identityMountType = "identity"
|
identityMountType = "identity"
|
||||||
cubbyholeMountType = "cubbyhole"
|
cubbyholeMountType = "cubbyhole"
|
||||||
|
pluginMountType = "plugin"
|
||||||
|
|
||||||
MountTableUpdateStorage = true
|
MountTableUpdateStorage = true
|
||||||
MountTableNoUpdateStorage = false
|
MountTableNoUpdateStorage = false
|
||||||
@@ -221,7 +223,7 @@ type MountConfig struct {
|
|||||||
DefaultLeaseTTL time.Duration `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` // Override for global default
|
DefaultLeaseTTL time.Duration `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` // Override for global default
|
||||||
MaxLeaseTTL time.Duration `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` // Override for global default
|
MaxLeaseTTL time.Duration `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` // Override for global default
|
||||||
ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"` // Override for global default
|
ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"` // Override for global default
|
||||||
PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
PluginNameDeprecated string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||||
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"`
|
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"`
|
||||||
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"`
|
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"`
|
||||||
ListingVisibility ListingVisibilityType `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"`
|
ListingVisibility ListingVisibilityType `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"`
|
||||||
@@ -234,7 +236,7 @@ type APIMountConfig struct {
|
|||||||
DefaultLeaseTTL string `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
DefaultLeaseTTL string `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
||||||
MaxLeaseTTL string `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
MaxLeaseTTL string `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
||||||
ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"`
|
ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"`
|
||||||
PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
PluginNameDeprecated string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||||
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"`
|
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"`
|
||||||
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"`
|
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"`
|
||||||
ListingVisibility ListingVisibilityType `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"`
|
ListingVisibility ListingVisibilityType `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"`
|
||||||
@@ -417,12 +419,7 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
|
|||||||
|
|
||||||
var backend logical.Backend
|
var backend logical.Backend
|
||||||
sysView := c.mountEntrySysView(entry)
|
sysView := c.mountEntrySysView(entry)
|
||||||
conf := make(map[string]string)
|
|
||||||
if entry.Config.PluginName != "" {
|
|
||||||
conf["plugin_name"] = entry.Config.PluginName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consider having plugin name under entry.Options
|
|
||||||
backend, err = c.newLogicalBackend(ctx, entry, sysView, view)
|
backend, err = c.newLogicalBackend(ctx, entry, sysView, view)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -433,8 +430,10 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
|
|||||||
|
|
||||||
// Check for the correct backend type
|
// Check for the correct backend type
|
||||||
backendType := backend.Type()
|
backendType := backend.Type()
|
||||||
if entry.Type == "plugin" && backendType != logical.TypeLogical {
|
if backendType != logical.TypeLogical {
|
||||||
return fmt.Errorf("cannot mount %q of type %q as a logical backend", entry.Config.PluginName, backendType)
|
if entry.Type != "kv" && entry.Type != "system" && entry.Type != "cubbyhole" {
|
||||||
|
return fmt.Errorf(`unknown backend type: "%s"`, entry.Type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addPathCheckers(c, entry, backend, viewPath)
|
addPathCheckers(c, entry, backend, viewPath)
|
||||||
@@ -1021,15 +1020,10 @@ func (c *Core) setupMounts(ctx context.Context) error {
|
|||||||
var backend logical.Backend
|
var backend logical.Backend
|
||||||
// Create the new backend
|
// Create the new backend
|
||||||
sysView := c.mountEntrySysView(entry)
|
sysView := c.mountEntrySysView(entry)
|
||||||
// Set up conf to pass in plugin_name
|
|
||||||
conf := make(map[string]string)
|
|
||||||
if entry.Config.PluginName != "" {
|
|
||||||
conf["plugin_name"] = entry.Config.PluginName
|
|
||||||
}
|
|
||||||
backend, err = c.newLogicalBackend(ctx, entry, sysView, view)
|
backend, err = c.newLogicalBackend(ctx, entry, sysView, view)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Error("failed to create mount entry", "path", entry.Path, "error", err)
|
c.logger.Error("failed to create mount entry", "path", entry.Path, "error", err)
|
||||||
if entry.Type == "plugin" {
|
if !c.builtinRegistry.Contains(entry.Type, consts.PluginTypeSecrets) {
|
||||||
// If we encounter an error instantiating the backend due to an error,
|
// If we encounter an error instantiating the backend due to an error,
|
||||||
// skip backend initialization but register the entry to the mount table
|
// skip backend initialization but register the entry to the mount table
|
||||||
// to preserve storage and path.
|
// to preserve storage and path.
|
||||||
@@ -1045,8 +1039,11 @@ func (c *Core) setupMounts(ctx context.Context) error {
|
|||||||
{
|
{
|
||||||
// Check for the correct backend type
|
// Check for the correct backend type
|
||||||
backendType := backend.Type()
|
backendType := backend.Type()
|
||||||
if entry.Type == "plugin" && backendType != logical.TypeLogical {
|
|
||||||
return fmt.Errorf("cannot mount %q of type %q as a logical backend", entry.Config.PluginName, backendType)
|
if backendType != logical.TypeLogical {
|
||||||
|
if entry.Type != "kv" && entry.Type != "system" && entry.Type != "cubbyhole" {
|
||||||
|
return fmt.Errorf(`unknown backend type: "%s"`, entry.Type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addPathCheckers(c, entry, backend, barrierPath)
|
addPathCheckers(c, entry, backend, barrierPath)
|
||||||
@@ -1116,9 +1113,10 @@ func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView
|
|||||||
if alias, ok := mountAliases[t]; ok {
|
if alias, ok := mountAliases[t]; ok {
|
||||||
t = alias
|
t = alias
|
||||||
}
|
}
|
||||||
|
|
||||||
f, ok := c.logicalBackends[t]
|
f, ok := c.logicalBackends[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unknown backend type: %q", t)
|
f = plugin.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up conf to pass in plugin_name
|
// Set up conf to pass in plugin_name
|
||||||
@@ -1126,10 +1124,16 @@ func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView
|
|||||||
for k, v := range entry.Options {
|
for k, v := range entry.Options {
|
||||||
conf[k] = v
|
conf[k] = v
|
||||||
}
|
}
|
||||||
if entry.Config.PluginName != "" {
|
|
||||||
conf["plugin_name"] = entry.Config.PluginName
|
switch {
|
||||||
|
case entry.Type == "plugin":
|
||||||
|
conf["plugin_name"] = entry.Config.PluginNameDeprecated
|
||||||
|
default:
|
||||||
|
conf["plugin_name"] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf["plugin_type"] = consts.PluginTypeSecrets.String()
|
||||||
|
|
||||||
backendLogger := c.baseLogger.Named(fmt.Sprintf("secrets.%s.%s", t, entry.Accessor))
|
backendLogger := c.baseLogger.Named(fmt.Sprintf("secrets.%s.%s", t, entry.Accessor))
|
||||||
c.AddLogger(backendLogger)
|
c.AddLogger(backendLogger)
|
||||||
config := &logical.BackendConfig{
|
config := &logical.BackendConfig{
|
||||||
|
|||||||
@@ -487,7 +487,9 @@ func TestCore_MountTable_UpgradeToTyped(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
c.credentialBackends["noop"] = func(context.Context, *logical.BackendConfig) (logical.Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
me = &MountEntry{
|
me = &MountEntry{
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
log "github.com/hashicorp/go-hclog"
|
||||||
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/vault/helper/builtinplugins"
|
"github.com/hashicorp/vault/builtin/logical/database/dbplugin"
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
"github.com/hashicorp/vault/helper/jsonutil"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
|
backendplugin "github.com/hashicorp/vault/logical/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -28,16 +32,24 @@ var (
|
|||||||
// to be registered to the catalog before they can be used in backends. Builtin
|
// to be registered to the catalog before they can be used in backends. Builtin
|
||||||
// plugins are automatically detected and included in the catalog.
|
// plugins are automatically detected and included in the catalog.
|
||||||
type PluginCatalog struct {
|
type PluginCatalog struct {
|
||||||
catalogView *BarrierView
|
builtinRegistry BuiltinRegistry
|
||||||
directory string
|
catalogView *BarrierView
|
||||||
|
directory string
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) setupPluginCatalog() error {
|
func (c *Core) setupPluginCatalog(ctx context.Context) error {
|
||||||
c.pluginCatalog = &PluginCatalog{
|
c.pluginCatalog = &PluginCatalog{
|
||||||
catalogView: NewBarrierView(c.barrier, pluginCatalogPath),
|
builtinRegistry: c.builtinRegistry,
|
||||||
directory: c.pluginDirectory,
|
catalogView: NewBarrierView(c.barrier, pluginCatalogPath),
|
||||||
|
directory: c.pluginDirectory,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run upgrade if untyped plugins exist
|
||||||
|
err := c.pluginCatalog.UpgradePlugins(ctx, c.logger)
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Error("error while upgrading plugin storage", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.logger.IsInfo() {
|
if c.logger.IsInfo() {
|
||||||
@@ -47,25 +59,145 @@ func (c *Core) setupPluginCatalog() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPluginTypeFromUnknown will attempt to run the plugin to determine the
|
||||||
|
// type. It will first attempt to run as a database plugin then a backend
|
||||||
|
// plugin. Both of these will be run in metadata mode.
|
||||||
|
func (c *PluginCatalog) getPluginTypeFromUnknown(ctx context.Context, plugin *pluginutil.PluginRunner) (consts.PluginType, error) {
|
||||||
|
{
|
||||||
|
// Attempt to run as database plugin
|
||||||
|
client, err := dbplugin.NewPluginClient(ctx, nil, plugin, log.NewNullLogger(), true)
|
||||||
|
if err == nil {
|
||||||
|
// Close the client and cleanup the plugin process
|
||||||
|
client.Close()
|
||||||
|
return consts.PluginTypeDatabase, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Attempt to run as backend plugin
|
||||||
|
client, err := backendplugin.NewPluginClient(ctx, nil, plugin, log.NewNullLogger(), true)
|
||||||
|
if err == nil {
|
||||||
|
err := client.Setup(ctx, &logical.BackendConfig{})
|
||||||
|
if err != nil {
|
||||||
|
return consts.PluginTypeUnknown, err
|
||||||
|
}
|
||||||
|
|
||||||
|
backendType := client.Type()
|
||||||
|
client.Cleanup(ctx)
|
||||||
|
|
||||||
|
switch backendType {
|
||||||
|
case logical.TypeCredential:
|
||||||
|
return consts.PluginTypeCredential, nil
|
||||||
|
case logical.TypeLogical:
|
||||||
|
return consts.PluginTypeSecrets, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consts.PluginTypeUnknown, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePlugins will loop over all the plugins of unknown type and attempt to
|
||||||
|
// upgrade them to typed plugins
|
||||||
|
func (c *PluginCatalog) UpgradePlugins(ctx context.Context, logger log.Logger) error {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
// If the directory isn't set we can skip the upgrade attempt
|
||||||
|
if c.directory == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List plugins from old location
|
||||||
|
pluginsRaw, err := c.catalogView.List(ctx, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
plugins := make([]string, 0, len(pluginsRaw))
|
||||||
|
for _, p := range pluginsRaw {
|
||||||
|
if !strings.HasSuffix(p, "/") {
|
||||||
|
plugins = append(plugins, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("upgrading plugin information", "plugins", plugins)
|
||||||
|
|
||||||
|
var retErr error
|
||||||
|
for _, pluginName := range plugins {
|
||||||
|
pluginRaw, err := c.catalogView.Get(ctx, pluginName)
|
||||||
|
if err != nil {
|
||||||
|
retErr = multierror.Append(errwrap.Wrapf("failed to load plugin entry: {{err}}", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin := new(pluginutil.PluginRunner)
|
||||||
|
if err := jsonutil.DecodeJSON(pluginRaw.Value, plugin); err != nil {
|
||||||
|
retErr = multierror.Append(errwrap.Wrapf("failed to decode plugin entry: {{err}}", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepend the plugin directory to the command
|
||||||
|
cmdOld := plugin.Command
|
||||||
|
plugin.Command = filepath.Join(c.directory, plugin.Command)
|
||||||
|
|
||||||
|
pluginType, err := c.getPluginTypeFromUnknown(ctx, plugin)
|
||||||
|
if err != nil {
|
||||||
|
retErr = multierror.Append(retErr, fmt.Errorf("could not upgrade plugin %s: %s", pluginName, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if pluginType == consts.PluginTypeUnknown {
|
||||||
|
retErr = multierror.Append(retErr, fmt.Errorf("could not upgrade plugin %s: plugin of unknown type", pluginName))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upgrade the storage
|
||||||
|
err = c.setInternal(ctx, pluginName, pluginType, cmdOld, plugin.Args, plugin.Env, plugin.Sha256)
|
||||||
|
if err != nil {
|
||||||
|
retErr = multierror.Append(retErr, fmt.Errorf("could not upgrade plugin %s: %s", pluginName, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.catalogView.Delete(ctx, pluginName)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("could not remove plugin", "plugin", pluginName, "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("upgraded plugin type", "plugin", pluginName, "type", pluginType.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return retErr
|
||||||
|
}
|
||||||
|
|
||||||
// Get retrieves a plugin with the specified name from the catalog. It first
|
// Get retrieves a plugin with the specified name from the catalog. It first
|
||||||
// looks for external plugins with this name and then looks for builtin plugins.
|
// looks for external plugins with this name and then looks for builtin plugins.
|
||||||
// It returns a PluginRunner or an error if no plugin was found.
|
// It returns a PluginRunner or an error if no plugin was found.
|
||||||
func (c *PluginCatalog) Get(ctx context.Context, name string) (*pluginutil.PluginRunner, error) {
|
func (c *PluginCatalog) Get(ctx context.Context, name string, pluginType consts.PluginType) (*pluginutil.PluginRunner, error) {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
|
|
||||||
// If the directory isn't set only look for builtin plugins.
|
// If the directory isn't set only look for builtin plugins.
|
||||||
if c.directory != "" {
|
if c.directory != "" {
|
||||||
// Look for external plugins in the barrier
|
// Look for external plugins in the barrier
|
||||||
out, err := c.catalogView.Get(ctx, name)
|
out, err := c.catalogView.Get(ctx, pluginType.String()+"/"+name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errwrap.Wrapf(fmt.Sprintf("failed to retrieve plugin %q: {{err}}", name), err)
|
return nil, errwrap.Wrapf(fmt.Sprintf("failed to retrieve plugin %q: {{err}}", name), err)
|
||||||
}
|
}
|
||||||
|
if out == nil {
|
||||||
|
// Also look for external plugins under what their name would have been if they
|
||||||
|
// were registered before plugin types existed.
|
||||||
|
out, err = c.catalogView.Get(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errwrap.Wrapf(fmt.Sprintf("failed to retrieve plugin %q: {{err}}", name), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if out != nil {
|
if out != nil {
|
||||||
entry := new(pluginutil.PluginRunner)
|
entry := new(pluginutil.PluginRunner)
|
||||||
if err := jsonutil.DecodeJSON(out.Value, entry); err != nil {
|
if err := jsonutil.DecodeJSON(out.Value, entry); err != nil {
|
||||||
return nil, errwrap.Wrapf("failed to decode plugin entry: {{err}}", err)
|
return nil, errwrap.Wrapf("failed to decode plugin entry: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
if entry.Type != pluginType && entry.Type != consts.PluginTypeUnknown {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// prepend the plugin directory to the command
|
// prepend the plugin directory to the command
|
||||||
entry.Command = filepath.Join(c.directory, entry.Command)
|
entry.Command = filepath.Join(c.directory, entry.Command)
|
||||||
@@ -74,9 +206,10 @@ func (c *PluginCatalog) Get(ctx context.Context, name string) (*pluginutil.Plugi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Look for builtin plugins
|
// Look for builtin plugins
|
||||||
if factory, ok := builtinplugins.Get(name); ok {
|
if factory, ok := c.builtinRegistry.Get(name, pluginType); ok {
|
||||||
return &pluginutil.PluginRunner{
|
return &pluginutil.PluginRunner{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Type: pluginType,
|
||||||
Builtin: true,
|
Builtin: true,
|
||||||
BuiltinFactory: factory,
|
BuiltinFactory: factory,
|
||||||
}, nil
|
}, nil
|
||||||
@@ -87,7 +220,7 @@ func (c *PluginCatalog) Get(ctx context.Context, name string) (*pluginutil.Plugi
|
|||||||
|
|
||||||
// Set registers a new external plugin with the catalog, or updates an existing
|
// Set registers a new external plugin with the catalog, or updates an existing
|
||||||
// external plugin. It takes the name, command and SHA256 of the plugin.
|
// external plugin. It takes the name, command and SHA256 of the plugin.
|
||||||
func (c *PluginCatalog) Set(ctx context.Context, name, command string, args []string, env []string, sha256 []byte) error {
|
func (c *PluginCatalog) Set(ctx context.Context, name string, pluginType consts.PluginType, command string, args []string, env []string, sha256 []byte) error {
|
||||||
if c.directory == "" {
|
if c.directory == "" {
|
||||||
return ErrDirectoryNotConfigured
|
return ErrDirectoryNotConfigured
|
||||||
}
|
}
|
||||||
@@ -102,6 +235,10 @@ func (c *PluginCatalog) Set(ctx context.Context, name, command string, args []st
|
|||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
return c.setInternal(ctx, name, pluginType, command, args, env, sha256)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PluginCatalog) setInternal(ctx context.Context, name string, pluginType consts.PluginType, command string, args []string, env []string, sha256 []byte) error {
|
||||||
// Best effort check to make sure the command isn't breaking out of the
|
// Best effort check to make sure the command isn't breaking out of the
|
||||||
// configured plugin directory.
|
// configured plugin directory.
|
||||||
commandFull := filepath.Join(c.directory, command)
|
commandFull := filepath.Join(c.directory, command)
|
||||||
@@ -118,8 +255,28 @@ func (c *PluginCatalog) Set(ctx context.Context, name, command string, args []st
|
|||||||
return errors.New("can not execute files outside of configured plugin directory")
|
return errors.New("can not execute files outside of configured plugin directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the plugin type is unknown, we want to attempt to determine the type
|
||||||
|
if pluginType == consts.PluginTypeUnknown {
|
||||||
|
// entryTmp should only be used for the below type check, it uses the
|
||||||
|
// full command instead of the relative command.
|
||||||
|
entryTmp := &pluginutil.PluginRunner{
|
||||||
|
Name: name,
|
||||||
|
Command: commandFull,
|
||||||
|
Args: args,
|
||||||
|
Env: env,
|
||||||
|
Sha256: sha256,
|
||||||
|
Builtin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginType, err = c.getPluginTypeFromUnknown(ctx, entryTmp)
|
||||||
|
if err != nil || pluginType == consts.PluginTypeUnknown {
|
||||||
|
return errors.New("unable to determine plugin type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
entry := &pluginutil.PluginRunner{
|
entry := &pluginutil.PluginRunner{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Type: pluginType,
|
||||||
Command: command,
|
Command: command,
|
||||||
Args: args,
|
Args: args,
|
||||||
Env: env,
|
Env: env,
|
||||||
@@ -133,7 +290,7 @@ func (c *PluginCatalog) Set(ctx context.Context, name, command string, args []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
logicalEntry := logical.StorageEntry{
|
logicalEntry := logical.StorageEntry{
|
||||||
Key: name,
|
Key: pluginType.String() + "/" + name,
|
||||||
Value: buf,
|
Value: buf,
|
||||||
}
|
}
|
||||||
if err := c.catalogView.Put(ctx, &logicalEntry); err != nil {
|
if err := c.catalogView.Put(ctx, &logicalEntry); err != nil {
|
||||||
@@ -144,16 +301,23 @@ func (c *PluginCatalog) Set(ctx context.Context, name, command string, args []st
|
|||||||
|
|
||||||
// Delete is used to remove an external plugin from the catalog. Builtin plugins
|
// Delete is used to remove an external plugin from the catalog. Builtin plugins
|
||||||
// can not be deleted.
|
// can not be deleted.
|
||||||
func (c *PluginCatalog) Delete(ctx context.Context, name string) error {
|
func (c *PluginCatalog) Delete(ctx context.Context, name string, pluginType consts.PluginType) error {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
return c.catalogView.Delete(ctx, name)
|
// Check the name under which the plugin exists, but if it's unfound, don't return any error.
|
||||||
|
pluginKey := pluginType.String() + "/" + name
|
||||||
|
out, err := c.catalogView.Get(ctx, pluginKey)
|
||||||
|
if err != nil || out == nil {
|
||||||
|
pluginKey = name
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.catalogView.Delete(ctx, pluginKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List returns a list of all the known plugin names. If an external and builtin
|
// List returns a list of all the known plugin names. If an external and builtin
|
||||||
// plugin share the same name, only one instance of the name will be returned.
|
// plugin share the same name, only one instance of the name will be returned.
|
||||||
func (c *PluginCatalog) List(ctx context.Context) ([]string, error) {
|
func (c *PluginCatalog) List(ctx context.Context, pluginType consts.PluginType) ([]string, error) {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
|
|
||||||
@@ -163,14 +327,27 @@ func (c *PluginCatalog) List(ctx context.Context) ([]string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the keys for builtin plugins
|
// Get the builtin plugins.
|
||||||
builtinKeys := builtinplugins.Keys()
|
builtinKeys := c.builtinRegistry.Keys(pluginType)
|
||||||
|
|
||||||
// Use a map to unique the two lists
|
// Use a map to unique the two lists.
|
||||||
mapKeys := make(map[string]bool)
|
mapKeys := make(map[string]bool)
|
||||||
|
|
||||||
|
pluginTypePrefix := pluginType.String() + "/"
|
||||||
|
|
||||||
for _, plugin := range keys {
|
for _, plugin := range keys {
|
||||||
mapKeys[plugin] = true
|
|
||||||
|
// Only list user-added plugins if they're of the given type.
|
||||||
|
if entry, err := c.Get(ctx, plugin, pluginType); err == nil && entry != nil {
|
||||||
|
|
||||||
|
// Some keys will be prepended with the plugin type, but other ones won't.
|
||||||
|
// Users don't expect to see the plugin type, so we need to strip that here.
|
||||||
|
idx := strings.Index(plugin, pluginTypePrefix)
|
||||||
|
if idx == 0 {
|
||||||
|
plugin = plugin[len(pluginTypePrefix):]
|
||||||
|
}
|
||||||
|
mapKeys[plugin] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, plugin := range builtinKeys {
|
for _, plugin := range builtinKeys {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/builtinplugins"
|
"github.com/hashicorp/vault/helper/builtinplugins"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/pluginutil"
|
"github.com/hashicorp/vault/helper/pluginutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,16 +25,17 @@ func TestPluginCatalog_CRUD(t *testing.T) {
|
|||||||
core.pluginCatalog.directory = sym
|
core.pluginCatalog.directory = sym
|
||||||
|
|
||||||
// Get builtin plugin
|
// Get builtin plugin
|
||||||
p, err := core.pluginCatalog.Get(context.Background(), "mysql-database-plugin")
|
p, err := core.pluginCatalog.Get(context.Background(), "mysql-database-plugin", consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedBuiltin := &pluginutil.PluginRunner{
|
expectedBuiltin := &pluginutil.PluginRunner{
|
||||||
Name: "mysql-database-plugin",
|
Name: "mysql-database-plugin",
|
||||||
|
Type: consts.PluginTypeDatabase,
|
||||||
Builtin: true,
|
Builtin: true,
|
||||||
}
|
}
|
||||||
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin")
|
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Registry.Get("mysql-database-plugin", consts.PluginTypeDatabase)
|
||||||
|
|
||||||
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
||||||
t.Fatal("expected BuiltinFactory did not match actual")
|
t.Fatal("expected BuiltinFactory did not match actual")
|
||||||
@@ -52,19 +54,20 @@ func TestPluginCatalog_CRUD(t *testing.T) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
command := fmt.Sprintf("%s", filepath.Base(file.Name()))
|
command := fmt.Sprintf("%s", filepath.Base(file.Name()))
|
||||||
err = core.pluginCatalog.Set(context.Background(), "mysql-database-plugin", command, []string{"--test"}, []string{"FOO=BAR"}, []byte{'1'})
|
err = core.pluginCatalog.Set(context.Background(), "mysql-database-plugin", consts.PluginTypeDatabase, command, []string{"--test"}, []string{"FOO=BAR"}, []byte{'1'})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the plugin
|
// Get the plugin
|
||||||
p, err = core.pluginCatalog.Get(context.Background(), "mysql-database-plugin")
|
p, err = core.pluginCatalog.Get(context.Background(), "mysql-database-plugin", consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := &pluginutil.PluginRunner{
|
expected := &pluginutil.PluginRunner{
|
||||||
Name: "mysql-database-plugin",
|
Name: "mysql-database-plugin",
|
||||||
|
Type: consts.PluginTypeDatabase,
|
||||||
Command: filepath.Join(sym, filepath.Base(file.Name())),
|
Command: filepath.Join(sym, filepath.Base(file.Name())),
|
||||||
Args: []string{"--test"},
|
Args: []string{"--test"},
|
||||||
Env: []string{"FOO=BAR"},
|
Env: []string{"FOO=BAR"},
|
||||||
@@ -77,22 +80,23 @@ func TestPluginCatalog_CRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete the plugin
|
// Delete the plugin
|
||||||
err = core.pluginCatalog.Delete(context.Background(), "mysql-database-plugin")
|
err = core.pluginCatalog.Delete(context.Background(), "mysql-database-plugin", consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get builtin plugin
|
// Get builtin plugin
|
||||||
p, err = core.pluginCatalog.Get(context.Background(), "mysql-database-plugin")
|
p, err = core.pluginCatalog.Get(context.Background(), "mysql-database-plugin", consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedBuiltin = &pluginutil.PluginRunner{
|
expectedBuiltin = &pluginutil.PluginRunner{
|
||||||
Name: "mysql-database-plugin",
|
Name: "mysql-database-plugin",
|
||||||
|
Type: consts.PluginTypeDatabase,
|
||||||
Builtin: true,
|
Builtin: true,
|
||||||
}
|
}
|
||||||
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin")
|
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Registry.Get("mysql-database-plugin", consts.PluginTypeDatabase)
|
||||||
|
|
||||||
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
||||||
t.Fatal("expected BuiltinFactory did not match actual")
|
t.Fatal("expected BuiltinFactory did not match actual")
|
||||||
@@ -115,11 +119,11 @@ func TestPluginCatalog_List(t *testing.T) {
|
|||||||
core.pluginCatalog.directory = sym
|
core.pluginCatalog.directory = sym
|
||||||
|
|
||||||
// Get builtin plugins and sort them
|
// Get builtin plugins and sort them
|
||||||
builtinKeys := builtinplugins.Keys()
|
builtinKeys := builtinplugins.Registry.Keys(consts.PluginTypeDatabase)
|
||||||
sort.Strings(builtinKeys)
|
sort.Strings(builtinKeys)
|
||||||
|
|
||||||
// List only builtin plugins
|
// List only builtin plugins
|
||||||
plugins, err := core.pluginCatalog.List(context.Background())
|
plugins, err := core.pluginCatalog.List(context.Background(), consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
@@ -142,23 +146,24 @@ func TestPluginCatalog_List(t *testing.T) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
command := filepath.Base(file.Name())
|
command := filepath.Base(file.Name())
|
||||||
err = core.pluginCatalog.Set(context.Background(), "mysql-database-plugin", command, []string{"--test"}, []string{}, []byte{'1'})
|
err = core.pluginCatalog.Set(context.Background(), "mysql-database-plugin", consts.PluginTypeDatabase, command, []string{"--test"}, []string{}, []byte{'1'})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set another plugin
|
// Set another plugin
|
||||||
err = core.pluginCatalog.Set(context.Background(), "aaaaaaa", command, []string{"--test"}, []string{}, []byte{'1'})
|
err = core.pluginCatalog.Set(context.Background(), "aaaaaaa", consts.PluginTypeDatabase, command, []string{"--test"}, []string{}, []byte{'1'})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List the plugins
|
// List the plugins
|
||||||
plugins, err = core.pluginCatalog.List(context.Background())
|
plugins, err = core.pluginCatalog.List(context.Background(), consts.PluginTypeDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// plugins has a test-added plugin called "aaaaaaa" that is not built in
|
||||||
if len(plugins) != len(builtinKeys)+1 {
|
if len(plugins) != len(builtinKeys)+1 {
|
||||||
t.Fatalf("unexpected length of plugin list, expected %d, got %d", len(builtinKeys)+1, len(plugins))
|
t.Fatalf("unexpected length of plugin list, expected %d, got %d", len(builtinKeys)+1, len(plugins))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,14 +45,12 @@ func (c *Core) reloadMatchingPluginMounts(ctx context.Context, mounts []string)
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.Type == "plugin" {
|
err := c.reloadBackendCommon(ctx, entry, isAuth)
|
||||||
err := c.reloadBackendCommon(ctx, entry, isAuth)
|
if err != nil {
|
||||||
if err != nil {
|
errors = multierror.Append(errors, errwrap.Wrapf(fmt.Sprintf("cannot reload plugin on %q: {{err}}", mount), err))
|
||||||
errors = multierror.Append(errors, errwrap.Wrapf(fmt.Sprintf("cannot reload plugin on %q: {{err}}", mount), err))
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
c.logger.Info("successfully reloaded plugin", "plugin", entry.Config.PluginName, "path", entry.Path)
|
|
||||||
}
|
}
|
||||||
|
c.logger.Info("successfully reloaded plugin", "plugin", entry.Type, "path", entry.Path)
|
||||||
}
|
}
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
@@ -77,8 +75,7 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro
|
|||||||
if ns.ID != entry.Namespace().ID {
|
if ns.ID != entry.Namespace().ID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if entry.Type == pluginName || (entry.Type == "plugin" && entry.Config.PluginNameDeprecated == pluginName) {
|
||||||
if entry.Config.PluginName == pluginName && entry.Type == "plugin" {
|
|
||||||
err := c.reloadBackendCommon(ctx, entry, false)
|
err := c.reloadBackendCommon(ctx, entry, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -94,7 +91,7 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.Config.PluginName == pluginName && entry.Type == "plugin" {
|
if entry.Type == pluginName || (entry.Type == "plugin" && entry.Config.PluginNameDeprecated == pluginName) {
|
||||||
err := c.reloadBackendCommon(ctx, entry, true)
|
err := c.reloadBackendCommon(ctx, entry, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -713,7 +713,7 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp
|
|||||||
case "plugin":
|
case "plugin":
|
||||||
// If we are a plugin type and the plugin name is "kv" check the
|
// If we are a plugin type and the plugin name is "kv" check the
|
||||||
// mount entry options.
|
// mount entry options.
|
||||||
if matchingMountEntry.Config.PluginName == "kv" && (matchingMountEntry.Options == nil || matchingMountEntry.Options["leased_passthrough"] != "true") {
|
if matchingMountEntry.Config.PluginNameDeprecated == "kv" && (matchingMountEntry.Options == nil || matchingMountEntry.Options["leased_passthrough"] != "true") {
|
||||||
registerLease = false
|
registerLease = false
|
||||||
resp.Secret.Renewable = false
|
resp.Secret.Renewable = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ type NoopBackend struct {
|
|||||||
Invalidations []string
|
Invalidations []string
|
||||||
DefaultLeaseTTL time.Duration
|
DefaultLeaseTTL time.Duration
|
||||||
MaxLeaseTTL time.Duration
|
MaxLeaseTTL time.Duration
|
||||||
|
BackendType logical.BackendType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NoopBackend) HandleRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
func (n *NoopBackend) HandleRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
||||||
@@ -104,7 +105,10 @@ func (n *NoopBackend) Initialize(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *NoopBackend) Type() logical.BackendType {
|
func (n *NoopBackend) Type() logical.BackendType {
|
||||||
return logical.TypeLogical
|
if n.BackendType == logical.TypeUnknown {
|
||||||
|
return logical.TypeLogical
|
||||||
|
}
|
||||||
|
return n.BackendType
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouter_Mount(t *testing.T) {
|
func TestRouter_Mount(t *testing.T) {
|
||||||
|
|||||||
@@ -33,15 +33,18 @@ import (
|
|||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/audit"
|
"github.com/hashicorp/vault/audit"
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/logging"
|
"github.com/hashicorp/vault/helper/logging"
|
||||||
"github.com/hashicorp/vault/helper/reload"
|
"github.com/hashicorp/vault/helper/reload"
|
||||||
"github.com/hashicorp/vault/helper/salt"
|
"github.com/hashicorp/vault/helper/salt"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
"github.com/hashicorp/vault/physical"
|
"github.com/hashicorp/vault/physical"
|
||||||
|
dbMysql "github.com/hashicorp/vault/plugins/database/mysql"
|
||||||
|
dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql"
|
||||||
"github.com/mitchellh/go-testing-interface"
|
"github.com/mitchellh/go-testing-interface"
|
||||||
|
|
||||||
physInmem "github.com/hashicorp/vault/physical/inmem"
|
physInmem "github.com/hashicorp/vault/physical/inmem"
|
||||||
@@ -113,17 +116,19 @@ func TestCoreWithConfig(t testing.T, conf *CoreConfig) *Core {
|
|||||||
// specified seal for testing.
|
// specified seal for testing.
|
||||||
func TestCoreWithSeal(t testing.T, testSeal Seal, enableRaw bool) *Core {
|
func TestCoreWithSeal(t testing.T, testSeal Seal, enableRaw bool) *Core {
|
||||||
conf := &CoreConfig{
|
conf := &CoreConfig{
|
||||||
Seal: testSeal,
|
Seal: testSeal,
|
||||||
EnableUI: false,
|
EnableUI: false,
|
||||||
EnableRaw: enableRaw,
|
EnableRaw: enableRaw,
|
||||||
|
BuiltinRegistry: NewMockBuiltinRegistry(),
|
||||||
}
|
}
|
||||||
return TestCoreWithSealAndUI(t, conf)
|
return TestCoreWithSealAndUI(t, conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoreUI(t testing.T, enableUI bool) *Core {
|
func TestCoreUI(t testing.T, enableUI bool) *Core {
|
||||||
conf := &CoreConfig{
|
conf := &CoreConfig{
|
||||||
EnableUI: enableUI,
|
EnableUI: enableUI,
|
||||||
EnableRaw: true,
|
EnableRaw: true,
|
||||||
|
BuiltinRegistry: NewMockBuiltinRegistry(),
|
||||||
}
|
}
|
||||||
return TestCoreWithSealAndUI(t, conf)
|
return TestCoreWithSealAndUI(t, conf)
|
||||||
}
|
}
|
||||||
@@ -176,6 +181,7 @@ func testCoreConfig(t testing.T, physicalBackend physical.Backend, logger log.Lo
|
|||||||
noopBackends["noop"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
|
noopBackends["noop"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
|
||||||
b := new(framework.Backend)
|
b := new(framework.Backend)
|
||||||
b.Setup(ctx, config)
|
b.Setup(ctx, config)
|
||||||
|
b.BackendType = logical.TypeCredential
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
noopBackends["http"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
|
noopBackends["http"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
|
||||||
@@ -207,6 +213,7 @@ func testCoreConfig(t testing.T, physicalBackend physical.Backend, logger log.Lo
|
|||||||
CredentialBackends: credentialBackends,
|
CredentialBackends: credentialBackends,
|
||||||
DisableMlock: true,
|
DisableMlock: true,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
|
BuiltinRegistry: NewMockBuiltinRegistry(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf
|
return conf
|
||||||
@@ -348,7 +355,7 @@ func TestDynamicSystemView(c *Core) *dynamicSystemView {
|
|||||||
|
|
||||||
// TestAddTestPlugin registers the testFunc as part of the plugin command to the
|
// TestAddTestPlugin registers the testFunc as part of the plugin command to the
|
||||||
// plugin catalog. If provided, uses tmpDir as the plugin directory.
|
// plugin catalog. If provided, uses tmpDir as the plugin directory.
|
||||||
func TestAddTestPlugin(t testing.T, c *Core, name, testFunc string, env []string, tempDir string) {
|
func TestAddTestPlugin(t testing.T, c *Core, name string, pluginType consts.PluginType, testFunc string, env []string, tempDir string) {
|
||||||
file, err := os.Open(os.Args[0])
|
file, err := os.Open(os.Args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -410,7 +417,7 @@ func TestAddTestPlugin(t testing.T, c *Core, name, testFunc string, env []string
|
|||||||
c.pluginCatalog.directory = fullPath
|
c.pluginCatalog.directory = fullPath
|
||||||
|
|
||||||
args := []string{fmt.Sprintf("--test.run=%s", testFunc)}
|
args := []string{fmt.Sprintf("--test.run=%s", testFunc)}
|
||||||
err = c.pluginCatalog.Set(context.Background(), name, fileName, args, env, sum)
|
err = c.pluginCatalog.Set(context.Background(), name, pluginType, fileName, args, env, sum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -638,7 +645,7 @@ func (n *rawHTTP) Setup(ctx context.Context, config *logical.BackendConfig) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *rawHTTP) Type() logical.BackendType {
|
func (n *rawHTTP) Type() logical.BackendType {
|
||||||
return logical.TypeUnknown
|
return logical.TypeLogical
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateRandBytes(length int) ([]byte, error) {
|
func GenerateRandBytes(length int) ([]byte, error) {
|
||||||
@@ -1177,6 +1184,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||||||
DisableMlock: true,
|
DisableMlock: true,
|
||||||
EnableUI: true,
|
EnableUI: true,
|
||||||
EnableRaw: true,
|
EnableRaw: true,
|
||||||
|
BuiltinRegistry: NewMockBuiltinRegistry(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if base != nil {
|
if base != nil {
|
||||||
@@ -1192,6 +1200,9 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||||||
coreConfig.DisableSealWrap = base.DisableSealWrap
|
coreConfig.DisableSealWrap = base.DisableSealWrap
|
||||||
coreConfig.DevLicenseDuration = base.DevLicenseDuration
|
coreConfig.DevLicenseDuration = base.DevLicenseDuration
|
||||||
coreConfig.DisableCache = base.DisableCache
|
coreConfig.DisableCache = base.DisableCache
|
||||||
|
if base.BuiltinRegistry != nil {
|
||||||
|
coreConfig.BuiltinRegistry = base.BuiltinRegistry
|
||||||
|
}
|
||||||
|
|
||||||
if !coreConfig.DisableMlock {
|
if !coreConfig.DisableMlock {
|
||||||
base.DisableMlock = false
|
base.DisableMlock = false
|
||||||
@@ -1262,7 +1273,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||||||
cores := []*Core{}
|
cores := []*Core{}
|
||||||
coreConfigs := []*CoreConfig{}
|
coreConfigs := []*CoreConfig{}
|
||||||
for i := 0; i < numCores; i++ {
|
for i := 0; i < numCores; i++ {
|
||||||
localConfig := coreConfig.Clone()
|
localConfig := *coreConfig
|
||||||
localConfig.RedirectAddr = fmt.Sprintf("https://127.0.0.1:%d", listeners[i][0].Address.Port)
|
localConfig.RedirectAddr = fmt.Sprintf("https://127.0.0.1:%d", listeners[i][0].Address.Port)
|
||||||
if localConfig.ClusterAddr != "" {
|
if localConfig.ClusterAddr != "" {
|
||||||
localConfig.ClusterAddr = fmt.Sprintf("https://127.0.0.1:%d", listeners[i][0].Address.Port+105)
|
localConfig.ClusterAddr = fmt.Sprintf("https://127.0.0.1:%d", listeners[i][0].Address.Port+105)
|
||||||
@@ -1279,12 +1290,12 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||||||
|
|
||||||
localConfig.LicensingConfig = testGetLicensingConfig(pubKey)
|
localConfig.LicensingConfig = testGetLicensingConfig(pubKey)
|
||||||
|
|
||||||
c, err := NewCore(localConfig)
|
c, err := NewCore(&localConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
cores = append(cores, c)
|
cores = append(cores, c)
|
||||||
coreConfigs = append(coreConfigs, localConfig)
|
coreConfigs = append(coreConfigs, &localConfig)
|
||||||
if opts != nil && opts.HandlerFunc != nil {
|
if opts != nil && opts.HandlerFunc != nil {
|
||||||
handlers[i] = opts.HandlerFunc(&HandlerProperties{
|
handlers[i] = opts.HandlerFunc(&HandlerProperties{
|
||||||
Core: c,
|
Core: c,
|
||||||
@@ -1483,3 +1494,56 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||||||
|
|
||||||
return &testCluster
|
return &testCluster
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewMockBuiltinRegistry() *mockBuiltinRegistry {
|
||||||
|
return &mockBuiltinRegistry{
|
||||||
|
forTesting: map[string]consts.PluginType{
|
||||||
|
"mysql-database-plugin": consts.PluginTypeDatabase,
|
||||||
|
"postgresql-database-plugin": consts.PluginTypeDatabase,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockBuiltinRegistry struct {
|
||||||
|
forTesting map[string]consts.PluginType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockBuiltinRegistry) Get(name string, pluginType consts.PluginType) (func() (interface{}, error), bool) {
|
||||||
|
testPluginType, ok := m.forTesting[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if pluginType != testPluginType {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if name == "postgresql-database-plugin" {
|
||||||
|
return dbPostgres.New, true
|
||||||
|
}
|
||||||
|
return dbMysql.New(dbMysql.MetadataLen, dbMysql.MetadataLen, dbMysql.UsernameLen), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys only supports getting a realistic list of the keys for database plugins.
|
||||||
|
func (m *mockBuiltinRegistry) Keys(pluginType consts.PluginType) []string {
|
||||||
|
if pluginType != consts.PluginTypeDatabase {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
This is a hard-coded reproduction of the db plugin keys in helper/builtinplugins/registry.go.
|
||||||
|
The registry isn't directly used because it causes import cycles.
|
||||||
|
*/
|
||||||
|
return []string{
|
||||||
|
"mysql-database-plugin",
|
||||||
|
"mysql-aurora-database-plugin",
|
||||||
|
"mysql-rds-database-plugin",
|
||||||
|
"mysql-legacy-database-plugin",
|
||||||
|
"postgresql-database-plugin",
|
||||||
|
"mssql-database-plugin",
|
||||||
|
"cassandra-database-plugin",
|
||||||
|
"mongodb-database-plugin",
|
||||||
|
"hana-database-plugin",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockBuiltinRegistry) Contains(name string, pluginType consts.PluginType) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -561,6 +561,7 @@ func NewTokenStore(ctx context.Context, logger log.Logger, core *Core, config *l
|
|||||||
salt.DefaultLocation,
|
salt.DefaultLocation,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
BackendType: logical.TypeCredential,
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Backend.Paths = append(t.Backend.Paths, t.paths()...)
|
t.Backend.Paths = append(t.Backend.Paths, t.paths()...)
|
||||||
|
|||||||
Reference in New Issue
Block a user