Coverage for harbor_cli/commands/api/cve_allowlist.py: 28%

42 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-09 12:09 +0100

1from __future__ import annotations 

2 

3from typing import List 

4 

5import typer 

6from harborapi.models.models import CVEAllowlist 

7from harborapi.models.models import CVEAllowlistItem 

8 

9from ...logs import logger 

10from ...output.console import exit 

11from ...output.render import render_result 

12from ...state import state 

13from ...utils import parse_commalist 

14 

15# Create a command group 

16app = typer.Typer( 

17 name="cve-allowlist", 

18 help="Manage the system-wide CVE allowlist.", 

19 no_args_is_help=True, 

20) 

21 

22 

23@app.command("get") 

24def get_allowlist(ctx: typer.Context) -> None: 

25 """Get the current CVE allowlist.""" 

26 allowlist = state.run(state.client.get_cve_allowlist(), "Fetching system info...") 

27 render_result(allowlist, ctx) 

28 

29 

30@app.command("update") 

31def update_allowlist( 

32 ctx: typer.Context, 

33 cves: List[str] = typer.Option( 

34 [], 

35 "--cve", 

36 help="CVE IDs to add/remove. Can be a comma-separated list, or specified multiple times.", 

37 callback=parse_commalist, 

38 ), 

39 remove: bool = typer.Option( 

40 False, 

41 "--remove", 

42 help="Remove the given CVE IDs from the allowlist instead of adding them.", 

43 ), 

44) -> None: 

45 """Add/remove CVE IDs to the CVE allowlist.""" 

46 current = state.run(state.client.get_cve_allowlist()) 

47 

48 # Check if the current allowlist is defined 

49 if current.items is None: 

50 if remove: 

51 exit("CVE allowlist is empty, nothing to remove.") 

52 current.items = [] 

53 

54 if remove: 

55 current.items = [item for item in current.items if item.cve_id not in cves] 

56 else: 

57 # Make a list of all CVE IDs in the current allowlist 

58 current_ids = [item.cve_id for item in current.items if item.cve_id is not None] 

59 # Create new CVEAllowListItem objects for each CVE ID 

60 to_add = [ 

61 CVEAllowlistItem(cve_id=cve_id) 

62 for cve_id in cves 

63 if cve_id not in current_ids 

64 ] 

65 current.items.extend(to_add) 

66 

67 state.run(state.client.update_cve_allowlist(current), "Updating CVE allowlist...") 

68 if remove: 

69 logger.info( 

70 f"Removed {len(cves)} CVEs from CVE allowlist. Total: {len(current.items)}" 

71 ) 

72 else: 

73 logger.info( 

74 f"Added {len(cves)} CVEs to CVE allowlist. Total: {len(current.items)}" 

75 ) 

76 

77 

78@app.command("clear") 

79def clear_allowlist( 

80 ctx: typer.Context, 

81 full_clear: bool = typer.Option( 

82 False, 

83 "--full", 

84 help="Also clear the allowlist of all metadata (such as project ID, expiration, etc).", 

85 ), 

86) -> None: 

87 """Clear the current CVE allowlist of all CVEs, and optionally all metadata as well.""" 

88 if full_clear: 

89 allowlist = CVEAllowlist(items=[]) # create a whole new allowlist 

90 else: 

91 # Fetch existing allowlist to preserve metadata 

92 allowlist = state.run( 

93 state.client.get_cve_allowlist(), "Fetching current allowlist..." 

94 ) 

95 allowlist.items = [] 

96 

97 state.run(state.client.update_cve_allowlist(allowlist), "Clearing CVE allowlist...") 

98 msg = "Cleared CVE allowlist of CVEs." 

99 if full_clear: 

100 msg += " Also cleared metadata." 

101 logger.info(msg)