exosphere-cli 2.3.0__tar.gz → 2.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/PKG-INFO +1 -1
  2. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/pyproject.toml +1 -1
  3. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/api.py +24 -2
  4. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/freebsd.py +19 -1
  5. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/LICENSE +0 -0
  6. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/README.md +0 -0
  7. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/__init__.py +0 -0
  8. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/cli.py +0 -0
  9. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/__init__.py +0 -0
  10. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/config.py +0 -0
  11. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/connections.py +0 -0
  12. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/host.py +0 -0
  13. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/inventory.py +0 -0
  14. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/report.py +0 -0
  15. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/sudo.py +0 -0
  16. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/ui.py +0 -0
  17. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/utils.py +0 -0
  18. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/commands/version.py +0 -0
  19. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/config.py +0 -0
  20. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/context.py +0 -0
  21. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/data.py +0 -0
  22. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/database.py +0 -0
  23. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/errors.py +0 -0
  24. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/fspaths.py +0 -0
  25. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/inventory.py +0 -0
  26. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/main.py +0 -0
  27. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/migrations.py +0 -0
  28. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/objects.py +0 -0
  29. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/pipelining.py +0 -0
  30. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/__init__.py +0 -0
  31. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/debian.py +0 -0
  32. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/factory.py +0 -0
  33. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/openbsd.py +0 -0
  34. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/providers/redhat.py +0 -0
  35. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/repl.py +0 -0
  36. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/reporting.py +0 -0
  37. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/schema/__init__.py +0 -0
  38. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/schema/host-report.schema.json +0 -0
  39. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/security.py +0 -0
  40. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/setup/__init__.py +0 -0
  41. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/setup/detect.py +0 -0
  42. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/templates/report.html.j2 +0 -0
  43. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/templates/report.md.j2 +0 -0
  44. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/templates/report.txt.j2 +0 -0
  45. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/__init__.py +0 -0
  46. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/app.py +0 -0
  47. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/context.py +0 -0
  48. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/dashboard.py +0 -0
  49. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/elements.py +0 -0
  50. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/inventory.py +0 -0
  51. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/logs.py +0 -0
  52. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/messages.py +0 -0
  53. {exosphere_cli-2.3.0 → exosphere_cli-2.4.0}/src/exosphere/ui/style.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: exosphere-cli
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: CLI/TUI driven patch reporting for remote Unix-like systems.
5
5
  Author: Alexandre Gauthier
6
6
  Author-email: Alexandre Gauthier <alex@underwares.org>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "exosphere-cli"
3
- version = "2.3.0"
3
+ version = "2.4.0"
4
4
  description = "CLI/TUI driven patch reporting for remote Unix-like systems."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -6,13 +6,23 @@ well as helper functions and decorators to be used by package manager
6
6
  provider implementations.
7
7
  """
8
8
 
9
+ import functools
9
10
  import logging
10
11
  from abc import ABC, abstractmethod
11
12
  from collections.abc import Callable
12
13
 
13
14
  from fabric import Connection
15
+ from invoke.exceptions import AuthFailure
14
16
 
15
17
  from exosphere.data import Update
18
+ from exosphere.errors import DataRefreshError
19
+
20
+ _SUDO_AUTH_FAILURE_MESSAGE = (
21
+ "Sudo failed: "
22
+ "Ensure the user is configured with passwordless sudo. "
23
+ "You can use 'exosphere sudo generate' to produce a sudoers snippet for this host. "
24
+ "See: https://exosphere.readthedocs.io/en/stable/connections.html#id1"
25
+ )
16
26
 
17
27
 
18
28
  def requires_sudo(func: Callable) -> Callable:
@@ -23,9 +33,21 @@ def requires_sudo(func: Callable) -> Callable:
23
33
  it requires sudo privileges to execute. You should add it to any
24
34
  method that requires elevated privileges, i.e. whenever you are
25
35
  using 'cx.sudo()' instead of 'cx.run()'.
36
+
37
+ Additionally, the decorator provides enhanced error handling for
38
+ sudo related failures, presenting a clear message about sudo policies
39
+ and sudoers configuration when an AuthFailure or related exception occurs.
26
40
  """
27
- setattr(func, "__requires_sudo", True)
28
- return func
41
+
42
+ @functools.wraps(func)
43
+ def wrapper(*args: object, **kwargs: object) -> object:
44
+ try:
45
+ return func(*args, **kwargs)
46
+ except AuthFailure as e:
47
+ raise DataRefreshError(_SUDO_AUTH_FAILURE_MESSAGE) from e
48
+
49
+ setattr(wrapper, "__requires_sudo", True)
50
+ return wrapper
29
51
 
30
52
 
31
53
  class PkgManager(ABC):
@@ -26,6 +26,7 @@ class Pkg(PkgManager):
26
26
 
27
27
  SUDOERS_COMMANDS: list[str] | None = [
28
28
  "/usr/sbin/pkg update -q",
29
+ "/usr/sbin/pkg audit -qF",
29
30
  ]
30
31
 
31
32
  def __init__(self) -> None:
@@ -41,7 +42,11 @@ class Pkg(PkgManager):
41
42
  """
42
43
  Synchronize the package repository.
43
44
 
44
- This method is equivalent to running 'pkg update -q'.
45
+ It will also download the latest version of the vuln.xml
46
+ database to check for security updates.
47
+
48
+ This method is equivalent to running 'pkg update -q', followed
49
+ by 'pkg audit -qF'.
45
50
 
46
51
  :param cx: Fabric Connection object
47
52
  :return: True if synchronization is successful, False otherwise.
@@ -56,6 +61,19 @@ class Pkg(PkgManager):
56
61
  )
57
62
  return False
58
63
 
64
+ # Sync vulnerability data via pkg audit -qF, which forces a download
65
+ # of the vuln.xml database. We do not store or parse the output, as
66
+ # the cost of running it a second time in get_updates() is negligible,
67
+ # and will be a local operation anyways.
68
+ self.logger.debug("Synchronizing vuln.xml via pkg audit")
69
+ audit_result = cx.sudo("/usr/sbin/pkg audit -qF", hide=True, warn=True)
70
+
71
+ if audit_result.failed and audit_result.stderr:
72
+ self.logger.error(
73
+ f"Failed to synchronize vuln.xml via pkg audit: {audit_result.stderr}"
74
+ )
75
+ return False
76
+
59
77
  self.logger.debug("FreeBSD pkg repositories synchronized successfully")
60
78
 
61
79
  return True
File without changes
File without changes