Events: Add outbound detail protobufs, request status code, and update event encrypt filter. (#1569)
* feat (events): Add status code to audit events * feat (events): Add the resp proto msg to every audit event * chore (events): Update eventlogger dep This latest version will redact any map and/or map field which isn't explicitly classified via a Taggable interface * feat (events): Begin to add tagging to response proto msgs
This commit is contained in:
23 files changed
+914
-129
No files matched your search
@@ -32,31 +32,31 @@ type AuthMethod struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Output only. The ID of the Auth Method.
|
||||
Id string `protobuf:"bytes,10,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Id string `protobuf:"bytes,10,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// The ID of the Scope of which this Auth Method is a part.
|
||||
ScopeId string `protobuf:"bytes,20,opt,name=scope_id,proto3" json:"scope_id,omitempty"`
|
||||
ScopeId string `protobuf:"bytes,20,opt,name=scope_id,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Output only. Scope information for this Auth method.
|
||||
Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty"`
|
||||
Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Optional name for identification purposes.
|
||||
Name *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Name *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=name,proto3" json:"name,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Optional user-set description for identification purposes.
|
||||
Description *wrapperspb.StringValue `protobuf:"bytes,50,opt,name=description,proto3" json:"description,omitempty"`
|
||||
Description *wrapperspb.StringValue `protobuf:"bytes,50,opt,name=description,proto3" json:"description,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Output only. The time this resource was created.
|
||||
CreatedTime *timestamppb.Timestamp `protobuf:"bytes,60,opt,name=created_time,proto3" json:"created_time,omitempty"`
|
||||
CreatedTime *timestamppb.Timestamp `protobuf:"bytes,60,opt,name=created_time,proto3" json:"created_time,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Output only. The time this resource was last updated.
|
||||
UpdatedTime *timestamppb.Timestamp `protobuf:"bytes,70,opt,name=updated_time,proto3" json:"updated_time,omitempty"`
|
||||
UpdatedTime *timestamppb.Timestamp `protobuf:"bytes,70,opt,name=updated_time,proto3" json:"updated_time,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Version is used in mutation requests, after the initial creation, to ensure this resource has not changed.
|
||||
// The mutation will fail if the version does not match the latest known good version.
|
||||
Version uint32 `protobuf:"varint,80,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Version uint32 `protobuf:"varint,80,opt,name=version,proto3" json:"version,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// The Auth Method type.
|
||||
Type string `protobuf:"bytes,90,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Type string `protobuf:"bytes,90,opt,name=type,proto3" json:"type,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// The attributes that are applicable for the specific Auth Method type.
|
||||
Attributes *structpb.Struct `protobuf:"bytes,100,opt,name=attributes,proto3" json:"attributes,omitempty"`
|
||||
// Output only. Whether this auth method is the primary auth method for it's scope.
|
||||
// To change this value update the primary_auth_method_id field on the scope.
|
||||
IsPrimary bool `protobuf:"varint,110,opt,name=is_primary,proto3" json:"is_primary,omitempty"`
|
||||
IsPrimary bool `protobuf:"varint,110,opt,name=is_primary,proto3" json:"is_primary,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Output only. The available actions on this resource for this user.
|
||||
AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"`
|
||||
AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Output only. The authorized actions for the scope's collections.
|
||||
AuthorizedCollectionActions map[string]*structpb.ListValue `protobuf:"bytes,310,rep,name=authorized_collection_actions,proto3" json:"authorized_collection_actions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package authmethods
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/eventlogger/filters/encrypt"
|
||||
)
|
||||
|
||||
// Tags implements the encrypt.Taggable interface which allows
|
||||
// AuthMethod map fields to be classified for the encrypt filter.
|
||||
func (req *AuthMethod) Tags() ([]encrypt.PointerTag, error) {
|
||||
tags := make([]encrypt.PointerTag, 0, len(req.AuthorizedCollectionActions))
|
||||
for k := range req.AuthorizedCollectionActions {
|
||||
tags = append(tags, encrypt.PointerTag{
|
||||
Pointer: fmt.Sprintf("/AuthorizedCollectionActions/%s", k),
|
||||
Classification: encrypt.PublicClassification,
|
||||
})
|
||||
}
|
||||
if req.Attributes != nil {
|
||||
switch req.Type {
|
||||
case "oidc":
|
||||
oidcTags := []encrypt.PointerTag{
|
||||
// public fields
|
||||
{
|
||||
Pointer: "/Attributes/Fields/state",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/issuer",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/client_id",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/client_secret_hmac",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/max_age",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/signing_algorithms",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/api_url_prefix",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/callback_url",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/allowed_audiences",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/claims_scopes",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/account_claim_maps",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/disable_discovered_config_validation",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/dry_run",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
// secrets
|
||||
{
|
||||
Pointer: "/Attributes/Fields/client_secret",
|
||||
Classification: encrypt.SecretClassification,
|
||||
},
|
||||
}
|
||||
tags = append(tags, oidcTags...)
|
||||
case "password":
|
||||
pwTags := []encrypt.PointerTag{
|
||||
{
|
||||
Pointer: "/Attributes/Fields/min_login_name_length",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
{
|
||||
Pointer: "/Attributes/Fields/min_password_length",
|
||||
Classification: encrypt.PublicClassification,
|
||||
},
|
||||
}
|
||||
tags = append(tags, pwTags...)
|
||||
}
|
||||
}
|
||||
return tags, nil
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package authmethods
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/eventlogger/filters/encrypt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
func TestAuthMethod_Tags(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
now := time.Now()
|
||||
wrapper := wrapper.TestWrapper(t)
|
||||
testEncryptingFilter := &encrypt.Filter{
|
||||
Wrapper: wrapper,
|
||||
HmacSalt: []byte("salt"),
|
||||
HmacInfo: []byte("info"),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
testEvent *eventlogger.Event
|
||||
wantEvent *eventlogger.Event
|
||||
}{
|
||||
{
|
||||
name: "validate-oidc-filtering",
|
||||
testEvent: &eventlogger.Event{
|
||||
Type: "test",
|
||||
CreatedAt: now,
|
||||
Payload: &AuthMethod{
|
||||
Id: "id",
|
||||
ScopeId: "scope-id",
|
||||
Name: &wrapperspb.StringValue{Value: "name"},
|
||||
Description: &wrapperspb.StringValue{Value: "description"},
|
||||
Type: "oidc",
|
||||
Attributes: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"state": structpb.NewStringValue("public-state"),
|
||||
"issuer": structpb.NewStringValue("public-issuer"),
|
||||
"client_id": structpb.NewStringValue("public-client_id"),
|
||||
"client_secret_hmac": structpb.NewStringValue("public-client_secret_hmac"),
|
||||
"max_age": structpb.NewStringValue("public-max_age"),
|
||||
"signing_algorithms": structpb.NewStringValue("public-signing_algorithms"),
|
||||
"api_url_prefix": structpb.NewStringValue("public-api_url_prefix"),
|
||||
"callback_url": structpb.NewStringValue("public-callback_url"),
|
||||
"allowed_audiences": structpb.NewStringValue("public-allowed_audiences"),
|
||||
"claims_scopes": structpb.NewStringValue("public-claims_scopes"),
|
||||
"account_claim_maps": structpb.NewStringValue("public-account_claim_maps"),
|
||||
"disable_discovered_config_validation": structpb.NewStringValue("public-disable_discovered_config_validation"),
|
||||
"dry_run": structpb.NewStringValue("public-dry_run"),
|
||||
"client_secret": structpb.NewStringValue("secret-client_secret"),
|
||||
},
|
||||
},
|
||||
AuthorizedActions: []string{"action-1", "action-2"},
|
||||
AuthorizedCollectionActions: map[string]*structpb.ListValue{
|
||||
"auth-methods": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantEvent: &eventlogger.Event{
|
||||
Type: "test",
|
||||
CreatedAt: now,
|
||||
Payload: &AuthMethod{
|
||||
Id: "id",
|
||||
ScopeId: "scope-id",
|
||||
Name: &wrapperspb.StringValue{Value: "name"},
|
||||
Description: &wrapperspb.StringValue{Value: "description"},
|
||||
Type: "oidc",
|
||||
Attributes: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"state": structpb.NewStringValue("public-state"),
|
||||
"issuer": structpb.NewStringValue("public-issuer"),
|
||||
"client_id": structpb.NewStringValue("public-client_id"),
|
||||
"client_secret_hmac": structpb.NewStringValue("public-client_secret_hmac"),
|
||||
"max_age": structpb.NewStringValue("public-max_age"),
|
||||
"signing_algorithms": structpb.NewStringValue("public-signing_algorithms"),
|
||||
"api_url_prefix": structpb.NewStringValue("public-api_url_prefix"),
|
||||
"callback_url": structpb.NewStringValue("public-callback_url"),
|
||||
"allowed_audiences": structpb.NewStringValue("public-allowed_audiences"),
|
||||
"claims_scopes": structpb.NewStringValue("public-claims_scopes"),
|
||||
"account_claim_maps": structpb.NewStringValue("public-account_claim_maps"),
|
||||
"disable_discovered_config_validation": structpb.NewStringValue("public-disable_discovered_config_validation"),
|
||||
"dry_run": structpb.NewStringValue("public-dry_run"),
|
||||
"client_secret": structpb.NewStringValue("<REDACTED>"),
|
||||
},
|
||||
},
|
||||
AuthorizedActions: []string{"action-1", "action-2"},
|
||||
AuthorizedCollectionActions: map[string]*structpb.ListValue{
|
||||
"auth-methods": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "validate-password-filtering",
|
||||
testEvent: &eventlogger.Event{
|
||||
Type: "test",
|
||||
CreatedAt: now,
|
||||
Payload: &AuthMethod{
|
||||
Id: "id",
|
||||
ScopeId: "scope-id",
|
||||
Name: &wrapperspb.StringValue{Value: "name"},
|
||||
Description: &wrapperspb.StringValue{Value: "description"},
|
||||
Type: "oidc",
|
||||
Attributes: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"min_login_name_length": structpb.NewStringValue("public-min_login_name_length"),
|
||||
"min_password_length": structpb.NewStringValue("public-min_password_length"),
|
||||
},
|
||||
},
|
||||
AuthorizedActions: []string{"action-1", "action-2"},
|
||||
AuthorizedCollectionActions: map[string]*structpb.ListValue{
|
||||
"auth-methods": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantEvent: &eventlogger.Event{
|
||||
Type: "test",
|
||||
CreatedAt: now,
|
||||
Payload: &AuthMethod{
|
||||
Id: "id",
|
||||
ScopeId: "scope-id",
|
||||
Name: &wrapperspb.StringValue{Value: "name"},
|
||||
Description: &wrapperspb.StringValue{Value: "description"},
|
||||
Type: "oidc",
|
||||
Attributes: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"min_login_name_length": structpb.NewStringValue("public-min_login_name_length"),
|
||||
"min_password_length": structpb.NewStringValue("public-min_password_length"),
|
||||
},
|
||||
},
|
||||
AuthorizedActions: []string{"action-1", "action-2"},
|
||||
AuthorizedCollectionActions: map[string]*structpb.ListValue{
|
||||
"auth-methods": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
got, err := testEncryptingFilter.Process(ctx, tt.testEvent)
|
||||
require.NoError(err)
|
||||
require.NotNil(got)
|
||||
actualJson, err := json.Marshal(got)
|
||||
require.NoError(err)
|
||||
t.Log(string(actualJson))
|
||||
|
||||
wantJson, err := json.Marshal(tt.wantEvent)
|
||||
require.NoError(err)
|
||||
assert.JSONEq(string(wantJson), string(actualJson))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user