-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Fix unit tests on Windows #7270
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
Conversation
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.
I still need to spin up a Windows VM to do a real test on is_executable
here, but otherwise, this LGTM other than a few nits.
certbot/compat/misc.py
Outdated
@@ -30,6 +30,10 @@ | |||
MASK_FOR_PRIVATE_KEY_PERMISSIONS = 0 | |||
|
|||
|
|||
# For Linux: define OS specific standard binaries directories | |||
STD_BINARIES_DIRS = ["/usr/sbin", "/usr/local/bin", "/usr/local/sbin"] if POSIX_MODE else [] |
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.
nit: I'd change this to "BINARY" in both the name of the constant and comments around it. The singular version feels more idiomatic and have more results on Google.
I also personally would prefer to spell out "standard" rather than "std", but that's a personal preference you can ignore if you want.
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.
Done.
certbot/plugins/util_test.py
Outdated
@@ -30,12 +30,14 @@ def test_path_surgery(self, mock_debug): | |||
self.assertEqual(mock_debug.call_count, 0) | |||
self.assertEqual(os.environ["PATH"], all_path["PATH"]) | |||
no_path = {"PATH": "/tmp/"} |
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.
nit: Can we move this variable into the body if the if
statement too?
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.
Done.
certbot/tests/hook_test.py
Outdated
# certbot.compat.filesystem to give rights only to the current user. This implies removing | ||
# all ACEs except the first one from the DACL created by original _generate_dacl function. | ||
|
||
from certbot.compat.filesystem import _generate_dacl |
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.
Since this test relies on mocking the internals of filesystem.is_executable
, I propose moving the majority of the code in this test to a new class in certbot/tests/compat/filesystem_test.py
and updating the code here to just mock out filesystem.is_executable
entirely with a comment about it being hard to test without a mock on Windows.
What do you think?
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.
I agree. Done.
@@ -52,26 +53,42 @@ def _call(cls, exe): | |||
from certbot.util import exe_exists | |||
return exe_exists(exe) | |||
|
|||
@mock.patch("certbot.util.os.path.isfile") |
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.
I have the same high level comments about testing here as I do above. I personally think these tests should be moved to filesystem_test.py
and we can keep simple tests here that just mock out filesystem.is_executable
if we want.
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.
Done.
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.
Other than two more tiny nits, when manually testing this, I was surprised by the behavior I saw. In a command prompt not running as administrator, I checked out this code, activated the venv, and ran:
import os
import tempfile
import win32security
from certbot.compat import filesystem
from certbot.util import safe_open
with tempfile.TemporaryDirectory() as dir_path:
file_name = 'foo'
file_path = os.path.join(dir_path, file_name)
safe_open(file_path, chmod=0o666).close()
print(win32security.LookupAccountSid(None, filesystem._get_current_user()))
assert not filesystem.is_executable(file_path)
The output I got was:
('IEUser', 'MSEDGEWIN10', 1)
Traceback (most recent call last):
File "test.py", line 15, in <module>
assert not filesystem.is_executable(file_path)
AssertionError
Can you explain what's going on here?
Co-Authored-By: Brad Warren <bmw@users.noreply.github.com>
This is because you are member of the Administrators group, and this group has always all the permissions. So effectively, the file is executable for your user. To give more details here, I use this high-level approach since |
That makes sense for the behavior from Is there a way we can prevent the behavior shown here?
Output was:
If you call |
Your are encountering this error because you run this code from a non privileged shell, and the effective rights here are accessible only when you are in a privileged shell. However, Windows documentation about GetEffectiveRightsFromAcl says that the privileges hold by the user at call time are not taken into account to get the result, so you do not see it. However, the situation you described will not happen: certbot refuses to run on a non-privileged shell. So you will always have the maximum permissions you can get from the file, and |
Windows why? Are you familiar with an easy way to take the current privileges into account? I think that'd be ideal, but if not, I think we should add a simple comment in the code describing this behavior. Also, I just noticed our avoidance of |
For your first remark, no, I think there is no easy way do to that, and found no clue how it could be properly handled on internet. In fact, I think it is an approach from Posix (having a program designed for an arbitrary user) that is not applicable on Windows. On Windows, you can mark an executable or a script as requiring privileged rights. It appears as so in the interface, and if you try to run it, it will trigger automatically the privileges escalation, and fail if your account cannot acquire them. So I suppose that you design and write your program with the assumption it will be run under elevated privileges, and mark the executable as so. This is basically what we did for certbot internally, this is also what I will do for the executable created by the installers if possible. For Yes, I think it can be forbidden. I can give a reference to |
OK @bmw, I forbid |
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.
LGTM!
Other than the test failures I just noticed which are stopping me from merging the PR 😛 |
Looks like lint is still angry |
Pylint is happy again |
Fixes #6850
This PR makes the last corrections needed to run all unit tests on Windows:
@broken_on_windows
decorator.