OSS Port: Activity log breakdowns (#14160)
* Activity log breakdowns * s/path/namespace_path * Remove ent specific tests
This commit is contained in:
parent
72da792112
commit
6898e038ec
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.19.3
|
||||
// protoc v3.17.3
|
||||
// source: vault/activity/activity_log.proto
|
||||
|
||||
package activity
|
||||
|
@ -37,6 +37,8 @@ type EntityRecord struct {
|
|||
// non_entity records whether the given EntityRecord is
|
||||
// for a TWE or an entity-bound token.
|
||||
NonEntity bool `protobuf:"varint,4,opt,name=non_entity,json=nonEntity,proto3" json:"non_entity,omitempty"`
|
||||
// MountAccessor is the path used by client to perform login
|
||||
MountAccessor string `protobuf:"bytes,5,opt,name=mount_accessor,json=mountAccessor,proto3" json:"mount_accessor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *EntityRecord) Reset() {
|
||||
|
@ -99,6 +101,13 @@ func (x *EntityRecord) GetNonEntity() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (x *EntityRecord) GetMountAccessor() string {
|
||||
if x != nil {
|
||||
return x.MountAccessor
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LogFragment struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
@ -306,7 +315,7 @@ var File_vault_activity_activity_log_proto protoreflect.FileDescriptor
|
|||
var file_vault_activity_activity_log_proto_rawDesc = []byte{
|
||||
0x0a, 0x21, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
|
||||
0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x08, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x22, 0x8b, 0x01,
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x08, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x22, 0xb2, 0x01,
|
||||
0x0a, 0x0c, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e,
|
||||
|
@ -315,44 +324,47 @@ var file_vault_activity_activity_log_proto_rawDesc = []byte{
|
|||
0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x6e, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x09, 0x6e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x86, 0x02, 0x0a, 0x0b,
|
||||
0x4c, 0x6f, 0x67, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6f,
|
||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69,
|
||||
0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52,
|
||||
0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x56, 0x0a, 0x11, 0x6e, 0x6f, 0x6e, 0x5f,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x03, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x4c,
|
||||
0x6f, 0x67, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4e, 0x6f, 0x6e, 0x45, 0x6e,
|
||||
0x74, 0x69, 0x74, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||
0x0f, 0x6e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73,
|
||||
0x1a, 0x42, 0x0a, 0x14, 0x4e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x6f, 0x6b,
|
||||
0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0x45, 0x0a, 0x11, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63,
|
||||
0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, 0x6f, 0x67, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x63, 0x74,
|
||||
0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x63, 0x6f,
|
||||
0x72, 0x64, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xb4, 0x01, 0x0a, 0x0a,
|
||||
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x63, 0x74, 0x69,
|
||||
0x76, 0x69, 0x74, 0x79, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2e,
|
||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x49, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x1a, 0x45, 0x0a, 0x17, 0x43,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49,
|
||||
0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||
0x38, 0x01, 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x6f, 0x67, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2b, 0x5a, 0x29, 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, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x09, 0x6e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x6d,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
|
||||
0x6f, 0x72, 0x22, 0x86, 0x02, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e,
|
||||
0x67, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x72,
|
||||
0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x30, 0x0a,
|
||||
0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
|
||||
0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79,
|
||||
0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12,
|
||||
0x56, 0x0a, 0x11, 0x6e, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x6f,
|
||||
0x6b, 0x65, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x63, 0x74,
|
||||
0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x4c, 0x6f, 0x67, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x4e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
|
||||
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x6e, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x69, 0x74,
|
||||
0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x4e, 0x6f, 0x6e, 0x45, 0x6e,
|
||||
0x74, 0x69, 0x74, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x45, 0x0a, 0x11, 0x45,
|
||||
0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, 0x6f, 0x67,
|
||||
0x12, 0x30, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x16, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74,
|
||||
0x69, 0x74, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x22, 0xb4, 0x01, 0x0a, 0x0a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x12, 0x5f, 0x0a, 0x15, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x2c, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x54, 0x6f, 0x6b, 0x65,
|
||||
0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x49, 0x64, 0x1a, 0x45, 0x0a, 0x17, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x6f, 0x67,
|
||||
0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x42, 0x2b, 0x5a, 0x29, 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, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -4,10 +4,9 @@ option go_package = "github.com/hashicorp/vault/vault/activity";
|
|||
|
||||
package activity;
|
||||
|
||||
// EntityRecord is generated the first time an client is active
|
||||
// each month. This can store clients associated with entities
|
||||
// or nonEntity clients, and really is a ClientRecord, not
|
||||
// specifically an EntityRecord
|
||||
// EntityRecord is generated the first time a client is active each month. This
|
||||
// can store clients associated with entities or nonEntity clients, and really
|
||||
// is a ClientRecord, not specifically an EntityRecord.
|
||||
message EntityRecord {
|
||||
string client_id = 1;
|
||||
string namespace_id = 2;
|
||||
|
@ -15,8 +14,11 @@ message EntityRecord {
|
|||
// 4 bytes per record to store nanoseconds.
|
||||
int64 timestamp = 3;
|
||||
// non_entity records whether the given EntityRecord is
|
||||
// for a TWE or an entity-bound token.
|
||||
bool non_entity = 4;
|
||||
// for a TWE or an entity-bound token.
|
||||
bool non_entity = 4;
|
||||
// MountAccessor is the auth mount accessor of the token used to perform the
|
||||
// activity.
|
||||
string mount_accessor = 5;
|
||||
}
|
||||
|
||||
message LogFragment {
|
||||
|
|
|
@ -11,23 +11,50 @@ import (
|
|||
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/helper/timeutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/compressutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
// About 66 bytes per record:
|
||||
//{"namespace_id":"xxxxx","entities":1234,"non_entity_tokens":1234},
|
||||
// = approx 7900 namespaces in 512KiB
|
||||
// So one storage entry is fine (for now).
|
||||
type NamespaceRecord struct {
|
||||
NamespaceID string `json:"namespace_id"`
|
||||
Entities uint64 `json:"entities"`
|
||||
NonEntityTokens uint64 `json:"non_entity_tokens"`
|
||||
NamespaceID string `json:"namespace_id"`
|
||||
Entities uint64 `json:"entities"`
|
||||
NonEntityTokens uint64 `json:"non_entity_tokens"`
|
||||
Mounts []*MountRecord `json:"mounts"`
|
||||
}
|
||||
|
||||
type CountsRecord struct {
|
||||
EntityClients int `json:"entity_clients"`
|
||||
NonEntityClients int `json:"non_entity_clients"`
|
||||
}
|
||||
|
||||
type NewClientRecord struct {
|
||||
Counts *CountsRecord `json:"counts"`
|
||||
Namespaces []*MonthlyNamespaceRecord `json:"namespaces"`
|
||||
}
|
||||
|
||||
type MonthRecord struct {
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Counts *CountsRecord `json:"counts"`
|
||||
Namespaces []*MonthlyNamespaceRecord `json:"namespaces"`
|
||||
NewClients *NewClientRecord `json:"new_clients"`
|
||||
}
|
||||
|
||||
type MonthlyNamespaceRecord struct {
|
||||
NamespaceID string `json:"namespace_id"`
|
||||
Counts *CountsRecord `json:"counts"`
|
||||
Mounts []*MountRecord `json:"mounts"`
|
||||
}
|
||||
|
||||
type MountRecord struct {
|
||||
Path string `json:"path"`
|
||||
Counts *CountsRecord `json:"counts"`
|
||||
}
|
||||
|
||||
type PrecomputedQuery struct {
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
Namespaces []*NamespaceRecord `json:"namespaces"`
|
||||
Months []*MonthRecord `json:"months"`
|
||||
}
|
||||
|
||||
type PrecomputedQueryStore struct {
|
||||
|
@ -50,13 +77,22 @@ func (s *PrecomputedQueryStore) Put(ctx context.Context, p *PrecomputedQuery) er
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.view.Put(ctx, &logical.StorageEntry{
|
||||
Key: path,
|
||||
Value: asJson,
|
||||
|
||||
compressedPq, err := compressutil.Compress(asJson, &compressutil.CompressionConfig{
|
||||
Type: compressutil.CompressionTypeLZ4,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.view.Put(ctx, &logical.StorageEntry{
|
||||
Key: path,
|
||||
Value: compressedPq,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -199,12 +235,21 @@ func (s *PrecomputedQueryStore) Get(ctx context.Context, startTime, endTime time
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
value, notCompressed, err := compressutil.Decompress(entry.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if notCompressed {
|
||||
value = entry.Value
|
||||
}
|
||||
|
||||
p := &PrecomputedQuery{}
|
||||
err = json.Unmarshal(entry.Value, p)
|
||||
err = json.Unmarshal(value, p)
|
||||
if err != nil {
|
||||
s.logger.Warn("failed query lookup at", "path", path)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/hashicorp/vault/helper/constants"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/helper/timeutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/compressutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/hashicorp/vault/vault/activity"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
@ -121,7 +122,7 @@ func TestActivityLog_Creation_WrappingTokens(t *testing.T) {
|
|||
}
|
||||
|
||||
id, isTWE := te.CreateClientID()
|
||||
a.HandleTokenUsage(te, id, isTWE)
|
||||
a.HandleTokenUsage(context.Background(), te, id, isTWE)
|
||||
|
||||
a.fragmentLock.Lock()
|
||||
if a.fragment != nil {
|
||||
|
@ -138,7 +139,7 @@ func TestActivityLog_Creation_WrappingTokens(t *testing.T) {
|
|||
}
|
||||
|
||||
id, isTWE = teNew.CreateClientID()
|
||||
a.HandleTokenUsage(teNew, id, isTWE)
|
||||
a.HandleTokenUsage(context.Background(), teNew, id, isTWE)
|
||||
|
||||
a.fragmentLock.Lock()
|
||||
if a.fragment != nil {
|
||||
|
@ -229,6 +230,15 @@ func readSegmentFromStorage(t *testing.T, c *Core, path string) *logical.Storage
|
|||
t.Fatalf("expected non-nil log segment at %q", path)
|
||||
}
|
||||
|
||||
value, notCompressed, err := compressutil.Decompress(logSegment.Value)
|
||||
// If the data wasn't compressed, fallback to old behavior
|
||||
if !notCompressed {
|
||||
logSegment.Value = value
|
||||
}
|
||||
if err != nil {
|
||||
return logSegment
|
||||
}
|
||||
|
||||
return logSegment
|
||||
}
|
||||
|
||||
|
@ -366,12 +376,12 @@ func TestActivityLog_SaveTokensToStorageDoesNotUpdateTokenCount(t *testing.T) {
|
|||
idNonEntity, isTWE := tokenEntryOne.CreateClientID()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
a.HandleTokenUsage(&tokenEntryOne, idNonEntity, isTWE)
|
||||
a.HandleTokenUsage(ctx, &tokenEntryOne, idNonEntity, isTWE)
|
||||
}
|
||||
|
||||
idEntity, isTWE := entityEntry.CreateClientID()
|
||||
for i := 0; i < 2; i++ {
|
||||
a.HandleTokenUsage(&entityEntry, idEntity, isTWE)
|
||||
a.HandleTokenUsage(ctx, &entityEntry, idEntity, isTWE)
|
||||
}
|
||||
err := a.saveCurrentSegmentToStorage(ctx, false)
|
||||
if err != nil {
|
||||
|
@ -398,12 +408,13 @@ func TestActivityLog_SaveTokensToStorageDoesNotUpdateTokenCount(t *testing.T) {
|
|||
nonEntityTokenFlag := false
|
||||
entityTokenFlag := false
|
||||
for _, client := range out.Clients {
|
||||
if client.NonEntity {
|
||||
if client.NonEntity == true {
|
||||
nonEntityTokenFlag = true
|
||||
if client.ClientID != idNonEntity {
|
||||
t.Fatalf("expected a client ID of %s, but saved instead %s", idNonEntity, client.ClientID)
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if client.NonEntity == false {
|
||||
entityTokenFlag = true
|
||||
if client.ClientID != idEntity {
|
||||
t.Fatalf("expected a client ID of %s, but saved instead %s", idEntity, client.ClientID)
|
||||
|
@ -584,8 +595,8 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
}
|
||||
ts := time.Now().Unix()
|
||||
|
||||
// First 7000 should fit in one segment
|
||||
for i := 0; i < 7000; i++ {
|
||||
// First 4000 should fit in one segment
|
||||
for i := 0; i < 4000; i++ {
|
||||
a.AddEntityToFragment(genID(i), "root", ts)
|
||||
}
|
||||
|
||||
|
@ -609,12 +620,12 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("could not unmarshal protobuf: %v", err)
|
||||
}
|
||||
if len(entityLog0.Clients) != 7000 {
|
||||
t.Fatalf("unexpected entity length. Expected %d, got %d", 7000, len(entityLog0.Clients))
|
||||
if len(entityLog0.Clients) != 4000 {
|
||||
t.Fatalf("unexpected entity length. Expected %d, got %d", 4000, len(entityLog0.Clients))
|
||||
}
|
||||
|
||||
// 7000 more local entities
|
||||
for i := 7000; i < 14000; i++ {
|
||||
// 4000 more local entities
|
||||
for i := 4000; i < 8000; i++ {
|
||||
a.AddEntityToFragment(genID(i), "root", ts)
|
||||
}
|
||||
|
||||
|
@ -629,7 +640,7 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
Clients: make([]*activity.EntityRecord, 0, 100),
|
||||
NonEntityTokens: tokens1,
|
||||
}
|
||||
for i := 7000; i < 7100; i++ {
|
||||
for i := 4000; i < 4100; i++ {
|
||||
fragment1.Clients = append(fragment1.Clients, &activity.EntityRecord{
|
||||
ClientID: genID(i),
|
||||
NamespaceID: "root",
|
||||
|
@ -648,7 +659,7 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
Clients: make([]*activity.EntityRecord, 0, 100),
|
||||
NonEntityTokens: tokens2,
|
||||
}
|
||||
for i := 14000; i < 14100; i++ {
|
||||
for i := 8000; i < 8100; i++ {
|
||||
fragment2.Clients = append(fragment2.Clients, &activity.EntityRecord{
|
||||
ClientID: genID(i),
|
||||
NamespaceID: "root",
|
||||
|
@ -679,8 +690,8 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("could not unmarshal protobuf: %v", err)
|
||||
}
|
||||
if len(entityLog0.Clients) != activitySegmentEntityCapacity {
|
||||
t.Fatalf("unexpected entity length. Expected %d, got %d", activitySegmentEntityCapacity,
|
||||
if len(entityLog0.Clients) != activitySegmentClientCapacity {
|
||||
t.Fatalf("unexpected client length. Expected %d, got %d", activitySegmentClientCapacity,
|
||||
len(entityLog0.Clients))
|
||||
}
|
||||
|
||||
|
@ -690,7 +701,7 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("could not unmarshal protobuf: %v", err)
|
||||
}
|
||||
expectedCount := 14100 - activitySegmentEntityCapacity
|
||||
expectedCount := 8100 - activitySegmentClientCapacity
|
||||
if len(entityLog1.Clients) != expectedCount {
|
||||
t.Fatalf("unexpected entity length. Expected %d, got %d", expectedCount,
|
||||
len(entityLog1.Clients))
|
||||
|
@ -703,7 +714,7 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) {
|
|||
for _, e := range entityLog1.Clients {
|
||||
entityPresent[e.ClientID] = struct{}{}
|
||||
}
|
||||
for i := 0; i < 14100; i++ {
|
||||
for i := 0; i < 8100; i++ {
|
||||
expectedID := genID(i)
|
||||
if _, present := entityPresent[expectedID]; !present {
|
||||
t.Fatalf("entity ID %v = %v not present", i, expectedID)
|
||||
|
@ -1093,7 +1104,7 @@ func (a *ActivityLog) resetEntitiesInMemory(t *testing.T) {
|
|||
clientSequenceNumber: 0,
|
||||
}
|
||||
|
||||
a.clientTracker.activeClients = make(map[string]struct{})
|
||||
a.partialMonthClientTracker = make(map[string]*activity.EntityRecord)
|
||||
}
|
||||
|
||||
func TestActivityLog_loadCurrentClientSegment(t *testing.T) {
|
||||
|
@ -1285,7 +1296,7 @@ func TestActivityLog_loadPriorEntitySegment(t *testing.T) {
|
|||
if tc.refresh {
|
||||
a.l.Lock()
|
||||
a.fragmentLock.Lock()
|
||||
a.clientTracker.activeClients = make(map[string]struct{})
|
||||
a.partialMonthClientTracker = make(map[string]*activity.EntityRecord)
|
||||
a.currentSegment.startTimestamp = tc.time
|
||||
a.fragmentLock.Unlock()
|
||||
a.l.Unlock()
|
||||
|
@ -1459,7 +1470,6 @@ func setupActivityRecordsInStorage(t *testing.T, base time.Time, includeEntities
|
|||
} else {
|
||||
WriteToStorage(t, core, ActivityLogPrefix+"entity/"+fmt.Sprint(base.Unix())+"/"+strconv.Itoa(i-1), entityData)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1805,7 +1815,7 @@ func TestActivityLog_DeleteWorker(t *testing.T) {
|
|||
func checkAPIWarnings(t *testing.T, originalEnabled, newEnabled bool, resp *logical.Response) {
|
||||
t.Helper()
|
||||
|
||||
expectWarning := originalEnabled && !newEnabled
|
||||
expectWarning := originalEnabled == true && newEnabled == false
|
||||
|
||||
switch {
|
||||
case !expectWarning && resp != nil:
|
||||
|
@ -3333,12 +3343,14 @@ func TestActivityLog_partialMonthClientCount(t *testing.T) {
|
|||
|
||||
ctx := namespace.RootContext(nil)
|
||||
now := time.Now().UTC()
|
||||
a, entities, tokenCounts := setupActivityRecordsInStorage(t, timeutil.StartOfMonth(now), true, true)
|
||||
entities = entities[1:]
|
||||
entityCounts := make(map[string]uint64)
|
||||
a, clients, _ := setupActivityRecordsInStorage(t, timeutil.StartOfMonth(now), true, true)
|
||||
|
||||
for _, entity := range entities {
|
||||
entityCounts[entity.NamespaceID] += 1
|
||||
// clients[0] belongs to previous month
|
||||
clients = clients[1:]
|
||||
|
||||
clientCounts := make(map[string]uint64)
|
||||
for _, client := range clients {
|
||||
clientCounts[client.NamespaceID] += 1
|
||||
}
|
||||
|
||||
a.SetEnable(true)
|
||||
|
@ -3349,15 +3361,6 @@ func TestActivityLog_partialMonthClientCount(t *testing.T) {
|
|||
}
|
||||
wg.Wait()
|
||||
|
||||
// entities[0] is from a previous month
|
||||
partialMonthEntityCount := len(entities)
|
||||
var partialMonthTokenCount int
|
||||
for _, countByNS := range tokenCounts {
|
||||
partialMonthTokenCount += int(countByNS)
|
||||
}
|
||||
|
||||
expectedClientCount := partialMonthEntityCount + partialMonthTokenCount
|
||||
|
||||
results, err := a.partialMonthClientCount(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -3371,48 +3374,35 @@ func TestActivityLog_partialMonthClientCount(t *testing.T) {
|
|||
t.Fatalf("malformed results. got %v", results)
|
||||
}
|
||||
|
||||
clientCountResponse := make([]*ClientCountInNamespace, 0)
|
||||
clientCountResponse := make([]*ResponseNamespace, 0)
|
||||
err = mapstructure.Decode(byNamespace, &clientCountResponse)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, clientCount := range clientCountResponse {
|
||||
|
||||
if int(entityCounts[clientCount.NamespaceID]) != clientCount.Counts.DistinctEntities {
|
||||
t.Errorf("bad entity count for namespace %s . expected %d, got %d", clientCount.NamespaceID, int(entityCounts[clientCount.NamespaceID]), clientCount.Counts.DistinctEntities)
|
||||
if int(clientCounts[clientCount.NamespaceID]) != clientCount.Counts.DistinctEntities {
|
||||
t.Errorf("bad entity count for namespace %s . expected %d, got %d", clientCount.NamespaceID, int(clientCounts[clientCount.NamespaceID]), clientCount.Counts.DistinctEntities)
|
||||
}
|
||||
if int(tokenCounts[clientCount.NamespaceID]) != clientCount.Counts.NonEntityTokens {
|
||||
t.Errorf("bad token count for namespace %s . expected %d, got %d", clientCount.NamespaceID, int(tokenCounts[clientCount.NamespaceID]), clientCount.Counts.NonEntityTokens)
|
||||
}
|
||||
|
||||
totalCount := int(entityCounts[clientCount.NamespaceID] + tokenCounts[clientCount.NamespaceID])
|
||||
totalCount := int(clientCounts[clientCount.NamespaceID])
|
||||
if totalCount != clientCount.Counts.Clients {
|
||||
t.Errorf("bad client count for namespace %s . expected %d, got %d", clientCount.NamespaceID, totalCount, clientCount.Counts.Clients)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
entityCount, ok := results["distinct_entities"]
|
||||
distinctEntities, ok := results["distinct_entities"]
|
||||
if !ok {
|
||||
t.Fatalf("malformed results. got %v", results)
|
||||
}
|
||||
if entityCount != partialMonthEntityCount {
|
||||
t.Errorf("bad entity count. expected %d, got %d", partialMonthEntityCount, entityCount)
|
||||
if distinctEntities != len(clients) {
|
||||
t.Errorf("bad entity count. expected %d, got %d", len(clients), distinctEntities)
|
||||
}
|
||||
|
||||
tokenCount, ok := results["non_entity_tokens"]
|
||||
if !ok {
|
||||
t.Fatalf("malformed results. got %v", results)
|
||||
}
|
||||
if tokenCount != partialMonthTokenCount {
|
||||
t.Errorf("bad token count. expected %d, got %d", partialMonthTokenCount, tokenCount)
|
||||
}
|
||||
clientCount, ok := results["clients"]
|
||||
if !ok {
|
||||
t.Fatalf("malformed results. got %v", results)
|
||||
}
|
||||
if clientCount != expectedClientCount {
|
||||
t.Errorf("bad client count. expected %d, got %d", expectedClientCount, clientCount)
|
||||
if clientCount != len(clients) {
|
||||
t.Errorf("bad client count. expected %d, got %d", len(clients), clientCount)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,13 @@ package vault
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/constants"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/hashicorp/vault/vault/activity"
|
||||
)
|
||||
|
@ -13,39 +16,50 @@ import (
|
|||
// InjectActivityLogDataThisMonth populates the in-memory client store
|
||||
// with some entities and tokens, overriding what was already there
|
||||
// It is currently used for API integration tests
|
||||
func (c *Core) InjectActivityLogDataThisMonth(t *testing.T) (map[string]uint64, map[string]uint64) {
|
||||
func (c *Core) InjectActivityLogDataThisMonth(t *testing.T) map[string]*activity.EntityRecord {
|
||||
t.Helper()
|
||||
tokens := make(map[string]uint64, 0)
|
||||
entitiesByNS := make(map[string]uint64, 0)
|
||||
tokens["root"] = 5
|
||||
entitiesByNS["root"] = 5
|
||||
|
||||
if constants.IsEnterprise {
|
||||
tokens["ns0"] = 5
|
||||
tokens["ns1"] = 1
|
||||
tokens["ns2"] = 1
|
||||
entitiesByNS["ns0"] = 1
|
||||
entitiesByNS["ns1"] = 1
|
||||
entitiesByNS["ns2"] = 1
|
||||
}
|
||||
|
||||
c.activityLog.l.Lock()
|
||||
defer c.activityLog.l.Unlock()
|
||||
c.activityLog.fragmentLock.Lock()
|
||||
defer c.activityLog.fragmentLock.Unlock()
|
||||
|
||||
c.activityLog.clientTracker.nonEntityCountByNamespaceID = tokens
|
||||
c.activityLog.clientTracker.entityCountByNamespaceID = entitiesByNS
|
||||
return entitiesByNS, tokens
|
||||
for i := 0; i < 3; i++ {
|
||||
er := &activity.EntityRecord{
|
||||
ClientID: fmt.Sprintf("testclientid-%d", i),
|
||||
NamespaceID: "root",
|
||||
MountAccessor: fmt.Sprintf("testmountaccessor-%d", i),
|
||||
Timestamp: time.Now().Unix(),
|
||||
NonEntity: i%2 == 0,
|
||||
}
|
||||
c.activityLog.partialMonthClientTracker[er.ClientID] = er
|
||||
}
|
||||
|
||||
if constants.IsEnterprise {
|
||||
for j := 0; j < 2; j++ {
|
||||
for i := 0; i < 2; i++ {
|
||||
er := &activity.EntityRecord{
|
||||
ClientID: fmt.Sprintf("ns-%d-testclientid-%d", j, i),
|
||||
NamespaceID: fmt.Sprintf("ns-%d", j),
|
||||
MountAccessor: fmt.Sprintf("ns-%d-testmountaccessor-%d", j, i),
|
||||
Timestamp: time.Now().Unix(),
|
||||
NonEntity: i%2 == 0,
|
||||
}
|
||||
c.activityLog.partialMonthClientTracker[er.ClientID] = er
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c.activityLog.partialMonthClientTracker
|
||||
}
|
||||
|
||||
// Return the in-memory activeClients from an activity log
|
||||
func (c *Core) GetActiveClients() map[string]struct{} {
|
||||
out := make(map[string]struct{})
|
||||
func (c *Core) GetActiveClients() map[string]*activity.EntityRecord {
|
||||
out := make(map[string]*activity.EntityRecord)
|
||||
|
||||
c.stateLock.RLock()
|
||||
c.activityLog.fragmentLock.RLock()
|
||||
for k, v := range c.activityLog.clientTracker.activeClients {
|
||||
for k, v := range c.activityLog.partialMonthClientTracker {
|
||||
out[k] = v
|
||||
}
|
||||
c.activityLog.fragmentLock.RUnlock()
|
||||
|
@ -136,7 +150,7 @@ func (a *ActivityLog) ExpectCurrentSegmentRefreshed(t *testing.T, expectedStart
|
|||
if a.currentSegment.tokenCount.CountByNamespaceID == nil {
|
||||
t.Errorf("expected non-nil currentSegment.tokenCount.CountByNamespaceID")
|
||||
}
|
||||
if a.clientTracker.activeClients == nil {
|
||||
if a.partialMonthClientTracker == nil {
|
||||
t.Errorf("expected non-nil activeClients")
|
||||
}
|
||||
if len(a.currentSegment.currentClients.Clients) > 0 {
|
||||
|
@ -145,8 +159,8 @@ func (a *ActivityLog) ExpectCurrentSegmentRefreshed(t *testing.T, expectedStart
|
|||
if len(a.currentSegment.tokenCount.CountByNamespaceID) > 0 {
|
||||
t.Errorf("expected no token counts to be loaded. got: %v", a.currentSegment.tokenCount.CountByNamespaceID)
|
||||
}
|
||||
if len(a.clientTracker.activeClients) > 0 {
|
||||
t.Errorf("expected no active entity segment to be loaded. got: %v", a.clientTracker.activeClients)
|
||||
if len(a.partialMonthClientTracker) > 0 {
|
||||
t.Errorf("expected no active entity segment to be loaded. got: %v", a.partialMonthClientTracker)
|
||||
}
|
||||
|
||||
if verifyTimeNotZero {
|
||||
|
@ -159,7 +173,7 @@ func (a *ActivityLog) ExpectCurrentSegmentRefreshed(t *testing.T, expectedStart
|
|||
}
|
||||
|
||||
// ActiveEntitiesEqual checks that only the set of `test` exists in `active`
|
||||
func ActiveEntitiesEqual(active map[string]struct{}, test []*activity.EntityRecord) bool {
|
||||
func ActiveEntitiesEqual(active map[string]*activity.EntityRecord, test []*activity.EntityRecord) bool {
|
||||
if len(active) != len(test) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
package activity
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/builtin/credential/userpass"
|
||||
"github.com/hashicorp/vault/helper/timeutil"
|
||||
vaulthttp "github.com/hashicorp/vault/http"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/hashicorp/vault/vault"
|
||||
)
|
||||
|
||||
func validateClientCounts(t *testing.T, resp *api.Secret, expectedEntities, expectedTokens int) {
|
||||
if resp == nil {
|
||||
t.Fatal("nil response")
|
||||
}
|
||||
if resp.Data == nil {
|
||||
t.Fatal("no data")
|
||||
}
|
||||
|
||||
expectedClients := expectedEntities + expectedTokens
|
||||
|
||||
entityCountJSON, ok := resp.Data["distinct_entities"]
|
||||
if !ok {
|
||||
t.Fatalf("no entity count: %v", resp.Data)
|
||||
}
|
||||
entityCount, err := entityCountJSON.(json.Number).Int64()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if entityCount != int64(expectedEntities) {
|
||||
t.Errorf("bad entity count. expected %v, got %v", expectedEntities, entityCount)
|
||||
}
|
||||
|
||||
tokenCountJSON, ok := resp.Data["non_entity_tokens"]
|
||||
if !ok {
|
||||
t.Fatalf("no token count: %v", resp.Data)
|
||||
}
|
||||
tokenCount, err := tokenCountJSON.(json.Number).Int64()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tokenCount != int64(expectedTokens) {
|
||||
t.Errorf("bad token count. expected %v, got %v", expectedTokens, tokenCount)
|
||||
}
|
||||
|
||||
clientCountJSON, ok := resp.Data["clients"]
|
||||
if !ok {
|
||||
t.Fatalf("no client count: %v", resp.Data)
|
||||
}
|
||||
clientCount, err := clientCountJSON.(json.Number).Int64()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if clientCount != int64(expectedClients) {
|
||||
t.Errorf("bad client count. expected %v, got %v", expectedClients, clientCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActivityLog_MonthlyActivityApi(t *testing.T) {
|
||||
timeutil.SkipAtEndOfMonth(t)
|
||||
|
||||
coreConfig := &vault.CoreConfig{
|
||||
CredentialBackends: map[string]logical.Factory{
|
||||
"userpass": userpass.Factory,
|
||||
},
|
||||
ActivityLogConfig: vault.ActivityLogCoreConfig{
|
||||
ForceEnable: true,
|
||||
},
|
||||
}
|
||||
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
|
||||
HandlerFunc: vaulthttp.Handler,
|
||||
})
|
||||
cluster.Start()
|
||||
defer cluster.Cleanup()
|
||||
|
||||
client := cluster.Cores[0].Client
|
||||
core := cluster.Cores[0].Core
|
||||
|
||||
resp, err := client.Logical().Read("sys/internal/counters/activity/monthly")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validateClientCounts(t, resp, 0, 0)
|
||||
|
||||
// inject some data and query the API
|
||||
entities, tokens := core.InjectActivityLogDataThisMonth(t)
|
||||
var expectedEntities int
|
||||
for _, entityCount := range entities {
|
||||
expectedEntities += int(entityCount)
|
||||
}
|
||||
var expectedTokens int
|
||||
for _, tokenCount := range tokens {
|
||||
expectedTokens += int(tokenCount)
|
||||
}
|
||||
|
||||
resp, err = client.Logical().Read("sys/internal/counters/activity/monthly")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validateClientCounts(t, resp, expectedEntities, expectedTokens)
|
||||
|
||||
// we expect a 204 if activity log is disabled
|
||||
core.GetActivityLog().SetEnable(false)
|
||||
req := client.NewRequest("GET", "/v1/sys/internal/counters/activity/monthly")
|
||||
rawResp, err := client.RawRequest(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if rawResp == nil {
|
||||
t.Error("nil response")
|
||||
}
|
||||
if rawResp.StatusCode != http.StatusNoContent {
|
||||
t.Errorf("expected status code %v, got %v", http.StatusNoContent, rawResp.StatusCode)
|
||||
}
|
||||
}
|
|
@ -225,6 +225,11 @@ func (b *SystemBackend) handleActivityConfigUpdate(ctx context.Context, req *log
|
|||
if config.RetentionMonths < 0 {
|
||||
return logical.ErrorResponse("retention_months must be greater than or equal to 0"), logical.ErrInvalidRequest
|
||||
}
|
||||
|
||||
if config.RetentionMonths > 36 {
|
||||
config.RetentionMonths = 36
|
||||
warnings = append(warnings, "retention_months cannot be greater than 36; capped to 36.")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -408,7 +408,7 @@ func (c *Core) checkToken(ctx context.Context, req *logical.Request, unauth bool
|
|||
|
||||
// If it is an authenticated ( i.e with vault token ) request, increment client count
|
||||
if !unauth && c.activityLog != nil {
|
||||
c.activityLog.HandleTokenUsage(te, clientID, isTWE)
|
||||
c.activityLog.HandleTokenUsage(ctx, te, clientID, isTWE)
|
||||
}
|
||||
return auth, te, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue