-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VAULT-14735: generate mock clients for activity log #20252
Changes from all commits
6cd8763
93fd96b
068c608
853e887
7ad03db
c212cc3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,14 @@ package vault | |
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/hashicorp/go-uuid" | ||
"github.com/hashicorp/vault/helper/namespace" | ||
"github.com/hashicorp/vault/sdk/framework" | ||
"github.com/hashicorp/vault/sdk/logical" | ||
"github.com/hashicorp/vault/vault/activity" | ||
"github.com/hashicorp/vault/vault/activity/generation" | ||
"google.golang.org/protobuf/encoding/protojson" | ||
) | ||
|
@@ -51,3 +56,123 @@ func (b *SystemBackend) handleActivityWriteData(ctx context.Context, request *lo | |
} | ||
return nil, nil | ||
} | ||
|
||
// singleMonthActivityClients holds a single month's client IDs, in the order they were seen | ||
type singleMonthActivityClients struct { | ||
// clients are indexed by ID | ||
clients []*activity.EntityRecord | ||
} | ||
|
||
// multipleMonthsActivityClients holds multiple month's data | ||
type multipleMonthsActivityClients struct { | ||
// months are in order, with month 0 being the current month and index 1 being 1 month ago | ||
months []*singleMonthActivityClients | ||
} | ||
|
||
// addNewClients generates clients according to the given parameters, and adds them to the month | ||
// the client will always have the mountAccessor as its mount accessor | ||
func (s *singleMonthActivityClients) addNewClients(c *generation.Client, mountAccessor string) error { | ||
count := 1 | ||
if c.Count > 1 { | ||
count = int(c.Count) | ||
} | ||
clientType := entityActivityType | ||
if c.NonEntity { | ||
clientType = nonEntityTokenActivityType | ||
} | ||
for i := 0; i < count; i++ { | ||
record := &activity.EntityRecord{ | ||
ClientID: c.Id, | ||
NamespaceID: c.Namespace, | ||
NonEntity: c.NonEntity, | ||
MountAccessor: mountAccessor, | ||
ClientType: clientType, | ||
} | ||
if record.ClientID == "" { | ||
var err error | ||
record.ClientID, err = uuid.GenerateUUID() | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
s.clients = append(s.clients, record) | ||
} | ||
return nil | ||
} | ||
|
||
// processMonth populates a month of client data | ||
func (m *multipleMonthsActivityClients) processMonth(ctx context.Context, core *Core, month *generation.Data) error { | ||
if month.GetAll() == nil { | ||
return errors.New("segmented monthly data is not yet supported") | ||
} | ||
|
||
// default to using the root namespace and the first mount on the root namespace | ||
mounts, err := core.ListMounts() | ||
if err != nil { | ||
return err | ||
} | ||
defaultMountAccessorRootNS := "" | ||
for _, mount := range mounts { | ||
miagilepner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if mount.NamespaceID == namespace.RootNamespaceID { | ||
defaultMountAccessorRootNS = mount.Accessor | ||
break | ||
} | ||
} | ||
addingTo := m.months[month.GetMonthsAgo()] | ||
|
||
for _, clients := range month.GetAll().Clients { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am a bit confused, is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
could be the value, and it means generate 10 distinct clients with namespace "root" and mount "kv". I can change the variable to |
||
if clients.Repeated || clients.RepeatedFromMonth > 0 { | ||
return errors.New("repeated clients are not yet supported") | ||
} | ||
|
||
if clients.Namespace == "" { | ||
clients.Namespace = namespace.RootNamespaceID | ||
} | ||
|
||
// verify that the namespace exists | ||
ns, err := core.NamespaceByID(ctx, clients.Namespace) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// verify that the mount exists | ||
if clients.Mount != "" { | ||
nctx := namespace.ContextWithNamespace(ctx, ns) | ||
mountEntry := core.router.MatchingMountEntry(nctx, clients.Mount) | ||
if mountEntry == nil { | ||
return fmt.Errorf("unable to find matching mount in namespace %s", clients.Namespace) | ||
} | ||
} | ||
|
||
mountAccessor := defaultMountAccessorRootNS | ||
if clients.Namespace != namespace.RootNamespaceID && clients.Mount == "" { | ||
// if we're not using the root namespace, find a mount on the namespace that we are using | ||
found := false | ||
for _, mount := range mounts { | ||
if mount.NamespaceID == clients.Namespace { | ||
mountAccessor = mount.Accessor | ||
found = true | ||
break | ||
} | ||
} | ||
if !found { | ||
return fmt.Errorf("unable to find matching mount in namespace %s", clients.Namespace) | ||
} | ||
} | ||
err = addingTo.addNewClients(clients, mountAccessor) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func newMultipleMonthsActivityClients(numberOfMonths int) *multipleMonthsActivityClients { | ||
m := &multipleMonthsActivityClients{ | ||
months: make([]*singleMonthActivityClients, numberOfMonths), | ||
} | ||
for i := 0; i < numberOfMonths; i++ { | ||
m.months[i] = new(singleMonthActivityClients) | ||
} | ||
return m | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can add the new
ClientType
field here, or do you think that's more deserving of a separate PR?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can add it here