-
Notifications
You must be signed in to change notification settings - Fork 49
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
Add: snaps confinement test (new) #663
Conversation
The original snappy/test-snap-confinement-mode is actually testing the system's confinement whether it is "strict". If it is, test passes. Otherwise, the missing feature to make system in strict confinement will be listed. This commit renamed the job ID and purpose to make it more clear. Also, restructured the python script to put the original test into SystemConfinement class as a test and added docstring to make it easier to understand and maintain.
Add SnapsConfinement class in snap_confinement_test.py to check all the installed snaps' confinement, devmode, and revision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic stuff!
The code below is quite testable, but there's no tests. I added some comments below that could be helpful with that.
See other comments for other tweaks.
that are exempted from the confinement check. | ||
""" | ||
|
||
whitelist_snaps = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're following modern naming schemes in which "allowlist" is preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion! I'll modify the naming in the next commit.
|
||
class SystemConfinement: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both classes in this testing program have only one method and they don't benefit from being a class. Simple function would be cleaner (for instance the indentation would be better allowing cleaner code).
Furthermore the function could be decomposed further to facilitate unit testing. For instance the "check_snap_confinment" could accept snap's data as an argument, and do the checks. Then in the main scope in the iterating over snaps could be done and this function could be invoked for each.
In turn the unit test becomes simple - the snap data would have to be prepared with the conditions you want, and so on...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I was referring to the structure snappy tests.
I think the idea is to separate the test cases by classes, and the data like features_should_include
or allowlist_snaps
could be located in that class. Re-write it to only functions are OK, but I think both ways have their own advantages.
Regarding decomposing the functions to apply unit testing, there are 2 things I'd like to discuss with you.
- For this test case, I feel the unit tests could be implemented for functions in snapd.py. As this test is calling the functions in snapd.py and get data in the dictionaries, it seems to me that unit tests for this test case are not necessary.
- In my opinion, wrapping those
if conditions
to functions or not are fine. If the functions will not be reused or extended, keeping these simpleif conditions
will be easier to understand the test steps. If we are going to wrap them in functions likecheck_snap_confinement()
orcheck_snap_demode()
, it will be better to keep the class structure and implement these functions in classes. Something like,
class SnapsConfinement:
def __init__(self):
data = Snapd.list()
def check_snap_confinement(self, snap, snap_name):
confinement = snap.get("confinement")
if confinement != "strict":
logging.error(
"Snap '%s' confinement is expected to be 'strict' "
"but got '%s'", snap_name, confinement,
)
return False
return True
And iterate the snaps self.data
and get the snap name in invoked()
functions.
Which way do you prefer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keeping these simple if conditions will be easier to understand the test steps.
I agree with this statement.
If what you want to have is a class that reflects one idea of a test, like "check snaps' confinement", then I think natural decomposition would be to iterate over the snaps in invoked
and call the is_snap_confined
check for each (btw. I changed the name on purpose - for checks that end in booleans the is_something is clearer tbh).
I hope this answers your question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the clarification.
I rethought it a little bit. Since these 2 test classes are simple, I would prefer just to flatten them into functions test_system_confinement()
and test_snaps_confinement()
. And the attributes features_should_include
and allowlist_snaps
for each class become a local variable in each function.
To keep the test steps easy to understand, I would leave the if conditions
as they are.
Feel free to give any comments in case I misunderstand anything.
|
||
def main(): | ||
logging.basicConfig(format='%(levelname)s: %(message)s') | ||
sub_commands = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic, very Pythonic approach, <3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick answer about the RE below. I'll answer more soon.
Codecov Report
@@ Coverage Diff @@
## main #663 +/- ##
======================================
Coverage ? 2.10%
======================================
Files ? 127
Lines ? 15031
Branches ? 2596
======================================
Hits ? 316
Misses ? 14652
Partials ? 63 |
Hi @kissiel , |
Updated the code. Flatten the test classes to test functions to make them simpler. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! +1
Thank you for all the changes!
I really hope that the CI will not choke on the test_
function prefix (it may look like a unit test ;) )
snappy-snap-automated was added into client cert desktop plan with pull request canonical#663. When nesting to the desktop plan, it was misplaced to manual plan on client-cert-desktop-22-04.pxu. 20-04 and 18-04 didn't misplace. This commit fixes it to move the snappy-snap-automated to auto plan.
snappy-snap-automated was added into client cert desktop plan with pull request canonical#663. When nesting to the desktop plan, it was misplaced to manual plan on client-cert-desktop-22-04.pxu. 20-04 and 18-04 didn't misplace. This commit fixes it to move the snappy-snap-automated to auto plan.
Fix snappy-snap-automated misplaced to manual plan snappy-snap-automated was added into client cert desktop plan with pull request #663. When nesting to the desktop plan, it was misplaced to manual plan on client-cert-desktop-22-04.pxu. 20-04 and 18-04 didn't misplace. This commit fixes it to move the snappy-snap-automated to auto plan.
Resolved issues
Jira task https://warthogs.atlassian.net/browse/CQT-2907
Rational
Murcia project's customer asked us to include 2 snaps in the GM image. One of the snap is
strict
confined and installed in devmode, the other one isdevmode
confined and also installed in devmode.[1]Recently this problem was found. For security reason, this should not be allowed on the image we delivered.
So we were asked to create a test case to catch this in the future.
[1] snap confinement document https://snapcraft.io/docs/snap-confinement
Information
We originally have a test case called
snappy/test-snap-confinement-mode
. It checks the confinement and sandbox features of the system, if the system confinement is notstrict
, the test case will print out the missing requirements (e.g. sandbox features or cgroup version). Therefore, this test is testing the confinement of the system. We don't actually test the snap confinements of each installed snap.In the problematic image of Murcia project, there are 2 snaps sideloaded at the last stage of image installation.
Requirement
After checking with OEM SWE team, the requriments of this test are checking the following things for each installed snap,
x1
.strict
.classic
anddevmode
confinement are not allowed.installed in devmode
should beFalse
.What are implemented in this pull request?
SystemConfinement
class andSnapsConfinement
class corresponding to the system confinement test and snap confinement test(the new test created)bugit
,checkboxXX
,mir-test-tools
,graphic-test-tools
.snappy/test-system-confinement
andsnappy/test-snaps-confinement
to snappy-snap-automated test plan.Sideload test results
https://pastebin.canonical.com/p/hsyFyRVtVQ/
https://pastebin.canonical.com/p/CngKh9fNyD/
https://pastebin.canonical.com/p/gT8WNzbjbt/