mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Make activities typed and auto-generate docs for each type (#9069)
* Make activities type and auto-generate docs for each type * Add pageOrderInSection to not break site * Add do not edit note to generated file * Add make generate-doc step * Fix main merge
This commit is contained in:
parent
54e8b3e250
commit
39f1029390
38 changed files with 1412 additions and 199 deletions
5
Makefile
5
Makefile
|
|
@ -176,6 +176,9 @@ generate-mock: .prefix
|
|||
go install github.com/groob/mockimpl@latest
|
||||
go generate github.com/fleetdm/fleet/v4/server/mock github.com/fleetdm/fleet/v4/server/mock/mockresult
|
||||
|
||||
generate-doc: .prefix
|
||||
go generate github.com/fleetdm/fleet/v4/server/fleet
|
||||
|
||||
deps: deps-js deps-go
|
||||
|
||||
deps-js:
|
||||
|
|
@ -400,4 +403,4 @@ db-replica-reset: fleet
|
|||
|
||||
# db-replica-run runs fleet serve with one main and one read MySQL instance.
|
||||
db-replica-run: fleet
|
||||
FLEET_MYSQL_ADDRESS=127.0.0.1:3308 FLEET_MYSQL_READ_REPLICA_ADDRESS=127.0.0.1:3309 FLEET_MYSQL_READ_REPLICA_USERNAME=fleet FLEET_MYSQL_READ_REPLICA_DATABASE=fleet FLEET_MYSQL_READ_REPLICA_PASSWORD=insecure ./build/fleet serve --dev --dev_license
|
||||
FLEET_MYSQL_ADDRESS=127.0.0.1:3308 FLEET_MYSQL_READ_REPLICA_ADDRESS=127.0.0.1:3309 FLEET_MYSQL_READ_REPLICA_USERNAME=fleet FLEET_MYSQL_READ_REPLICA_DATABASE=fleet FLEET_MYSQL_READ_REPLICA_PASSWORD=insecure ./build/fleet serve --dev --dev_license
|
||||
|
|
@ -145,7 +145,7 @@ func TestApplyTeamSpecs(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +241,7 @@ func TestApplyAppConfig(t *testing.T) {
|
|||
return userRoleSpecList, nil
|
||||
}
|
||||
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ func TestApplyAppConfigDryRunIssue(t *testing.T) {
|
|||
return userRoleSpecList[1], nil
|
||||
}
|
||||
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +507,7 @@ func TestApplyPolicies(t *testing.T) {
|
|||
}
|
||||
return nil, errors.New("unexpected team name!")
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -609,7 +609,7 @@ func TestApplyPacks(t *testing.T) {
|
|||
ds.ListPacksFunc = func(ctx context.Context, opt fleet.PackListOptions) ([]*fleet.Pack, error) {
|
||||
return nil, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -672,7 +672,7 @@ func TestApplyQueries(t *testing.T) {
|
|||
appliedQueries = queries
|
||||
return nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -809,7 +809,7 @@ func TestApplySpecs(t *testing.T) {
|
|||
}
|
||||
|
||||
// activities
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func TestDeletePack(t *testing.T) {
|
|||
Disabled: false,
|
||||
}, true, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ func TestDeleteQuery(t *testing.T) {
|
|||
ObserverCanRun: false,
|
||||
}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func TestLiveQuery(t *testing.T) {
|
|||
ds.CountHostsInTargetsFunc = func(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets, now time.Time) (fleet.TargetMetrics, error) {
|
||||
return fleet.TargetMetrics{TotalHosts: 1, OnlineHosts: 1}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ func TestUserDelete(t *testing.T) {
|
|||
deletedUser = id
|
||||
return nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
assert.Equal(t, fleet.ActivityTypeDeletedUser, activityType)
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
assert.Equal(t, fleet.ActivityTypeDeletedUser{}.ActivityName(), activity.ActivityName())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ func TestUserCreateForcePasswordReset(t *testing.T) {
|
|||
ds.InviteByEmailFunc = func(ctx context.Context, email string) (*fleet.Invite, error) {
|
||||
return nil, ¬FoundError{}
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ func TestCreateBulkUsers(t *testing.T) {
|
|||
ds.InviteByEmailFunc = func(ctx context.Context, email string) (*fleet.Invite, error) {
|
||||
return nil, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -142,12 +142,11 @@ func TestCreateBulkUsers(t *testing.T) {
|
|||
|
||||
assert.Equal(t, "", runAppForTest(t, []string{"user", "create-users", "--csv", csvFile}))
|
||||
assert.Equal(t, expectedText, runAppForTest(t, []string{"get", "user_roles", "--json"}))
|
||||
|
||||
}
|
||||
|
||||
func TestDeleteBulkUsers(t *testing.T) {
|
||||
_, ds := runServerWithMockedDS(t)
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
csvFilePath := writeTmpCsv(t,
|
||||
|
|
|
|||
512
docs/Using-Fleet/Audit-Activities.md
Normal file
512
docs/Using-Fleet/Audit-Activities.md
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
<!-- DO NOT EDIT. This document is automatically generated. -->
|
||||
# Audit Activities
|
||||
|
||||
Fleet logs the following information for administrative actions (in JSON):
|
||||
|
||||
- `created_at`: Timestamp of the event.
|
||||
- `id`: Unique ID of the generated event in Fleet.
|
||||
- `actor_full_name`: Author user name (missing if the user was deleted).
|
||||
- `actor_id`: Unique ID of the author in Fleet (missing if the user was deleted).
|
||||
- `actor_gravatar`: Gravatar URL of the author (missing if the user was deleted).
|
||||
- `actor_email`: E-mail of the author (missing if the user was deleted).
|
||||
- `type`: Type of the activity (see all types below).
|
||||
- `details`: Specific details depending on the type of activity (see details for each activity type below).
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"created_at": "2022-12-20T14:54:17Z",
|
||||
"id": 6,
|
||||
"actor_full_name": "Gandalf",
|
||||
"actor_id": 2,
|
||||
"actor_gravatar": "foo@example.com",
|
||||
"actor_email": "foo@example.com",
|
||||
"type": "edited_saved_query",
|
||||
"details":{
|
||||
"query_id": 42,
|
||||
"query_name": "Some query name"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## List of activities and their specific details
|
||||
|
||||
### Type `created_pack`
|
||||
|
||||
Generated when creating scheduled query packs.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "pack_id": the id of the created pack.
|
||||
- "pack_name": the name of the created pack.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"pack_id": 123,
|
||||
"pack_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `edited_pack`
|
||||
|
||||
Generated when editing scheduled query packs.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "pack_id": the id of the edited pack.
|
||||
- "pack_name": the name of the edited pack.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"pack_id": 123,
|
||||
"pack_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_pack`
|
||||
|
||||
Generated when deleting scheduled query packs.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "pack_name": the name of the created pack.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"pack_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `applied_spec_pack`
|
||||
|
||||
Generated when applying a scheduled query pack spec.
|
||||
|
||||
This activity does not contain any detail fields.
|
||||
|
||||
### Type `created_policy`
|
||||
|
||||
Generated when creating policies.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "policy_id": the ID of the created policy.
|
||||
- "policy_name": the name of the created policy.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"policy_id": 123,
|
||||
"policy_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `edited_policy`
|
||||
|
||||
Generated when editing policies.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "policy_id": the ID of the edited policy.
|
||||
- "policy_name": the name of the edited policy.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"policy_id": 123,
|
||||
"policy_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_policy`
|
||||
|
||||
Generated when deleting policies.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "policy_id": the ID of the deleted policy.
|
||||
- "policy_name": the name of the deleted policy.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"policy_id": 123,
|
||||
"policy_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `applied_spec_policy`
|
||||
|
||||
Generated when applying policy specs.
|
||||
|
||||
This activity contains a field "policies" where each item is a policy spec with the following fields:
|
||||
- "name": Name of the applied policy.
|
||||
- "query": SQL query of the policy.
|
||||
- "description": Description of the policy.
|
||||
- "critical": Marks the policy as high impact.
|
||||
- "resolution": Describes how to solve a failing policy.
|
||||
- "team": Name of the team this policy belongs to.
|
||||
- "platform": Comma-separated string to indicate the target platforms.
|
||||
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"policies": [
|
||||
{
|
||||
"name":"Gatekeeper enabled (macOS)",
|
||||
"query":"SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;",
|
||||
"critical":false,
|
||||
"platform":"darwin",
|
||||
"resolution":"To enable Gatekeeper, on the failing device [...]",
|
||||
"description":"Checks to make sure that the Gatekeeper feature is [...]"
|
||||
},
|
||||
{
|
||||
"name":"Full disk encryption enabled (Windows)",
|
||||
"query":"SELECT 1 FROM bitlocker_info WHERE drive_letter='C:' AND protection_status=1;",
|
||||
"critical":false,
|
||||
"platform":"windows",
|
||||
"resolution":"To get additional information, run the following osquery [...]",
|
||||
"description":"Checks to make sure that full disk encryption is enabled on Windows devices."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Type `created_saved_query`
|
||||
|
||||
Generated when creating a new query.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "query_id": the ID of the created query.
|
||||
- "query_name": the name of the created query.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"query_id": 123,
|
||||
"query_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `edited_saved_query`
|
||||
|
||||
Generated when editing a saved query.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "query_id": the ID of the query being edited.
|
||||
- "query_name": the name of the query being edited.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"query_id": 123,
|
||||
"query_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_saved_query`
|
||||
|
||||
Generated when deleting a saved query.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "query_name": the name of the query being deleted.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"query_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_multiple_saved_query`
|
||||
|
||||
Generated when deleting multiple saved queries.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "query_ids": list of IDs of the deleted saved queries.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"query_ids": [1, 42, 100]
|
||||
}
|
||||
```
|
||||
|
||||
### Type `applied_spec_saved_query`
|
||||
|
||||
Generated when applying a query spec.
|
||||
|
||||
This activity contains a field "specs" where each item is a query spec with the following fields:
|
||||
- "name": Name of the query.
|
||||
- "description": Description of the query.
|
||||
- "query": SQL query.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"specs": [
|
||||
{
|
||||
"name":"Get OpenSSL versions",
|
||||
"query":"SELECT name AS name, version AS version, 'deb_packages' AS source FROM [...]",
|
||||
"description":"Retrieves the OpenSSL version."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Type `created_team`
|
||||
|
||||
Generated when creating teams.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "team_id": unique ID of the created team.
|
||||
- "team_name": the name of the created team.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"team_id": 123,
|
||||
"team_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_team`
|
||||
|
||||
Generated when deleting teams.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "team_id": unique ID of the deleted team.
|
||||
- "team_name": the name of the deleted team.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"team_id": 123,
|
||||
"team_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `applied_spec_team`
|
||||
|
||||
Generated when applying team specs.
|
||||
|
||||
This activity contains a field "teams" where each item contains the team details with the following fields:
|
||||
- "id": Unique ID of the team.
|
||||
- "name": Name of the team.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"teams": [
|
||||
{
|
||||
"id": 123,
|
||||
"name": "foo"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Type `edited_agent_options`
|
||||
|
||||
Generated when agent options are edited (either globally or for a team).
|
||||
|
||||
This activity contains the following fields:
|
||||
- "global": "true" if the user updated the global agent options, "false" if the agent options of a team were updated.
|
||||
- "team_id": unique ID of the team for which the agent options were updated (null if global is true).
|
||||
- "team_name": the name of the team for which the agent options were updated (null if global is true).
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"team_id": 123,
|
||||
"team_name": "foo",
|
||||
"global": false
|
||||
}
|
||||
```
|
||||
|
||||
### Type `live_query`
|
||||
|
||||
Generated when running live queries.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "targets_count": Number of hosts where the live query was targeted to run.
|
||||
- "query_sql": The SQL query to run on hosts.
|
||||
- "query_name": Name of the query (this field is not set if this was not a saved query).
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"targets_count": 5000,
|
||||
"query_sql": "SELECT * from osquery_info;",
|
||||
"query_name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `user_added_by_sso`
|
||||
|
||||
Generated when new users are added via SSO JIT provisioning
|
||||
|
||||
This activity does not contain any detail fields.
|
||||
|
||||
### Type `user_logged_in`
|
||||
|
||||
Generated when users successfully log in to Fleet.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "public_ip": Public IP of the login request.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"public_ip": "168.226.215.82"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `created_user`
|
||||
|
||||
Generated when a user is created.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "user_id": Unique ID of the created user in Fleet.
|
||||
- "user_name": Name of the created user.
|
||||
- "user_email": E-mail of the created user.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 42,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_user`
|
||||
|
||||
Generated when a user is deleted.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "user_id": Unique ID of the deleted user in Fleet.
|
||||
- "user_name": Name of the deleted user.
|
||||
- "user_email": E-mail of the deleted user.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 42,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `changed_user_global_role`
|
||||
|
||||
Generated when user global roles are changed.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": New global role of the edited user.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 42,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Observer"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_user_global_role`
|
||||
|
||||
Generated when user global roles are deleted.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": Deleted global role of the edited user.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 43,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Maintainer"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `changed_user_team_role`
|
||||
|
||||
Generated when user team roles are changed.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": Team role set to the edited user.
|
||||
- "team_id": Unique ID of the team of the changed role.
|
||||
- "team_name": Name of the team of the changed role.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 43,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Maintainer",
|
||||
"team_id": 5,
|
||||
"team_name": "Bar"
|
||||
}
|
||||
```
|
||||
|
||||
### Type `deleted_user_team_role`
|
||||
|
||||
Generated when user team roles are deleted.
|
||||
|
||||
This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": Team role deleted from the edited user.
|
||||
- "team_id": Unique ID of the team of the deleted role.
|
||||
- "team_name": Name of the team of the deleted role.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 44,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Observer",
|
||||
"team_id": 2,
|
||||
"team_name": "Zoo"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
<meta name="pageOrderInSection" value="1400">
|
||||
|
|
@ -69,8 +69,10 @@ func (svc *Service) NewTeam(ctx context.Context, p fleet.TeamPayload) (*fleet.Te
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeCreatedTeam,
|
||||
&map[string]interface{}{"team_id": team.ID, "team_name": team.Name},
|
||||
fleet.ActivityTypeCreatedTeam{
|
||||
ID: team.ID,
|
||||
Name: team.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -177,8 +179,11 @@ func (svc *Service) ModifyTeamAgentOptions(ctx context.Context, teamID uint, tea
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeEditedAgentOptions,
|
||||
&map[string]interface{}{"global": false, "team_id": team.ID, "team_name": team.Name},
|
||||
fleet.ActivityTypeEditedAgentOptions{
|
||||
Global: false,
|
||||
TeamID: &team.ID,
|
||||
TeamName: &team.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "create edited agent options activity")
|
||||
}
|
||||
|
|
@ -330,8 +335,10 @@ func (svc *Service) DeleteTeam(ctx context.Context, teamID uint) error {
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedTeam,
|
||||
&map[string]interface{}{"team_id": teamID, "team_name": name},
|
||||
fleet.ActivityTypeDeletedTeam{
|
||||
ID: teamID,
|
||||
Name: name,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -410,11 +417,7 @@ func (svc *Service) ApplyTeamSpecs(ctx context.Context, specs []*fleet.TeamSpec,
|
|||
return err
|
||||
}
|
||||
|
||||
type activityDetail struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
var details []activityDetail
|
||||
var details []fleet.TeamActivityDetail
|
||||
|
||||
for _, spec := range specs {
|
||||
var secrets []*fleet.EnrollSecret
|
||||
|
|
@ -462,7 +465,7 @@ func (svc *Service) ApplyTeamSpecs(ctx context.Context, specs []*fleet.TeamSpec,
|
|||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "creating team from spec")
|
||||
}
|
||||
details = append(details, activityDetail{
|
||||
details = append(details, fleet.TeamActivityDetail{
|
||||
ID: team.ID,
|
||||
Name: team.Name,
|
||||
})
|
||||
|
|
@ -473,7 +476,7 @@ func (svc *Service) ApplyTeamSpecs(ctx context.Context, specs []*fleet.TeamSpec,
|
|||
return ctxerr.Wrap(ctx, err, "editing team from spec")
|
||||
}
|
||||
|
||||
details = append(details, activityDetail{
|
||||
details = append(details, fleet.TeamActivityDetail{
|
||||
ID: team.ID,
|
||||
Name: team.Name,
|
||||
})
|
||||
|
|
@ -483,8 +486,9 @@ func (svc *Service) ApplyTeamSpecs(ctx context.Context, specs []*fleet.TeamSpec,
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeAppliedSpecTeam,
|
||||
&map[string]interface{}{"teams": details},
|
||||
fleet.ActivityTypeAppliedSpecTeam{
|
||||
Teams: details,
|
||||
},
|
||||
); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "create applied team spec activity")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ func (svc *Service) GetSSOUser(ctx context.Context, auth fleet.Auth) (*fleet.Use
|
|||
err = svc.ds.NewActivity(
|
||||
ctx,
|
||||
user,
|
||||
fleet.ActivityTypeUserAddedBySSO,
|
||||
&map[string]interface{}{},
|
||||
fleet.ActivityTypeUserAddedBySSO{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import (
|
|||
)
|
||||
|
||||
// NewActivity stores an activity item that the user performed
|
||||
func (ds *Datastore) NewActivity(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
detailsBytes, err := json.Marshal(details)
|
||||
func (ds *Datastore) NewActivity(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
detailsBytes, err := json.Marshal(activity)
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "marshaling activity details")
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ func (ds *Datastore) NewActivity(ctx context.Context, user *fleet.User, activity
|
|||
`INSERT INTO activities (user_id, user_name, activity_type, details) VALUES(?,?,?,?)`,
|
||||
user.ID,
|
||||
user.Name,
|
||||
activityType,
|
||||
activity.ActivityName(),
|
||||
detailsBytes,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mysql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
|
|
@ -28,6 +29,27 @@ func TestActivity(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type dummyActivity struct {
|
||||
name string `json:"-"`
|
||||
details map[string]interface{}
|
||||
}
|
||||
|
||||
func (d dummyActivity) MarshalJSON() ([]byte, error) {
|
||||
b, err := json.Marshal(d.details)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (d dummyActivity) ActivityName() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
func (d dummyActivity) Documentation() (activity string, details string, detailsExample string) {
|
||||
return "", "", ""
|
||||
}
|
||||
|
||||
func testActivityUsernameChange(t *testing.T, ds *Datastore) {
|
||||
u := &fleet.User{
|
||||
Password: []byte("asd"),
|
||||
|
|
@ -38,8 +60,14 @@ func testActivityUsernameChange(t *testing.T, ds *Datastore) {
|
|||
}
|
||||
_, err := ds.NewUser(context.Background(), u)
|
||||
require.Nil(t, err)
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, "test1", &map[string]interface{}{"detail": 1, "sometext": "aaa"}))
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, "test2", &map[string]interface{}{"detail": 2}))
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, dummyActivity{
|
||||
name: "test1",
|
||||
details: map[string]interface{}{"detail": 1, "sometext": "aaa"},
|
||||
}))
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, dummyActivity{
|
||||
name: "test2",
|
||||
details: map[string]interface{}{"detail": 2},
|
||||
}))
|
||||
|
||||
activities, err := ds.ListActivities(context.Background(), fleet.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
|
|
@ -76,8 +104,14 @@ func testActivityNew(t *testing.T, ds *Datastore) {
|
|||
}
|
||||
_, err := ds.NewUser(context.Background(), u)
|
||||
require.Nil(t, err)
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, "test1", &map[string]interface{}{"detail": 1, "sometext": "aaa"}))
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, "test2", &map[string]interface{}{"detail": 2}))
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, dummyActivity{
|
||||
name: "test1",
|
||||
details: map[string]interface{}{"detail": 1, "sometext": "aaa"},
|
||||
}))
|
||||
require.NoError(t, ds.NewActivity(context.Background(), u, dummyActivity{
|
||||
name: "test2",
|
||||
details: map[string]interface{}{"detail": 2},
|
||||
}))
|
||||
|
||||
opt := fleet.ListOptions{
|
||||
Page: 0,
|
||||
|
|
|
|||
|
|
@ -4,62 +4,427 @@ import (
|
|||
"encoding/json"
|
||||
)
|
||||
|
||||
const (
|
||||
// ActivityTypeUserLoggedIn is the activity type for logging in a user
|
||||
ActivityTypeUserLoggedIn = "user_logged_in"
|
||||
// ActivityTypeCreatedPack is the activity type for created packs
|
||||
ActivityTypeCreatedPack = "created_pack"
|
||||
// ActivityTypeEditedPack is the activity type for edited packs
|
||||
ActivityTypeEditedPack = "edited_pack"
|
||||
// ActivityTypeDeletedPack is the activity type for deleted packs
|
||||
ActivityTypeDeletedPack = "deleted_pack"
|
||||
// ActivityTypeAppliedSpecPack is the activity type for pack specs applied
|
||||
ActivityTypeAppliedSpecPack = "applied_spec_pack"
|
||||
// ActivityTypeCreatedPolicy is the activity type for created policies
|
||||
ActivityTypeCreatedPolicy = "created_policy"
|
||||
// ActivityTypeEditedPolicy is the activity type for edited policies
|
||||
ActivityTypeEditedPolicy = "edited_policy"
|
||||
// ActivityTypeDeletedPolicy is the activity type for deleted policies
|
||||
ActivityTypeDeletedPolicy = "deleted_policy"
|
||||
// ActivityTypeAppliedSpecPolicy is the activity type for saved queries spec applied
|
||||
ActivityTypeAppliedSpecPolicy = "applied_spec_policy"
|
||||
// ActivityTypeCreatedSavedQuery is the activity type for created saved queries
|
||||
ActivityTypeCreatedSavedQuery = "created_saved_query"
|
||||
// ActivityTypeEditedSavedQuery is the activity type for edited saved queries
|
||||
ActivityTypeEditedSavedQuery = "edited_saved_query"
|
||||
// ActivityTypeDeletedSavedQuery is the activity type for deleted saved queries
|
||||
ActivityTypeDeletedSavedQuery = "deleted_saved_query"
|
||||
// ActivityTypeDeletedMultipleSavedQuery is the activity type for multiple deleted saved queries
|
||||
ActivityTypeDeletedMultipleSavedQuery = "deleted_multiple_saved_query"
|
||||
// ActivityTypeAppliedSpecSavedQuery is the activity type for saved queries spec applied
|
||||
ActivityTypeAppliedSpecSavedQuery = "applied_spec_saved_query"
|
||||
// ActivityTypeCreatedTeam is the activity type for created team
|
||||
ActivityTypeCreatedTeam = "created_team"
|
||||
// ActivityTypeDeletedTeam is the activity type for deleted team
|
||||
ActivityTypeDeletedTeam = "deleted_team"
|
||||
// ActivityTypeLiveQuery is the activity type for live queries
|
||||
ActivityTypeLiveQuery = "live_query"
|
||||
// ActivityTypeUserAddedBySSO is the activity type for new users added
|
||||
// via SSO JIT provisioning
|
||||
ActivityTypeUserAddedBySSO = "user_added_by_sso"
|
||||
// ActivityTypeEditedAgentOptions is the activity type for when the agent
|
||||
// options are edited (either globally or for a team).
|
||||
ActivityTypeEditedAgentOptions = "edited_agent_options"
|
||||
// ActivityTypeAppliedSpecTeam is the activity type for a team spec applied
|
||||
ActivityTypeAppliedSpecTeam = "applied_spec_team"
|
||||
// ActivityTypeCreatedUser is the activity type for created users.
|
||||
ActivityTypeCreatedUser = "created_user"
|
||||
// ActivityTypeDeletedUser is the activity type for deleted users.
|
||||
ActivityTypeDeletedUser = "deleted_user"
|
||||
// ActivityTypeChangedUserGlobalRole is the activity type for changed user global role.
|
||||
ActivityTypeChangedUserGlobalRole = "changed_user_global_role"
|
||||
// ActivityTypeDeletedUserGlobalRole is the activity type for deleted user global role.
|
||||
ActivityTypeDeletedUserGlobalRole = "deleted_user_global_role"
|
||||
// ActivityTypeChangedUserTeamRole is the activity type for changed user team role.
|
||||
ActivityTypeChangedUserTeamRole = "changed_user_team_role"
|
||||
// ActivityTypeDeletedUserTeamRole is the activity type for deleted user team role.
|
||||
ActivityTypeDeletedUserTeamRole = "deleted_user_team_role"
|
||||
)
|
||||
//go:generate go run gen_activity_doc.go ../../docs/Using-Fleet/Audit-Activities.md
|
||||
|
||||
// ActivityDetailsList is used to generate documentation.
|
||||
var ActivityDetailsList = []ActivityDetails{
|
||||
ActivityTypeCreatedPack{},
|
||||
ActivityTypeEditedPack{},
|
||||
ActivityTypeDeletedPack{},
|
||||
ActivityTypeAppliedSpecPack{},
|
||||
|
||||
ActivityTypeCreatedPolicy{},
|
||||
ActivityTypeEditedPolicy{},
|
||||
ActivityTypeDeletedPolicy{},
|
||||
ActivityTypeAppliedSpecPolicy{},
|
||||
ActivityTypeCreatedSavedQuery{},
|
||||
ActivityTypeEditedSavedQuery{},
|
||||
ActivityTypeDeletedSavedQuery{},
|
||||
ActivityTypeDeletedMultipleSavedQuery{},
|
||||
ActivityTypeAppliedSpecSavedQuery{},
|
||||
|
||||
ActivityTypeCreatedTeam{},
|
||||
ActivityTypeDeletedTeam{},
|
||||
ActivityTypeAppliedSpecTeam{},
|
||||
|
||||
ActivityTypeEditedAgentOptions{},
|
||||
|
||||
ActivityTypeLiveQuery{},
|
||||
|
||||
ActivityTypeUserAddedBySSO{},
|
||||
|
||||
ActivityTypeUserLoggedIn{},
|
||||
|
||||
ActivityTypeCreatedUser{},
|
||||
ActivityTypeDeletedUser{},
|
||||
ActivityTypeChangedUserGlobalRole{},
|
||||
ActivityTypeDeletedUserGlobalRole{},
|
||||
ActivityTypeChangedUserTeamRole{},
|
||||
ActivityTypeDeletedUserTeamRole{},
|
||||
}
|
||||
|
||||
type ActivityDetails interface {
|
||||
// ActivityName is the name/type of the activity.
|
||||
ActivityName() string
|
||||
// Documentation is used by "go generate" to generate markdown docs.
|
||||
Documentation() (activity string, details string, detailsExample string)
|
||||
}
|
||||
|
||||
type ActivityTypeCreatedPack struct {
|
||||
ID uint `json:"pack_id"`
|
||||
Name string `json:"pack_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedPack) ActivityName() string {
|
||||
return "created_pack"
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedPack) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when creating scheduled query packs.`,
|
||||
`This activity contains the following fields:
|
||||
- "pack_id": the id of the created pack.
|
||||
- "pack_name": the name of the created pack.`, `{
|
||||
"pack_id": 123,
|
||||
"pack_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeEditedPack struct {
|
||||
ID uint `json:"pack_id"`
|
||||
Name string `json:"pack_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedPack) ActivityName() string {
|
||||
return "edited_pack"
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedPack) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when editing scheduled query packs.`,
|
||||
`This activity contains the following fields:
|
||||
- "pack_id": the id of the edited pack.
|
||||
- "pack_name": the name of the edited pack.`, `{
|
||||
"pack_id": 123,
|
||||
"pack_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedPack struct {
|
||||
Name string `json:"pack_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedPack) ActivityName() string {
|
||||
return "deleted_pack"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedPack) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when deleting scheduled query packs.`,
|
||||
`This activity contains the following fields:
|
||||
- "pack_name": the name of the created pack.`, `{
|
||||
"pack_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeAppliedSpecPack struct{}
|
||||
|
||||
func (a ActivityTypeAppliedSpecPack) ActivityName() string {
|
||||
return "applied_spec_pack"
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecPack) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when applying a scheduled query pack spec.`,
|
||||
`This activity does not contain any detail fields.`, ""
|
||||
}
|
||||
|
||||
type ActivityTypeCreatedPolicy struct {
|
||||
ID uint `json:"policy_id"`
|
||||
Name string `json:"policy_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedPolicy) ActivityName() string {
|
||||
return "created_policy"
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedPolicy) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when creating policies.`,
|
||||
`This activity contains the following fields:
|
||||
- "policy_id": the ID of the created policy.
|
||||
- "policy_name": the name of the created policy.`, `{
|
||||
"policy_id": 123,
|
||||
"policy_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeEditedPolicy struct {
|
||||
ID uint `json:"policy_id"`
|
||||
Name string `json:"policy_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedPolicy) ActivityName() string {
|
||||
return "edited_policy"
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedPolicy) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when editing policies.`,
|
||||
`This activity contains the following fields:
|
||||
- "policy_id": the ID of the edited policy.
|
||||
- "policy_name": the name of the edited policy.`, `{
|
||||
"policy_id": 123,
|
||||
"policy_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedPolicy struct {
|
||||
ID uint `json:"policy_id"`
|
||||
Name string `json:"policy_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedPolicy) ActivityName() string {
|
||||
return "deleted_policy"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedPolicy) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when deleting policies.`,
|
||||
`This activity contains the following fields:
|
||||
- "policy_id": the ID of the deleted policy.
|
||||
- "policy_name": the name of the deleted policy.`, `{
|
||||
"policy_id": 123,
|
||||
"policy_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeAppliedSpecPolicy struct {
|
||||
Policies []*PolicySpec `json:"policies"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecPolicy) ActivityName() string {
|
||||
return "applied_spec_policy"
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecPolicy) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when applying policy specs.`,
|
||||
`This activity contains a field "policies" where each item is a policy spec with the following fields:
|
||||
- "name": Name of the applied policy.
|
||||
- "query": SQL query of the policy.
|
||||
- "description": Description of the policy.
|
||||
- "critical": Marks the policy as high impact.
|
||||
- "resolution": Describes how to solve a failing policy.
|
||||
- "team": Name of the team this policy belongs to.
|
||||
- "platform": Comma-separated string to indicate the target platforms.
|
||||
`, `{
|
||||
"policies": [
|
||||
{
|
||||
"name":"Gatekeeper enabled (macOS)",
|
||||
"query":"SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;",
|
||||
"critical":false,
|
||||
"platform":"darwin",
|
||||
"resolution":"To enable Gatekeeper, on the failing device [...]",
|
||||
"description":"Checks to make sure that the Gatekeeper feature is [...]"
|
||||
},
|
||||
{
|
||||
"name":"Full disk encryption enabled (Windows)",
|
||||
"query":"SELECT 1 FROM bitlocker_info WHERE drive_letter='C:' AND protection_status=1;",
|
||||
"critical":false,
|
||||
"platform":"windows",
|
||||
"resolution":"To get additional information, run the following osquery [...]",
|
||||
"description":"Checks to make sure that full disk encryption is enabled on Windows devices."
|
||||
}
|
||||
]
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeCreatedSavedQuery struct {
|
||||
ID uint `json:"query_id"`
|
||||
Name string `json:"query_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedSavedQuery) ActivityName() string {
|
||||
return "created_saved_query"
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedSavedQuery) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when creating a new query.`,
|
||||
`This activity contains the following fields:
|
||||
- "query_id": the ID of the created query.
|
||||
- "query_name": the name of the created query.`, `{
|
||||
"query_id": 123,
|
||||
"query_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeEditedSavedQuery struct {
|
||||
ID uint `json:"query_id"`
|
||||
Name string `json:"query_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedSavedQuery) ActivityName() string {
|
||||
return "edited_saved_query"
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedSavedQuery) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when editing a saved query.`,
|
||||
`This activity contains the following fields:
|
||||
- "query_id": the ID of the query being edited.
|
||||
- "query_name": the name of the query being edited.`, `{
|
||||
"query_id": 123,
|
||||
"query_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedSavedQuery struct {
|
||||
Name string `json:"query_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedSavedQuery) ActivityName() string {
|
||||
return "deleted_saved_query"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedSavedQuery) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when deleting a saved query.`,
|
||||
`This activity contains the following fields:
|
||||
- "query_name": the name of the query being deleted.`, `{
|
||||
"query_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedMultipleSavedQuery struct {
|
||||
IDs []uint `json:"query_ids"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedMultipleSavedQuery) ActivityName() string {
|
||||
return "deleted_multiple_saved_query"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedMultipleSavedQuery) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when deleting multiple saved queries.`,
|
||||
`This activity contains the following fields:
|
||||
- "query_ids": list of IDs of the deleted saved queries.`, `{
|
||||
"query_ids": [1, 42, 100]
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeAppliedSpecSavedQuery struct {
|
||||
Specs []*QuerySpec `json:"specs"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecSavedQuery) ActivityName() string {
|
||||
return "applied_spec_saved_query"
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecSavedQuery) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when applying a query spec.`,
|
||||
`This activity contains a field "specs" where each item is a query spec with the following fields:
|
||||
- "name": Name of the query.
|
||||
- "description": Description of the query.
|
||||
- "query": SQL query.`, `{
|
||||
"specs": [
|
||||
{
|
||||
"name":"Get OpenSSL versions",
|
||||
"query":"SELECT name AS name, version AS version, 'deb_packages' AS source FROM [...]",
|
||||
"description":"Retrieves the OpenSSL version."
|
||||
}
|
||||
]
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeCreatedTeam struct {
|
||||
ID uint `json:"team_id"`
|
||||
Name string `json:"team_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedTeam) ActivityName() string {
|
||||
return "created_team"
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedTeam) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when creating teams.`,
|
||||
`This activity contains the following fields:
|
||||
- "team_id": unique ID of the created team.
|
||||
- "team_name": the name of the created team.`, `{
|
||||
"team_id": 123,
|
||||
"team_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedTeam struct {
|
||||
ID uint `json:"team_id"`
|
||||
Name string `json:"team_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedTeam) ActivityName() string {
|
||||
return "deleted_team"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedTeam) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when deleting teams.`,
|
||||
`This activity contains the following fields:
|
||||
- "team_id": unique ID of the deleted team.
|
||||
- "team_name": the name of the deleted team.`, `{
|
||||
"team_id": 123,
|
||||
"team_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type TeamActivityDetail struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ActivityTypeAppliedSpecTeam struct {
|
||||
Teams []TeamActivityDetail `json:"teams"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecTeam) ActivityName() string {
|
||||
return "applied_spec_team"
|
||||
}
|
||||
|
||||
func (a ActivityTypeAppliedSpecTeam) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when applying team specs.`,
|
||||
`This activity contains a field "teams" where each item contains the team details with the following fields:
|
||||
- "id": Unique ID of the team.
|
||||
- "name": Name of the team.`, `{
|
||||
"teams": [
|
||||
{
|
||||
"id": 123,
|
||||
"name": "foo"
|
||||
}
|
||||
]
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeEditedAgentOptions struct {
|
||||
Global bool `json:"global"`
|
||||
TeamID *uint `json:"team_id"`
|
||||
TeamName *string `json:"team_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedAgentOptions) ActivityName() string {
|
||||
return "edited_agent_options"
|
||||
}
|
||||
|
||||
func (a ActivityTypeEditedAgentOptions) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when agent options are edited (either globally or for a team).`,
|
||||
`This activity contains the following fields:
|
||||
- "global": "true" if the user updated the global agent options, "false" if the agent options of a team were updated.
|
||||
- "team_id": unique ID of the team for which the agent options were updated (null if global is true).
|
||||
- "team_name": the name of the team for which the agent options were updated (null if global is true).`, `{
|
||||
"team_id": 123,
|
||||
"team_name": "foo",
|
||||
"global": false
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeLiveQuery struct {
|
||||
TargetsCount uint `json:"targets_count"`
|
||||
QuerySQL string `json:"query_sql"`
|
||||
QueryName *string `json:"query_name,omitempty"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeLiveQuery) ActivityName() string {
|
||||
return "live_query"
|
||||
}
|
||||
|
||||
func (a ActivityTypeLiveQuery) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when running live queries.`,
|
||||
`This activity contains the following fields:
|
||||
- "targets_count": Number of hosts where the live query was targeted to run.
|
||||
- "query_sql": The SQL query to run on hosts.
|
||||
- "query_name": Name of the query (this field is not set if this was not a saved query).`, `{
|
||||
"targets_count": 5000,
|
||||
"query_sql": "SELECT * from osquery_info;",
|
||||
"query_name": "foo"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeUserAddedBySSO struct{}
|
||||
|
||||
func (a ActivityTypeUserAddedBySSO) ActivityName() string {
|
||||
return "user_added_by_sso"
|
||||
}
|
||||
|
||||
func (a ActivityTypeUserAddedBySSO) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when new users are added via SSO JIT provisioning`,
|
||||
`This activity does not contain any detail fields.`, ""
|
||||
}
|
||||
|
||||
type Activity struct {
|
||||
CreateTimestamp
|
||||
|
|
@ -72,6 +437,178 @@ type Activity struct {
|
|||
Details *json.RawMessage `json:"details" db:"details"`
|
||||
}
|
||||
|
||||
type ActivityTypeUserLoggedIn struct {
|
||||
PublicIP string `json:"public_ip"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeUserLoggedIn) ActivityName() string {
|
||||
return "user_logged_in"
|
||||
}
|
||||
|
||||
func (a ActivityTypeUserLoggedIn) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when users successfully log in to Fleet.`,
|
||||
`This activity contains the following fields:
|
||||
- "public_ip": Public IP of the login request.`, `{
|
||||
"public_ip": "168.226.215.82"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeCreatedUser struct {
|
||||
UserID uint `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedUser) ActivityName() string {
|
||||
return "created_user"
|
||||
}
|
||||
|
||||
func (a ActivityTypeCreatedUser) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when a user is created.`,
|
||||
`This activity contains the following fields:
|
||||
- "user_id": Unique ID of the created user in Fleet.
|
||||
- "user_name": Name of the created user.
|
||||
- "user_email": E-mail of the created user.`, `{
|
||||
"user_id": 42,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedUser struct {
|
||||
UserID uint `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedUser) ActivityName() string {
|
||||
return "deleted_user"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedUser) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when a user is deleted.`,
|
||||
`This activity contains the following fields:
|
||||
- "user_id": Unique ID of the deleted user in Fleet.
|
||||
- "user_name": Name of the deleted user.
|
||||
- "user_email": E-mail of the deleted user.`, `{
|
||||
"user_id": 42,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeChangedUserGlobalRole struct {
|
||||
UserID uint `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeChangedUserGlobalRole) ActivityName() string {
|
||||
return "changed_user_global_role"
|
||||
}
|
||||
|
||||
func (a ActivityTypeChangedUserGlobalRole) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when user global roles are changed.`,
|
||||
`This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": New global role of the edited user.`, `{
|
||||
"user_id": 42,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Observer"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedUserGlobalRole struct {
|
||||
UserID uint `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
OldRole string `json:"role"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedUserGlobalRole) ActivityName() string {
|
||||
return "deleted_user_global_role"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedUserGlobalRole) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when user global roles are deleted.`,
|
||||
`This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": Deleted global role of the edited user.`, `{
|
||||
"user_id": 43,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Maintainer"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeChangedUserTeamRole struct {
|
||||
UserID uint `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
Role string `json:"role"`
|
||||
TeamID uint `json:"team_id"`
|
||||
TeamName string `json:"team_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeChangedUserTeamRole) ActivityName() string {
|
||||
return "changed_user_team_role"
|
||||
}
|
||||
|
||||
func (a ActivityTypeChangedUserTeamRole) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when user team roles are changed.`,
|
||||
`This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": Team role set to the edited user.
|
||||
- "team_id": Unique ID of the team of the changed role.
|
||||
- "team_name": Name of the team of the changed role.`, `{
|
||||
"user_id": 43,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Maintainer",
|
||||
"team_id": 5,
|
||||
"team_name": "Bar"
|
||||
}`
|
||||
}
|
||||
|
||||
type ActivityTypeDeletedUserTeamRole struct {
|
||||
UserID uint `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
Role string `json:"role"`
|
||||
TeamID uint `json:"team_id"`
|
||||
TeamName string `json:"team_name"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedUserTeamRole) ActivityName() string {
|
||||
return "deleted_user_team_role"
|
||||
}
|
||||
|
||||
func (a ActivityTypeDeletedUserTeamRole) Documentation() (activity string, details string, detailsExample string) {
|
||||
return `Generated when user team roles are deleted.`,
|
||||
`This activity contains the following fields:
|
||||
- "user_id": Unique ID of the edited user in Fleet.
|
||||
- "user_name": Name of the edited user.
|
||||
- "user_email": E-mail of the edited user.
|
||||
- "role": Team role deleted from the edited user.
|
||||
- "team_id": Unique ID of the team of the deleted role.
|
||||
- "team_name": Name of the team of the deleted role.`, `{
|
||||
"user_id": 44,
|
||||
"user_name": "Foo",
|
||||
"user_email": "foo@example.com",
|
||||
"role": "Observer",
|
||||
"team_id": 2,
|
||||
"team_name": "Zoo"
|
||||
}`
|
||||
}
|
||||
|
||||
// AuthzType implement AuthzTyper to be able to verify access to activities
|
||||
func (*Activity) AuthzType() string {
|
||||
return "activity"
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ type Datastore interface {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ActivitiesStore
|
||||
|
||||
NewActivity(ctx context.Context, user *User, activityType string, details *map[string]interface{}) error
|
||||
NewActivity(ctx context.Context, user *User, activity ActivityDetails) error
|
||||
ListActivities(ctx context.Context, opt ListOptions) ([]*Activity, error)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
73
server/fleet/gen_activity_doc.go
Normal file
73
server/fleet/gen_activity_doc.go
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString(`<!-- DO NOT EDIT. This document is automatically generated. -->
|
||||
# Audit Activities
|
||||
|
||||
Fleet logs the following information for administrative actions (in JSON):
|
||||
|
||||
- ` + "`" + `created_at` + "`" + `: Timestamp of the event.
|
||||
- ` + "`" + `id` + "`" + `: Unique ID of the generated event in Fleet.
|
||||
- ` + "`" + `actor_full_name` + "`" + `: Author user name (missing if the user was deleted).
|
||||
- ` + "`" + `actor_id` + "`" + `: Unique ID of the author in Fleet (missing if the user was deleted).
|
||||
- ` + "`" + `actor_gravatar` + "`" + `: Gravatar URL of the author (missing if the user was deleted).
|
||||
- ` + "`" + `actor_email` + "`" + `: E-mail of the author (missing if the user was deleted).
|
||||
- ` + "`" + `type` + "`" + `: Type of the activity (see all types below).
|
||||
- ` + "`" + `details` + "`" + `: Specific details depending on the type of activity (see details for each activity type below).
|
||||
|
||||
Example:
|
||||
` + "```" + `json
|
||||
{
|
||||
"created_at": "2022-12-20T14:54:17Z",
|
||||
"id": 6,
|
||||
"actor_full_name": "Gandalf",
|
||||
"actor_id": 2,
|
||||
"actor_gravatar": "foo@example.com",
|
||||
"actor_email": "foo@example.com",
|
||||
"type": "edited_saved_query",
|
||||
"details":{
|
||||
"query_id": 42,
|
||||
"query_name": "Some query name"
|
||||
}
|
||||
}
|
||||
` + "```" + `
|
||||
|
||||
## List of activities and their specific details
|
||||
|
||||
`)
|
||||
|
||||
activityMap := map[string]struct{}{}
|
||||
for _, activity := range fleet.ActivityDetailsList {
|
||||
if _, ok := activityMap[activity.ActivityName()]; ok {
|
||||
panic(fmt.Sprintf("type %s already used", activity.ActivityName()))
|
||||
}
|
||||
activityMap[activity.ActivityName()] = struct{}{}
|
||||
|
||||
fmt.Fprintf(&b, "### Type `%s`\n\n", activity.ActivityName())
|
||||
activityTypeDoc, detailsDoc, detailsExampleDoc := activity.Documentation()
|
||||
fmt.Fprintf(&b, activityTypeDoc+"\n\n"+detailsDoc+"\n\n")
|
||||
if detailsExampleDoc != "" {
|
||||
fmt.Fprintf(&b, "#### Example\n\n```json\n%s\n```\n\n", detailsExampleDoc)
|
||||
}
|
||||
}
|
||||
b.WriteString(`
|
||||
|
||||
<meta name="pageOrderInSection" value="1400">`)
|
||||
|
||||
if err := os.WriteFile(os.Args[1], []byte(b.String()), 0600); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -335,7 +335,7 @@ type UpdateHostOperatingSystemFunc func(ctx context.Context, hostID uint, hostOS
|
|||
|
||||
type CleanupHostOperatingSystemsFunc func(ctx context.Context) error
|
||||
|
||||
type NewActivityFunc func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error
|
||||
type NewActivityFunc func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error
|
||||
|
||||
type ListActivitiesFunc func(ctx context.Context, opt fleet.ListOptions) ([]*fleet.Activity, error)
|
||||
|
||||
|
|
@ -2070,9 +2070,9 @@ func (s *DataStore) CleanupHostOperatingSystems(ctx context.Context) error {
|
|||
return s.CleanupHostOperatingSystemsFunc(ctx)
|
||||
}
|
||||
|
||||
func (s *DataStore) NewActivity(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
func (s *DataStore) NewActivity(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
s.NewActivityFuncInvoked = true
|
||||
return s.NewActivityFunc(ctx, user, activityType, details)
|
||||
return s.NewActivityFunc(ctx, user, activity)
|
||||
}
|
||||
|
||||
func (s *DataStore) ListActivities(ctx context.Context, opt fleet.ListOptions) ([]*fleet.Activity, error) {
|
||||
|
|
|
|||
|
|
@ -45,8 +45,12 @@ func logRoleChangeActivities(ctx context.Context, ds fleet.Datastore, adminUser
|
|||
if err := ds.NewActivity(
|
||||
ctx,
|
||||
adminUser,
|
||||
fleet.ActivityTypeChangedUserGlobalRole,
|
||||
&map[string]interface{}{"user_name": user.Name, "user_id": user.ID, "user_email": user.Email, "role": *user.GlobalRole},
|
||||
fleet.ActivityTypeChangedUserGlobalRole{
|
||||
UserID: user.ID,
|
||||
UserName: user.Name,
|
||||
UserEmail: user.Email,
|
||||
Role: *user.GlobalRole,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -55,8 +59,12 @@ func logRoleChangeActivities(ctx context.Context, ds fleet.Datastore, adminUser
|
|||
if err := ds.NewActivity(
|
||||
ctx,
|
||||
adminUser,
|
||||
fleet.ActivityTypeDeletedUserGlobalRole,
|
||||
&map[string]interface{}{"user_name": user.Name, "user_id": user.ID, "user_email": user.Email, "role": *oldRole},
|
||||
fleet.ActivityTypeDeletedUserGlobalRole{
|
||||
UserID: user.ID,
|
||||
UserName: user.Name,
|
||||
UserEmail: user.Email,
|
||||
OldRole: *oldRole,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -76,8 +84,14 @@ func logRoleChangeActivities(ctx context.Context, ds fleet.Datastore, adminUser
|
|||
if err := ds.NewActivity(
|
||||
ctx,
|
||||
adminUser,
|
||||
fleet.ActivityTypeChangedUserTeamRole,
|
||||
&map[string]interface{}{"user_name": user.Name, "user_id": user.ID, "user_email": user.Email, "team_name": t.Name, "team_id": t.ID, "role": t.Role},
|
||||
fleet.ActivityTypeChangedUserTeamRole{
|
||||
UserID: user.ID,
|
||||
UserName: user.Name,
|
||||
UserEmail: user.Email,
|
||||
Role: t.Role,
|
||||
TeamID: t.ID,
|
||||
TeamName: t.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -89,8 +103,14 @@ func logRoleChangeActivities(ctx context.Context, ds fleet.Datastore, adminUser
|
|||
if err := ds.NewActivity(
|
||||
ctx,
|
||||
adminUser,
|
||||
fleet.ActivityTypeDeletedUserTeamRole,
|
||||
&map[string]interface{}{"user_name": user.Name, "user_id": user.ID, "user_email": user.Email, "team_name": o.Name, "team_id": o.ID, "role": o.Role},
|
||||
fleet.ActivityTypeDeletedUserTeamRole{
|
||||
UserID: user.ID,
|
||||
UserName: user.Name,
|
||||
UserEmail: user.Email,
|
||||
Role: o.Role,
|
||||
TeamID: o.ID,
|
||||
TeamName: o.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,8 +107,8 @@ func Test_logRoleChangeActivities(t *testing.T) {
|
|||
ctx := context.Background()
|
||||
ds := new(mock.Store)
|
||||
var activities []string
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
activities = append(activities, activityType)
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
activities = append(activities, activity.ActivityName())
|
||||
return nil
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
|
|
|||
|
|
@ -412,8 +412,9 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeEditedAgentOptions,
|
||||
&map[string]interface{}{"global": true, "team_id": nil, "team_name": nil},
|
||||
fleet.ActivityTypeEditedAgentOptions{
|
||||
Global: true,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,18 +162,17 @@ func (svc *Service) NewDistributedQueryCampaign(ctx context.Context, queryString
|
|||
return nil, ctxerr.Wrap(ctx, err, "counting hosts")
|
||||
}
|
||||
|
||||
activityData := map[string]interface{}{
|
||||
"targets_count": campaign.Metrics.TotalHosts,
|
||||
"query_sql": query.Query,
|
||||
activityData := fleet.ActivityTypeLiveQuery{
|
||||
TargetsCount: campaign.Metrics.TotalHosts,
|
||||
QuerySQL: query.Query,
|
||||
}
|
||||
if queryID != nil {
|
||||
activityData["query_name"] = query.Name
|
||||
activityData.QueryName = &query.Name
|
||||
}
|
||||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeLiveQuery,
|
||||
&activityData,
|
||||
activityData,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mock"
|
||||
|
|
@ -85,14 +86,15 @@ func TestLiveQueryAuth(t *testing.T) {
|
|||
return fleet.TargetMetrics{}, nil
|
||||
}
|
||||
var queryName, querySQL string
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
name := (*details)["query_name"]
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
act := activity.(fleet.ActivityTypeLiveQuery)
|
||||
name := act.QueryName
|
||||
if name == nil {
|
||||
queryName = ""
|
||||
} else {
|
||||
queryName = name.(string)
|
||||
queryName = *name
|
||||
}
|
||||
querySQL = (*details)["query_sql"].(string)
|
||||
querySQL = act.QuerySQL
|
||||
return nil
|
||||
}
|
||||
ds.QueryFunc = func(ctx context.Context, id uint) (*fleet.Query, error) {
|
||||
|
|
|
|||
|
|
@ -73,8 +73,10 @@ func (svc Service) NewGlobalPolicy(ctx context.Context, p fleet.PolicyPayload) (
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeCreatedPolicy,
|
||||
&map[string]interface{}{"policy_id": policy.ID, "policy_name": policy.Name},
|
||||
fleet.ActivityTypeCreatedPolicy{
|
||||
ID: policy.ID,
|
||||
Name: policy.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -211,8 +213,10 @@ func (svc Service) DeleteGlobalPolicies(ctx context.Context, ids []uint) ([]uint
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedPolicy,
|
||||
&map[string]interface{}{"policy_id": id, "policy_name": policiesByID[id].Name},
|
||||
fleet.ActivityTypeDeletedPolicy{
|
||||
ID: id,
|
||||
Name: policiesByID[id].Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "adding new activity for deleted policy")
|
||||
}
|
||||
|
|
@ -479,7 +483,8 @@ func (svc *Service) ApplyPolicySpecs(ctx context.Context, policies []*fleet.Poli
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeAppliedSpecPolicy,
|
||||
&map[string]interface{}{"policies": policies},
|
||||
fleet.ActivityTypeAppliedSpecPolicy{
|
||||
Policies: policies,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func TestGlobalPoliciesAuth(t *testing.T) {
|
|||
ds.ApplyPolicySpecsFunc = func(ctx context.Context, authorID uint, specs []*fleet.PolicySpec) error {
|
||||
return nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
ds.SavePolicyFunc = func(ctx context.Context, p *fleet.Policy) error {
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ func setupAuthTest(t *testing.T) (fleet.Datastore, map[string]fleet.User, *httpt
|
|||
sessions[sessionKey] = session
|
||||
return session, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
return ds, usersMap, server
|
||||
|
|
|
|||
|
|
@ -2047,18 +2047,17 @@ func (s *integrationTestSuite) TestListActivities() {
|
|||
|
||||
ctx := context.Background()
|
||||
u := s.users["admin1@example.com"]
|
||||
details := make(map[string]interface{})
|
||||
|
||||
prevActivities, err := s.ds.ListActivities(ctx, fleet.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.ds.NewActivity(ctx, &u, fleet.ActivityTypeAppliedSpecPack, &details)
|
||||
err = s.ds.NewActivity(ctx, &u, fleet.ActivityTypeAppliedSpecPack{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.ds.NewActivity(ctx, &u, fleet.ActivityTypeDeletedPack, &details)
|
||||
err = s.ds.NewActivity(ctx, &u, fleet.ActivityTypeDeletedPack{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.ds.NewActivity(ctx, &u, fleet.ActivityTypeEditedPack, &details)
|
||||
err = s.ds.NewActivity(ctx, &u, fleet.ActivityTypeEditedPack{})
|
||||
require.NoError(t, err)
|
||||
|
||||
lenPage := len(prevActivities) + 2
|
||||
|
|
@ -2066,16 +2065,16 @@ func (s *integrationTestSuite) TestListActivities() {
|
|||
var listResp listActivitiesResponse
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listResp, "per_page", strconv.Itoa(lenPage), "order_key", "id")
|
||||
require.Len(t, listResp.Activities, lenPage)
|
||||
assert.Equal(t, fleet.ActivityTypeAppliedSpecPack, listResp.Activities[lenPage-2].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeDeletedPack, listResp.Activities[lenPage-1].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeAppliedSpecPack{}.ActivityName(), listResp.Activities[lenPage-2].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeDeletedPack{}.ActivityName(), listResp.Activities[lenPage-1].Type)
|
||||
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listResp, "per_page", strconv.Itoa(lenPage), "order_key", "id", "page", "1")
|
||||
require.Len(t, listResp.Activities, 1)
|
||||
assert.Equal(t, fleet.ActivityTypeEditedPack, listResp.Activities[0].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeEditedPack{}.ActivityName(), listResp.Activities[0].Type)
|
||||
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listResp, "per_page", "1", "order_key", "id", "order_direction", "desc")
|
||||
require.Len(t, listResp.Activities, 1)
|
||||
assert.Equal(t, fleet.ActivityTypeEditedPack, listResp.Activities[0].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeEditedPack{}.ActivityName(), listResp.Activities[0].Type)
|
||||
}
|
||||
|
||||
func (s *integrationTestSuite) TestListGetCarves() {
|
||||
|
|
@ -4468,7 +4467,7 @@ func (s *integrationTestSuite) TestAppConfig() {
|
|||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listActivities, "order_key", "id", "order_direction", "desc")
|
||||
if !assert.Len(t, listActivities.Activities, 1) {
|
||||
// if there is an activity, make sure it is not edited_agent_options
|
||||
require.NotEqual(t, fleet.ActivityTypeEditedAgentOptions, listActivities.Activities[0].Type)
|
||||
require.NotEqual(t, fleet.ActivityTypeEditedAgentOptions{}.ActivityName(), listActivities.Activities[0].Type)
|
||||
}
|
||||
|
||||
// and it did not update the appconfig
|
||||
|
|
@ -4488,7 +4487,7 @@ func (s *integrationTestSuite) TestAppConfig() {
|
|||
}`), http.StatusOK, &acResp)
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listActivities, "order_key", "id", "order_direction", "desc")
|
||||
require.True(t, len(listActivities.Activities) > 1)
|
||||
require.Equal(t, fleet.ActivityTypeEditedAgentOptions, listActivities.Activities[0].Type)
|
||||
require.Equal(t, fleet.ActivityTypeEditedAgentOptions{}.ActivityName(), listActivities.Activities[0].Type)
|
||||
require.NotNil(t, listActivities.Activities[0].Details)
|
||||
assert.JSONEq(t, `{"global": true, "team_id": null, "team_name": null}`, string(*listActivities.Activities[0].Details))
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
|||
var listActivities listActivitiesResponse
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listActivities, "order_key", "id", "order_direction", "desc")
|
||||
require.True(t, len(listActivities.Activities) > 0)
|
||||
assert.Equal(t, fleet.ActivityTypeAppliedSpecTeam, listActivities.Activities[0].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeAppliedSpecTeam{}.ActivityName(), listActivities.Activities[0].Type)
|
||||
require.NotNil(t, listActivities.Activities[0].Details)
|
||||
assert.JSONEq(t, fmt.Sprintf(`{"teams": [{"id": %d, "name": %q}]}`, team.ID, team.Name), string(*listActivities.Activities[0].Details))
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
|||
// an activity was created for the newly created team via the applied spec
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listActivities, "order_key", "id", "order_direction", "desc")
|
||||
require.True(t, len(listActivities.Activities) > 0)
|
||||
assert.Equal(t, fleet.ActivityTypeAppliedSpecTeam, listActivities.Activities[0].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeAppliedSpecTeam{}.ActivityName(), listActivities.Activities[0].Type)
|
||||
require.NotNil(t, listActivities.Activities[0].Details)
|
||||
assert.JSONEq(t, fmt.Sprintf(`{"teams": [{"id": %d, "name": %q}]}`, team.ID, team.Name), string(*listActivities.Activities[0].Details))
|
||||
|
||||
|
|
@ -667,7 +667,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamEndpoints() {
|
|||
var listActivities listActivitiesResponse
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &listActivities, "order_key", "id", "order_direction", "desc")
|
||||
require.True(t, len(listActivities.Activities) > 0)
|
||||
assert.Equal(t, fleet.ActivityTypeEditedAgentOptions, listActivities.Activities[0].Type)
|
||||
assert.Equal(t, fleet.ActivityTypeEditedAgentOptions{}.ActivityName(), listActivities.Activities[0].Type)
|
||||
require.NotNil(t, listActivities.Activities[0].Details)
|
||||
assert.JSONEq(t, fmt.Sprintf(`{"global": false, "team_id": %d, "team_name": %q}`, tm1ID, team.Name), string(*listActivities.Activities[0].Details))
|
||||
|
||||
|
|
@ -1475,7 +1475,7 @@ func (s *integrationEnterpriseTestSuite) TestSSOJITProvisioning() {
|
|||
require.NotEmpty(t, activitiesResp.Activities)
|
||||
require.Condition(t, func() bool {
|
||||
for _, a := range activitiesResp.Activities {
|
||||
if a.Type == fleet.ActivityTypeUserAddedBySSO && *a.ActorEmail == auth.UserID() {
|
||||
if (a.Type == fleet.ActivityTypeUserAddedBySSO{}.ActivityName()) && *a.ActorEmail == auth.UserID() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ func (s *integrationSSOTestSuite) TestSSOLogin() {
|
|||
require.NotEmpty(t, activitiesResp.Activities)
|
||||
require.Condition(t, func() bool {
|
||||
for _, a := range activitiesResp.Activities {
|
||||
if a.Type == fleet.ActivityTypeUserLoggedIn && *a.ActorEmail == auth.UserID() {
|
||||
if (a.Type == fleet.ActivityTypeUserLoggedIn{}.ActivityName()) && *a.ActorEmail == auth.UserID() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1429,7 +1429,7 @@ func TestNewDistributedQueryCampaign(t *testing.T) {
|
|||
},
|
||||
})
|
||||
q := "select year, month, day, hour, minutes, seconds from time"
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
campaign, err := svc.NewDistributedQueryCampaign(viewerCtx, q, nil, fleet.HostTargets{HostIDs: []uint{2}, LabelIDs: []uint{1}})
|
||||
|
|
@ -2196,7 +2196,7 @@ func TestObserversCanOnlyRunDistributedCampaigns(t *testing.T) {
|
|||
})
|
||||
|
||||
q := "select year, month, day, hour, minutes, seconds from time"
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
_, err := svc.NewDistributedQueryCampaign(viewerCtx, q, nil, fleet.HostTargets{HostIDs: []uint{2}, LabelIDs: []uint{1}})
|
||||
|
|
@ -2230,7 +2230,7 @@ func TestObserversCanOnlyRunDistributedCampaigns(t *testing.T) {
|
|||
ds.HostIDsInTargetsFunc = func(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets) ([]uint, error) {
|
||||
return []uint{1, 3, 5}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
lq.On("RunQuery", "21", "select 1;", []uint{1, 3, 5}).Return(nil)
|
||||
|
|
@ -2270,7 +2270,7 @@ func TestTeamMaintainerCanRunNewDistributedCampaigns(t *testing.T) {
|
|||
})
|
||||
|
||||
q := "select year, month, day, hour, minutes, seconds from time"
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
// var gotQuery *fleet.Query
|
||||
|
|
@ -2288,7 +2288,7 @@ func TestTeamMaintainerCanRunNewDistributedCampaigns(t *testing.T) {
|
|||
ds.HostIDsInTargetsFunc = func(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets) ([]uint, error) {
|
||||
return []uint{1, 3, 5}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
lq.On("RunQuery", "0", "select year, month, day, hour, minutes, seconds from time", []uint{1, 3, 5}).Return(nil)
|
||||
|
|
|
|||
|
|
@ -170,8 +170,10 @@ func (svc *Service) NewPack(ctx context.Context, p fleet.PackPayload) (*fleet.Pa
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeCreatedPack,
|
||||
&map[string]interface{}{"pack_id": pack.ID, "pack_name": pack.Name},
|
||||
fleet.ActivityTypeCreatedPack{
|
||||
ID: pack.ID,
|
||||
Name: pack.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -264,8 +266,10 @@ func (svc *Service) ModifyPack(ctx context.Context, id uint, p fleet.PackPayload
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeEditedPack,
|
||||
&map[string]interface{}{"pack_id": pack.ID, "pack_name": pack.Name},
|
||||
fleet.ActivityTypeEditedPack{
|
||||
ID: pack.ID,
|
||||
Name: pack.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -358,8 +362,9 @@ func (svc *Service) DeletePack(ctx context.Context, name string) error {
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedPack,
|
||||
&map[string]interface{}{"pack_name": name},
|
||||
fleet.ActivityTypeDeletedPack{
|
||||
Name: pack.Name,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -405,8 +410,9 @@ func (svc *Service) DeletePackByID(ctx context.Context, id uint) error {
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedPack,
|
||||
&map[string]interface{}{"pack_name": pack.Name},
|
||||
fleet.ActivityTypeDeletedPack{
|
||||
Name: pack.Name,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -480,8 +486,7 @@ func (svc *Service) ApplyPackSpecs(ctx context.Context, specs []*fleet.PackSpec)
|
|||
return result, svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeAppliedSpecPack,
|
||||
&map[string]interface{}{},
|
||||
fleet.ActivityTypeAppliedSpecPack{},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func TestNewPackSavesTargets(t *testing.T) {
|
|||
ds.NewPackFunc = func(ctx context.Context, pack *fleet.Pack, opts ...fleet.OptionalArg) (*fleet.Pack, error) {
|
||||
return pack, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -185,8 +185,10 @@ func (svc *Service) NewQuery(ctx context.Context, p fleet.QueryPayload) (*fleet.
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeCreatedSavedQuery,
|
||||
&map[string]interface{}{"query_id": query.ID, "query_name": query.Name},
|
||||
fleet.ActivityTypeCreatedSavedQuery{
|
||||
ID: query.ID,
|
||||
Name: query.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -266,8 +268,10 @@ func (svc *Service) ModifyQuery(ctx context.Context, id uint, p fleet.QueryPaylo
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeEditedSavedQuery,
|
||||
&map[string]interface{}{"query_id": query.ID, "query_name": query.Name},
|
||||
fleet.ActivityTypeEditedSavedQuery{
|
||||
ID: query.ID,
|
||||
Name: query.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -321,8 +325,9 @@ func (svc *Service) DeleteQuery(ctx context.Context, name string) error {
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedSavedQuery,
|
||||
&map[string]interface{}{"query_name": name},
|
||||
fleet.ActivityTypeDeletedSavedQuery{
|
||||
Name: name,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -372,8 +377,9 @@ func (svc *Service) DeleteQueryByID(ctx context.Context, id uint) error {
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedSavedQuery,
|
||||
&map[string]interface{}{"query_name": query.Name},
|
||||
fleet.ActivityTypeDeletedSavedQuery{
|
||||
Name: query.Name,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -427,8 +433,9 @@ func (svc *Service) DeleteQueries(ctx context.Context, ids []uint) (uint, error)
|
|||
err = svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedMultipleSavedQuery,
|
||||
&map[string]interface{}{"query_ids": ids},
|
||||
fleet.ActivityTypeDeletedMultipleSavedQuery{
|
||||
IDs: ids,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return n, err
|
||||
|
|
@ -502,8 +509,9 @@ func (svc *Service) ApplyQuerySpecs(ctx context.Context, specs []*fleet.QuerySpe
|
|||
return svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeAppliedSpecSavedQuery,
|
||||
&map[string]interface{}{"specs": specs},
|
||||
fleet.ActivityTypeAppliedSpecSavedQuery{
|
||||
Specs: specs,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ func TestQueryAuth(t *testing.T) {
|
|||
}
|
||||
return &fleet.Query{ID: 8888, AuthorID: ptr.Uint(6666)}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
ds.QueryFunc = func(ctx context.Context, id uint) (*fleet.Query, error) {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func TestStreamCampaignResultsClosesReditOnWSClose(t *testing.T) {
|
|||
ds.CountHostsInTargetsFunc = func(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets, now time.Time) (fleet.TargetMetrics, error) {
|
||||
return fleet.TargetMetrics{TotalHosts: 1}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
ds.SessionByKeyFunc = func(ctx context.Context, key string) (*fleet.Session, error) {
|
||||
|
|
|
|||
|
|
@ -48,8 +48,11 @@ func (svc *Service) NewUser(ctx context.Context, p fleet.UserPayload) (*fleet.Us
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
adminUser,
|
||||
fleet.ActivityTypeCreatedUser,
|
||||
&map[string]interface{}{"user_name": user.Name, "user_id": user.ID, "user_email": user.Email},
|
||||
fleet.ActivityTypeCreatedUser{
|
||||
UserID: user.ID,
|
||||
UserName: user.Name,
|
||||
UserEmail: user.Email,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,8 +192,8 @@ func (svc *Service) Login(ctx context.Context, email, password string) (*fleet.U
|
|||
return nil, nil, fleet.NewAuthFailedError(err.Error())
|
||||
}
|
||||
|
||||
if err := svc.ds.NewActivity(ctx, user, fleet.ActivityTypeUserLoggedIn, &map[string]interface{}{
|
||||
"public_ip": publicip.FromContext(ctx),
|
||||
if err := svc.ds.NewActivity(ctx, user, fleet.ActivityTypeUserLoggedIn{
|
||||
PublicIP: publicip.FromContext(ctx),
|
||||
}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -515,9 +515,8 @@ func (svc *Service) LoginSSOUser(ctx context.Context, user *fleet.User, redirect
|
|||
err = svc.ds.NewActivity(
|
||||
ctx,
|
||||
user,
|
||||
fleet.ActivityTypeUserLoggedIn,
|
||||
&map[string]interface{}{
|
||||
"public_ip": publicip.FromContext(ctx),
|
||||
fleet.ActivityTypeUserLoggedIn{
|
||||
PublicIP: publicip.FromContext(ctx),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -81,8 +81,10 @@ func (svc Service) NewTeamPolicy(ctx context.Context, teamID uint, p fleet.Polic
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeCreatedPolicy,
|
||||
&map[string]interface{}{"policy_id": policy.ID, "policy_name": policy.Name},
|
||||
fleet.ActivityTypeCreatedPolicy{
|
||||
ID: policy.ID,
|
||||
Name: policy.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -244,8 +246,10 @@ func (svc Service) DeleteTeamPolicies(ctx context.Context, teamID uint, ids []ui
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeDeletedPolicy,
|
||||
&map[string]interface{}{"policy_id": id, "policy_name": policiesByID[id].Name},
|
||||
fleet.ActivityTypeDeletedPolicy{
|
||||
ID: id,
|
||||
Name: policiesByID[id].Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "adding new activity for deleted policy")
|
||||
}
|
||||
|
|
@ -337,8 +341,10 @@ func (svc *Service) modifyPolicy(ctx context.Context, teamID *uint, id uint, p f
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
fleet.ActivityTypeEditedPolicy,
|
||||
&map[string]interface{}{"policy_id": policy.ID, "policy_name": policy.Name},
|
||||
fleet.ActivityTypeEditedPolicy{
|
||||
ID: policy.ID,
|
||||
Name: policy.Name,
|
||||
},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func TestTeamPoliciesAuth(t *testing.T) {
|
|||
ds.ApplyPolicySpecsFunc = func(ctx context.Context, authorID uint, specs []*fleet.PolicySpec) error {
|
||||
return nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
ds.TeamFunc = func(ctx context.Context, tid uint) (*fleet.Team, error) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ func TestTeamAuth(t *testing.T) {
|
|||
ds.NewTeamFunc = func(ctx context.Context, team *fleet.Team) (*fleet.Team, error) {
|
||||
return &fleet.Team{}, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
ds.TeamFunc = func(ctx context.Context, tid uint) (*fleet.Team, error) {
|
||||
|
|
@ -264,8 +264,9 @@ func TestApplyTeamSpecs(t *testing.T) {
|
|||
return team, nil
|
||||
}
|
||||
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
require.Len(t, (*details)["teams"], 1)
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
act := activity.(fleet.ActivityTypeAppliedSpecTeam)
|
||||
require.Len(t, act.Teams, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -344,8 +345,9 @@ func TestApplyTeamSpecs(t *testing.T) {
|
|||
return &fleet.Team{}, nil
|
||||
}
|
||||
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
require.Len(t, (*details)["teams"], 1)
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
act := activity.(fleet.ActivityTypeAppliedSpecTeam)
|
||||
require.Len(t, act.Teams, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -431,8 +431,11 @@ func (svc *Service) DeleteUser(ctx context.Context, id uint) error {
|
|||
if err := svc.ds.NewActivity(
|
||||
ctx,
|
||||
adminUser,
|
||||
fleet.ActivityTypeDeletedUser,
|
||||
&map[string]interface{}{"user_name": user.Name, "user_id": user.ID, "user_email": user.Email},
|
||||
fleet.ActivityTypeDeletedUser{
|
||||
UserID: user.ID,
|
||||
UserName: user.Name,
|
||||
UserEmail: user.Email,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ func TestUserAuth(t *testing.T) {
|
|||
ds.ListSessionsForUserFunc = func(ctx context.Context, id uint) ([]*fleet.Session, error) {
|
||||
return nil, nil
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue