Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i/prompting{,requestrules}: merge rules which have identical lifespans #14757

Conversation

olivercalder
Copy link
Member

@olivercalder olivercalder commented Nov 24, 2024

This PR is based on #14635.

When a rule is added or modified directly, or when a rule is created as a result of a prompt reply, merge it with any existing rule which has an identical path pattern. That way, a single rule represents the complete rule state for a given path pattern.

A good use case for this is if a user is prompted for read access to /foo/bar, which they grant forever, resulting in a pseudo-rule like allow read /foo/bar forever. If the user is then asked for write access to /foo/bar and they reply with allow read,write /foo/bar forever, then instead of there coexisting the following rules:

  • allow read /foo/bar forever
  • allow read,write /foo/bar forever
    We instead end up with a single "merged" rule for that path pattern, equal to the latter. This is simple enough, since the read part of the rule is identical.

Things get a bit more interesting when we start varying the outcome and lifespan of the rules to be merged:

  • If the outcomes differ for a particular permission, throw an error, as these rules are in conflict
  • If the lifespans differ for a particular permission, preserve the "longer" of the two lifespans
    • If a user previously said allow read,write /foo/bar timespan:5m and then said allow read,execute /foo/bar forever, the resulting rule constraints would look like (in actual json):
{
    "path-pattern": "/foo/bar",
    "permissions": {
        "read": {
            "outcome": "allow",
            "lifespan": "forever"
        },
        "write": {
            "outcome": "allow",
            "lifespan": "timespan",
            "expiration": "<timestamp-plus-5-minutes>"
        },
        "execute": {
            "outcome": "allow",
            "lifespan": "forever"
        }
    }

This work is tracked internally by https://warthogs.atlassian.net/browse/SNAPDENG-33373

@github-actions github-actions bot added the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label Nov 24, 2024
@pedronis pedronis added the Needs Samuele review Needs a review from Samuele before it can land label Dec 2, 2024
Copy link

codecov bot commented Dec 3, 2024

Codecov Report

Attention: Patch coverage is 94.88636% with 9 lines in your changes missing coverage. Please review.

Project coverage is 78.27%. Comparing base (24a0034) to head (024d155).
Report is 110 commits behind head on master.

Files with missing lines Patch % Lines
interfaces/prompting/requestrules/requestrules.go 94.40% 6 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #14757      +/-   ##
==========================================
+ Coverage   78.20%   78.27%   +0.06%     
==========================================
  Files        1151     1158       +7     
  Lines      151396   153291    +1895     
==========================================
+ Hits       118402   119986    +1584     
- Misses      25662    25914     +252     
- Partials     7332     7391      +59     
Flag Coverage Δ
unittests 78.27% <94.88%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@olivercalder olivercalder force-pushed the prompting-single-rule-per-path-pattern branch from 218da75 to f3719b1 Compare December 4, 2024 00:10
@olivercalder olivercalder marked this pull request as ready for review December 4, 2024 00:10
@olivercalder olivercalder force-pushed the prompting-single-rule-per-path-pattern branch 2 times, most recently from d962dbc to d73422c Compare December 9, 2024 18:52
@olivercalder olivercalder force-pushed the prompting-single-rule-per-path-pattern branch from d73422c to 76cf4f3 Compare December 18, 2024 19:22
@github-actions github-actions bot removed the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label Dec 18, 2024
@olivercalder olivercalder force-pushed the prompting-single-rule-per-path-pattern branch from 76cf4f3 to 44f8aaa Compare January 7, 2025 18:30
Copy link
Member Author

@olivercalder olivercalder left a comment

Choose a reason for hiding this comment

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

Question for reviewers

interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

thanks, did a first pass

interfaces/prompting/prompting.go Outdated Show resolved Hide resolved
} else if newID, exists := mergedRules[rule.ID]; exists {
data = map[string]string{
"removed": "merged",
"merged-into": newID.String(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

is emitting this very valuable? the rule is not really fully going away

Copy link
Member Author

Choose a reason for hiding this comment

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

The notice data as a whole, or the "merged-into" field? I think it is important include at least "removed": "merged", since the rule with the original ID no longer exists, and all that exists is now the ID of the rule into which it was merged.

Let's say rules with IDs A and B exist, and the client has retrieved these rule details from snapd. Then snapd restarts, and as part of re-loading the rules from disk, it merges rule B into rule A. The client needs to get a notice with "removed": "merged" for rule B (as opposed to just getting a notice with empty data for B), so that it knows it can drop rule B without first needing to retrieve rule details for B via a separate API request. Also including "merged-into" avoids a race condition if the notice that rule A has been updated has not yet been recorded: if the client sees that rule B has been merged but doesn't yet know into which other rule it was merged, it has to wait for the notice for rule A before it has the new merged rule contents, and even then, it has to manually check rule contents to know which rule the semantics formerly associated with rule B now belong. Including "merged-into": "A" lets the client know exactly what happened to rule B, and where to find the rule which now covers what B used to cover.

Copy link
Contributor

Choose a reason for hiding this comment

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

is the client expected to keep rule IDs in its state longer (eg through persistence) than needed for the basic prompting interaction?

Copy link
Member Author

Choose a reason for hiding this comment

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

The security center is the only current client for rule IDs, and it displays existing rules in a table and lets users inspect or delete them. So aside from initially loading rules or notice-driven updates, it's holding the current rule state and displaying it. It could query all rules every time it receives any notice, but I think we can provide better information than that using notice data.

interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
@olivercalder olivercalder requested a review from pedronis January 11, 2025 23:22
@bboozzoo bboozzoo requested a review from zyga January 13, 2025 11:30
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
interfaces/prompting/requestrules/requestrules.go Outdated Show resolved Hide resolved
@olivercalder olivercalder requested a review from bboozzoo January 13, 2025 21:56
Copy link
Contributor

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

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

LGTM

@olivercalder olivercalder added this to the 2.68 milestone Jan 14, 2025
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

thank you

Copy link

github-actions bot commented Jan 14, 2025

Wed Jan 15 16:33:02 UTC 2025

No spread failures

@olivercalder olivercalder force-pushed the prompting-single-rule-per-path-pattern branch from 223d0be to 024d155 Compare January 14, 2025 23:54
@olivercalder
Copy link
Member Author

Rebased to pull in test fixes from master.

@olivercalder olivercalder merged commit 9cb84ab into canonical:master Jan 15, 2025
56 of 60 checks passed
sespiros added a commit to sespiros/snapd that referenced this pull request Jan 23, 2025
…to snap-integrity-remove-pack

* sespiros/snap-integrity-remove-pack: (86 commits)
  multiple: remove dm-verity support from snap pack
  asserts: snap integrity assertion (canonical#14870)
  overlord: cleanup some old edges
  i/builtin: make auditd-support grant seccomp setpriority (canonical#14940)
  tests: use quotation marks to support directories with spaces (canonical#14948)
  t/m/snap-service-install-mode: fix line being longer than expected
  interfaces/opengl: Enable parsing of nvidia driver information files (canonical#14893)
  i/b/fwupd: allow access to dell bios recovery (canonical#14920)
  tests: divide spread into fundamental/non-fundamental (canonical#14785)
  c/snap-bootstrap: refactor systemd-mount dm-verity/overlayfs options API (canonical#14790)
  o/snapstate: do not restart again for snapd along the undo path inside undoUnlinkCurrentSnap (canonical#14917)
  release: 2.67.1
  tests: fix missing spread failures in PR comments (canonical#14931)
  i/prompting{,requestrules}: merge rules which have identical lifespans (canonical#14757)
  tests: skip apparmor-prompting-integration-tests in armhf (canonical#14919)
  cmd/snap-bootstrap: mount drivers tree if present (canonical#14522)
  i/p/patterns: disallow /./ and /../ in path patterns (canonical#14774)
  osutil/user: look up getent executable in known host directories (canonical#14792)
  overlord: wait for snapd restart after requesting by undo of 'link-snap' (canonical#14850)
  interfaces: update template with new syscalls (canonical#14861)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Samuele review Needs a review from Samuele before it can land
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants