Skip to content

Soft-delete entries for host script results so the details are still available in activities#19457

Merged
mna merged 16 commits intomainfrom
mna-17387-soft-delete-host-script-results
Jun 12, 2024
Merged

Soft-delete entries for host script results so the details are still available in activities#19457
mna merged 16 commits intomainfrom
mna-17387-soft-delete-host-script-results

Conversation

@mna
Copy link
Copy Markdown
Member

@mna mna commented Jun 3, 2024

Checklist for submitter

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.
  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements)
  • Added/updated tests
  • If database migrations are included, checked table schema to confirm autoupdate
  • Manual QA for all new/changed functionality

@mna mna temporarily deployed to Docker Hub June 3, 2024 17:57 — with GitHub Actions Inactive
@mna mna temporarily deployed to Docker Hub June 3, 2024 18:08 — with GitHub Actions Inactive
@mna mna temporarily deployed to Docker Hub June 3, 2024 19:36 — with GitHub Actions Inactive
// Team specific auth check
if err := svc.authz.Authorize(ctx, &fleet.HostSoftwareInstallerResultAuthz{HostTeamID: res.HostTeamID}, fleet.ActionRead); err != nil {
return nil, err
if res.HostDeletedAt == nil {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that if the host was deleted, the only authorization done is "list hosts" above. Should there be a different authz for that case?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to come up with something else but I couldn't, the other alternative is to keep some host information around.

We never merged this, and if you remember: but at some point we tried to solve a similar problem, (but for users that were deleted), we were considering having a table like deleted_user_data that kept information like this.

Something like that would be more tricky for hosts because the table is so huge that there will be the temptation to slowly move all the fields.

// get the software install details, does not work because the installer does
// not exist anymore.
softwareRes = getSoftwareInstallResultsResponse{}
s.DoJSON("GET", "/api/latest/fleet/software/install/results/"+installID, nil, http.StatusNotFound, &softwareRes)
Copy link
Copy Markdown
Member Author

@mna mna Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that deleting a software installer will still result in not being able to view the activity details. This PR only handles the host's soft-deletion (to keep scope reasonable and mostly in-line with estimation).

@mna mna marked this pull request as ready for review June 3, 2024 20:06
@mna mna requested a review from a team as a code owner June 3, 2024 20:06
Copy link
Copy Markdown
Contributor

@roperzh roperzh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on your comment I wonder if we should scope software installers in a completely different ticket.

asking because I think we also need to update places like the one below to ignore software installers with a NOT NULL deleted_at, is that correct?

func (ds *Datastore) GetSummaryHostSoftwareInstalls(ctx context.Context, installerID uint) (*fleet.SoftwareInstallerStatusSummary, error) {
var dest fleet.SoftwareInstallerStatusSummary
stmt := fmt.Sprintf(`
SELECT
COALESCE(SUM( IF(status = :software_status_pending, 1, 0)), 0) AS pending,
COALESCE(SUM( IF(status = :software_status_failed, 1, 0)), 0) AS failed,
COALESCE(SUM( IF(status = :software_status_installed, 1, 0)), 0) AS installed
FROM (
SELECT
software_installer_id,
%s
FROM
host_software_installs hsi
WHERE
software_installer_id = :installer_id
AND id IN(
SELECT
max(id) -- ensure we use only the most recently created install attempt for each host
FROM host_software_installs
WHERE
software_installer_id = :installer_id
GROUP BY
host_id)) s`, softwareInstallerHostStatusNamedQuery("hsi", "status"))
query, args, err := sqlx.Named(stmt, map[string]interface{}{
"installer_id": installerID,
"software_status_pending": fleet.SoftwareInstallerPending,
"software_status_failed": fleet.SoftwareInstallerFailed,
"software_status_installed": fleet.SoftwareInstallerInstalled,
})
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "get summary host software installs: named query")
}
err = sqlx.GetContext(ctx, ds.reader(ctx), &dest, query, args...)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "get summary host software install status")
}
return &dest, nil
}

(I'm not sure if similar considerations also applies to scripts)

// Team specific auth check
if err := svc.authz.Authorize(ctx, &fleet.HostSoftwareInstallerResultAuthz{HostTeamID: res.HostTeamID}, fleet.ActionRead); err != nil {
return nil, err
if res.HostDeletedAt == nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to come up with something else but I couldn't, the other alternative is to keep some host information around.

We never merged this, and if you remember: but at some point we tried to solve a similar problem, (but for users that were deleted), we were considering having a table like deleted_user_data that kept information like this.

Something like that would be more tricky for hosts because the table is so huge that there will be the temptation to slowly move all the fields.

@mna
Copy link
Copy Markdown
Member Author

mna commented Jun 10, 2024

@roperzh

I think we also need to update places like the one below to ignore software installers with a NOT NULL deleted_at, is that correct?

Oh that's a great catch, that's correct and I'm not sure if we have something similar for scripts, I'll check. Wondering if we're opening up a can of worms with that fix (or that approach to the fix), given how error-prone it will be to make queries that target those tables and don't explicitly join with hosts...

@mna
Copy link
Copy Markdown
Member Author

mna commented Jun 10, 2024

Ok what I think I'll do is scope it back down to scripts only, as @roperzh suggested. Not only do software installers involve other queries, but the installer activities will still fail if the installer is removed, whereas the scripts work in all cases (removing the named script doesn't remove the host script results entry, it just removes the relationship with the saved script).

@mna mna force-pushed the mna-17387-soft-delete-host-script-results branch from ec69a95 to 47a7b4b Compare June 11, 2024 14:55
@mna mna changed the title Soft-delete entries for host script and software install results so the details are still available in activities Soft-delete entries for host script results so the details are still available in activities Jun 11, 2024
@mna
Copy link
Copy Markdown
Member Author

mna commented Jun 11, 2024

@roperzh

(I'm not sure if similar considerations also applies to scripts)

I did a search for all uses of host_script_results, I couldn't see any that would be wrong due to the soft-deletion (e.g. aggregations that would consider deleted execution requests).

roperzh
roperzh previously approved these changes Jun 12, 2024
Copy link
Copy Markdown
Contributor

@roperzh roperzh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mna mna merged commit 3044eb9 into main Jun 12, 2024
@mna mna deleted the mna-17387-soft-delete-host-script-results branch June 12, 2024 14:26
@georgekarrv
Copy link
Copy Markdown
Member

#17387

georgekarrv pushed a commit that referenced this pull request Jun 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants