VAULT-14734: activity log write endpoint (#20019)

* add noop endpoint with testonly build flag

* add tests for endpoint

* cleanup

* fix test name

* add changelog

* pr fixes
This commit is contained in:
miagilepner 2023-04-12 18:26:26 +02:00 committed by GitHub
parent e6b890f7ed
commit 1ea85c56d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 989 additions and 10 deletions

View File

@ -30,13 +30,16 @@ default: dev
bin: prep
@CGO_ENABLED=$(CGO_ENABLED) BUILD_TAGS='$(BUILD_TAGS) ui' sh -c "'$(CURDIR)/scripts/build.sh'"
testonly:
$(eval BUILD_TAGS += testonly)
# dev creates binaries for testing Vault locally. These are put
# into ./bin/ as well as $GOPATH/bin
dev: prep
dev: prep testonly
@CGO_ENABLED=$(CGO_ENABLED) BUILD_TAGS='$(BUILD_TAGS)' VAULT_DEV_BUILD=1 sh -c "'$(CURDIR)/scripts/build.sh'"
dev-ui: assetcheck prep
dev-ui: assetcheck prep testonly
@CGO_ENABLED=$(CGO_ENABLED) BUILD_TAGS='$(BUILD_TAGS) ui' VAULT_DEV_BUILD=1 sh -c "'$(CURDIR)/scripts/build.sh'"
dev-dynamic: prep
dev-dynamic: prep testonly
@CGO_ENABLED=1 BUILD_TAGS='$(BUILD_TAGS)' VAULT_DEV_BUILD=1 sh -c "'$(CURDIR)/scripts/build.sh'"
# *-mem variants will enable memory profiling which will write snapshots of heap usage
@ -51,14 +54,14 @@ dev-dynamic-mem: dev-dynamic
# Creates a Docker image by adding the compiled linux/amd64 binary found in ./bin.
# The resulting image is tagged "vault:dev".
docker-dev: prep
docker-dev: prep testonly
docker build --build-arg VERSION=$(GO_VERSION_MIN) --build-arg BUILD_TAGS="$(BUILD_TAGS)" -f scripts/docker/Dockerfile -t vault:dev .
docker-dev-ui: prep
docker-dev-ui: prep testonly
docker build --build-arg VERSION=$(GO_VERSION_MIN) --build-arg BUILD_TAGS="$(BUILD_TAGS)" -f scripts/docker/Dockerfile.ui -t vault:dev-ui .
# test runs the unit tests and vets the code
test: prep
test: prep testonly
@CGO_ENABLED=$(CGO_ENABLED) \
VAULT_ADDR= \
VAULT_TOKEN= \
@ -66,13 +69,13 @@ test: prep
VAULT_ACC= \
$(GO_CMD) test -tags='$(BUILD_TAGS)' $(TEST) $(TESTARGS) -timeout=$(TEST_TIMEOUT) -parallel=20
testcompile: prep
testcompile: prep testonly
@for pkg in $(TEST) ; do \
$(GO_CMD) test -v -c -tags='$(BUILD_TAGS)' $$pkg -parallel=4 ; \
done
# testacc runs acceptance tests
testacc: prep
testacc: prep testonly
@if [ "$(TEST)" = "./..." ]; then \
echo "ERROR: Set TEST to a specific package"; \
exit 1; \
@ -80,7 +83,7 @@ testacc: prep
VAULT_ACC=1 $(GO_CMD) test -tags='$(BUILD_TAGS)' $(TEST) -v $(TESTARGS) -timeout=$(EXTENDED_TEST_TIMEOUT)
# testrace runs the race checker
testrace: prep
testrace: prep testonly
@CGO_ENABLED=1 \
VAULT_ADDR= \
VAULT_TOKEN= \
@ -203,6 +206,7 @@ proto: bootstrap
@sh -c "'$(CURDIR)/scripts/protocversioncheck.sh' '$(PROTOC_VERSION_MIN)'"
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative vault/*.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative vault/activity/activity_log.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative vault/activity/generation/generate_data.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helper/storagepacker/types.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helper/forwarding/types.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative sdk/logical/*.proto

3
changelog/20019.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
core/activity: add an endpoint to write test activity log data, guarded by a build flag
```

View File

@ -0,0 +1,762 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.21.12
// source: vault/activity/generation/generate_data.proto
package generation
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type WriteOptions int32
const (
WriteOptions_WRITE_UNKNOWN WriteOptions = 0
WriteOptions_WRITE_PRECOMPUTED_QUERIES WriteOptions = 1
WriteOptions_WRITE_DISTINCT_CLIENTS WriteOptions = 2
WriteOptions_WRITE_ENTITIES WriteOptions = 3
WriteOptions_WRITE_DIRECT_TOKENS WriteOptions = 4
WriteOptions_WRITE_INTENT_LOGS WriteOptions = 5
)
// Enum value maps for WriteOptions.
var (
WriteOptions_name = map[int32]string{
0: "WRITE_UNKNOWN",
1: "WRITE_PRECOMPUTED_QUERIES",
2: "WRITE_DISTINCT_CLIENTS",
3: "WRITE_ENTITIES",
4: "WRITE_DIRECT_TOKENS",
5: "WRITE_INTENT_LOGS",
}
WriteOptions_value = map[string]int32{
"WRITE_UNKNOWN": 0,
"WRITE_PRECOMPUTED_QUERIES": 1,
"WRITE_DISTINCT_CLIENTS": 2,
"WRITE_ENTITIES": 3,
"WRITE_DIRECT_TOKENS": 4,
"WRITE_INTENT_LOGS": 5,
}
)
func (x WriteOptions) Enum() *WriteOptions {
p := new(WriteOptions)
*p = x
return p
}
func (x WriteOptions) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (WriteOptions) Descriptor() protoreflect.EnumDescriptor {
return file_vault_activity_generation_generate_data_proto_enumTypes[0].Descriptor()
}
func (WriteOptions) Type() protoreflect.EnumType {
return &file_vault_activity_generation_generate_data_proto_enumTypes[0]
}
func (x WriteOptions) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use WriteOptions.Descriptor instead.
func (WriteOptions) EnumDescriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{0}
}
type ActivityLogMockInput struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Write []WriteOptions `protobuf:"varint,1,rep,packed,name=write,proto3,enum=generation.WriteOptions" json:"write,omitempty"`
Data []*Data `protobuf:"bytes,2,rep,name=data,proto3" json:"data,omitempty"`
}
func (x *ActivityLogMockInput) Reset() {
*x = ActivityLogMockInput{}
if protoimpl.UnsafeEnabled {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActivityLogMockInput) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActivityLogMockInput) ProtoMessage() {}
func (x *ActivityLogMockInput) ProtoReflect() protoreflect.Message {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActivityLogMockInput.ProtoReflect.Descriptor instead.
func (*ActivityLogMockInput) Descriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{0}
}
func (x *ActivityLogMockInput) GetWrite() []WriteOptions {
if x != nil {
return x.Write
}
return nil
}
func (x *ActivityLogMockInput) GetData() []*Data {
if x != nil {
return x.Data
}
return nil
}
type Data struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Types that are assignable to Month:
//
// *Data_CurrentMonth
// *Data_MonthsAgo
Month isData_Month `protobuf_oneof:"month"`
// Types that are assignable to Clients:
//
// *Data_All
// *Data_Segments
Clients isData_Clients `protobuf_oneof:"clients"`
EmptySegmentIndexes []int32 `protobuf:"varint,5,rep,packed,name=empty_segment_indexes,json=emptySegmentIndexes,proto3" json:"empty_segment_indexes,omitempty"`
SkipSegmentIndexes []int32 `protobuf:"varint,6,rep,packed,name=skip_segment_indexes,json=skipSegmentIndexes,proto3" json:"skip_segment_indexes,omitempty"`
NumSegments int32 `protobuf:"varint,7,opt,name=num_segments,json=numSegments,proto3" json:"num_segments,omitempty"`
}
func (x *Data) Reset() {
*x = Data{}
if protoimpl.UnsafeEnabled {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Data) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Data) ProtoMessage() {}
func (x *Data) ProtoReflect() protoreflect.Message {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Data.ProtoReflect.Descriptor instead.
func (*Data) Descriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{1}
}
func (m *Data) GetMonth() isData_Month {
if m != nil {
return m.Month
}
return nil
}
func (x *Data) GetCurrentMonth() bool {
if x, ok := x.GetMonth().(*Data_CurrentMonth); ok {
return x.CurrentMonth
}
return false
}
func (x *Data) GetMonthsAgo() int32 {
if x, ok := x.GetMonth().(*Data_MonthsAgo); ok {
return x.MonthsAgo
}
return 0
}
func (m *Data) GetClients() isData_Clients {
if m != nil {
return m.Clients
}
return nil
}
func (x *Data) GetAll() *Clients {
if x, ok := x.GetClients().(*Data_All); ok {
return x.All
}
return nil
}
func (x *Data) GetSegments() *Segments {
if x, ok := x.GetClients().(*Data_Segments); ok {
return x.Segments
}
return nil
}
func (x *Data) GetEmptySegmentIndexes() []int32 {
if x != nil {
return x.EmptySegmentIndexes
}
return nil
}
func (x *Data) GetSkipSegmentIndexes() []int32 {
if x != nil {
return x.SkipSegmentIndexes
}
return nil
}
func (x *Data) GetNumSegments() int32 {
if x != nil {
return x.NumSegments
}
return 0
}
type isData_Month interface {
isData_Month()
}
type Data_CurrentMonth struct {
CurrentMonth bool `protobuf:"varint,1,opt,name=current_month,json=currentMonth,proto3,oneof"`
}
type Data_MonthsAgo struct {
MonthsAgo int32 `protobuf:"varint,2,opt,name=months_ago,json=monthsAgo,proto3,oneof"`
}
func (*Data_CurrentMonth) isData_Month() {}
func (*Data_MonthsAgo) isData_Month() {}
type isData_Clients interface {
isData_Clients()
}
type Data_All struct {
All *Clients `protobuf:"bytes,3,opt,name=all,proto3,oneof"` // you cant have repeated fields in a oneof, which is why these are separate message types
}
type Data_Segments struct {
Segments *Segments `protobuf:"bytes,4,opt,name=segments,proto3,oneof"`
}
func (*Data_All) isData_Clients() {}
func (*Data_Segments) isData_Clients() {}
type Segments struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Segments []*Segment `protobuf:"bytes,1,rep,name=segments,proto3" json:"segments,omitempty"`
}
func (x *Segments) Reset() {
*x = Segments{}
if protoimpl.UnsafeEnabled {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Segments) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Segments) ProtoMessage() {}
func (x *Segments) ProtoReflect() protoreflect.Message {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Segments.ProtoReflect.Descriptor instead.
func (*Segments) Descriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{2}
}
func (x *Segments) GetSegments() []*Segment {
if x != nil {
return x.Segments
}
return nil
}
type Segment struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
SegmentIndex *int32 `protobuf:"varint,1,opt,name=segment_index,json=segmentIndex,proto3,oneof" json:"segment_index,omitempty"`
Clients *Clients `protobuf:"bytes,2,opt,name=clients,proto3" json:"clients,omitempty"`
}
func (x *Segment) Reset() {
*x = Segment{}
if protoimpl.UnsafeEnabled {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Segment) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Segment) ProtoMessage() {}
func (x *Segment) ProtoReflect() protoreflect.Message {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Segment.ProtoReflect.Descriptor instead.
func (*Segment) Descriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{3}
}
func (x *Segment) GetSegmentIndex() int32 {
if x != nil && x.SegmentIndex != nil {
return *x.SegmentIndex
}
return 0
}
func (x *Segment) GetClients() *Clients {
if x != nil {
return x.Clients
}
return nil
}
type Clients struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Clients []*Client `protobuf:"bytes,1,rep,name=clients,proto3" json:"clients,omitempty"`
}
func (x *Clients) Reset() {
*x = Clients{}
if protoimpl.UnsafeEnabled {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Clients) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Clients) ProtoMessage() {}
func (x *Clients) ProtoReflect() protoreflect.Message {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Clients.ProtoReflect.Descriptor instead.
func (*Clients) Descriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{4}
}
func (x *Clients) GetClients() []*Client {
if x != nil {
return x.Clients
}
return nil
}
type Client struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Count int32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
TimesSeen int32 `protobuf:"varint,3,opt,name=times_seen,json=timesSeen,proto3" json:"times_seen,omitempty"`
Repeated bool `protobuf:"varint,4,opt,name=repeated,proto3" json:"repeated,omitempty"`
RepeatedFromMonth int32 `protobuf:"varint,5,opt,name=repeated_from_month,json=repeatedFromMonth,proto3" json:"repeated_from_month,omitempty"`
Namespace string `protobuf:"bytes,6,opt,name=namespace,proto3" json:"namespace,omitempty"`
Mount string `protobuf:"bytes,7,opt,name=mount,proto3" json:"mount,omitempty"`
NonEntity bool `protobuf:"varint,8,opt,name=non_entity,json=nonEntity,proto3" json:"non_entity,omitempty"`
}
func (x *Client) Reset() {
*x = Client{}
if protoimpl.UnsafeEnabled {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Client) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Client) ProtoMessage() {}
func (x *Client) ProtoReflect() protoreflect.Message {
mi := &file_vault_activity_generation_generate_data_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Client.ProtoReflect.Descriptor instead.
func (*Client) Descriptor() ([]byte, []int) {
return file_vault_activity_generation_generate_data_proto_rawDescGZIP(), []int{5}
}
func (x *Client) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *Client) GetCount() int32 {
if x != nil {
return x.Count
}
return 0
}
func (x *Client) GetTimesSeen() int32 {
if x != nil {
return x.TimesSeen
}
return 0
}
func (x *Client) GetRepeated() bool {
if x != nil {
return x.Repeated
}
return false
}
func (x *Client) GetRepeatedFromMonth() int32 {
if x != nil {
return x.RepeatedFromMonth
}
return 0
}
func (x *Client) GetNamespace() string {
if x != nil {
return x.Namespace
}
return ""
}
func (x *Client) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *Client) GetNonEntity() bool {
if x != nil {
return x.NonEntity
}
return false
}
var File_vault_activity_generation_generate_data_proto protoreflect.FileDescriptor
var file_vault_activity_generation_generate_data_proto_rawDesc = []byte{
0x0a, 0x2d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x65,
0x72, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x14, 0x41,
0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x63, 0x6b, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x57, 0x72, 0x69, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x05, 0x77, 0x72,
0x69, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x10, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xc8, 0x02, 0x0a, 0x04, 0x44, 0x61,
0x74, 0x61, 0x12, 0x25, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f,
0x6e, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x75, 0x72,
0x72, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0a, 0x6d, 0x6f, 0x6e,
0x74, 0x68, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52,
0x09, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x73, 0x41, 0x67, 0x6f, 0x12, 0x27, 0x0a, 0x03, 0x61, 0x6c,
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x48, 0x01, 0x52, 0x03,
0x61, 0x6c, 0x6c, 0x12, 0x32, 0x0a, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x48, 0x01, 0x52, 0x08, 0x73,
0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x6d, 0x70, 0x74, 0x79,
0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x05, 0x52, 0x13, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x65, 0x67,
0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x73,
0x6b, 0x69, 0x70, 0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65,
0x78, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x05, 0x52, 0x12, 0x73, 0x6b, 0x69, 0x70, 0x53,
0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x21, 0x0a,
0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x42, 0x07, 0x0a, 0x05, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x73, 0x22, 0x3b, 0x0a, 0x08, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x12, 0x2f, 0x0a, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74,
0x73, 0x22, 0x74, 0x0a, 0x07, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0d,
0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e,
0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x07, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e,
0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x37, 0x0a, 0x07, 0x43, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x73, 0x12, 0x2c, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
0x22, 0xec, 0x01, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18,
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x53, 0x65, 0x65, 0x6e,
0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01,
0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13,
0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x6f,
0x6e, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x72, 0x65, 0x70, 0x65, 0x61,
0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x09,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x08,
0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2a,
0xa0, 0x01, 0x0a, 0x0c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x12, 0x11, 0x0a, 0x0d, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
0x4e, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x45,
0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53,
0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x54,
0x49, 0x4e, 0x43, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x12,
0x0a, 0x0e, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x49, 0x45, 0x53,
0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45,
0x43, 0x54, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x57,
0x52, 0x49, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x4f, 0x47, 0x53,
0x10, 0x05, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74,
0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2f,
0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_vault_activity_generation_generate_data_proto_rawDescOnce sync.Once
file_vault_activity_generation_generate_data_proto_rawDescData = file_vault_activity_generation_generate_data_proto_rawDesc
)
func file_vault_activity_generation_generate_data_proto_rawDescGZIP() []byte {
file_vault_activity_generation_generate_data_proto_rawDescOnce.Do(func() {
file_vault_activity_generation_generate_data_proto_rawDescData = protoimpl.X.CompressGZIP(file_vault_activity_generation_generate_data_proto_rawDescData)
})
return file_vault_activity_generation_generate_data_proto_rawDescData
}
var file_vault_activity_generation_generate_data_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_vault_activity_generation_generate_data_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_vault_activity_generation_generate_data_proto_goTypes = []interface{}{
(WriteOptions)(0), // 0: generation.WriteOptions
(*ActivityLogMockInput)(nil), // 1: generation.ActivityLogMockInput
(*Data)(nil), // 2: generation.Data
(*Segments)(nil), // 3: generation.Segments
(*Segment)(nil), // 4: generation.Segment
(*Clients)(nil), // 5: generation.Clients
(*Client)(nil), // 6: generation.Client
}
var file_vault_activity_generation_generate_data_proto_depIdxs = []int32{
0, // 0: generation.ActivityLogMockInput.write:type_name -> generation.WriteOptions
2, // 1: generation.ActivityLogMockInput.data:type_name -> generation.Data
5, // 2: generation.Data.all:type_name -> generation.Clients
3, // 3: generation.Data.segments:type_name -> generation.Segments
4, // 4: generation.Segments.segments:type_name -> generation.Segment
5, // 5: generation.Segment.clients:type_name -> generation.Clients
6, // 6: generation.Clients.clients:type_name -> generation.Client
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_vault_activity_generation_generate_data_proto_init() }
func file_vault_activity_generation_generate_data_proto_init() {
if File_vault_activity_generation_generate_data_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_vault_activity_generation_generate_data_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActivityLogMockInput); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_vault_activity_generation_generate_data_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Data); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_vault_activity_generation_generate_data_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Segments); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_vault_activity_generation_generate_data_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Segment); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_vault_activity_generation_generate_data_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Clients); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_vault_activity_generation_generate_data_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Client); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_vault_activity_generation_generate_data_proto_msgTypes[1].OneofWrappers = []interface{}{
(*Data_CurrentMonth)(nil),
(*Data_MonthsAgo)(nil),
(*Data_All)(nil),
(*Data_Segments)(nil),
}
file_vault_activity_generation_generate_data_proto_msgTypes[3].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_vault_activity_generation_generate_data_proto_rawDesc,
NumEnums: 1,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_vault_activity_generation_generate_data_proto_goTypes,
DependencyIndexes: file_vault_activity_generation_generate_data_proto_depIdxs,
EnumInfos: file_vault_activity_generation_generate_data_proto_enumTypes,
MessageInfos: file_vault_activity_generation_generate_data_proto_msgTypes,
}.Build()
File_vault_activity_generation_generate_data_proto = out.File
file_vault_activity_generation_generate_data_proto_rawDesc = nil
file_vault_activity_generation_generate_data_proto_goTypes = nil
file_vault_activity_generation_generate_data_proto_depIdxs = nil
}

View File

@ -0,0 +1,57 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
syntax = "proto3";
option go_package = "github.com/hashicorp/vault/vault/activity/generation";
package generation;
enum WriteOptions {
WRITE_UNKNOWN=0;
WRITE_PRECOMPUTED_QUERIES = 1;
WRITE_DISTINCT_CLIENTS=2;
WRITE_ENTITIES=3;
WRITE_DIRECT_TOKENS=4;
WRITE_INTENT_LOGS=5;
}
message ActivityLogMockInput {
repeated WriteOptions write = 1;
repeated Data data = 2;
}
message Data {
oneof month {
bool current_month = 1;
int32 months_ago = 2;
}
oneof clients {
Clients all = 3; // you cant have repeated fields in a oneof, which is why these are separate message types
Segments segments = 4;
}
repeated int32 empty_segment_indexes = 5;
repeated int32 skip_segment_indexes = 6;
int32 num_segments = 7;
}
message Segments {
repeated Segment segments = 1;
}
message Segment {
optional int32 segment_index = 1;
Clients clients = 2;
}
message Clients {
repeated Client clients = 1;
}
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;
}

View File

@ -72,7 +72,7 @@ func (b *SystemBackend) activityPaths() []*framework.Path {
// rootActivityPaths are available only in the root namespace
func (b *SystemBackend) rootActivityPaths() []*framework.Path {
return []*framework.Path{
paths := []*framework.Path{
b.activityQueryPath(),
b.monthlyActivityCountPath(),
{
@ -135,6 +135,10 @@ func (b *SystemBackend) rootActivityPaths() []*framework.Path {
},
},
}
if writePath := b.activityWritePath(); writePath != nil {
paths = append(paths, writePath)
}
return paths
}
func parseStartEndTimes(a *ActivityLog, d *framework.FieldData) (time.Time, time.Time, error) {

View File

@ -0,0 +1,12 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
//go:build !testonly
package vault
import (
"github.com/hashicorp/vault/sdk/framework"
)
func (b *SystemBackend) activityWritePath() *framework.Path { return nil }

View File

@ -0,0 +1,53 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
//go:build testonly
package vault
import (
"context"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/vault/activity/generation"
"google.golang.org/protobuf/encoding/protojson"
)
const helpText = "Create activity log data for testing purposes"
func (b *SystemBackend) activityWritePath() *framework.Path {
return &framework.Path{
Pattern: "internal/counters/activity/write$",
HelpDescription: helpText,
HelpSynopsis: helpText,
Fields: map[string]*framework.FieldSchema{
"input": {
Type: framework.TypeString,
Description: "JSON input for generating mock data",
},
},
Operations: map[logical.Operation]framework.OperationHandler{
logical.CreateOperation: &framework.PathOperation{
Callback: b.handleActivityWriteData,
Summary: "Write activity log data",
},
},
}
}
func (b *SystemBackend) handleActivityWriteData(ctx context.Context, request *logical.Request, data *framework.FieldData) (*logical.Response, error) {
json := data.Get("input")
input := &generation.ActivityLogMockInput{}
err := protojson.Unmarshal([]byte(json.(string)), input)
if err != nil {
return logical.ErrorResponse("Invalid input data: %s", err), logical.ErrInvalidRequest
}
if len(input.Write) == 0 {
return logical.ErrorResponse("Missing required \"write\" values"), logical.ErrInvalidRequest
}
if len(input.Data) == 0 {
return logical.ErrorResponse("Missing required \"data\" values"), logical.ErrInvalidRequest
}
return nil, nil
}

View File

@ -0,0 +1,84 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
//go:build testonly
package vault
import (
"testing"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require"
)
// TestSystemBackend_handleActivityWriteData calls the activity log write endpoint and confirms that the inputs are
// correctly validated
func TestSystemBackend_handleActivityWriteData(t *testing.T) {
testCases := []struct {
name string
operation logical.Operation
input map[string]interface{}
wantError error
}{
{
name: "read fails",
operation: logical.ReadOperation,
wantError: logical.ErrUnsupportedOperation,
},
{
name: "empty write fails",
operation: logical.CreateOperation,
wantError: logical.ErrInvalidRequest,
},
{
name: "wrong key fails",
operation: logical.CreateOperation,
input: map[string]interface{}{"other": "data"},
wantError: logical.ErrInvalidRequest,
},
{
name: "incorrectly formatted data fails",
operation: logical.CreateOperation,
input: map[string]interface{}{"input": "data"},
wantError: logical.ErrInvalidRequest,
},
{
name: "incorrect json data fails",
operation: logical.CreateOperation,
input: map[string]interface{}{"input": `{"other":"json"}`},
wantError: logical.ErrInvalidRequest,
},
{
name: "empty write value fails",
operation: logical.CreateOperation,
input: map[string]interface{}{"input": `{"write":[],"data":[]}`},
wantError: logical.ErrInvalidRequest,
},
{
name: "empty data value fails",
operation: logical.CreateOperation,
input: map[string]interface{}{"input": `{"write":["WRITE_PRECOMPUTED_QUERIES"],"data":[]}`},
wantError: logical.ErrInvalidRequest,
},
{
name: "correctly formatted data succeeds",
operation: logical.CreateOperation,
input: map[string]interface{}{"input": `{"write":["WRITE_PRECOMPUTED_QUERIES"],"data":[{"current_month":true,"all":{"clients":[{"count":5}]}}]}`},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
b := testSystemBackend(t)
req := logical.TestRequest(t, tc.operation, "internal/counters/activity/write")
req.Data = tc.input
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
if tc.wantError != nil {
require.Equal(t, tc.wantError, err, resp.Error())
} else {
require.NoError(t, err)
}
})
}
}