complio 0.1.1__py3-none-any.whl
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.
- CHANGELOG.md +208 -0
- README.md +343 -0
- complio/__init__.py +48 -0
- complio/cli/__init__.py +0 -0
- complio/cli/banner.py +87 -0
- complio/cli/commands/__init__.py +0 -0
- complio/cli/commands/history.py +439 -0
- complio/cli/commands/scan.py +700 -0
- complio/cli/main.py +115 -0
- complio/cli/output.py +338 -0
- complio/config/__init__.py +17 -0
- complio/config/settings.py +333 -0
- complio/connectors/__init__.py +9 -0
- complio/connectors/aws/__init__.py +0 -0
- complio/connectors/aws/client.py +342 -0
- complio/connectors/base.py +135 -0
- complio/core/__init__.py +10 -0
- complio/core/registry.py +228 -0
- complio/core/runner.py +351 -0
- complio/py.typed +0 -0
- complio/reporters/__init__.py +7 -0
- complio/reporters/generator.py +417 -0
- complio/tests_library/__init__.py +0 -0
- complio/tests_library/base.py +492 -0
- complio/tests_library/identity/__init__.py +0 -0
- complio/tests_library/identity/access_key_rotation.py +302 -0
- complio/tests_library/identity/mfa_enforcement.py +327 -0
- complio/tests_library/identity/root_account_protection.py +470 -0
- complio/tests_library/infrastructure/__init__.py +0 -0
- complio/tests_library/infrastructure/cloudtrail_encryption.py +286 -0
- complio/tests_library/infrastructure/cloudtrail_log_validation.py +274 -0
- complio/tests_library/infrastructure/cloudtrail_logging.py +400 -0
- complio/tests_library/infrastructure/ebs_encryption.py +244 -0
- complio/tests_library/infrastructure/ec2_security_groups.py +321 -0
- complio/tests_library/infrastructure/iam_password_policy.py +460 -0
- complio/tests_library/infrastructure/nacl_security.py +356 -0
- complio/tests_library/infrastructure/rds_encryption.py +252 -0
- complio/tests_library/infrastructure/s3_encryption.py +301 -0
- complio/tests_library/infrastructure/s3_public_access.py +369 -0
- complio/tests_library/infrastructure/secrets_manager_encryption.py +248 -0
- complio/tests_library/infrastructure/vpc_flow_logs.py +287 -0
- complio/tests_library/logging/__init__.py +0 -0
- complio/tests_library/logging/cloudwatch_alarms.py +354 -0
- complio/tests_library/logging/cloudwatch_logs_encryption.py +281 -0
- complio/tests_library/logging/cloudwatch_retention.py +252 -0
- complio/tests_library/logging/config_enabled.py +393 -0
- complio/tests_library/logging/eventbridge_rules.py +460 -0
- complio/tests_library/logging/guardduty_enabled.py +436 -0
- complio/tests_library/logging/security_hub_enabled.py +416 -0
- complio/tests_library/logging/sns_encryption.py +273 -0
- complio/tests_library/network/__init__.py +0 -0
- complio/tests_library/network/alb_nlb_security.py +421 -0
- complio/tests_library/network/api_gateway_security.py +452 -0
- complio/tests_library/network/cloudfront_https.py +332 -0
- complio/tests_library/network/direct_connect_security.py +343 -0
- complio/tests_library/network/nacl_configuration.py +367 -0
- complio/tests_library/network/network_firewall.py +355 -0
- complio/tests_library/network/transit_gateway_security.py +318 -0
- complio/tests_library/network/vpc_endpoints_security.py +339 -0
- complio/tests_library/network/vpn_security.py +333 -0
- complio/tests_library/network/waf_configuration.py +428 -0
- complio/tests_library/security/__init__.py +0 -0
- complio/tests_library/security/kms_key_rotation.py +314 -0
- complio/tests_library/storage/__init__.py +0 -0
- complio/tests_library/storage/backup_encryption.py +288 -0
- complio/tests_library/storage/dynamodb_encryption.py +280 -0
- complio/tests_library/storage/efs_encryption.py +257 -0
- complio/tests_library/storage/elasticache_encryption.py +370 -0
- complio/tests_library/storage/redshift_encryption.py +252 -0
- complio/tests_library/storage/s3_versioning.py +264 -0
- complio/utils/__init__.py +26 -0
- complio/utils/errors.py +179 -0
- complio/utils/exceptions.py +151 -0
- complio/utils/history.py +243 -0
- complio/utils/logger.py +391 -0
- complio-0.1.1.dist-info/METADATA +385 -0
- complio-0.1.1.dist-info/RECORD +79 -0
- complio-0.1.1.dist-info/WHEEL +4 -0
- complio-0.1.1.dist-info/entry_points.txt +3 -0
complio/cli/main.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Complio CLI - Main entry point.
|
|
3
|
+
|
|
4
|
+
This module defines the main CLI application and command groups.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
from complio.cli import output
|
|
12
|
+
from complio.cli.banner import print_banner
|
|
13
|
+
|
|
14
|
+
# CLI version (sync with pyproject.toml)
|
|
15
|
+
VERSION = "0.1.0"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# ============================================================================
|
|
19
|
+
# MAIN CLI GROUP
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@click.group(invoke_without_command=True)
|
|
24
|
+
@click.version_option(version=VERSION, prog_name="complio")
|
|
25
|
+
@click.pass_context
|
|
26
|
+
def cli(ctx: click.Context) -> None:
|
|
27
|
+
"""
|
|
28
|
+
🔒 Complio - ISO 27001 Compliance Scanner for AWS
|
|
29
|
+
|
|
30
|
+
Automated compliance testing against ISO 27001:2022 controls.
|
|
31
|
+
40 tests covering encryption, network, IAM, and logging.
|
|
32
|
+
|
|
33
|
+
\b
|
|
34
|
+
Prerequisites:
|
|
35
|
+
AWS CLI configured: aws configure
|
|
36
|
+
|
|
37
|
+
\b
|
|
38
|
+
Quick Start:
|
|
39
|
+
complio scan # Scan with default profile
|
|
40
|
+
complio scan --region eu-west-3 # Specific region
|
|
41
|
+
complio scan --profile production # Specific AWS profile
|
|
42
|
+
|
|
43
|
+
\b
|
|
44
|
+
Commands:
|
|
45
|
+
scan Run ISO 27001 compliance tests
|
|
46
|
+
history View past scan results
|
|
47
|
+
compare Compare two scans
|
|
48
|
+
clear-history Clear scan history
|
|
49
|
+
|
|
50
|
+
\b
|
|
51
|
+
Examples:
|
|
52
|
+
# Run compliance scan
|
|
53
|
+
complio scan
|
|
54
|
+
|
|
55
|
+
# View scan history
|
|
56
|
+
complio history
|
|
57
|
+
|
|
58
|
+
# Compare two scans
|
|
59
|
+
complio compare scan-123 scan-456
|
|
60
|
+
|
|
61
|
+
Documentation: https://github.com/Tiger972/complio
|
|
62
|
+
"""
|
|
63
|
+
# Ensure context object exists
|
|
64
|
+
ctx.ensure_object(dict)
|
|
65
|
+
|
|
66
|
+
# Show banner when no subcommand is provided
|
|
67
|
+
if ctx.invoked_subcommand is None:
|
|
68
|
+
print_banner()
|
|
69
|
+
output.print_message("")
|
|
70
|
+
click.echo(ctx.get_help())
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# ============================================================================
|
|
74
|
+
# SCAN COMMAND
|
|
75
|
+
# ============================================================================
|
|
76
|
+
|
|
77
|
+
from complio.cli.commands.scan import scan
|
|
78
|
+
|
|
79
|
+
cli.add_command(scan)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# ============================================================================
|
|
83
|
+
# HISTORY COMMANDS
|
|
84
|
+
# ============================================================================
|
|
85
|
+
|
|
86
|
+
from complio.cli.commands.history import history, compare, clear_history_cmd
|
|
87
|
+
|
|
88
|
+
cli.add_command(history)
|
|
89
|
+
cli.add_command(compare)
|
|
90
|
+
cli.add_command(clear_history_cmd)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# ============================================================================
|
|
94
|
+
# MAIN ENTRY POINT
|
|
95
|
+
# ============================================================================
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def main() -> None:
|
|
99
|
+
"""Main entry point for CLI."""
|
|
100
|
+
try:
|
|
101
|
+
cli()
|
|
102
|
+
except KeyboardInterrupt:
|
|
103
|
+
output.print_message("\n")
|
|
104
|
+
output.warning("Operation cancelled by user")
|
|
105
|
+
sys.exit(130)
|
|
106
|
+
except Exception as e:
|
|
107
|
+
output.error(
|
|
108
|
+
"Unexpected error",
|
|
109
|
+
f"{type(e).__name__}: {str(e)}",
|
|
110
|
+
)
|
|
111
|
+
sys.exit(1)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
if __name__ == "__main__":
|
|
115
|
+
main()
|
complio/cli/output.py
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI output formatting utilities.
|
|
3
|
+
|
|
4
|
+
This module provides rich, user-friendly terminal output using the Rich library.
|
|
5
|
+
Includes formatted messages for success, errors, warnings, and information.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Color-coded output (green=success, red=error, yellow=warning, blue=info)
|
|
9
|
+
- Styled tables for structured data
|
|
10
|
+
- Progress indicators
|
|
11
|
+
- Panels for grouped information
|
|
12
|
+
- Consistent formatting across all CLI commands
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from typing import Any, Optional
|
|
16
|
+
|
|
17
|
+
from rich.console import Console
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
from rich.table import Table
|
|
20
|
+
from rich.text import Text
|
|
21
|
+
|
|
22
|
+
# Initialize Rich console for styled output
|
|
23
|
+
console = Console()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ============================================================================
|
|
27
|
+
# OUTPUT FUNCTIONS
|
|
28
|
+
# ============================================================================
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def success(message: str, detail: Optional[str] = None) -> None:
|
|
32
|
+
"""Print success message in green.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
message: Main success message
|
|
36
|
+
detail: Optional additional detail to display below message
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
>>> success("Credentials encrypted successfully", "Profile: production")
|
|
40
|
+
✓ Credentials encrypted successfully
|
|
41
|
+
Profile: production
|
|
42
|
+
"""
|
|
43
|
+
text = Text()
|
|
44
|
+
text.append("✓ ", style="bold green")
|
|
45
|
+
text.append(message, style="green")
|
|
46
|
+
console.print(text)
|
|
47
|
+
|
|
48
|
+
if detail:
|
|
49
|
+
console.print(f" {detail}", style="dim green")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def error(message: str, detail: Optional[str] = None, exit_code: int = 1) -> None:
|
|
53
|
+
"""Print error message in red and exit.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
message: Main error message
|
|
57
|
+
detail: Optional additional detail (e.g., exception message)
|
|
58
|
+
exit_code: Exit code (default: 1)
|
|
59
|
+
|
|
60
|
+
Example:
|
|
61
|
+
>>> error("Failed to decrypt credentials", "Invalid password")
|
|
62
|
+
✗ Failed to decrypt credentials
|
|
63
|
+
Invalid password
|
|
64
|
+
[Exits with code 1]
|
|
65
|
+
"""
|
|
66
|
+
text = Text()
|
|
67
|
+
text.append("✗ ", style="bold red")
|
|
68
|
+
text.append(message, style="red")
|
|
69
|
+
console.print(text)
|
|
70
|
+
|
|
71
|
+
if detail:
|
|
72
|
+
console.print(f" {detail}", style="dim red")
|
|
73
|
+
|
|
74
|
+
raise SystemExit(exit_code)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def warning(message: str, detail: Optional[str] = None) -> None:
|
|
78
|
+
"""Print warning message in yellow.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
message: Main warning message
|
|
82
|
+
detail: Optional additional detail
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
>>> warning("Profile already exists", "Will overwrite existing credentials")
|
|
86
|
+
⚠ Profile already exists
|
|
87
|
+
Will overwrite existing credentials
|
|
88
|
+
"""
|
|
89
|
+
text = Text()
|
|
90
|
+
text.append("⚠ ", style="bold yellow")
|
|
91
|
+
text.append(message, style="yellow")
|
|
92
|
+
console.print(text)
|
|
93
|
+
|
|
94
|
+
if detail:
|
|
95
|
+
console.print(f" {detail}", style="dim yellow")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def info(message: str, detail: Optional[str] = None) -> None:
|
|
99
|
+
"""Print info message in blue.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
message: Main info message
|
|
103
|
+
detail: Optional additional detail
|
|
104
|
+
|
|
105
|
+
Example:
|
|
106
|
+
>>> info("Loading credentials", "Profile: production")
|
|
107
|
+
ℹ Loading credentials
|
|
108
|
+
Profile: production
|
|
109
|
+
"""
|
|
110
|
+
text = Text()
|
|
111
|
+
text.append("ℹ ", style="bold blue")
|
|
112
|
+
text.append(message, style="blue")
|
|
113
|
+
console.print(text)
|
|
114
|
+
|
|
115
|
+
if detail:
|
|
116
|
+
console.print(f" {detail}", style="dim blue")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def print_message(message: str, style: str = "") -> None:
|
|
120
|
+
"""Print plain message with optional style.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
message: Message to print
|
|
124
|
+
style: Optional Rich style string (e.g., "bold", "dim", "cyan")
|
|
125
|
+
|
|
126
|
+
Example:
|
|
127
|
+
>>> print_message("Processing...", style="dim")
|
|
128
|
+
Processing...
|
|
129
|
+
"""
|
|
130
|
+
console.print(message, style=style)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def print_panel(
|
|
134
|
+
title: str,
|
|
135
|
+
content: str,
|
|
136
|
+
style: str = "blue",
|
|
137
|
+
border_style: str = "blue",
|
|
138
|
+
) -> None:
|
|
139
|
+
"""Print content in a styled panel.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
title: Panel title
|
|
143
|
+
content: Panel content
|
|
144
|
+
style: Content text style
|
|
145
|
+
border_style: Border color style
|
|
146
|
+
|
|
147
|
+
Example:
|
|
148
|
+
>>> print_panel("Configuration", "Region: eu-west-1\\nProfile: prod", style="cyan")
|
|
149
|
+
╭─── Configuration ────╮
|
|
150
|
+
│ Region: eu-west-1 │
|
|
151
|
+
│ Profile: prod │
|
|
152
|
+
╰──────────────────────╯
|
|
153
|
+
"""
|
|
154
|
+
panel = Panel(
|
|
155
|
+
content,
|
|
156
|
+
title=title,
|
|
157
|
+
border_style=border_style,
|
|
158
|
+
title_align="left",
|
|
159
|
+
)
|
|
160
|
+
console.print(panel)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def print_table(
|
|
164
|
+
title: str,
|
|
165
|
+
headers: list[str],
|
|
166
|
+
rows: list[list[str]],
|
|
167
|
+
caption: Optional[str] = None,
|
|
168
|
+
) -> None:
|
|
169
|
+
"""Print data in a formatted table.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
title: Table title
|
|
173
|
+
headers: Column headers
|
|
174
|
+
rows: Table rows (list of lists)
|
|
175
|
+
caption: Optional table caption/footer
|
|
176
|
+
|
|
177
|
+
Example:
|
|
178
|
+
>>> print_table(
|
|
179
|
+
... "Stored Profiles",
|
|
180
|
+
... ["Profile", "Created"],
|
|
181
|
+
... [["production", "2024-01-15"], ["staging", "2024-01-16"]]
|
|
182
|
+
... )
|
|
183
|
+
┏━━━━━━━━━━━┳━━━━━━━━━━━━┓
|
|
184
|
+
┃ Profile ┃ Created ┃
|
|
185
|
+
┡━━━━━━━━━━━╇━━━━━━━━━━━━┩
|
|
186
|
+
│ production│ 2024-01-15 │
|
|
187
|
+
│ staging │ 2024-01-16 │
|
|
188
|
+
└───────────┴────────────┘
|
|
189
|
+
"""
|
|
190
|
+
table = Table(title=title, caption=caption, show_header=True, header_style="bold cyan")
|
|
191
|
+
|
|
192
|
+
# Add columns
|
|
193
|
+
for header in headers:
|
|
194
|
+
table.add_column(header, style="white")
|
|
195
|
+
|
|
196
|
+
# Add rows
|
|
197
|
+
for row in rows:
|
|
198
|
+
table.add_row(*row)
|
|
199
|
+
|
|
200
|
+
console.print(table)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def print_separator(char: str = "─", length: int = 60) -> None:
|
|
204
|
+
"""Print a horizontal separator line.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
char: Character to use for separator
|
|
208
|
+
length: Length of separator
|
|
209
|
+
|
|
210
|
+
Example:
|
|
211
|
+
>>> print_separator()
|
|
212
|
+
────────────────────────────────────────────────────────────
|
|
213
|
+
"""
|
|
214
|
+
console.print(char * length, style="dim")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def print_header(title: str) -> None:
|
|
218
|
+
"""Print a formatted section header.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
title: Header title
|
|
222
|
+
|
|
223
|
+
Example:
|
|
224
|
+
>>> print_header("Credential Configuration")
|
|
225
|
+
|
|
226
|
+
═══════════════════════════════════════════
|
|
227
|
+
Credential Configuration
|
|
228
|
+
═══════════════════════════════════════════
|
|
229
|
+
"""
|
|
230
|
+
console.print()
|
|
231
|
+
console.print("═" * 60, style="cyan")
|
|
232
|
+
console.print(f" {title}", style="bold cyan")
|
|
233
|
+
console.print("═" * 60, style="cyan")
|
|
234
|
+
console.print()
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def confirm(message: str, default: bool = False) -> bool:
|
|
238
|
+
"""Prompt user for yes/no confirmation.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
message: Confirmation question
|
|
242
|
+
default: Default value if user just presses Enter
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
True if user confirms, False otherwise
|
|
246
|
+
|
|
247
|
+
Example:
|
|
248
|
+
>>> if confirm("Delete profile 'production'?"):
|
|
249
|
+
... print("Deleting...")
|
|
250
|
+
Delete profile 'production'? [y/N]: y
|
|
251
|
+
Deleting...
|
|
252
|
+
"""
|
|
253
|
+
suffix = " [Y/n]: " if default else " [y/N]: "
|
|
254
|
+
response = console.input(f"[yellow]{message}{suffix}[/yellow]").strip().lower()
|
|
255
|
+
|
|
256
|
+
if not response:
|
|
257
|
+
return default
|
|
258
|
+
|
|
259
|
+
return response in ("y", "yes")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def prompt(message: str, default: Optional[str] = None, password: bool = False) -> str:
|
|
263
|
+
"""Prompt user for input.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
message: Prompt message
|
|
267
|
+
default: Default value if user just presses Enter
|
|
268
|
+
password: If True, hide input (for passwords)
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
User input string
|
|
272
|
+
|
|
273
|
+
Example:
|
|
274
|
+
>>> name = prompt("Enter profile name", default="default")
|
|
275
|
+
Enter profile name [default]: production
|
|
276
|
+
>>> # Returns: "production"
|
|
277
|
+
"""
|
|
278
|
+
suffix = f" [{default}]: " if default else ": "
|
|
279
|
+
prompt_text = f"[cyan]{message}{suffix}[/cyan]"
|
|
280
|
+
|
|
281
|
+
if password:
|
|
282
|
+
response = console.input(prompt_text, password=True).strip()
|
|
283
|
+
else:
|
|
284
|
+
response = console.input(prompt_text).strip()
|
|
285
|
+
|
|
286
|
+
if not response and default:
|
|
287
|
+
return default
|
|
288
|
+
|
|
289
|
+
return response
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
# ============================================================================
|
|
293
|
+
# OUTPUT HELPER CLASS (FOR COMPATIBILITY)
|
|
294
|
+
# ============================================================================
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class ComplianceOutput:
|
|
298
|
+
"""
|
|
299
|
+
Helper class for output operations.
|
|
300
|
+
|
|
301
|
+
This class wraps the module-level output functions in a class interface
|
|
302
|
+
for convenience and compatibility with existing code.
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
@staticmethod
|
|
306
|
+
def success(message: str, detail: Optional[str] = None) -> None:
|
|
307
|
+
"""Print success message."""
|
|
308
|
+
success(message, detail)
|
|
309
|
+
|
|
310
|
+
@staticmethod
|
|
311
|
+
def error(message: str, detail: Optional[str] = None, exit_code: int = 1) -> None:
|
|
312
|
+
"""Print error message."""
|
|
313
|
+
error(message, detail, exit_code)
|
|
314
|
+
|
|
315
|
+
@staticmethod
|
|
316
|
+
def warning(message: str, detail: Optional[str] = None) -> None:
|
|
317
|
+
"""Print warning message."""
|
|
318
|
+
warning(message, detail)
|
|
319
|
+
|
|
320
|
+
@staticmethod
|
|
321
|
+
def info(message: str, detail: Optional[str] = None) -> None:
|
|
322
|
+
"""Print info message."""
|
|
323
|
+
info(message, detail)
|
|
324
|
+
|
|
325
|
+
@staticmethod
|
|
326
|
+
def print_message(message: str, style: str = "") -> None:
|
|
327
|
+
"""Print plain message."""
|
|
328
|
+
print_message(message, style)
|
|
329
|
+
|
|
330
|
+
@staticmethod
|
|
331
|
+
def prompt(message: str, default: Optional[str] = None) -> str:
|
|
332
|
+
"""Prompt user for input."""
|
|
333
|
+
return prompt(message, default, password=False)
|
|
334
|
+
|
|
335
|
+
@staticmethod
|
|
336
|
+
def prompt_password(message: str) -> str:
|
|
337
|
+
"""Prompt user for password (hidden input)."""
|
|
338
|
+
return prompt(message, password=True)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Configuration management for Complio."""
|
|
2
|
+
|
|
3
|
+
from complio.config.settings import (
|
|
4
|
+
ComplioSettings,
|
|
5
|
+
VALID_AWS_REGIONS,
|
|
6
|
+
VALID_LOG_LEVELS,
|
|
7
|
+
VALID_OUTPUT_FORMATS,
|
|
8
|
+
get_settings,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"ComplioSettings",
|
|
13
|
+
"get_settings",
|
|
14
|
+
"VALID_AWS_REGIONS",
|
|
15
|
+
"VALID_LOG_LEVELS",
|
|
16
|
+
"VALID_OUTPUT_FORMATS",
|
|
17
|
+
]
|