Skip to content

Commit

Permalink
VAULT-14735: generate mock clients for activity log (#20252)
Browse files Browse the repository at this point in the history
* first part of segment client generation

* fix imports

* initial pr fixes

* refactor and fix

* update comments

* assign client type
  • Loading branch information
miagilepner authored May 23, 2023
1 parent 2ef3f7c commit 5b23dd5
Show file tree
Hide file tree
Showing 4 changed files with 324 additions and 47 deletions.
72 changes: 31 additions & 41 deletions vault/activity/generation/generate_data.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 5 additions & 6 deletions vault/activity/generation/generate_data.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ message Clients {
message Client {
string id = 1;
int32 count = 2;
int32 times_seen = 3;
bool repeated = 4;
int32 repeated_from_month = 5;
string namespace = 6;
string mount = 7;
bool non_entity = 8;
bool repeated = 3;
int32 repeated_from_month = 4;
string namespace = 5;
string mount = 6;
bool non_entity = 7;
}
125 changes: 125 additions & 0 deletions vault/logical_system_activity_write_testonly.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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 {
if mount.NamespaceID == namespace.RootNamespaceID {
defaultMountAccessorRootNS = mount.Accessor
break
}
}
addingTo := m.months[month.GetMonthsAgo()]

for _, clients := range month.GetAll().Clients {
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
}
Loading

0 comments on commit 5b23dd5

Please sign in to comment.