From c7952c247dd370117a9a3cb8adbf28e246175c29 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 11 Mar 2022 12:14:46 +0100 Subject: [PATCH] share updated event Signed-off-by: jkoberg --- audit/pkg/service/service.go | 17 ++++++++ audit/pkg/types/constants.go | 20 +++++++++ audit/pkg/types/conversion.go | 82 ++++++++++++++++++++++++----------- audit/pkg/types/events.go | 1 + audit/pkg/types/types.go | 14 ++++++ go.mod | 4 +- go.sum | 4 +- 7 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 audit/pkg/types/constants.go diff --git a/audit/pkg/service/service.go b/audit/pkg/service/service.go index 4f1f4b1aab..31bb760788 100644 --- a/audit/pkg/service/service.go +++ b/audit/pkg/service/service.go @@ -45,6 +45,8 @@ func StartAuditLogger(ctx context.Context, ch <-chan interface{}, log log.Logger switch ev := i.(type) { case events.ShareCreated: auditEvent = types.ShareCreated(ev) + case events.ShareUpdated: + auditEvent = types.ShareUpdated(ev) default: log.Error().Interface("event", ev).Msg(fmt.Sprintf("can't handle event of type '%T'", ev)) continue @@ -95,5 +97,20 @@ func Marshal(format string, log log.Logger) Marshaller { return nil case "json": return json.Marshal + case "minimal": + return func(ev interface{}) ([]byte, error) { + b, err := json.Marshal(ev) + if err != nil { + return nil, err + } + + m := make(map[string]interface{}) + if err := json.Unmarshal(b, &m); err != nil { + return nil, err + } + + format := fmt.Sprintf("%s)\n %s", m["Action"], m["Message"]) + return []byte(format), nil + } } } diff --git a/audit/pkg/types/constants.go b/audit/pkg/types/constants.go new file mode 100644 index 0000000000..33dd335f1f --- /dev/null +++ b/audit/pkg/types/constants.go @@ -0,0 +1,20 @@ +package types + +import "fmt" + +// short identifiers for audit actions +const ( + ActionShareCreated = "share_created" + ActionSharePermissionUpdated = "share_permission_updated" + ActionShareDisplayNameUpdated = "share_name_updated" +) + +// MessageShareCreated returns the human readable string that describes the action +func MessageShareCreated(sharer, item, grantee string) string { + return fmt.Sprintf("user '%s' shared file '%s' with '%s'", sharer, item, grantee) +} + +// MessageShareUpdated returns the human readable string that describes the action +func MessageShareUpdated(sharer, shareID, fieldUpdated string) string { + return fmt.Sprintf("user '%s' updated field '%s' of share '%s'", sharer, fieldUpdated, shareID) +} diff --git a/audit/pkg/types/conversion.go b/audit/pkg/types/conversion.go index c4ab66f5e4..e939310b77 100644 --- a/audit/pkg/types/conversion.go +++ b/audit/pkg/types/conversion.go @@ -1,20 +1,13 @@ package types import ( - "fmt" "time" "github.com/cs3org/reva/v2/pkg/events" -) -// actions -const ( - actionShareCreated = "file_shared" -) - -// messages -const ( - messageShareCreated = "user '%s' shared file '%s' with '%s'" + group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" + user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" ) // BasicAuditEvent creates an AuditEvent from given values @@ -37,39 +30,30 @@ func BasicAuditEvent(uid string, ctime string, msg string, action string) AuditE } // SharingAuditEvent creates an AuditEventSharing from given values -func SharingAuditEvent(fileid string, uid string, base AuditEvent) AuditEventSharing { +func SharingAuditEvent(shareid string, fileid string, uid string, base AuditEvent) AuditEventSharing { return AuditEventSharing{ AuditEvent: base, FileID: fileid, Owner: uid, + ShareID: shareid, // NOTE: those values are not in the events and can therefore not be filled at the moment - ShareID: "", - Path: "", + Path: "", } } // ShareCreated converts a ShareCreated Event to an AuditEventShareCreated func ShareCreated(ev events.ShareCreated) AuditEventShareCreated { - with := "" - typ := "" - if ev.GranteeUserID != nil && ev.GranteeUserID.OpaqueId != "" { - with = ev.GranteeUserID.OpaqueId - typ = "user" - } else if ev.GranteeGroupID != nil && ev.GranteeGroupID.OpaqueId != "" { - with = ev.GranteeGroupID.OpaqueId - typ = "group" - } uid := ev.Sharer.OpaqueId - t := time.Unix(int64(ev.CTime.Seconds), int64(ev.CTime.Nanos)).Format(time.RFC3339) - base := BasicAuditEvent(uid, t, fmt.Sprintf(messageShareCreated, uid, ev.ItemID.OpaqueId, with), actionShareCreated) + with, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID) + base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageShareCreated(uid, ev.ItemID.OpaqueId, with), ActionShareCreated) return AuditEventShareCreated{ - AuditEventSharing: SharingAuditEvent(ev.ItemID.OpaqueId, uid, base), + AuditEventSharing: SharingAuditEvent("", ev.ItemID.OpaqueId, uid, base), ShareOwner: uid, ShareWith: with, ShareType: typ, - // NOTE: those values are not in the events and can therefore not be filled at the moment + // NOTE: those values are not in the event and can therefore not be filled at the moment ItemType: "", ExpirationDate: "", SharePass: false, @@ -77,3 +61,49 @@ func ShareCreated(ev events.ShareCreated) AuditEventShareCreated { ShareToken: "", } } + +// ShareUpdated converts a ShareUpdated event to an AuditEventShareUpdated +func ShareUpdated(ev events.ShareUpdated) AuditEventShareUpdated { + uid := ev.Sharer.OpaqueId + with, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID) + base := BasicAuditEvent(uid, formatTime(ev.MTime), MessageShareUpdated(uid, ev.ShareID.OpaqueId, ev.Updated), updateType(ev.Updated)) + return AuditEventShareUpdated{ + AuditEventSharing: SharingAuditEvent(ev.ShareID.GetOpaqueId(), ev.ItemID.OpaqueId, uid, base), + ShareOwner: uid, + ShareWith: with, + ShareType: typ, + Permissions: ev.Permissions.Permissions.String(), + + // NOTE: those values are not in the event and can therefore not be filled at the moment + ItemType: "", + ExpirationDate: "", + SharePass: false, + ShareToken: "", + } +} + +func extractGrantee(uid *user.UserId, gid *group.GroupId) (string, string) { + switch { + case uid != nil && uid.OpaqueId != "": + return uid.OpaqueId, "user" + case gid != nil && gid.OpaqueId != "": + return gid.OpaqueId, "group" + } + + return "", "" +} + +func formatTime(t *types.Timestamp) string { + return time.Unix(int64(t.Seconds), int64(t.Nanos)).Format(time.RFC3339) +} + +func updateType(u string) string { + switch { + case u == "permissions": + return ActionSharePermissionUpdated + case u == "displayname": + return ActionShareDisplayNameUpdated + default: + return "" + } +} diff --git a/audit/pkg/types/events.go b/audit/pkg/types/events.go index 7a9825ef0f..6f698e32d3 100644 --- a/audit/pkg/types/events.go +++ b/audit/pkg/types/events.go @@ -8,5 +8,6 @@ import ( func RegisteredEvents() []events.Unmarshaller { return []events.Unmarshaller{ events.ShareCreated{}, + events.ShareUpdated{}, } } diff --git a/audit/pkg/types/types.go b/audit/pkg/types/types.go index cd07e994f0..43c2715f48 100644 --- a/audit/pkg/types/types.go +++ b/audit/pkg/types/types.go @@ -38,3 +38,17 @@ type AuditEventShareCreated struct { ShareOwner string // The UID of the share owner. ShareToken string // For link shares the unique token, else null } + +// AuditEventShareUpdated is the event logged when a share is updated +type AuditEventShareUpdated struct { + AuditEventSharing + + ItemType string // file or folder + ExpirationDate string // The text expiration date in format 'yyyy-mm-dd' + SharePass bool // If the share is password protected. + Permissions string // The permissions string eg: "READ" + ShareType string // group user or link + ShareWith string // The UID or GID of the share recipient. (not available for public link) + ShareOwner string // The UID of the share owner. + ShareToken string // For link shares the unique token, else null +} diff --git a/go.mod b/go.mod index 829dead3e4..123ee84b2a 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/blevesearch/bleve/v2 v2.3.1 github.com/coreos/go-oidc/v3 v3.1.0 github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 - github.com/cs3org/reva/v2 v2.0.0-20220304131900-b8be80d1ba81 + github.com/cs3org/reva/v2 v2.0.0 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 @@ -276,3 +276,5 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 + +replace github.com/cs3org/reva/v2 => github.com/kobergj/reva/v2 v2.0.0-20220310160623-7d38443c6b77 diff --git a/go.sum b/go.sum index ac07e635c5..c2ae4629c2 100644 --- a/go.sum +++ b/go.sum @@ -342,8 +342,6 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.0.0-20220304131900-b8be80d1ba81 h1:g6c1HYGTSpDnf6uNPXYIOySVk0P545zWUPmdPWEcMps= -github.com/cs3org/reva/v2 v2.0.0-20220304131900-b8be80d1ba81/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0= 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= @@ -912,6 +910,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= +github.com/kobergj/reva/v2 v2.0.0-20220310160623-7d38443c6b77 h1:8SY2Q0iV7yw+3gmr2o70OKHHcNZTpmfR07iz11Z/pN0= +github.com/kobergj/reva/v2 v2.0.0-20220310160623-7d38443c6b77/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0= github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=