cloudsplaining 0.6.2__tar.gz → 0.7.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.
- cloudsplaining-0.7.0/LICENSE +12 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/PKG-INFO +6 -4
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/README.md +2 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/__init__.py +10 -11
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/bin/cli.py +3 -1
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/bin/version.py +1 -1
- cloudsplaining-0.7.0/cloudsplaining/command/__init__.py +11 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/create_exclusions_file.py +15 -7
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/create_multi_account_config_file.py +17 -10
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/download.py +33 -22
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/expand_policy.py +12 -5
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/scan.py +122 -59
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/scan_multi_account.py +121 -79
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/scan_policy_file.py +54 -84
- cloudsplaining-0.7.0/cloudsplaining/output/dist/js/index.js +63 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/policy_finding.py +46 -49
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/report.py +17 -12
- cloudsplaining-0.7.0/cloudsplaining/output/src/components/Summary.vue +167 -0
- cloudsplaining-0.7.0/cloudsplaining/output/src/components/charts/SummaryFindings.vue +124 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/assume_role_policy_document.py +7 -8
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/authorization_details.py +17 -25
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/group_details.py +40 -59
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/inline_policy.py +83 -92
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/managed_policy_detail.py +100 -122
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/policy_document.py +58 -85
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/resource_policy_document.py +8 -19
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/role_details.py +45 -64
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/statement_detail.py +49 -76
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/user_details.py +42 -61
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/aws_login.py +14 -21
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/constants.py +6 -5
- cloudsplaining-0.7.0/cloudsplaining/shared/exceptions.py +2 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/exclusions.py +26 -25
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/utils.py +19 -27
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/validation.py +9 -8
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/PKG-INFO +6 -4
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/SOURCES.txt +2 -1
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/requires.txt +1 -1
- cloudsplaining-0.7.0/pyproject.toml +79 -0
- cloudsplaining-0.7.0/setup.cfg +4 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/setup.py +31 -43
- cloudsplaining-0.6.2/cloudsplaining/command/__init__.py +0 -8
- cloudsplaining-0.6.2/cloudsplaining/output/dist/js/index.js +0 -334
- cloudsplaining-0.6.2/cloudsplaining/output/src/components/Summary.vue +0 -164
- cloudsplaining-0.6.2/cloudsplaining/output/src/components/charts/SummaryFindings.vue +0 -108
- cloudsplaining-0.6.2/cloudsplaining/shared/exceptions.py +0 -3
- cloudsplaining-0.6.2/setup.cfg +0 -38
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/MANIFEST.in +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/bin/__init__.py +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/__init__.py +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/dist/index.html +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/dist/js/chunk-vendors.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/public/index.html +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/App.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/1-overview.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/2-triage-guidance.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/3-remediation-guidance.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/4-validation.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-assumable-by-compute-service.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-credentials-exposure.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-data-exfiltration.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-infrastructure-modification.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-privilege-escalation.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-resource-exposure.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/definition-service-wildcard.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/glossary.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/how-do-i-validate-results.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/identifying-false-positives.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/logo.png +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/summary.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/assets/what-should-i-do.md +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/Appendix.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/Button.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/Glossary.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/Guidance.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/InlinePolicies.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/LinkToFinding.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/ManagedPolicies.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/PolicyTable.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/Principals.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/ReportMetadata.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/TaskTable.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/AssumeRoleDetails.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/FindingCard.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/FindingDetails.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/PolicyDocumentDetails.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/PrivilegeEscalationDetails.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/PrivilegeEscalationFormat.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/RiskAlertIndicators.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/finding/StandardRiskDetails.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/principals/PrincipalMetadata.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/components/principals/RisksPerPrincipal.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/main.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/routes/routes.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/sampleData.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/groups-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/inline-policies-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/managed-policies-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/other-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/principals-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/roles-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/test/task-table-test.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/glossary.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/groups.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/inline-policies.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/managed-policies.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/other.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/principals.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/roles.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/util/task-table.js +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/Appendices.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/AwsPolicies.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/CustomerPolicies.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/Guidance.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/IamPrincipals.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/InlinePolicies.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/src/views/Summary.vue +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/output/template.html +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/py.typed +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/scan/__init__.py +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/__init__.py +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/default-exclusions.yml +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/shared/multi-account-config.yml +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/dependency_links.txt +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/entry_points.txt +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/top_level.txt +0 -0
- {cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining.egg-info/zip-safe +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Copyright (c) 2020, Salesforce.com, Inc.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
7
|
+
|
|
8
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
9
|
+
|
|
10
|
+
* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
11
|
+
|
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cloudsplaining
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: AWS IAM Security Assessment tool that identifies violations of least privilege and generates a risk-prioritized HTML report.
|
|
5
5
|
Home-page: https://github.com/salesforce/cloudsplaining
|
|
6
6
|
Author: Kinnaird McQuade
|
|
@@ -11,7 +11,9 @@ Project-URL: Example Report, https://opensource.salesforce.com/cloudsplaining
|
|
|
11
11
|
Project-URL: Code, https://github.com/salesforce/cloudsplaining/
|
|
12
12
|
Project-URL: Twitter, https://twitter.com/kmcquade3
|
|
13
13
|
Project-URL: Red Team Report, https://opensource.salesforce.com/policy_sentry
|
|
14
|
-
Description:
|
|
14
|
+
Description: ## NOTE: This repo/project has been restored by Salesforce.
|
|
15
|
+
|
|
16
|
+
Cloudsplaining
|
|
15
17
|
--------------
|
|
16
18
|
|
|
17
19
|
Cloudsplaining is an AWS IAM Security Assessment tool that identifies violations of least privilege and generates a risk-prioritized HTML report.
|
|
@@ -400,13 +402,13 @@ Description: Cloudsplaining
|
|
|
400
402
|
Keywords: aws iam roles policy policies privileges security
|
|
401
403
|
Platform: UNKNOWN
|
|
402
404
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
403
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
404
405
|
Classifier: Programming Language :: Python :: 3.8
|
|
405
406
|
Classifier: Programming Language :: Python :: 3.9
|
|
406
407
|
Classifier: Programming Language :: Python :: 3.10
|
|
407
408
|
Classifier: Programming Language :: Python :: 3.11
|
|
408
409
|
Classifier: Programming Language :: Python :: 3.12
|
|
410
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
409
411
|
Classifier: License :: OSI Approved :: MIT License
|
|
410
412
|
Classifier: Operating System :: OS Independent
|
|
411
|
-
Requires-Python: >=3.
|
|
413
|
+
Requires-Python: >=3.8
|
|
412
414
|
Description-Content-Type: text/markdown
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
# pylint: disable=missing-module-docstring
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
2
4
|
import logging
|
|
3
5
|
import sys
|
|
4
6
|
|
|
5
7
|
# Set default logging handler to avoid "No handler found" warnings.
|
|
6
|
-
from logging import NullHandler
|
|
7
|
-
|
|
8
|
+
# from logging import NullHandler
|
|
8
9
|
# logging.getLogger(__name__).addHandler(NullHandler())
|
|
9
10
|
# Uncomment to get the full debug logs.
|
|
10
11
|
# 2020-10-06 10:04:17,200 - root - DEBUG - Leveraging the bundled IAM Definition.
|
|
11
12
|
# Need to figure out how to get click_log to do this for me.
|
|
12
|
-
from typing import Union, Optional
|
|
13
|
-
|
|
14
13
|
logger = logging.getLogger(__name__)
|
|
15
14
|
logger.setLevel(logging.WARNING)
|
|
16
15
|
handler = logging.StreamHandler(sys.stdout)
|
|
@@ -23,8 +22,8 @@ logger.addHandler(handler)
|
|
|
23
22
|
name = "cloudsplaining" # pylint: disable=invalid-name
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
def change_log_level(log_level:
|
|
27
|
-
""""Change log level of module logger"""
|
|
25
|
+
def change_log_level(log_level: int | str) -> None:
|
|
26
|
+
""" "Change log level of module logger"""
|
|
28
27
|
logger.setLevel(log_level)
|
|
29
28
|
|
|
30
29
|
|
|
@@ -32,7 +31,7 @@ def change_log_level(log_level: Union[int, str]) -> None:
|
|
|
32
31
|
def set_stream_logger(
|
|
33
32
|
name: str = "cloudsplaining",
|
|
34
33
|
level: int = logging.DEBUG,
|
|
35
|
-
format_string:
|
|
34
|
+
format_string: str | None = None,
|
|
36
35
|
) -> None:
|
|
37
36
|
"""
|
|
38
37
|
Add a stream handler for the given name and level to the logging module.
|
|
@@ -71,10 +70,10 @@ def set_log_level(verbose: int) -> None:
|
|
|
71
70
|
:return:
|
|
72
71
|
"""
|
|
73
72
|
if verbose == 1:
|
|
74
|
-
set_stream_logger(level=
|
|
73
|
+
set_stream_logger(level=logging.WARNING)
|
|
75
74
|
elif verbose == 2:
|
|
76
|
-
set_stream_logger(level=
|
|
75
|
+
set_stream_logger(level=logging.INFO)
|
|
77
76
|
elif verbose >= 3:
|
|
78
|
-
set_stream_logger(level=
|
|
77
|
+
set_stream_logger(level=logging.DEBUG)
|
|
79
78
|
else:
|
|
80
|
-
set_stream_logger(level=
|
|
79
|
+
set_stream_logger(level=logging.CRITICAL)
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
# For full license text, see the LICENSE file in the repo root
|
|
6
6
|
# or https://opensource.org/licenses/BSD-3-Clause
|
|
7
7
|
"""
|
|
8
|
-
|
|
8
|
+
Cloudsplaining is an AWS IAM Assessment tool that identifies violations of least privilege and generates a risk-prioritized HTML report with a triage worksheet.
|
|
9
9
|
"""
|
|
10
|
+
|
|
10
11
|
import click
|
|
12
|
+
|
|
11
13
|
from cloudsplaining import command
|
|
12
14
|
from cloudsplaining.bin.version import __version__
|
|
13
15
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# pylint: disable=missing-module-docstring
|
|
2
|
-
__version__ =
|
|
2
|
+
__version__ = "0.7.0"
|
{cloudsplaining-0.6.2 → cloudsplaining-0.7.0}/cloudsplaining/command/create_exclusions_file.py
RENAMED
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
Create YML Template files for the exclusions template command.
|
|
3
3
|
This way, users don't have to remember exactly how to phrase the yaml files, since this command creates it for them.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
# Copyright (c) 2020, salesforce.com, inc.
|
|
6
7
|
# All rights reserved.
|
|
7
8
|
# Licensed under the BSD 3-Clause license.
|
|
8
9
|
# For full license text, see the LICENSE file in the repo root
|
|
9
10
|
# or https://opensource.org/licenses/BSD-3-Clause
|
|
10
|
-
import os
|
|
11
11
|
import logging
|
|
12
|
+
import os
|
|
13
|
+
|
|
12
14
|
import click
|
|
13
|
-
|
|
15
|
+
|
|
14
16
|
from cloudsplaining import set_log_level
|
|
15
17
|
from cloudsplaining.shared import utils
|
|
18
|
+
from cloudsplaining.shared.constants import EXCLUSIONS_TEMPLATE
|
|
16
19
|
|
|
17
20
|
logger = logging.getLogger(__name__)
|
|
18
21
|
|
|
@@ -21,7 +24,14 @@ logger = logging.getLogger(__name__)
|
|
|
21
24
|
context_settings=dict(max_content_width=160),
|
|
22
25
|
short_help="Creates a YML file to be used as a custom exclusions template",
|
|
23
26
|
)
|
|
24
|
-
@click.option(
|
|
27
|
+
@click.option(
|
|
28
|
+
"-o",
|
|
29
|
+
"--output-file",
|
|
30
|
+
type=click.Path(exists=False),
|
|
31
|
+
default=os.path.join(os.getcwd(), "exclusions.yml"),
|
|
32
|
+
required=True,
|
|
33
|
+
help="Relative path to output file where we want to store the exclusions template.",
|
|
34
|
+
)
|
|
25
35
|
@click.option("--verbose", "-v", "verbosity", count=True)
|
|
26
36
|
def create_exclusions_file(output_file: str, verbosity: int) -> None:
|
|
27
37
|
"""
|
|
@@ -30,7 +40,7 @@ def create_exclusions_file(output_file: str, verbosity: int) -> None:
|
|
|
30
40
|
"""
|
|
31
41
|
set_log_level(verbosity)
|
|
32
42
|
|
|
33
|
-
with open(output_file, "a") as file_obj:
|
|
43
|
+
with open(output_file, "a", encoding="utf-8") as file_obj:
|
|
34
44
|
for line in EXCLUSIONS_TEMPLATE:
|
|
35
45
|
file_obj.write(line)
|
|
36
46
|
utils.print_green(f"Success! Exclusions template file written to: {output_file}")
|
|
@@ -40,6 +50,4 @@ def create_exclusions_file(output_file: str, verbosity: int) -> None:
|
|
|
40
50
|
)
|
|
41
51
|
print("\tcloudsplaining download")
|
|
42
52
|
print("You can use this with the scan command as shown below: ")
|
|
43
|
-
print(
|
|
44
|
-
"\tcloudsplaining scan --exclusions-file exclusions.yml --input-file default.json"
|
|
45
|
-
)
|
|
53
|
+
print("\tcloudsplaining scan --exclusions-file exclusions.yml --input-file default.json")
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
Create YML Template files for the exclusions template command.
|
|
3
3
|
This way, users don't have to remember exactly how to phrase the yaml files, since this command creates it for them.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
# Copyright (c) 2020, salesforce.com, inc.
|
|
6
7
|
# All rights reserved.
|
|
7
8
|
# Licensed under the BSD 3-Clause license.
|
|
8
9
|
# For full license text, see the LICENSE file in the repo root
|
|
9
10
|
# or https://opensource.org/licenses/BSD-3-Clause
|
|
10
|
-
import os
|
|
11
11
|
import logging
|
|
12
|
+
import os
|
|
13
|
+
|
|
12
14
|
import click
|
|
13
|
-
|
|
15
|
+
|
|
14
16
|
from cloudsplaining import set_log_level
|
|
15
17
|
from cloudsplaining.shared import utils
|
|
18
|
+
from cloudsplaining.shared.constants import MULTI_ACCOUNT_CONFIG_TEMPLATE
|
|
16
19
|
|
|
17
20
|
logger = logging.getLogger(__name__)
|
|
18
21
|
OK_GREEN = "\033[92m"
|
|
@@ -23,7 +26,15 @@ END = "\033[0m"
|
|
|
23
26
|
context_settings=dict(max_content_width=160),
|
|
24
27
|
short_help="Creates a YML file to be used for multi-account scanning",
|
|
25
28
|
)
|
|
26
|
-
@click.option(
|
|
29
|
+
@click.option(
|
|
30
|
+
"-o",
|
|
31
|
+
"--output-file",
|
|
32
|
+
"output_file",
|
|
33
|
+
type=click.Path(exists=False),
|
|
34
|
+
default=os.path.join(os.getcwd(), "multi-account-config.yml"),
|
|
35
|
+
required=True,
|
|
36
|
+
help="Relative path to output file where we want to store the multi account config template.",
|
|
37
|
+
)
|
|
27
38
|
@click.option("-v", "--verbose", "verbosity", help="Log verbosity level.", count=True)
|
|
28
39
|
def create_multi_account_config_file(output_file: str, verbosity: int) -> None:
|
|
29
40
|
"""
|
|
@@ -32,17 +43,13 @@ def create_multi_account_config_file(output_file: str, verbosity: int) -> None:
|
|
|
32
43
|
set_log_level(verbosity)
|
|
33
44
|
|
|
34
45
|
if os.path.exists(output_file):
|
|
35
|
-
logger.debug(
|
|
36
|
-
"%s exists. Removing the file and replacing its contents.", output_file
|
|
37
|
-
)
|
|
46
|
+
logger.debug("%s exists. Removing the file and replacing its contents.", output_file)
|
|
38
47
|
os.remove(output_file)
|
|
39
48
|
|
|
40
|
-
with open(output_file, "a") as file_obj:
|
|
49
|
+
with open(output_file, "a", encoding="utf-8") as file_obj:
|
|
41
50
|
for line in MULTI_ACCOUNT_CONFIG_TEMPLATE:
|
|
42
51
|
file_obj.write(line)
|
|
43
|
-
utils.print_green(
|
|
44
|
-
f"Success! Multi-account config file written to: {os.path.relpath(output_file)}"
|
|
45
|
-
)
|
|
52
|
+
utils.print_green(f"Success! Multi-account config file written to: {os.path.relpath(output_file)}")
|
|
46
53
|
print(
|
|
47
54
|
f"\nMake sure you edit the {os.path.relpath(output_file)} file and then run the scan-multi-account command, as shown below."
|
|
48
55
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Runs aws iam get-authorization-details on all accounts specified in the aws credentials file, and stores them in
|
|
2
|
-
account-alias.json
|
|
2
|
+
account-alias.json"""
|
|
3
|
+
|
|
3
4
|
# Copyright (c) 2020, salesforce.com, inc.
|
|
4
5
|
# All rights reserved.
|
|
5
6
|
# Licensed under the BSD 3-Clause license.
|
|
@@ -10,7 +11,7 @@ from __future__ import annotations
|
|
|
10
11
|
import json
|
|
11
12
|
import logging
|
|
12
13
|
import os
|
|
13
|
-
from typing import
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
14
15
|
|
|
15
16
|
import boto3
|
|
16
17
|
import click
|
|
@@ -28,13 +29,29 @@ logger = logging.getLogger(__name__)
|
|
|
28
29
|
short_help="Runs aws iam get-authorization-details on all accounts specified in the aws credentials "
|
|
29
30
|
"file, and stores them in account-alias.json"
|
|
30
31
|
)
|
|
31
|
-
@click.option(
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
@click.option(
|
|
33
|
+
"-p",
|
|
34
|
+
"--profile",
|
|
35
|
+
type=str,
|
|
36
|
+
required=False,
|
|
37
|
+
envvar="AWS_DEFAULT_PROFILE",
|
|
38
|
+
help="Specify 'all' to authenticate to AWS and scan from *all* AWS credentials profiles. Specify a non-default profile here. Defaults to the 'default' profile.",
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
"-o",
|
|
42
|
+
"--output",
|
|
43
|
+
type=click.Path(exists=True),
|
|
44
|
+
default=os.getcwd(),
|
|
45
|
+
help="Path to store the output. Defaults to current directory.",
|
|
46
|
+
)
|
|
47
|
+
@click.option(
|
|
48
|
+
"--include-non-default-policy-versions",
|
|
49
|
+
is_flag=True,
|
|
50
|
+
default=False,
|
|
51
|
+
help="When downloading AWS managed policy documents, also include the non-default policy versions. Note that this will dramatically increase the size of the downloaded file.",
|
|
52
|
+
)
|
|
34
53
|
@click.option("-v", "--verbose", "verbosity", help="Log verbosity level.", count=True)
|
|
35
|
-
def download(
|
|
36
|
-
profile: str, output: str, include_non_default_policy_versions: bool, verbosity: int
|
|
37
|
-
) -> int:
|
|
54
|
+
def download(profile: str, output: str, include_non_default_policy_versions: bool, verbosity: int) -> int:
|
|
38
55
|
"""
|
|
39
56
|
Runs aws iam get-authorization-details on all accounts specified in the aws credentials file, and stores them in
|
|
40
57
|
account-alias.json
|
|
@@ -50,10 +67,8 @@ def download(
|
|
|
50
67
|
else:
|
|
51
68
|
output_filename = os.path.join(output, "default.json")
|
|
52
69
|
|
|
53
|
-
results = get_account_authorization_details(
|
|
54
|
-
|
|
55
|
-
)
|
|
56
|
-
with open(output_filename, "w") as f:
|
|
70
|
+
results = get_account_authorization_details(session_data, include_non_default_policy_versions)
|
|
71
|
+
with open(output_filename, "w", encoding="utf-8") as f:
|
|
57
72
|
json.dump(results, f, indent=4, default=str)
|
|
58
73
|
# output_filename.write_text(json.dumps(results, indent=4, default=str))
|
|
59
74
|
print(f"Saved results to {output_filename}")
|
|
@@ -61,14 +76,14 @@ def download(
|
|
|
61
76
|
|
|
62
77
|
|
|
63
78
|
def get_account_authorization_details(
|
|
64
|
-
session_data:
|
|
65
|
-
) ->
|
|
79
|
+
session_data: dict[str, str], include_non_default_policy_versions: bool
|
|
80
|
+
) -> dict[str, list[Any]]:
|
|
66
81
|
"""Runs aws-iam-get-account-authorization-details"""
|
|
67
|
-
session = boto3.Session(**session_data) # type:ignore[arg-type]
|
|
82
|
+
session = boto3.Session(**session_data) # type:ignore[arg-type]
|
|
68
83
|
config = Config(connect_timeout=5, retries={"max_attempts": 10})
|
|
69
84
|
iam_client: IAMClient = session.client("iam", config=config)
|
|
70
85
|
|
|
71
|
-
results:
|
|
86
|
+
results: dict[str, list[Any]] = {
|
|
72
87
|
"UserDetailList": [],
|
|
73
88
|
"GroupDetailList": [],
|
|
74
89
|
"RoleDetailList": [],
|
|
@@ -100,9 +115,7 @@ def get_account_authorization_details(
|
|
|
100
115
|
else:
|
|
101
116
|
policy_version_list = []
|
|
102
117
|
for policy_version in policy.get("PolicyVersionList") or []:
|
|
103
|
-
if policy_version.get("VersionId") == policy.get(
|
|
104
|
-
"DefaultVersionId"
|
|
105
|
-
):
|
|
118
|
+
if policy_version.get("VersionId") == policy.get("DefaultVersionId"):
|
|
106
119
|
policy_version_list.append(policy_version)
|
|
107
120
|
break
|
|
108
121
|
entry = {
|
|
@@ -112,9 +125,7 @@ def get_account_authorization_details(
|
|
|
112
125
|
"Path": policy.get("Path"),
|
|
113
126
|
"DefaultVersionId": policy.get("DefaultVersionId"),
|
|
114
127
|
"AttachmentCount": policy.get("AttachmentCount"),
|
|
115
|
-
"PermissionsBoundaryUsageCount": policy.get(
|
|
116
|
-
"PermissionsBoundaryUsageCount"
|
|
117
|
-
),
|
|
128
|
+
"PermissionsBoundaryUsageCount": policy.get("PermissionsBoundaryUsageCount"),
|
|
118
129
|
"IsAttachable": policy.get("IsAttachable"),
|
|
119
130
|
"CreateDate": policy.get("CreateDate"),
|
|
120
131
|
"UpdateDate": policy.get("UpdateDate"),
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Expands the wildcards (*) on an IAM policy file so it is easier for a human to understand. Example: s3:g* vs s3:GetObject, s3:GetObjectAcl, etc.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
# Copyright (c) 2020, salesforce.com, inc.
|
|
5
6
|
# All rights reserved.
|
|
6
7
|
# Licensed under the BSD 3-Clause license.
|
|
7
8
|
# For full license text, see the LICENSE file in the repo rootgit pus
|
|
8
9
|
# or https://opensource.org/licenses/BSD-3-Clause
|
|
9
|
-
import logging
|
|
10
10
|
import json
|
|
11
|
+
import logging
|
|
12
|
+
|
|
11
13
|
import click
|
|
12
14
|
from policy_sentry.analysis.expand import get_expanded_policy
|
|
15
|
+
|
|
13
16
|
from cloudsplaining import set_log_level
|
|
14
17
|
|
|
15
18
|
logger = logging.getLogger(__name__)
|
|
16
19
|
|
|
17
20
|
|
|
18
|
-
@click.command(
|
|
19
|
-
|
|
21
|
+
@click.command(short_help="Expand the * Actions in IAM policy files to improve readability")
|
|
22
|
+
@click.option(
|
|
23
|
+
"-i",
|
|
24
|
+
"--input-file",
|
|
25
|
+
type=click.Path(exists=True),
|
|
26
|
+
required=True,
|
|
27
|
+
help="Path to the JSON policy file.",
|
|
20
28
|
)
|
|
21
|
-
@click.option("-i", "--input-file", type=click.Path(exists=True), required=True, help="Path to the JSON policy file.")
|
|
22
29
|
@click.option("-v", "--verbose", "verbosity", help="Log verbosity level.", count=True)
|
|
23
30
|
def expand_policy(input_file: str, verbosity: int) -> None:
|
|
24
31
|
"""
|
|
@@ -26,7 +33,7 @@ def expand_policy(input_file: str, verbosity: int) -> None:
|
|
|
26
33
|
"""
|
|
27
34
|
set_log_level(verbosity)
|
|
28
35
|
|
|
29
|
-
with open(input_file) as json_file:
|
|
36
|
+
with open(input_file, encoding="utf-8") as json_file:
|
|
30
37
|
logger.debug(f"Opening {input_file}")
|
|
31
38
|
data = json.load(json_file)
|
|
32
39
|
policy = get_expanded_policy(data)
|