Skip to content

Commit

Permalink
implement user and group audit events
Browse files Browse the repository at this point in the history
  • Loading branch information
David Christofas committed Apr 6, 2022
1 parent 8b06a9a commit 371d942
Show file tree
Hide file tree
Showing 19 changed files with 327 additions and 14 deletions.
14 changes: 14 additions & 0 deletions audit/pkg/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ func StartAuditLogger(ctx context.Context, ch <-chan interface{}, log log.Logger
auditEvent = types.SpaceEnabled(ev)
case events.SpaceDeleted:
auditEvent = types.SpaceDeleted(ev)
case events.UserCreated:
auditEvent = types.UserCreated(ev)
case events.UserDeleted:
auditEvent = types.UserDeleted(ev)
case events.UserFeatureChanged:
auditEvent = types.UserFeatureChanged(ev)
case events.GroupCreated:
auditEvent = types.GroupCreated(ev)
case events.GroupDeleted:
auditEvent = types.GroupDeleted(ev)
case events.GroupMemberAdded:
auditEvent = types.GroupMemberAdded(ev)
case events.GroupMemberRemoved:
auditEvent = types.GroupMemberRemoved(ev)
default:
log.Error().Interface("event", ev).Msg(fmt.Sprintf("can't handle event of type '%T'", ev))
continue
Expand Down
46 changes: 46 additions & 0 deletions audit/pkg/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ const (
ActionSpaceDisabled = "space_disabled"
ActionSpaceEnabled = "space_enabled"
ActionSpaceDeleted = "space_deleted"

// Users
ActionUserCreated = "user_created"
ActionUserDeleted = "user_deleted"
ActionUserFeatureChanged = "user_feature_changed"

// Groups
ActionGroupCreated = "group_created"
ActionGroupDeleted = "group_deleted"
ActionGroupMemberAdded = "group_member_added"
ActionGroupMemberRemoved = "group_member_removed"
)

// MessageShareCreated returns the human readable string that describes the action
Expand Down Expand Up @@ -136,3 +147,38 @@ func MessageSpaceEnabled(spaceID string) string {
func MessageSpaceDeleted(spaceID string) string {
return fmt.Sprintf("Space '%s' was deleted", spaceID)
}

// MessageUserCreated returns the human readable string that describes the action
func MessageUserCreated(userID string) string {
return fmt.Sprintf("User '%s' was created", userID)
}

// MessageUserDeleted returns the human readable string that describes the action
func MessageUserDeleted(userID string) string {
return fmt.Sprintf("User '%s' was deleted", userID)
}

// MessageUserFeatureChanged returns the human readable string that describes the action
func MessageUserFeatureChanged(userID, feature, value string) string {
return fmt.Sprintf("User '%s's' feature '%s' was changed to '%s'", userID, feature, value)
}

// MessageGroupCreated returns the human readable string that describes the action
func MessageGroupCreated(groupID string) string {
return fmt.Sprintf("Group '%s' was created", groupID)
}

// MessageGroupDeleted returns the human readable string that describes the action
func MessageGroupDeleted(groupID string) string {
return fmt.Sprintf("Group '%s' was deleted", groupID)
}

// MessageGroupMemberAdded returns the human readable string that describes the action
func MessageGroupMemberAdded(userID, groupID string) string {
return fmt.Sprintf("User '%s' was added to group '%s'", userID, groupID)
}

// MessageGroupMemberRemoved returns the human readable string that describes the action
func MessageGroupMemberRemoved(userID, groupID string) string {
return fmt.Sprintf("User '%s' was removed from group '%s'", userID, groupID)
}
70 changes: 70 additions & 0 deletions audit/pkg/types/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,76 @@ func SpaceDeleted(ev events.SpaceDeleted) AuditEventSpaceDeleted {
}
}

// UserCreated converts a UserCreated event to an AuditEventUserCreated
func UserCreated(ev events.UserCreated) AuditEventUserCreated {
base := BasicAuditEvent("", "", MessageUserCreated(ev.UserID), ActionUserCreated)
return AuditEventUserCreated{
AuditEvent: base,
UserID: ev.UserID,
}
}

// UserDeleted converts a UserCreated event to an AuditEventUserDeleted
func UserDeleted(ev events.UserDeleted) AuditEventUserDeleted {
base := BasicAuditEvent("", "", MessageUserDeleted(ev.UserID), ActionUserDeleted)
return AuditEventUserDeleted{
AuditEvent: base,
UserID: ev.UserID,
}
}

// UserFeatureChanged converts a UserFeatureChanged event to an AuditEventUserFeatureChanged
func UserFeatureChanged(ev events.UserFeatureChanged) AuditEventUserFeatureChanged {
msg := MessageUserFeatureChanged(ev.UserID, ev.Feature, ev.Value)
base := BasicAuditEvent("", "", msg, ActionUserFeatureChanged)
return AuditEventUserFeatureChanged{
AuditEvent: base,
UserID: ev.UserID,
Feature: ev.Feature,
Value: ev.Value,
}
}

// GroupCreated converts a GroupCreated event to an AuditEventGroupCreated
func GroupCreated(ev events.GroupCreated) AuditEventGroupCreated {
base := BasicAuditEvent("", "", MessageGroupCreated(ev.GroupID), ActionGroupCreated)
return AuditEventGroupCreated{
AuditEvent: base,
GroupID: ev.GroupID,
}
}

// GroupDeleted converts a GroupDeleted event to an AuditEventGroupDeleted
func GroupDeleted(ev events.GroupDeleted) AuditEventGroupDeleted {
base := BasicAuditEvent("", "", MessageGroupDeleted(ev.GroupID), ActionGroupDeleted)
return AuditEventGroupDeleted{
AuditEvent: base,
GroupID: ev.GroupID,
}
}

// GroupMemberAdded converts a GroupMemberAdded event to an AuditEventGroupMemberAdded
func GroupMemberAdded(ev events.GroupMemberAdded) AuditEventGroupMemberAdded {
msg := MessageGroupMemberAdded(ev.GroupID, ev.UserID)
base := BasicAuditEvent("", "", msg, ActionGroupMemberAdded)
return AuditEventGroupMemberAdded{
AuditEvent: base,
GroupID: ev.GroupID,
UserID: ev.UserID,
}
}

// GroupMemberRemoved converts a GroupMemberRemoved event to an AuditEventGroupMemberRemove
func GroupMemberRemoved(ev events.GroupMemberRemoved) AuditEventGroupMemberRemoved {
msg := MessageGroupMemberRemoved(ev.GroupID, ev.UserID)
base := BasicAuditEvent("", "", msg, ActionGroupMemberRemoved)
return AuditEventGroupMemberRemoved{
AuditEvent: base,
GroupID: ev.GroupID,
UserID: ev.UserID,
}
}

func extractGrantee(uid *user.UserId, gid *group.GroupId) (string, string) {
switch {
case uid != nil && uid.OpaqueId != "":
Expand Down
7 changes: 7 additions & 0 deletions audit/pkg/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,12 @@ func RegisteredEvents() []events.Unmarshaller {
events.SpaceEnabled{},
events.SpaceDisabled{},
events.SpaceDeleted{},
events.UserCreated{},
events.UserDeleted{},
events.UserFeatureChanged{},
events.GroupCreated{},
events.GroupDeleted{},
events.GroupMemberAdded{},
events.GroupMemberRemoved{},
}
}
46 changes: 46 additions & 0 deletions audit/pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,49 @@ type AuditEventSpaceEnabled struct {
type AuditEventSpaceDeleted struct {
AuditEventSpaces
}

// AuditEventUserCreated is the event logged when a user is created
type AuditEventUserCreated struct {
AuditEvent
UserID string
}

// AuditEventUserDeleted is the event logged when a user is deleted
type AuditEventUserDeleted struct {
AuditEvent
UserID string
}

// AuditEventUserFeatureChanged is the event logged when a user feature is changed
type AuditEventUserFeatureChanged struct {
AuditEvent
UserID string
Feature string
Value string
}

// AuditEventGroupCreated is the event logged when a group is created
type AuditEventGroupCreated struct {
AuditEvent
GroupID string
}

// AuditEventGroupDeleted is the event logged when a group is deleted
type AuditEventGroupDeleted struct {
AuditEvent
GroupID string
}

// AuditEventGroupMemberAdded is the event logged when a group member is added
type AuditEventGroupMemberAdded struct {
AuditEvent
GroupID string
UserID string
}

// AuditEventGroupMemberRemoved is the event logged when a group member is removed
type AuditEventGroupMemberRemoved struct {
AuditEvent
GroupID string
UserID string
}
12 changes: 12 additions & 0 deletions changelog/unreleased/user-group-audit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Enhancement: Implement audit events for user and groups

Added audit events for users and groups. This will log:
* User creation
* User deletion
* User property change (currently only email)
* Group creation
* Group deletion
* Group member add
* Group member remove

https://github.com/owncloud/ocis/pull/3467
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ require (
github.com/blevesearch/bleve/v2 v2.3.2
github.com/coreos/go-oidc/v3 v3.1.0
github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f
github.com/cs3org/reva/v2 v2.0.0-20220404075659-19fd0b28297b
github.com/cs3org/reva/v2 v2.0.0-20220406120423-c7a9ff164c46
github.com/disintegration/imaging v1.6.2
github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733
github.com/go-chi/chi/v5 v5.0.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,8 @@ github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD9
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f h1:emnlOWc1s2gx77MViLnZH9yh5TRHKsykRu6rJjx3lkM=
github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/reva/v2 v2.0.0-20220404075659-19fd0b28297b h1:CqHYID4t286wle5kXcFfUtxxw6Vz0XlbGCiB/Z8rDbI=
github.com/cs3org/reva/v2 v2.0.0-20220404075659-19fd0b28297b/go.mod h1:1siLO6MV57uSyzQxPbfM6qNA9NP6aagN3/yKOE/FwtM=
github.com/cs3org/reva/v2 v2.0.0-20220406120423-c7a9ff164c46 h1:OB0Y1r4T8OvcLT1apVvuc4Ne8t6HD2nGFzgpfGTAVcg=
github.com/cs3org/reva/v2 v2.0.0-20220406120423-c7a9ff164c46/go.mod h1:1siLO6MV57uSyzQxPbfM6qNA9NP6aagN3/yKOE/FwtM=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
Expand Down
2 changes: 2 additions & 0 deletions graph/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ include ../.make/generate.mk
ci-go-generate: $(MOCKERY) # CI runs ci-node-generate automatically before this target
$(MOCKERY) --dir pkg/service/v0 --case underscore --name GatewayClient
$(MOCKERY) --dir pkg/service/v0 --case underscore --name HTTPClient
$(MOCKERY) --dir pkg/service/v0 --case underscore --name Publisher


.PHONY: ci-node-generate
ci-node-generate:
34 changes: 34 additions & 0 deletions graph/mocks/publisher.go

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

7 changes: 7 additions & 0 deletions graph/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Config struct {

Spaces Spaces `yaml:"spaces"`
Identity Identity `yaml:"identity"`
Events Events `yaml:"events"`

Context context.Context `yaml:"-"`
}
Expand Down Expand Up @@ -62,3 +63,9 @@ type Identity struct {
Backend string `yaml:"backend" env:"GRAPH_IDENTITY_BACKEND"`
LDAP LDAP `yaml:"ldap"`
}

// Events combines the configuration options for the event bus.
type Events struct {
Endpoint string `yaml:"events_endpoint" env:"GRAPH_EVENTS_ENDPOINT" desc:"the address of the streaming service"`
Cluster string `yaml:"events_cluster" env:"GRAPH_EVENTS_CLUSTER" desc:"the clusterID of the streaming service. Mandatory when using nats"`
}
4 changes: 4 additions & 0 deletions graph/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func DefaultConfig() *config.Config {
GroupIDAttribute: "owncloudUUID",
},
},
Events: config.Events{
Endpoint: "127.0.0.1:9233",
Cluster: "ocis-cluster",
},
}
}

Expand Down
15 changes: 15 additions & 0 deletions graph/pkg/server/http/server.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package http

import (
"github.com/asim/go-micro/plugins/events/natsjs/v4"
"github.com/cs3org/reva/v2/pkg/events/server"
chimiddleware "github.com/go-chi/chi/v5/middleware"
graphMiddleware "github.com/owncloud/ocis/graph/pkg/middleware"
svc "github.com/owncloud/ocis/graph/pkg/service/v0"
"github.com/owncloud/ocis/ocis-pkg/account"
"github.com/owncloud/ocis/ocis-pkg/middleware"
"github.com/owncloud/ocis/ocis-pkg/service/http"
"github.com/owncloud/ocis/ocis-pkg/version"
"github.com/pkg/errors"
"go-micro.dev/v4"
)

Expand All @@ -25,6 +28,17 @@ func Server(opts ...Option) (http.Service, error) {
http.Flags(options.Flags...),
)

publisher, err := server.NewNatsStream(
natsjs.Address(options.Config.Events.Endpoint),
natsjs.ClusterID(options.Config.Events.Cluster),
)
if err != nil {
options.Logger.Error().
Err(err).
Msg("Error initializing events publisher")
return http.Service{}, errors.Wrap(err, "could not initialize events publisher")
}

handle := svc.NewService(
svc.Logger(options.Logger),
svc.Config(options.Config),
Expand All @@ -42,6 +56,7 @@ func Server(opts ...Option) (http.Service, error) {
account.JWTSecret(options.Config.TokenManager.JWTSecret),
),
),
svc.EventsPublisher(publisher),
)

{
Expand Down
Loading

0 comments on commit 371d942

Please sign in to comment.