mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-28 22:21:30 +01:00
Support registering plugin with name only (#5787)
* Support registering plugin with name only * Make RegisterPlugin backwards compatible * Add CLI backwards compat command to plugin info and deregister * Add server-side deprecation warnings if old read/dereg API endpoints are called * Address feedback
This commit is contained in:
parent
7d7ae3d8b8
commit
c6832a8099
@ -129,8 +129,9 @@ type GetPluginResponse struct {
|
|||||||
SHA256 string `json:"sha256"`
|
SHA256 string `json:"sha256"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPlugin retrieves information about the plugin.
|
||||||
func (c *Sys) GetPlugin(i *GetPluginInput) (*GetPluginResponse, error) {
|
func (c *Sys) GetPlugin(i *GetPluginInput) (*GetPluginResponse, error) {
|
||||||
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s/%s", i.Type, i.Name)
|
path := catalogPathByType(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())
|
||||||
@ -142,13 +143,13 @@ func (c *Sys) GetPlugin(i *GetPluginInput) (*GetPluginResponse, error) {
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
Data GetPluginResponse
|
Data *GetPluginResponse
|
||||||
}
|
}
|
||||||
err = resp.DecodeJSON(&result)
|
err = resp.DecodeJSON(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &result.Data, err
|
return result.Data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterPluginInput is used as input to the RegisterPlugin function.
|
// RegisterPluginInput is used as input to the RegisterPlugin function.
|
||||||
@ -171,8 +172,9 @@ 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/%s", i.Type, i.Name)
|
path := catalogPathByType(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
|
||||||
}
|
}
|
||||||
@ -198,7 +200,7 @@ type DeregisterPluginInput struct {
|
|||||||
// 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/%s", i.Type, i.Name)
|
path := catalogPathByType(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())
|
||||||
@ -209,3 +211,15 @@ func (c *Sys) DeregisterPlugin(i *DeregisterPluginInput) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// catalogPathByType is a helper to construct the proper API path by plugin type
|
||||||
|
func catalogPathByType(pluginType consts.PluginType, name string) string {
|
||||||
|
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s/%s", pluginType, name)
|
||||||
|
|
||||||
|
// Backwards compat, if type is not provided then use old path
|
||||||
|
if pluginType == consts.PluginTypeUnknown {
|
||||||
|
path = fmt.Sprintf("/v1/sys/plugins/catalog/%s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|||||||
@ -58,14 +58,23 @@ func (c *PluginDeregisterCommand) Run(args []string) int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pluginNameRaw, pluginTypeRaw string
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
switch {
|
switch {
|
||||||
case len(args) < 2:
|
case len(args) < 1:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1 or 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) > 2:
|
case len(args) > 2:
|
||||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1 or 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
// These cases should come after invalid cases have been checked
|
||||||
|
case len(args) == 1:
|
||||||
|
pluginTypeRaw = "unknown"
|
||||||
|
pluginNameRaw = args[0]
|
||||||
|
case len(args) == 2:
|
||||||
|
pluginTypeRaw = args[0]
|
||||||
|
pluginNameRaw = args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := c.Client()
|
client, err := c.Client()
|
||||||
@ -74,12 +83,12 @@ func (c *PluginDeregisterCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginType, err := consts.ParsePluginType(strings.TrimSpace(args[0]))
|
pluginType, err := consts.ParsePluginType(strings.TrimSpace(pluginTypeRaw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(err.Error())
|
c.UI.Error(err.Error())
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
pluginName := strings.TrimSpace(args[1])
|
pluginName := strings.TrimSpace(pluginNameRaw)
|
||||||
|
|
||||||
if err := client.Sys().DeregisterPlugin(&api.DeregisterPluginInput{
|
if err := client.Sys().DeregisterPlugin(&api.DeregisterPluginInput{
|
||||||
Name: pluginName,
|
Name: pluginName,
|
||||||
|
|||||||
@ -58,14 +58,23 @@ func (c *PluginInfoCommand) Run(args []string) int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pluginNameRaw, pluginTypeRaw string
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
switch {
|
switch {
|
||||||
case len(args) < 2:
|
case len(args) < 1:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1 or 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) > 2:
|
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 or 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
// These cases should come after invalid cases have been checked
|
||||||
|
case len(args) == 1:
|
||||||
|
pluginTypeRaw = "unknown"
|
||||||
|
pluginNameRaw = args[0]
|
||||||
|
case len(args) == 2:
|
||||||
|
pluginTypeRaw = args[0]
|
||||||
|
pluginNameRaw = args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := c.Client()
|
client, err := c.Client()
|
||||||
@ -74,12 +83,12 @@ func (c *PluginInfoCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginType, err := consts.ParsePluginType(strings.TrimSpace(args[0]))
|
pluginType, err := consts.ParsePluginType(strings.TrimSpace(pluginTypeRaw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(err.Error())
|
c.UI.Error(err.Error())
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
pluginName := strings.TrimSpace(args[1])
|
pluginName := strings.TrimSpace(pluginNameRaw)
|
||||||
|
|
||||||
resp, err := client.Sys().GetPlugin(&api.GetPluginInput{
|
resp, err := client.Sys().GetPlugin(&api.GetPluginInput{
|
||||||
Name: pluginName,
|
Name: pluginName,
|
||||||
@ -90,6 +99,11 @@ func (c *PluginInfoCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resp == nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("No value found for plugin %q", pluginName))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"args": resp.Args,
|
"args": resp.Args,
|
||||||
"builtin": resp.Builtin,
|
"builtin": resp.Builtin,
|
||||||
|
|||||||
@ -96,17 +96,26 @@ func (c *PluginRegisterCommand) Run(args []string) int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pluginNameRaw, pluginTypeRaw string
|
||||||
args = f.Args()
|
args = f.Args()
|
||||||
switch {
|
switch {
|
||||||
case len(args) < 2:
|
case len(args) < 1:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1 or 2, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) > 2:
|
case len(args) > 2:
|
||||||
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1 or 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")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
// These cases should come after invalid cases have been checked
|
||||||
|
case len(args) == 1:
|
||||||
|
pluginTypeRaw = "unknown"
|
||||||
|
pluginNameRaw = args[0]
|
||||||
|
case len(args) == 2:
|
||||||
|
pluginTypeRaw = args[0]
|
||||||
|
pluginNameRaw = args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := c.Client()
|
client, err := c.Client()
|
||||||
@ -115,12 +124,12 @@ func (c *PluginRegisterCommand) Run(args []string) int {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginType, err := consts.ParsePluginType(strings.TrimSpace(args[0]))
|
pluginType, err := consts.ParsePluginType(strings.TrimSpace(pluginTypeRaw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(err.Error())
|
c.UI.Error(err.Error())
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
pluginName := strings.TrimSpace(args[1])
|
pluginName := strings.TrimSpace(pluginNameRaw)
|
||||||
|
|
||||||
command := c.flagCommand
|
command := c.flagCommand
|
||||||
if command == "" {
|
if command == "" {
|
||||||
|
|||||||
@ -54,6 +54,6 @@ func ParsePluginType(pluginType string) (PluginType, error) {
|
|||||||
case "secret":
|
case "secret":
|
||||||
return PluginTypeSecrets, nil
|
return PluginTypeSecrets, nil
|
||||||
default:
|
default:
|
||||||
return PluginTypeUnknown, fmt.Errorf("%s is not a supported plugin type", pluginType)
|
return PluginTypeUnknown, fmt.Errorf("%q is not a supported plugin type", pluginType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -349,7 +349,17 @@ func (b *SystemBackend) handlePluginCatalogRead(ctx context.Context, req *logica
|
|||||||
return logical.ErrorResponse("missing plugin name"), nil
|
return logical.ErrorResponse("missing plugin name"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginType, err := consts.ParsePluginType(d.Get("type").(string))
|
pluginTypeStr := d.Get("type").(string)
|
||||||
|
if pluginTypeStr == "" {
|
||||||
|
// If the plugin type is not provided (i.e. the old
|
||||||
|
// sys/plugins/catalog/:name endpoint is being requested) short-circuit here
|
||||||
|
// and return a warning
|
||||||
|
resp := &logical.Response{}
|
||||||
|
resp.AddWarning(fmt.Sprintf("Deprecated API endpoint, cannot read plugin information from catalog for %q", pluginName))
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginType, err := consts.ParsePluginType(pluginTypeStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -388,7 +398,20 @@ 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
|
||||||
}
|
}
|
||||||
pluginType, err := consts.ParsePluginType(d.Get("type").(string))
|
|
||||||
|
var resp *logical.Response
|
||||||
|
pluginTypeStr := d.Get("type").(string)
|
||||||
|
if pluginTypeStr == "" {
|
||||||
|
// If the plugin type is not provided (i.e. the old
|
||||||
|
// sys/plugins/catalog/:name endpoint is being requested), set type to
|
||||||
|
// unknown and let pluginCatalog.Delete proceed. It should handle
|
||||||
|
// deregistering out of the old storage path (root of core/plugin-catalog)
|
||||||
|
resp = new(logical.Response)
|
||||||
|
resp.AddWarning(fmt.Sprintf("Deprecated API endpoint, cannot deregister plugin from catalog for %q", pluginName))
|
||||||
|
pluginTypeStr = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginType, err := consts.ParsePluginType(pluginTypeStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -396,7 +419,7 @@ func (b *SystemBackend) handlePluginCatalogDelete(ctx context.Context, req *logi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handlePluginReloadUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handlePluginReloadUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user