mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	 ef3e3eace2
			
		
	
	ef3e3eace2
	
	
	
		
			
			Removing the timeout logic from raw-response functions and adding documentation comments. The following functions are affected: - `ReadRaw` - `ReadRawWithContext` (newly added) - `ReadRawWithData` - `ReadRawWithDataWithContext` The previous logic of using `ctx, _ = c.c.withConfiguredTimeout(ctx)` could cause a potential [context leak](https://pkg.go.dev/context): > Failing to call the CancelFunc leaks the child and its children until the parent is canceled or the timer fires. The go vet tool checks that CancelFuncs are used on all control-flow paths. Cancelling the context would have caused more issues since the context would be cancelled before the request body is closed. Resolves: #18658
		
			
				
	
	
		
			136 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package command
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/mitchellh/cli"
 | |
| 	"github.com/posener/complete"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	_ cli.Command             = (*ReadCommand)(nil)
 | |
| 	_ cli.CommandAutocomplete = (*ReadCommand)(nil)
 | |
| )
 | |
| 
 | |
| type ReadCommand struct {
 | |
| 	*BaseCommand
 | |
| 
 | |
| 	testStdin io.Reader // for tests
 | |
| }
 | |
| 
 | |
| func (c *ReadCommand) Synopsis() string {
 | |
| 	return "Read data and retrieves secrets"
 | |
| }
 | |
| 
 | |
| func (c *ReadCommand) Help() string {
 | |
| 	helpText := `
 | |
| Usage: vault read [options] PATH
 | |
| 
 | |
|   Reads data from Vault at the given path. This can be used to read secrets,
 | |
|   generate dynamic credentials, get configuration details, and more.
 | |
| 
 | |
|   Read a secret from the static secrets engine:
 | |
| 
 | |
|       $ vault read secret/my-secret
 | |
| 
 | |
|   For a full list of examples and paths, please see the documentation that
 | |
|   corresponds to the secrets engine in use.
 | |
| 
 | |
| ` + c.Flags().Help()
 | |
| 
 | |
| 	return strings.TrimSpace(helpText)
 | |
| }
 | |
| 
 | |
| func (c *ReadCommand) Flags() *FlagSets {
 | |
| 	return c.flagSet(FlagSetHTTP | FlagSetOutputField | FlagSetOutputFormat)
 | |
| }
 | |
| 
 | |
| func (c *ReadCommand) AutocompleteArgs() complete.Predictor {
 | |
| 	return c.PredictVaultFiles()
 | |
| }
 | |
| 
 | |
| func (c *ReadCommand) AutocompleteFlags() complete.Flags {
 | |
| 	return c.Flags().Completions()
 | |
| }
 | |
| 
 | |
| func (c *ReadCommand) Run(args []string) int {
 | |
| 	f := c.Flags()
 | |
| 
 | |
| 	if err := f.Parse(args, ParseOptionAllowRawFormat(true)); err != nil {
 | |
| 		c.UI.Error(err.Error())
 | |
| 		return 1
 | |
| 	}
 | |
| 
 | |
| 	args = f.Args()
 | |
| 	switch {
 | |
| 	case len(args) < 1:
 | |
| 		c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
 | |
| 		return 1
 | |
| 	}
 | |
| 
 | |
| 	client, err := c.Client()
 | |
| 	if err != nil {
 | |
| 		c.UI.Error(err.Error())
 | |
| 		return 2
 | |
| 	}
 | |
| 
 | |
| 	// client.ReadRaw* methods require a manual timeout override
 | |
| 	ctx, cancel := context.WithTimeout(context.Background(), client.ClientTimeout())
 | |
| 	defer cancel()
 | |
| 
 | |
| 	// Pull our fake stdin if needed
 | |
| 	stdin := (io.Reader)(os.Stdin)
 | |
| 	if c.testStdin != nil {
 | |
| 		stdin = c.testStdin
 | |
| 	}
 | |
| 
 | |
| 	path := sanitizePath(args[0])
 | |
| 
 | |
| 	data, err := parseArgsDataStringLists(stdin, args[1:])
 | |
| 	if err != nil {
 | |
| 		c.UI.Error(fmt.Sprintf("Failed to parse K=V data: %s", err))
 | |
| 		return 1
 | |
| 	}
 | |
| 
 | |
| 	if Format(c.UI) != "raw" {
 | |
| 		secret, err := client.Logical().ReadWithDataWithContext(ctx, path, data)
 | |
| 		if err != nil {
 | |
| 			c.UI.Error(fmt.Sprintf("Error reading %s: %s", path, err))
 | |
| 			return 2
 | |
| 		}
 | |
| 		if secret == nil {
 | |
| 			c.UI.Error(fmt.Sprintf("No value found at %s", path))
 | |
| 			return 2
 | |
| 		}
 | |
| 
 | |
| 		if c.flagField != "" {
 | |
| 			return PrintRawField(c.UI, secret, c.flagField)
 | |
| 		}
 | |
| 
 | |
| 		return OutputSecret(c.UI, secret)
 | |
| 	}
 | |
| 
 | |
| 	resp, err := client.Logical().ReadRawWithDataWithContext(ctx, path, data)
 | |
| 	if err != nil {
 | |
| 		c.UI.Error(fmt.Sprintf("Error reading: %s: %s", path, err))
 | |
| 		return 2
 | |
| 	}
 | |
| 	if resp == nil || resp.Body == nil {
 | |
| 		c.UI.Error(fmt.Sprintf("No value found at %s", path))
 | |
| 		return 2
 | |
| 	}
 | |
| 	defer resp.Body.Close()
 | |
| 
 | |
| 	contents, err := io.ReadAll(resp.Body)
 | |
| 	if err != nil {
 | |
| 		c.UI.Error(fmt.Sprintf("Error reading: %s: %s", path, err))
 | |
| 		return 2
 | |
| 	}
 | |
| 
 | |
| 	return OutputData(c.UI, contents)
 | |
| }
 |