Skip to content

Commit

Permalink
chore: add err strings and help texts (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
thevilledev committed Jul 9, 2023
1 parent a2a8ddb commit 496e5db
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 32 deletions.
26 changes: 14 additions & 12 deletions internal/plugin/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package plugin

import (
"context"
"fmt"
"strings"
"errors"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
Expand All @@ -12,9 +11,16 @@ import (
// #nosec G101
const (
backendSecretType = "vercel_token"
vercelHelp = `
Vercel Secrets backend is a secrets backend for dynamically managing Vercel tokens.
`
backendPathHelp = `
Vercel Secrets backend is a secrets backend for dynamically managing Vercel tokens.`
secretTokenIDDescription = `
Token ID of the generated API key is stored in the plugin backend.
This ID is used for revocation purposes. It can only be used to identify a key,
and cannot be used to do API operations.`
)

var (
errBackendEmptyConfig = errors.New("configuration passed into backend is nil")
)

type backend struct {
Expand All @@ -27,7 +33,7 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
b := newBackend()

if conf == nil {
return nil, fmt.Errorf("configuration passed into backend is nil")
return nil, errBackendEmptyConfig
}

if err := b.Setup(ctx, conf); err != nil {
Expand All @@ -41,7 +47,7 @@ func newBackend() *backend {
b := &backend{}

b.Backend = &framework.Backend{
Help: strings.TrimSpace(vercelHelp),
Help: backendPathHelp,
BackendType: logical.TypeLogical,
Paths: framework.PathAppend(
b.pathConfig(),
Expand All @@ -54,11 +60,7 @@ func newBackend() *backend {
Fields: map[string]*framework.FieldSchema{
pathTokenID: {
Type: framework.TypeString,
Description: "Vercel API token ID.",
},
pathTokenBearerToken: {
Type: framework.TypeString,
Description: "Vercel API token.",
Description: secretTokenIDDescription,
},
},
Revoke: b.Revoke,
Expand Down
28 changes: 23 additions & 5 deletions internal/plugin/path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ const (
pathConfigBaseURL = "base_url"
pathConfigMaxTTL = "max_ttl"
defaultMaxTTL = 600

pathConfigHelpDescription = `
Configuration path used to set the API key that the plugin uses to communicate with the Vercel API.
Read operations are not supported. If you want to update the configuration, write it again.
Delete operation is supported.`
pathConfigHelpSynopsis = `
Configure the Vercel plugin backend.`
//nolint:gosec
pathConfigAPIKeyDescription = `
(Required) Vercel API key used to generate new tokens.`
pathConfigBaseURLDescription = `
(Optional) Base URL for the Vercel API. Used by mock tests mostly.`
pathConfigMaxTTLDescription = `
(Optional) Maximum TTL for all the API tokens generated by this plugin. Defaults to 600 seconds.`
)

var (
Expand All @@ -33,21 +47,25 @@ type backendConfig struct {
func (b *backend) pathConfig() []*framework.Path {
return []*framework.Path{
{
Pattern: pathPatternConfig,
Pattern: pathPatternConfig,
HelpSynopsis: pathConfigHelpSynopsis,
HelpDescription: pathConfigHelpDescription,

Fields: map[string]*framework.FieldSchema{
pathConfigAPIKey: {
Type: framework.TypeString,
Description: "API key for the Vercel account.",
Description: pathConfigAPIKeyDescription,
Required: true,
},
pathConfigBaseURL: {
Type: framework.TypeString,
Description: "Optional API base URL used by this backend.",
Description: pathConfigBaseURLDescription,
Default: client.DefaultBaseURL,
},
pathConfigMaxTTL: {
Type: framework.TypeDurationSecond,
Default: defaultMaxTTL,
Type: framework.TypeDurationSecond,
Description: pathConfigMaxTTLDescription,
Default: defaultMaxTTL,
},
},

Expand Down
9 changes: 8 additions & 1 deletion internal/plugin/path_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import (
)

const (
pathPatternInfo = "info"
pathPatternInfo = "info"
pathPatternHelpDescription = `
Build variables are set by the build process and include things like git tag, commit hash and build date.
Supports only read operations.`
pathPatternHelpSynopsis = `
Returns build information about this plugin.`
)

func (b *backend) pathInfo() []*framework.Path {
Expand All @@ -22,6 +27,8 @@ func (b *backend) pathInfo() []*framework.Path {
Callback: b.pathInfoRead,
},
},
HelpDescription: pathPatternHelpDescription,
HelpSynopsis: pathPatternHelpSynopsis,
},
}
}
Expand Down
33 changes: 22 additions & 11 deletions internal/plugin/path_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package plugin

import (
"context"
"errors"
"fmt"
"time"

Expand All @@ -16,24 +17,34 @@ const (
pathTokenID = "token_id"
pathTokenBearerToken = "bearer_token"
pathTokenTTL = "ttl"
//nolint:gosec
pathTokenTTLDescription = `
(Optional) TTL for the generated API key ("bearer token"). Less than or equal to the maximum TTL set in configuration.
Defaults to maximum TTL.`
pathTokenDescription = `
Supports only read operations. Token ID for the generated key is stored in the plugin backend for revocation purposes.
Generated bearer token is NOT stored in the plugin backend.
Tokens are automatically revoked & deleted by Vault once TTL hits zero.
Tokens cannot be renewed. Generate a new token if you need one.`
//nolint:gosec
pathTokenSynopsis = `
Generate a Vercel API token with the given TTL.`
)

var (
errTokenMaxTTLExceeded = errors.New("given TTL exceeds the maximum allowed value")
)

func (b *backend) pathToken() []*framework.Path {
return []*framework.Path{
{
Pattern: pathPatternToken,
Pattern: pathPatternToken,
HelpDescription: pathTokenDescription,
HelpSynopsis: pathTokenSynopsis,
Fields: map[string]*framework.FieldSchema{
pathTokenID: {
Type: framework.TypeString,
Description: "Token ID for the generated API key.",
},
pathTokenBearerToken: {
Type: framework.TypeString,
Description: "Generated API key.",
},
pathTokenTTL: {
Type: framework.TypeDurationSecond,
Description: "TTL for the generated API key. Less than or equal to the maximum TTL set in configuration.",
Description: pathTokenTTLDescription,
},
},
Operations: map[logical.Operation]framework.OperationHandler{
Expand Down Expand Up @@ -80,7 +91,7 @@ func (b *backend) pathTokenWrite(ctx context.Context, req *logical.Request,
}

if ttl > int64(cfg.MaxTTL) {
return nil, fmt.Errorf("TTL %d exceeds maximum of %d", ttl, int64(cfg.MaxTTL))
return nil, errTokenMaxTTLExceeded
}

svc := service.NewWithBaseURL(cfg.APIKey, cfg.BaseURL)
Expand Down
11 changes: 8 additions & 3 deletions internal/plugin/revoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@ package plugin

import (
"context"
"errors"
"fmt"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
"github.com/thevilledev/vault-plugin-secrets-vercel/internal/service"
)

var (
errRemoteTokenRevokeFailed = errors.New("failed to revoke token from Vercel")
)

func (b *backend) Revoke(ctx context.Context, req *logical.Request, _ *framework.FieldData) (*logical.Response, error) {
cfg, err := b.getConfig(ctx, req.Storage)
if err != nil {
return nil, err
}

if cfg.APIKey == "" {
return nil, fmt.Errorf("backend is missing the API key")
return nil, errBackendNotConfigured
}

svc := service.NewWithBaseURL(cfg.APIKey, cfg.BaseURL)
Expand All @@ -35,9 +40,9 @@ func (b *backend) Revoke(ctx context.Context, req *logical.Request, _ *framework

_, err = svc.DeleteAuthToken(ctx, ks)
if err != nil {
b.Logger().Error("token delete failed: %s", err)
b.Logger().Error("failed to revoke/delete the token from Vercel %s", err)

return nil, fmt.Errorf("failed to delete token: %w", err)
return nil, errRemoteTokenRevokeFailed
}

return &logical.Response{}, nil
Expand Down

0 comments on commit 496e5db

Please sign in to comment.