Skip to content

Commit

Permalink
Change cache schema from personas to tokens+users (#3737)
Browse files Browse the repository at this point in the history
* Change from personas to tokens+users

* Separate keyring tokens from auth tokens
  • Loading branch information
talanknight committed Sep 26, 2023
1 parent 2509498 commit 5d77193
Show file tree
Hide file tree
Showing 26 changed files with 1,744 additions and 2,036 deletions.
4 changes: 2 additions & 2 deletions internal/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
}, nil
},

"daemon add-persona": func() (cli.Command, error) {
return &daemon.AddPersonaCommand{
"daemon add-token": func() (cli.Command, error) {
return &daemon.AddTokenCommand{
Command: base.NewCommand(ui),
}, nil
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,68 +17,68 @@ import (
)

var (
_ cli.Command = (*AddPersonaCommand)(nil)
_ cli.CommandAutocomplete = (*AddPersonaCommand)(nil)
_ cli.Command = (*AddTokenCommand)(nil)
_ cli.CommandAutocomplete = (*AddTokenCommand)(nil)
)

type AddPersonaCommand struct {
type AddTokenCommand struct {
*base.Command
}

func (c *AddPersonaCommand) Synopsis() string {
return "Add a persona to a running boundary daemon"
func (c *AddTokenCommand) Synopsis() string {
return "Add an auth token to a running boundary daemon"
}

func (c *AddPersonaCommand) Help() string {
func (c *AddTokenCommand) Help() string {
helpText := `
Usage: boundary daemon add-persona [options]
Usage: boundary daemon add-token [options]
Add a persona to the daemon:
Add an auth token to the daemon:
$ boundary daemon add-persona
$ boundary daemon add-token
For a full list of examples, please see the documentation.
` + c.Flags().Help()
return strings.TrimSpace(helpText)
}

func (c *AddPersonaCommand) Flags() *base.FlagSets {
func (c *AddTokenCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetClient | base.FlagSetOutputFormat)
return set
}

func (c *AddPersonaCommand) AutocompleteArgs() complete.Predictor {
func (c *AddTokenCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *AddPersonaCommand) AutocompleteFlags() complete.Flags {
func (c *AddTokenCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}

func (c *AddPersonaCommand) Run(args []string) int {
func (c *AddTokenCommand) Run(args []string) int {
ctx := c.Context
f := c.Flags()
if err := f.Parse(args); err != nil {
c.PrintCliError(err)
return base.CommandUserError
}

apiErr, err := c.AddPersona(ctx)
apiErr, err := c.Add(ctx)
if err != nil {
c.PrintCliError(err)
return base.CommandCliError
}
if apiErr != nil {
c.PrintApiError(apiErr, "Error from daemon when adding a persona")
c.PrintApiError(apiErr, "Error from daemon when adding a token")
return base.CommandApiError

}
return base.CommandSuccess
}

func (c *AddPersonaCommand) AddPersona(ctx context.Context) (*api.Error, error) {
const op = "daemon.(AddPersonaCommand).AddPersona"
func (c *AddTokenCommand) Add(ctx context.Context) (*api.Error, error) {
const op = "daemon.(AddTokenCommand).Add"
keyringType, tokenName, err := c.DiscoverKeyringTokenInfo()
if err != nil {
return nil, err
Expand All @@ -92,9 +92,11 @@ func (c *AddPersonaCommand) AddPersona(ctx context.Context) (*api.Error, error)
return nil, err
}

pa := personaToAdd{
KeyringType: keyringType,
TokenName: tokenName,
pa := userTokenToAdd{
Keyring: &keyringToken{
KeyringType: keyringType,
TokenName: tokenName,
},
BoundaryAddr: client.Addr(),
AuthTokenId: at.Id,
}
Expand All @@ -104,11 +106,11 @@ func (c *AddPersonaCommand) AddPersona(ctx context.Context) (*api.Error, error)
return nil, err
}

return addPersona(ctx, dotPath, &pa)
return addToken(ctx, dotPath, &pa)
}

func addPersona(ctx context.Context, daemonPath string, p *personaToAdd) (*api.Error, error) {
const op = "daemon.addPersona"
func addToken(ctx context.Context, daemonPath string, p *userTokenToAdd) (*api.Error, error) {
const op = "daemon.addToken"
client, err := api.NewClient(nil)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
Expand All @@ -125,7 +127,7 @@ func addPersona(ctx context.Context, daemonPath string, p *personaToAdd) (*api.E
// like the system keychain. Explicitly clear the token for now
client.SetToken("")

req, err := client.NewRequest(ctx, "POST", "/personas", p)
req, err := client.NewRequest(ctx, "POST", "/tokens", p)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/commands/daemon/command_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ func (w *CommandWrapper) startDaemon(ctx context.Context) bool {

// addPersonaInCache runs AddPersonaCommand
func (w *CommandWrapper) addPersonaInCache(ctx context.Context) bool {
c := AddPersonaCommand{Command: base.NewCommand(w.ui)}
c := AddTokenCommand{Command: base.NewCommand(w.ui)}
c.Flags()
apiErr, err := c.AddPersona(ctx)
apiErr, err := c.Add(ctx)
return err == nil && apiErr == nil
}
94 changes: 0 additions & 94 deletions internal/cmd/commands/daemon/persona_handler.go

This file was deleted.

35 changes: 10 additions & 25 deletions internal/cmd/commands/daemon/search_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ const (
queryKey = "query"
resourceKey = "resource"

tokenNameKey = "token_name"
boundaryAddrKey = "boundary_addr"
keyringTypeKey = "keyring_type"
authTokenIdKey = "auth_token_id"
)

Expand All @@ -49,32 +47,19 @@ func newSearchTargetsHandlerFunc(ctx context.Context, repo *cache.Repository) (h
}

resource := r.URL.Query().Get(resourceKey)
tokenName := r.URL.Query().Get(tokenNameKey)
keyringType := r.URL.Query().Get(keyringTypeKey)
boundaryAddr := r.URL.Query().Get(boundaryAddrKey)
authTokenId := r.URL.Query().Get(authTokenIdKey)

switch {
case resource == "":
writeError(w, "resource is a required field but was empty", http.StatusBadRequest)
return
case tokenName == "":
writeError(w, fmt.Sprintf("%s is a required field but was empty", tokenNameKey), http.StatusBadRequest)
return
case keyringType == "":
writeError(w, fmt.Sprintf("%s is a required field but was empty", keyringTypeKey), http.StatusBadRequest)
return
case boundaryAddr == "":
writeError(w, fmt.Sprintf("%s is a required field but was empty", boundaryAddrKey), http.StatusBadRequest)
return
case authTokenId == "":
writeError(w, fmt.Sprintf("%s is a required field but was empty", authTokenIdKey), http.StatusBadRequest)
return
}

p, err := repo.LookupPersona(ctx, tokenName, keyringType,
cache.WithBoundaryAddress(boundaryAddr), cache.WithAuthTokenId(authTokenId), cache.WithUpdateLastAccessedTime(true))
if err != nil || p == nil {
t, err := repo.LookupToken(ctx, authTokenId, cache.WithUpdateLastAccessedTime(true))
if err != nil || t == nil {
writeError(w, "Forbidden", http.StatusForbidden)
return
}
Expand All @@ -84,9 +69,9 @@ func newSearchTargetsHandlerFunc(ctx context.Context, repo *cache.Repository) (h
var res *SearchResult
switch resource {
case "targets":
res, err = searchTargets(r.Context(), repo, p, query, filter)
res, err = searchTargets(r.Context(), repo, authTokenId, query, filter)
case "sessions":
res, err = searchSessions(r.Context(), repo, p, query, filter)
res, err = searchSessions(r.Context(), repo, authTokenId, query, filter)
default:
writeError(w, fmt.Sprintf("search doesn't support %q resource", resource), http.StatusBadRequest)
return
Expand Down Expand Up @@ -114,14 +99,14 @@ func newSearchTargetsHandlerFunc(ctx context.Context, repo *cache.Repository) (h
}, nil
}

func searchTargets(ctx context.Context, repo *cache.Repository, p *cache.Persona, query string, filter *handlers.Filter) (*SearchResult, error) {
func searchTargets(ctx context.Context, repo *cache.Repository, authTokenId, query string, filter *handlers.Filter) (*SearchResult, error) {
var found []*targets.Target
var err error
switch query {
case "":
found, err = repo.ListTargets(ctx, p)
found, err = repo.ListTargets(ctx, authTokenId)
default:
found, err = repo.QueryTargets(ctx, p, query)
found, err = repo.QueryTargets(ctx, authTokenId, query)
}
if err != nil {
return nil, err
Expand All @@ -138,14 +123,14 @@ func searchTargets(ctx context.Context, repo *cache.Repository, p *cache.Persona
}, nil
}

func searchSessions(ctx context.Context, repo *cache.Repository, p *cache.Persona, query string, filter *handlers.Filter) (*SearchResult, error) {
func searchSessions(ctx context.Context, repo *cache.Repository, authTokenId, query string, filter *handlers.Filter) (*SearchResult, error) {
var found []*sessions.Session
var err error
switch query {
case "":
found, err = repo.ListSessions(ctx, p)
found, err = repo.ListSessions(ctx, authTokenId)
default:
found, err = repo.QuerySessions(ctx, p, query)
found, err = repo.QuerySessions(ctx, authTokenId, query)
}
if err != nil {
return nil, err
Expand Down
6 changes: 3 additions & 3 deletions internal/cmd/commands/daemon/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (s *cacheServer) serve(ctx context.Context, cmd Commander, l net.Listener)
return
}
if at := cmd.ReadTokenFromKeyring(krType, tokName); at != nil {
if err := repo.AddPersona(ctx, client.Addr(), tokName, krType, at.Id); err != nil {
if err := repo.AddKeyringToken(ctx, client.Addr(), cache.KeyringToken{KeyringType: krType, TokenName: tokName, AuthTokenId: at.Id}); err != nil {
event.WriteError(ctx, op, err)
return
}
Expand Down Expand Up @@ -188,11 +188,11 @@ func (s *cacheServer) serve(ctx context.Context, cmd Commander, l net.Listener)
}
mux.HandleFunc("/v1/search", searchTargetsFn)

personaFn, err := newPersonaHandlerFunc(ctx, repo, tic)
tokenFn, err := newTokenHandlerFunc(ctx, repo, tic)
if err != nil {
return errors.Wrap(ctx, err, op)
}
mux.HandleFunc("/v1/personas", personaFn)
mux.HandleFunc("/v1/tokens", tokenFn)

stopFn, err := newStopHandlerFunc(ctx, s.conf.contextCancel)
if err != nil {
Expand Down
13 changes: 6 additions & 7 deletions internal/cmd/commands/daemon/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package daemon
import (
"context"
"io"
"strings"
"testing"

"github.com/hashicorp/boundary/api/sessions"
Expand Down Expand Up @@ -68,22 +69,20 @@ func (s *TestServer) Serve(t *testing.T) error {

// AddResources adds targets to the cache for the provided address, token name,
// and keyring type. They token info must already be known to the server.
func (s *TestServer) AddResources(t *testing.T, p *cache.Persona, tars []*targets.Target, sess []*sessions.Session) {
func (s *TestServer) AddResources(t *testing.T, p *cache.AuthToken, tars []*targets.Target, sess []*sessions.Session) {
t.Helper()
ctx := context.Background()
r, err := cache.NewRepository(ctx, s.cacheServer.store, s.cmd.ReadTokenFromKeyring)
require.NoError(t, err)

tarFn := func(ctx context.Context, addr string, tok string) ([]*targets.Target, error) {
at := s.cmd.ReadTokenFromKeyring(p.KeyringType, p.TokenName)
if addr != p.BoundaryAddr || tok != at.Token {
tarFn := func(ctx context.Context, _, tok string) ([]*targets.Target, error) {
if !strings.HasPrefix(tok, p.Id) {
return nil, nil
}
return tars, nil
}
sessFn := func(ctx context.Context, addr string, tok string) ([]*sessions.Session, error) {
at := s.cmd.ReadTokenFromKeyring(p.KeyringType, p.TokenName)
if addr != p.BoundaryAddr || tok != at.Token {
sessFn := func(ctx context.Context, _, tok string) ([]*sessions.Session, error) {
if !strings.HasPrefix(tok, p.Id) {
return nil, nil
}
return sess, nil
Expand Down
Loading

0 comments on commit 5d77193

Please sign in to comment.