mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-25 21:04:19 +00:00
Merge branch 'master' into PRWLR-5989-ensure-that-spf-records-are-published-for-all-exchange
This commit is contained in:
128 files changed
+10577
-2149
No files matched your search
@@ -12,6 +12,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.merge_commit_sha }}
|
||||
|
||||
- name: Set short git commit SHA
|
||||
id: vars
|
||||
|
||||
@@ -86,11 +86,11 @@ prowler dashboard
|
||||
|
||||
| Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/compliance/) | [Categories](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/misc/#categories) |
|
||||
|---|---|---|---|---|
|
||||
| AWS | 564 | 82 | 33 | 10 |
|
||||
| AWS | 564 | 82 | 34 | 10 |
|
||||
| GCP | 79 | 13 | 7 | 3 |
|
||||
| Azure | 140 | 18 | 8 | 3 |
|
||||
| Kubernetes | 83 | 7 | 4 | 7 |
|
||||
| GitHub | 1 | 1 | 1 | 0 |
|
||||
| GitHub | 3 | 2 | 1 | 0 |
|
||||
| M365 | 44 | 2 | 2 | 0 |
|
||||
| NHN (Unofficial) | 6 | 2 | 1 | 0 |
|
||||
|
||||
|
||||
+3
-1
@@ -2,12 +2,14 @@
|
||||
|
||||
All notable changes to the **Prowler API** are documented in this file.
|
||||
|
||||
## [v1.8.0] (Prowler UNRELEASED)
|
||||
## [v1.8.0] (Prowler v5.7.0)
|
||||
|
||||
### Added
|
||||
- Added huge improvements to `/findings/metadata` and resource related filters for findings [(#7690)](https://github.com/prowler-cloud/prowler/pull/7690).
|
||||
- Added improvements to `/overviews` endpoints [(#7690)](https://github.com/prowler-cloud/prowler/pull/7690).
|
||||
- Added new queue to perform backfill background tasks [(#7690)](https://github.com/prowler-cloud/prowler/pull/7690).
|
||||
- Added new endpoints to retrieve latest findings and metadata [(#7743)](https://github.com/prowler-cloud/prowler/pull/7743).
|
||||
- Added export support for Prowler ThreatScore in M365 [(7783)](https://github.com/prowler-cloud/prowler/pull/7783)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+134
-98
@@ -81,6 +81,114 @@ class ChoiceInFilter(BaseInFilter, ChoiceFilter):
|
||||
pass
|
||||
|
||||
|
||||
class CommonFindingFilters(FilterSet):
|
||||
# We filter providers from the scan in findings
|
||||
provider = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
|
||||
provider__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
|
||||
)
|
||||
provider_uid = CharFilter(field_name="scan__provider__uid", lookup_expr="exact")
|
||||
provider_uid__in = CharInFilter(field_name="scan__provider__uid", lookup_expr="in")
|
||||
provider_uid__icontains = CharFilter(
|
||||
field_name="scan__provider__uid", lookup_expr="icontains"
|
||||
)
|
||||
provider_alias = CharFilter(field_name="scan__provider__alias", lookup_expr="exact")
|
||||
provider_alias__in = CharInFilter(
|
||||
field_name="scan__provider__alias", lookup_expr="in"
|
||||
)
|
||||
provider_alias__icontains = CharFilter(
|
||||
field_name="scan__provider__alias", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
updated_at = DateFilter(field_name="updated_at", lookup_expr="date")
|
||||
|
||||
uid = CharFilter(field_name="uid")
|
||||
delta = ChoiceFilter(choices=Finding.DeltaChoices.choices)
|
||||
status = ChoiceFilter(choices=StatusChoices.choices)
|
||||
severity = ChoiceFilter(choices=SeverityChoices)
|
||||
impact = ChoiceFilter(choices=SeverityChoices)
|
||||
muted = BooleanFilter(
|
||||
help_text="If this filter is not provided, muted and non-muted findings will be returned."
|
||||
)
|
||||
|
||||
resources = UUIDInFilter(field_name="resource__id", lookup_expr="in")
|
||||
|
||||
region = CharFilter(method="filter_resource_region")
|
||||
region__in = CharInFilter(field_name="resource_regions", lookup_expr="overlap")
|
||||
region__icontains = CharFilter(
|
||||
field_name="resource_regions", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
service = CharFilter(method="filter_resource_service")
|
||||
service__in = CharInFilter(field_name="resource_services", lookup_expr="overlap")
|
||||
service__icontains = CharFilter(
|
||||
field_name="resource_services", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
resource_uid = CharFilter(field_name="resources__uid")
|
||||
resource_uid__in = CharInFilter(field_name="resources__uid", lookup_expr="in")
|
||||
resource_uid__icontains = CharFilter(
|
||||
field_name="resources__uid", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
resource_name = CharFilter(field_name="resources__name")
|
||||
resource_name__in = CharInFilter(field_name="resources__name", lookup_expr="in")
|
||||
resource_name__icontains = CharFilter(
|
||||
field_name="resources__name", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
resource_type = CharFilter(method="filter_resource_type")
|
||||
resource_type__in = CharInFilter(field_name="resource_types", lookup_expr="overlap")
|
||||
resource_type__icontains = CharFilter(
|
||||
field_name="resources__type", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
# Temporarily disabled until we implement tag filtering in the UI
|
||||
# resource_tag_key = CharFilter(field_name="resources__tags__key")
|
||||
# resource_tag_key__in = CharInFilter(
|
||||
# field_name="resources__tags__key", lookup_expr="in"
|
||||
# )
|
||||
# resource_tag_key__icontains = CharFilter(
|
||||
# field_name="resources__tags__key", lookup_expr="icontains"
|
||||
# )
|
||||
# resource_tag_value = CharFilter(field_name="resources__tags__value")
|
||||
# resource_tag_value__in = CharInFilter(
|
||||
# field_name="resources__tags__value", lookup_expr="in"
|
||||
# )
|
||||
# resource_tag_value__icontains = CharFilter(
|
||||
# field_name="resources__tags__value", lookup_expr="icontains"
|
||||
# )
|
||||
# resource_tags = CharInFilter(
|
||||
# method="filter_resource_tag",
|
||||
# lookup_expr="in",
|
||||
# help_text="Filter by resource tags `key:value` pairs.\nMultiple values may be "
|
||||
# "separated by commas.",
|
||||
# )
|
||||
|
||||
def filter_resource_service(self, queryset, name, value):
|
||||
return queryset.filter(resource_services__contains=[value])
|
||||
|
||||
def filter_resource_region(self, queryset, name, value):
|
||||
return queryset.filter(resource_regions__contains=[value])
|
||||
|
||||
def filter_resource_type(self, queryset, name, value):
|
||||
return queryset.filter(resource_types__contains=[value])
|
||||
|
||||
def filter_resource_tag(self, queryset, name, value):
|
||||
overall_query = Q()
|
||||
for key_value_pair in value:
|
||||
tag_key, tag_value = key_value_pair.split(":", 1)
|
||||
overall_query |= Q(
|
||||
resources__tags__key__icontains=tag_key,
|
||||
resources__tags__value__icontains=tag_value,
|
||||
)
|
||||
return queryset.filter(overall_query).distinct()
|
||||
|
||||
|
||||
class TenantFilter(FilterSet):
|
||||
inserted_at = DateFilter(field_name="inserted_at", lookup_expr="date")
|
||||
updated_at = DateFilter(field_name="updated_at", lookup_expr="date")
|
||||
@@ -257,94 +365,7 @@ class ResourceFilter(ProviderRelationshipFilterSet):
|
||||
return queryset.filter(tags__text_search=value)
|
||||
|
||||
|
||||
class FindingFilter(FilterSet):
|
||||
# We filter providers from the scan in findings
|
||||
provider = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
|
||||
provider__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
|
||||
)
|
||||
provider_uid = CharFilter(field_name="scan__provider__uid", lookup_expr="exact")
|
||||
provider_uid__in = CharInFilter(field_name="scan__provider__uid", lookup_expr="in")
|
||||
provider_uid__icontains = CharFilter(
|
||||
field_name="scan__provider__uid", lookup_expr="icontains"
|
||||
)
|
||||
provider_alias = CharFilter(field_name="scan__provider__alias", lookup_expr="exact")
|
||||
provider_alias__in = CharInFilter(
|
||||
field_name="scan__provider__alias", lookup_expr="in"
|
||||
)
|
||||
provider_alias__icontains = CharFilter(
|
||||
field_name="scan__provider__alias", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
updated_at = DateFilter(field_name="updated_at", lookup_expr="date")
|
||||
|
||||
uid = CharFilter(field_name="uid")
|
||||
delta = ChoiceFilter(choices=Finding.DeltaChoices.choices)
|
||||
status = ChoiceFilter(choices=StatusChoices.choices)
|
||||
severity = ChoiceFilter(choices=SeverityChoices)
|
||||
impact = ChoiceFilter(choices=SeverityChoices)
|
||||
muted = BooleanFilter(
|
||||
help_text="If this filter is not provided, muted and non-muted findings will be returned."
|
||||
)
|
||||
|
||||
resources = UUIDInFilter(field_name="resource__id", lookup_expr="in")
|
||||
|
||||
region = CharFilter(method="filter_resource_region")
|
||||
region__in = CharInFilter(field_name="resource_regions", lookup_expr="overlap")
|
||||
region__icontains = CharFilter(
|
||||
field_name="resource_regions", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
service = CharFilter(method="filter_resource_service")
|
||||
service__in = CharInFilter(field_name="resource_services", lookup_expr="overlap")
|
||||
service__icontains = CharFilter(
|
||||
field_name="resource_services", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
resource_uid = CharFilter(field_name="resources__uid")
|
||||
resource_uid__in = CharInFilter(field_name="resources__uid", lookup_expr="in")
|
||||
resource_uid__icontains = CharFilter(
|
||||
field_name="resources__uid", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
resource_name = CharFilter(field_name="resources__name")
|
||||
resource_name__in = CharInFilter(field_name="resources__name", lookup_expr="in")
|
||||
resource_name__icontains = CharFilter(
|
||||
field_name="resources__name", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
resource_type = CharFilter(method="filter_resource_type")
|
||||
resource_type__in = CharInFilter(field_name="resource_types", lookup_expr="overlap")
|
||||
resource_type__icontains = CharFilter(
|
||||
field_name="resources__type", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
# Temporarily disabled until we implement tag filtering in the UI
|
||||
# resource_tag_key = CharFilter(field_name="resources__tags__key")
|
||||
# resource_tag_key__in = CharInFilter(
|
||||
# field_name="resources__tags__key", lookup_expr="in"
|
||||
# )
|
||||
# resource_tag_key__icontains = CharFilter(
|
||||
# field_name="resources__tags__key", lookup_expr="icontains"
|
||||
# )
|
||||
# resource_tag_value = CharFilter(field_name="resources__tags__value")
|
||||
# resource_tag_value__in = CharInFilter(
|
||||
# field_name="resources__tags__value", lookup_expr="in"
|
||||
# )
|
||||
# resource_tag_value__icontains = CharFilter(
|
||||
# field_name="resources__tags__value", lookup_expr="icontains"
|
||||
# )
|
||||
# resource_tags = CharInFilter(
|
||||
# method="filter_resource_tag",
|
||||
# lookup_expr="in",
|
||||
# help_text="Filter by resource tags `key:value` pairs.\nMultiple values may be "
|
||||
# "separated by commas.",
|
||||
# )
|
||||
|
||||
class FindingFilter(CommonFindingFilters):
|
||||
scan = UUIDFilter(method="filter_scan_id")
|
||||
scan__in = UUIDInFilter(method="filter_scan_id_in")
|
||||
|
||||
@@ -512,16 +533,6 @@ class FindingFilter(FilterSet):
|
||||
|
||||
return queryset.filter(id__lt=end)
|
||||
|
||||
def filter_resource_tag(self, queryset, name, value):
|
||||
overall_query = Q()
|
||||
for key_value_pair in value:
|
||||
tag_key, tag_value = key_value_pair.split(":", 1)
|
||||
overall_query |= Q(
|
||||
resources__tags__key__icontains=tag_key,
|
||||
resources__tags__value__icontains=tag_value,
|
||||
)
|
||||
return queryset.filter(overall_query).distinct()
|
||||
|
||||
@staticmethod
|
||||
def maybe_date_to_datetime(value):
|
||||
dt = value
|
||||
@@ -530,6 +541,31 @@ class FindingFilter(FilterSet):
|
||||
return dt
|
||||
|
||||
|
||||
class LatestFindingFilter(CommonFindingFilters):
|
||||
class Meta:
|
||||
model = Finding
|
||||
fields = {
|
||||
"id": ["exact", "in"],
|
||||
"uid": ["exact", "in"],
|
||||
"delta": ["exact", "in"],
|
||||
"status": ["exact", "in"],
|
||||
"severity": ["exact", "in"],
|
||||
"impact": ["exact", "in"],
|
||||
"check_id": ["exact", "in", "icontains"],
|
||||
}
|
||||
filter_overrides = {
|
||||
FindingDeltaEnumField: {
|
||||
"filter_class": CharFilter,
|
||||
},
|
||||
StatusEnumField: {
|
||||
"filter_class": CharFilter,
|
||||
},
|
||||
SeverityEnumField: {
|
||||
"filter_class": CharFilter,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class ProviderSecretFilter(FilterSet):
|
||||
inserted_at = DateFilter(field_name="inserted_at", lookup_expr="date")
|
||||
updated_at = DateFilter(field_name="updated_at", lookup_expr="date")
|
||||
|
||||
@@ -218,9 +218,13 @@ class Provider(RowLevelSecurityProtectedModel):
|
||||
|
||||
@staticmethod
|
||||
def validate_m365_uid(value):
|
||||
if not re.match(r"^[a-zA-Z0-9-]+\.onmicrosoft\.com$", value):
|
||||
if not re.match(
|
||||
r"""^(?!-)[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.(?!-)[A-Za-z0-9]"""
|
||||
r"""(?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*\.[A-Za-z]{2,}$""",
|
||||
value,
|
||||
):
|
||||
raise ModelValidationError(
|
||||
detail="M365 tenant ID must be a valid domain.",
|
||||
detail="M365 domain ID must be a valid domain.",
|
||||
code="m365-uid",
|
||||
pointer="/data/attributes/uid",
|
||||
)
|
||||
@@ -426,6 +430,7 @@ class Scan(RowLevelSecurityProtectedModel):
|
||||
PeriodicTask, on_delete=models.CASCADE, null=True, blank=True
|
||||
)
|
||||
output_location = models.CharField(blank=True, null=True, max_length=200)
|
||||
|
||||
# TODO: mutelist foreign key
|
||||
|
||||
class Meta(RowLevelSecurityProtectedModel.Meta):
|
||||
|
||||
@@ -1238,6 +1238,416 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FindingDynamicFilterResponse'
|
||||
description: ''
|
||||
/api/v1/findings/latest:
|
||||
get:
|
||||
operationId: findings_latest_retrieve
|
||||
description: Retrieve a list of the latest findings from the latest scans for
|
||||
each provider with options for filtering by various criteria.
|
||||
summary: List the latest findings
|
||||
parameters:
|
||||
- in: query
|
||||
name: fields[findings]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- uid
|
||||
- delta
|
||||
- status
|
||||
- status_extended
|
||||
- severity
|
||||
- check_id
|
||||
- check_metadata
|
||||
- raw_result
|
||||
- inserted_at
|
||||
- updated_at
|
||||
- first_seen_at
|
||||
- muted
|
||||
- url
|
||||
- scan
|
||||
- resources
|
||||
description: endpoint return only specific fields in the response on a per-type
|
||||
basis by including a fields[TYPE] query parameter.
|
||||
explode: false
|
||||
- in: query
|
||||
name: filter[check_id]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[check_id__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[check_id__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[delta]
|
||||
schema:
|
||||
type: string
|
||||
nullable: true
|
||||
enum:
|
||||
- changed
|
||||
- new
|
||||
description: |-
|
||||
* `new` - New
|
||||
* `changed` - Changed
|
||||
- in: query
|
||||
name: filter[delta__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[id]
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: filter[id__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[impact]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- critical
|
||||
- high
|
||||
- informational
|
||||
- low
|
||||
- medium
|
||||
description: |-
|
||||
* `critical` - Critical
|
||||
* `high` - High
|
||||
* `medium` - Medium
|
||||
* `low` - Low
|
||||
* `informational` - Informational
|
||||
- in: query
|
||||
name: filter[impact__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[muted]
|
||||
schema:
|
||||
type: boolean
|
||||
description: If this filter is not provided, muted and non-muted findings
|
||||
will be returned.
|
||||
- in: query
|
||||
name: filter[provider]
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: filter[provider__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[provider_alias]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_alias__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_alias__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[provider_type]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
- kubernetes
|
||||
- m365
|
||||
description: |-
|
||||
* `aws` - AWS
|
||||
* `azure` - Azure
|
||||
* `gcp` - GCP
|
||||
* `kubernetes` - Kubernetes
|
||||
* `m365` - M365
|
||||
- in: query
|
||||
name: filter[provider_type__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
- kubernetes
|
||||
- m365
|
||||
description: |-
|
||||
Multiple values may be separated by commas.
|
||||
|
||||
* `aws` - AWS
|
||||
* `azure` - Azure
|
||||
* `gcp` - GCP
|
||||
* `kubernetes` - Kubernetes
|
||||
* `m365` - M365
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[provider_uid]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_uid__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_uid__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[region]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[region__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[region__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resource_name]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_name__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_name__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resource_type]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_type__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_type__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resource_uid]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_uid__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_uid__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resources]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- name: filter[search]
|
||||
required: false
|
||||
in: query
|
||||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[service]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[service__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[service__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[severity]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- critical
|
||||
- high
|
||||
- informational
|
||||
- low
|
||||
- medium
|
||||
description: |-
|
||||
* `critical` - Critical
|
||||
* `high` - High
|
||||
* `medium` - Medium
|
||||
* `low` - Low
|
||||
* `informational` - Informational
|
||||
- in: query
|
||||
name: filter[severity__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[status]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- FAIL
|
||||
- MANUAL
|
||||
- PASS
|
||||
description: |-
|
||||
* `FAIL` - Fail
|
||||
* `PASS` - Pass
|
||||
* `MANUAL` - Manual
|
||||
- in: query
|
||||
name: filter[status__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[uid]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[uid__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[updated_at]
|
||||
schema:
|
||||
type: string
|
||||
format: date
|
||||
- in: query
|
||||
name: include
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- scan
|
||||
- resources
|
||||
description: include query parameter to allow the client to customize which
|
||||
related resources should be returned.
|
||||
explode: false
|
||||
- name: sort
|
||||
required: false
|
||||
in: query
|
||||
description: '[list of fields to sort by](https://jsonapi.org/format/#fetching-sorting)'
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- status
|
||||
- -status
|
||||
- severity
|
||||
- -severity
|
||||
- check_id
|
||||
- -check_id
|
||||
- inserted_at
|
||||
- -inserted_at
|
||||
- updated_at
|
||||
- -updated_at
|
||||
explode: false
|
||||
tags:
|
||||
- Finding
|
||||
security:
|
||||
- jwtAuth: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/vnd.api+json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FindingResponse'
|
||||
description: ''
|
||||
/api/v1/findings/metadata:
|
||||
get:
|
||||
operationId: findings_metadata_retrieve
|
||||
@@ -1674,6 +2084,392 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FindingMetadataResponse'
|
||||
description: ''
|
||||
/api/v1/findings/metadata/latest:
|
||||
get:
|
||||
operationId: findings_metadata_latest_retrieve
|
||||
description: Fetch unique metadata values from a set of findings from the latest
|
||||
scans for each provider. This is useful for dynamic filtering.
|
||||
summary: Retrieve metadata values from the latest findings
|
||||
parameters:
|
||||
- in: query
|
||||
name: fields[findings-metadata]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- services
|
||||
- regions
|
||||
- resource_types
|
||||
description: endpoint return only specific fields in the response on a per-type
|
||||
basis by including a fields[TYPE] query parameter.
|
||||
explode: false
|
||||
- in: query
|
||||
name: filter[check_id]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[check_id__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[check_id__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[delta]
|
||||
schema:
|
||||
type: string
|
||||
nullable: true
|
||||
enum:
|
||||
- changed
|
||||
- new
|
||||
description: |-
|
||||
* `new` - New
|
||||
* `changed` - Changed
|
||||
- in: query
|
||||
name: filter[delta__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[id]
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: filter[id__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[impact]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- critical
|
||||
- high
|
||||
- informational
|
||||
- low
|
||||
- medium
|
||||
description: |-
|
||||
* `critical` - Critical
|
||||
* `high` - High
|
||||
* `medium` - Medium
|
||||
* `low` - Low
|
||||
* `informational` - Informational
|
||||
- in: query
|
||||
name: filter[impact__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[muted]
|
||||
schema:
|
||||
type: boolean
|
||||
description: If this filter is not provided, muted and non-muted findings
|
||||
will be returned.
|
||||
- in: query
|
||||
name: filter[provider]
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: filter[provider__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[provider_alias]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_alias__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_alias__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[provider_type]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
- kubernetes
|
||||
- m365
|
||||
description: |-
|
||||
* `aws` - AWS
|
||||
* `azure` - Azure
|
||||
* `gcp` - GCP
|
||||
* `kubernetes` - Kubernetes
|
||||
* `m365` - M365
|
||||
- in: query
|
||||
name: filter[provider_type__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
- kubernetes
|
||||
- m365
|
||||
description: |-
|
||||
Multiple values may be separated by commas.
|
||||
|
||||
* `aws` - AWS
|
||||
* `azure` - Azure
|
||||
* `gcp` - GCP
|
||||
* `kubernetes` - Kubernetes
|
||||
* `m365` - M365
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[provider_uid]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_uid__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[provider_uid__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[region]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[region__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[region__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resource_name]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_name__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_name__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resource_type]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_type__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_type__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resource_uid]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_uid__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[resource_uid__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[resources]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- name: filter[search]
|
||||
required: false
|
||||
in: query
|
||||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[service]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[service__icontains]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[service__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[severity]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- critical
|
||||
- high
|
||||
- informational
|
||||
- low
|
||||
- medium
|
||||
description: |-
|
||||
* `critical` - Critical
|
||||
* `high` - High
|
||||
* `medium` - Medium
|
||||
* `low` - Low
|
||||
* `informational` - Informational
|
||||
- in: query
|
||||
name: filter[severity__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[status]
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- FAIL
|
||||
- MANUAL
|
||||
- PASS
|
||||
description: |-
|
||||
* `FAIL` - Fail
|
||||
* `PASS` - Pass
|
||||
* `MANUAL` - Manual
|
||||
- in: query
|
||||
name: filter[status__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[uid]
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: filter[uid__in]
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Multiple values may be separated by commas.
|
||||
explode: false
|
||||
style: form
|
||||
- in: query
|
||||
name: filter[updated_at]
|
||||
schema:
|
||||
type: string
|
||||
format: date
|
||||
- name: sort
|
||||
required: false
|
||||
in: query
|
||||
description: '[list of fields to sort by](https://jsonapi.org/format/#fetching-sorting)'
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- status
|
||||
- -status
|
||||
- severity
|
||||
- -severity
|
||||
- check_id
|
||||
- -check_id
|
||||
- inserted_at
|
||||
- -inserted_at
|
||||
- updated_at
|
||||
- -updated_at
|
||||
explode: false
|
||||
tags:
|
||||
- Finding
|
||||
security:
|
||||
- jwtAuth: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/vnd.api+json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FindingMetadataResponse'
|
||||
description: ''
|
||||
/api/v1/integrations:
|
||||
get:
|
||||
operationId: integrations_list
|
||||
|
||||
@@ -2,7 +2,9 @@ import glob
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from unittest.mock import ANY, MagicMock, Mock, patch
|
||||
|
||||
import jwt
|
||||
@@ -916,6 +918,26 @@ class TestProviderViewSet:
|
||||
"uid": "8851db6b-42e5-4533-aa9e-30a32d67e875",
|
||||
"alias": "test",
|
||||
},
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "TestingPro.onMirosoft.com",
|
||||
"alias": "test",
|
||||
},
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "subdomain.domain.es",
|
||||
"alias": "test",
|
||||
},
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "microsoft.net",
|
||||
"alias": "test",
|
||||
},
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "subdomain1.subdomain2.subdomain3.subdomain4.domain.net",
|
||||
"alias": "test",
|
||||
},
|
||||
]
|
||||
),
|
||||
)
|
||||
@@ -984,6 +1006,51 @@ class TestProviderViewSet:
|
||||
"invalid_choice",
|
||||
"provider",
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "https://test.com",
|
||||
"alias": "test",
|
||||
},
|
||||
"m365-uid",
|
||||
"uid",
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "thisisnotadomain",
|
||||
"alias": "test",
|
||||
},
|
||||
"m365-uid",
|
||||
"uid",
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": "http://test.com",
|
||||
"alias": "test",
|
||||
},
|
||||
"m365-uid",
|
||||
"uid",
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": f"{'a' * 64}.domain.com",
|
||||
"alias": "test",
|
||||
},
|
||||
"m365-uid",
|
||||
"uid",
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "m365",
|
||||
"uid": f"subdomain.{'a' * 64}.com",
|
||||
"alias": "test",
|
||||
},
|
||||
"m365-uid",
|
||||
"uid",
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
@@ -2318,35 +2385,34 @@ class TestScanViewSet:
|
||||
assert response.status_code == 404
|
||||
assert response.json()["errors"]["detail"] == "The scan has no reports."
|
||||
|
||||
def test_report_local_file(
|
||||
self, authenticated_client, scans_fixture, tmp_path, monkeypatch
|
||||
):
|
||||
"""
|
||||
When output_location is a local file path, the view should read the file from disk
|
||||
and return it with proper headers.
|
||||
"""
|
||||
def test_report_local_file(self, authenticated_client, scans_fixture, monkeypatch):
|
||||
scan = scans_fixture[0]
|
||||
file_content = b"local zip file content"
|
||||
file_path = tmp_path / "report.zip"
|
||||
file_path.write_bytes(file_content)
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp_path = Path(tmp)
|
||||
base_tmp = tmp_path / "report_local_file"
|
||||
base_tmp.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
scan.output_location = str(file_path)
|
||||
scan.state = StateChoices.COMPLETED
|
||||
scan.save()
|
||||
file_content = b"local zip file content"
|
||||
file_path = base_tmp / "report.zip"
|
||||
file_path.write_bytes(file_content)
|
||||
|
||||
monkeypatch.setattr(
|
||||
glob,
|
||||
"glob",
|
||||
lambda pattern: [str(file_path)] if pattern == str(file_path) else [],
|
||||
)
|
||||
scan.output_location = str(file_path)
|
||||
scan.state = StateChoices.COMPLETED
|
||||
scan.save()
|
||||
|
||||
url = reverse("scan-report", kwargs={"pk": scan.id})
|
||||
response = authenticated_client.get(url)
|
||||
assert response.status_code == 200
|
||||
assert response.content == file_content
|
||||
content_disposition = response.get("Content-Disposition")
|
||||
assert content_disposition.startswith('attachment; filename="')
|
||||
assert f'filename="{file_path.name}"' in content_disposition
|
||||
monkeypatch.setattr(
|
||||
glob,
|
||||
"glob",
|
||||
lambda pattern: [str(file_path)] if pattern == str(file_path) else [],
|
||||
)
|
||||
|
||||
url = reverse("scan-report", kwargs={"pk": scan.id})
|
||||
response = authenticated_client.get(url)
|
||||
assert response.status_code == 200
|
||||
assert response.content == file_content
|
||||
content_disposition = response.get("Content-Disposition")
|
||||
assert content_disposition.startswith('attachment; filename="')
|
||||
assert f'filename="{file_path.name}"' in content_disposition
|
||||
|
||||
def test_compliance_invalid_framework(self, authenticated_client, scans_fixture):
|
||||
scan = scans_fixture[0]
|
||||
@@ -2481,31 +2547,36 @@ class TestScanViewSet:
|
||||
)
|
||||
|
||||
def test_compliance_local_file(
|
||||
self, authenticated_client, scans_fixture, tmp_path, monkeypatch
|
||||
self, authenticated_client, scans_fixture, monkeypatch
|
||||
):
|
||||
scan = scans_fixture[0]
|
||||
scan.state = StateChoices.COMPLETED
|
||||
base = tmp_path / "reports"
|
||||
comp_dir = base / "compliance"
|
||||
comp_dir.mkdir(parents=True)
|
||||
fname = comp_dir / "scan_cis.csv"
|
||||
fname.write_bytes(b"ignored")
|
||||
|
||||
scan.output_location = str(base / "scan.zip")
|
||||
scan.save()
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp_path = Path(tmp)
|
||||
base = tmp_path / "reports"
|
||||
comp_dir = base / "compliance"
|
||||
comp_dir.mkdir(parents=True, exist_ok=True)
|
||||
fname = comp_dir / "scan_cis.csv"
|
||||
fname.write_bytes(b"ignored")
|
||||
|
||||
monkeypatch.setattr(
|
||||
glob,
|
||||
"glob",
|
||||
lambda p: [str(fname)] if p.endswith("*_cis_1.4_aws.csv") else [],
|
||||
)
|
||||
scan.output_location = str(base / "scan.zip")
|
||||
scan.save()
|
||||
|
||||
url = reverse("scan-compliance", kwargs={"pk": scan.id, "name": "cis_1.4_aws"})
|
||||
resp = authenticated_client.get(url)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
cd = resp["Content-Disposition"]
|
||||
assert cd.startswith('attachment; filename="')
|
||||
assert cd.endswith(f'filename="{fname.name}"')
|
||||
monkeypatch.setattr(
|
||||
glob,
|
||||
"glob",
|
||||
lambda p: [str(fname)] if p.endswith("*_cis_1.4_aws.csv") else [],
|
||||
)
|
||||
|
||||
url = reverse(
|
||||
"scan-compliance", kwargs={"pk": scan.id, "name": "cis_1.4_aws"}
|
||||
)
|
||||
resp = authenticated_client.get(url)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
cd = resp["Content-Disposition"]
|
||||
assert cd.startswith('attachment; filename="')
|
||||
assert cd.endswith(f'filename="{fname.name}"')
|
||||
|
||||
@patch("api.v1.views.Task.objects.get")
|
||||
@patch("api.v1.views.TaskSerializer")
|
||||
@@ -3179,6 +3250,29 @@ class TestFindingViewSet:
|
||||
]
|
||||
}
|
||||
|
||||
def test_findings_latest(self, authenticated_client, latest_scan_finding):
|
||||
response = authenticated_client.get(
|
||||
reverse("finding-latest"),
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
# The latest scan only has one finding, in comparison with `GET /findings`
|
||||
assert len(response.json()["data"]) == 1
|
||||
assert (
|
||||
response.json()["data"][0]["attributes"]["status"]
|
||||
== latest_scan_finding.status
|
||||
)
|
||||
|
||||
def test_findings_metadata_latest(self, authenticated_client, latest_scan_finding):
|
||||
response = authenticated_client.get(
|
||||
reverse("finding-metadata_latest"),
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
attributes = response.json()["data"]["attributes"]
|
||||
|
||||
assert attributes["services"] == latest_scan_finding.resource_services
|
||||
assert attributes["regions"] == latest_scan_finding.resource_regions
|
||||
assert attributes["resource_types"] == latest_scan_finding.resource_types
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestJWTFields:
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
from rest_framework.response import Response
|
||||
|
||||
|
||||
class PaginateByPkMixin:
|
||||
"""
|
||||
Mixin to paginate on a list of PKs (cheaper than heavy JOINs),
|
||||
re-fetch the full objects with the desired select/prefetch,
|
||||
re-sort them to preserve DB ordering, then serialize + return.
|
||||
"""
|
||||
|
||||
def paginate_by_pk(
|
||||
self,
|
||||
request, # noqa: F841
|
||||
base_queryset,
|
||||
manager,
|
||||
select_related: list[str] | None = None,
|
||||
prefetch_related: list[str] | None = None,
|
||||
) -> Response:
|
||||
pk_list = base_queryset.values_list("id", flat=True)
|
||||
page = self.paginate_queryset(pk_list)
|
||||
if page is None:
|
||||
return Response(self.get_serializer(base_queryset, many=True).data)
|
||||
|
||||
queryset = manager.filter(id__in=page)
|
||||
if select_related:
|
||||
queryset = queryset.select_related(*select_related)
|
||||
if prefetch_related:
|
||||
queryset = queryset.prefetch_related(*prefetch_related)
|
||||
|
||||
queryset = sorted(queryset, key=lambda obj: page.index(obj.id))
|
||||
|
||||
serialized = self.get_serializer(queryset, many=True).data
|
||||
return self.get_paginated_response(serialized)
|
||||
+132
-17
@@ -65,6 +65,7 @@ from api.filters import (
|
||||
FindingFilter,
|
||||
IntegrationFilter,
|
||||
InvitationFilter,
|
||||
LatestFindingFilter,
|
||||
MembershipFilter,
|
||||
ProviderFilter,
|
||||
ProviderGroupFilter,
|
||||
@@ -110,6 +111,7 @@ from api.utils import (
|
||||
validate_invitation,
|
||||
)
|
||||
from api.uuid_utils import datetime_to_uuid7, uuid7_start
|
||||
from api.v1.mixins import PaginateByPkMixin
|
||||
from api.v1.serializers import (
|
||||
ComplianceOverviewFullSerializer,
|
||||
ComplianceOverviewMetadataSerializer,
|
||||
@@ -1671,10 +1673,24 @@ class ResourceViewSet(BaseRLSViewSet):
|
||||
],
|
||||
filters=True,
|
||||
),
|
||||
latest=extend_schema(
|
||||
tags=["Finding"],
|
||||
summary="List the latest findings",
|
||||
description="Retrieve a list of the latest findings from the latest scans for each provider with options for "
|
||||
"filtering by various criteria.",
|
||||
filters=True,
|
||||
),
|
||||
metadata_latest=extend_schema(
|
||||
tags=["Finding"],
|
||||
summary="Retrieve metadata values from the latest findings",
|
||||
description="Fetch unique metadata values from a set of findings from the latest scans for each provider. "
|
||||
"This is useful for dynamic filtering.",
|
||||
filters=True,
|
||||
),
|
||||
)
|
||||
@method_decorator(CACHE_DECORATOR, name="list")
|
||||
@method_decorator(CACHE_DECORATOR, name="retrieve")
|
||||
class FindingViewSet(BaseRLSViewSet):
|
||||
class FindingViewSet(PaginateByPkMixin, BaseRLSViewSet):
|
||||
queryset = Finding.all_objects.all()
|
||||
serializer_class = FindingSerializer
|
||||
filterset_class = FindingFilter
|
||||
@@ -1706,11 +1722,16 @@ class FindingViewSet(BaseRLSViewSet):
|
||||
def get_serializer_class(self):
|
||||
if self.action == "findings_services_regions":
|
||||
return FindingDynamicFilterSerializer
|
||||
elif self.action == "metadata":
|
||||
elif self.action in ["metadata", "metadata_latest"]:
|
||||
return FindingMetadataSerializer
|
||||
|
||||
return super().get_serializer_class()
|
||||
|
||||
def get_filterset_class(self):
|
||||
if self.action in ["latest", "metadata_latest"]:
|
||||
return LatestFindingFilter
|
||||
return FindingFilter
|
||||
|
||||
def get_queryset(self):
|
||||
tenant_id = self.request.tenant_id
|
||||
user_roles = get_role(self.request.user)
|
||||
@@ -1750,21 +1771,14 @@ class FindingViewSet(BaseRLSViewSet):
|
||||
return super().filter_queryset(queryset)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
base_qs = self.filter_queryset(self.get_queryset())
|
||||
paginated_ids = self.paginate_queryset(base_qs.values_list("id", flat=True))
|
||||
if paginated_ids is not None:
|
||||
ids = list(paginated_ids)
|
||||
findings = (
|
||||
Finding.all_objects.filter(tenant_id=self.request.tenant_id, id__in=ids)
|
||||
.select_related("scan")
|
||||
.prefetch_related("resources")
|
||||
)
|
||||
# Re-sort in Python to preserve ordering:
|
||||
findings = sorted(findings, key=lambda x: ids.index(x.id))
|
||||
serializer = self.get_serializer(findings, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
serializer = self.get_serializer(base_qs, many=True)
|
||||
return Response(serializer.data)
|
||||
filtered_queryset = self.filter_queryset(self.get_queryset())
|
||||
return self.paginate_by_pk(
|
||||
request,
|
||||
filtered_queryset,
|
||||
manager=Finding.all_objects,
|
||||
select_related=["scan"],
|
||||
prefetch_related=["resources"],
|
||||
)
|
||||
|
||||
@action(detail=False, methods=["get"], url_name="findings_services_regions")
|
||||
def findings_services_regions(self, request):
|
||||
@@ -1897,6 +1911,107 @@ class FindingViewSet(BaseRLSViewSet):
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(detail=False, methods=["get"], url_name="latest")
|
||||
def latest(self, request):
|
||||
tenant_id = request.tenant_id
|
||||
filtered_queryset = self.filter_queryset(self.get_queryset())
|
||||
|
||||
latest_scan_ids = (
|
||||
Scan.all_objects.filter(tenant_id=tenant_id, state=StateChoices.COMPLETED)
|
||||
.order_by("provider_id", "-inserted_at")
|
||||
.distinct("provider_id")
|
||||
.values_list("id", flat=True)
|
||||
)
|
||||
filtered_queryset = filtered_queryset.filter(
|
||||
tenant_id=tenant_id, scan_id__in=latest_scan_ids
|
||||
)
|
||||
|
||||
return self.paginate_by_pk(
|
||||
request,
|
||||
filtered_queryset,
|
||||
manager=Finding.all_objects,
|
||||
select_related=["scan"],
|
||||
prefetch_related=["resources"],
|
||||
)
|
||||
|
||||
@action(
|
||||
detail=False,
|
||||
methods=["get"],
|
||||
url_name="metadata_latest",
|
||||
url_path="metadata/latest",
|
||||
)
|
||||
def metadata_latest(self, request):
|
||||
tenant_id = request.tenant_id
|
||||
query_params = request.query_params
|
||||
|
||||
latest_scans_queryset = (
|
||||
Scan.all_objects.filter(tenant_id=tenant_id, state=StateChoices.COMPLETED)
|
||||
.order_by("provider_id", "-inserted_at")
|
||||
.distinct("provider_id")
|
||||
)
|
||||
latest_scans_ids = list(latest_scans_queryset.values_list("id", flat=True))
|
||||
|
||||
queryset = ResourceScanSummary.objects.filter(
|
||||
tenant_id=tenant_id,
|
||||
scan_id__in=latest_scans_queryset.values_list("id", flat=True),
|
||||
)
|
||||
# ToRemove: Temporary fallback mechanism
|
||||
present_ids = set(
|
||||
ResourceScanSummary.objects.filter(
|
||||
tenant_id=tenant_id, scan_id__in=latest_scans_ids
|
||||
)
|
||||
.values_list("scan_id", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
missing_scan_ids = [sid for sid in latest_scans_ids if sid not in present_ids]
|
||||
if missing_scan_ids:
|
||||
for scan_id in missing_scan_ids:
|
||||
backfill_scan_resource_summaries_task.apply_async(
|
||||
kwargs={"tenant_id": tenant_id, "scan_id": scan_id}
|
||||
)
|
||||
return Response(
|
||||
get_findings_metadata_no_aggregations(
|
||||
tenant_id, self.filter_queryset(self.get_queryset())
|
||||
)
|
||||
)
|
||||
|
||||
if service_filter := query_params.get("filter[service]") or query_params.get(
|
||||
"filter[service__in]"
|
||||
):
|
||||
queryset = queryset.filter(service__in=service_filter.split(","))
|
||||
if region_filter := query_params.get("filter[region]") or query_params.get(
|
||||
"filter[region__in]"
|
||||
):
|
||||
queryset = queryset.filter(region__in=region_filter.split(","))
|
||||
if resource_type_filter := query_params.get(
|
||||
"filter[resource_type]"
|
||||
) or query_params.get("filter[resource_type__in]"):
|
||||
queryset = queryset.filter(
|
||||
resource_type__in=resource_type_filter.split(",")
|
||||
)
|
||||
|
||||
services = list(
|
||||
queryset.values_list("service", flat=True).distinct().order_by("service")
|
||||
)
|
||||
regions = list(
|
||||
queryset.values_list("region", flat=True).distinct().order_by("region")
|
||||
)
|
||||
resource_types = list(
|
||||
queryset.values_list("resource_type", flat=True)
|
||||
.distinct()
|
||||
.order_by("resource_type")
|
||||
)
|
||||
|
||||
result = {
|
||||
"services": services,
|
||||
"regions": regions,
|
||||
"resource_types": resource_types,
|
||||
}
|
||||
|
||||
serializer = self.get_serializer(data=result)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(
|
||||
|
||||
@@ -929,6 +929,47 @@ def backfill_scan_metadata_fixture(scans_fixture, findings_fixture):
|
||||
backfill_resource_scan_summaries(tenant_id=tenant_id, scan_id=scan_id)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def latest_scan_finding(authenticated_client, providers_fixture, resources_fixture):
|
||||
provider = providers_fixture[0]
|
||||
tenant_id = str(providers_fixture[0].tenant_id)
|
||||
resource = resources_fixture[0]
|
||||
scan = Scan.objects.create(
|
||||
name="latest completed scan",
|
||||
provider=provider,
|
||||
trigger=Scan.TriggerChoices.MANUAL,
|
||||
state=StateChoices.COMPLETED,
|
||||
tenant_id=tenant_id,
|
||||
)
|
||||
finding = Finding.objects.create(
|
||||
tenant_id=tenant_id,
|
||||
uid="test_finding_uid_1",
|
||||
scan=scan,
|
||||
delta="new",
|
||||
status=Status.FAIL,
|
||||
status_extended="test status extended ",
|
||||
impact=Severity.critical,
|
||||
impact_extended="test impact extended one",
|
||||
severity=Severity.critical,
|
||||
raw_result={
|
||||
"status": Status.FAIL,
|
||||
"impact": Severity.critical,
|
||||
"severity": Severity.critical,
|
||||
},
|
||||
tags={"test": "dev-qa"},
|
||||
check_id="test_check_id",
|
||||
check_metadata={
|
||||
"CheckId": "test_check_id",
|
||||
"Description": "test description apple sauce",
|
||||
},
|
||||
first_seen_at="2024-01-02T00:00:00Z",
|
||||
)
|
||||
|
||||
finding.add_resources([resource])
|
||||
backfill_resource_scan_summaries(tenant_id, str(scan.id))
|
||||
return finding
|
||||
|
||||
|
||||
def get_authorization_header(access_token: str) -> dict:
|
||||
return {"Authorization": f"Bearer {access_token}"}
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ from prowler.lib.outputs.compliance.prowler_threatscore.prowler_threatscore_azur
|
||||
from prowler.lib.outputs.compliance.prowler_threatscore.prowler_threatscore_gcp import (
|
||||
ProwlerThreatScoreGCP,
|
||||
)
|
||||
from prowler.lib.outputs.compliance.prowler_threatscore.prowler_threatscore_m365 import (
|
||||
ProwlerThreatScoreM365,
|
||||
)
|
||||
from prowler.lib.outputs.csv.csv import CSV
|
||||
from prowler.lib.outputs.html.html import HTML
|
||||
from prowler.lib.outputs.ocsf.ocsf import OCSF
|
||||
@@ -85,6 +88,7 @@ COMPLIANCE_CLASS_MAP = {
|
||||
],
|
||||
"m365": [
|
||||
(lambda name: name.startswith("cis_"), M365CIS),
|
||||
(lambda name: name == "prowler_threatscore_m365", ProwlerThreatScoreM365),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
@@ -14,8 +15,9 @@ from tasks.jobs.export import (
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestOutputs:
|
||||
def test_compress_output_files_creates_zip(self, tmp_path):
|
||||
output_dir = tmp_path / "output"
|
||||
def test_compress_output_files_creates_zip(self, tmpdir):
|
||||
base_tmp = Path(str(tmpdir.mkdir("compress_output")))
|
||||
output_dir = base_tmp / "output"
|
||||
output_dir.mkdir()
|
||||
file_path = output_dir / "result.csv"
|
||||
file_path.write_text("data")
|
||||
@@ -54,16 +56,16 @@ class TestOutputs:
|
||||
|
||||
@patch("tasks.jobs.export.get_s3_client")
|
||||
@patch("tasks.jobs.export.base")
|
||||
def test_upload_to_s3_success(self, mock_base, mock_get_client, tmp_path):
|
||||
def test_upload_to_s3_success(self, mock_base, mock_get_client, tmpdir):
|
||||
mock_base.DJANGO_OUTPUT_S3_AWS_OUTPUT_BUCKET = "test-bucket"
|
||||
|
||||
zip_path = tmp_path / "outputs.zip"
|
||||
base_tmp = Path(str(tmpdir.mkdir("upload_success")))
|
||||
zip_path = base_tmp / "outputs.zip"
|
||||
zip_path.write_bytes(b"dummy")
|
||||
|
||||
compliance_dir = tmp_path / "compliance"
|
||||
compliance_dir = base_tmp / "compliance"
|
||||
compliance_dir.mkdir()
|
||||
compliance_file = compliance_dir / "report.csv"
|
||||
compliance_file.write_text("ok")
|
||||
(compliance_dir / "report.csv").write_text("ok")
|
||||
|
||||
client_mock = MagicMock()
|
||||
mock_get_client.return_value = client_mock
|
||||
@@ -72,7 +74,6 @@ class TestOutputs:
|
||||
|
||||
expected_uri = "s3://test-bucket/tenant-id/scan-id/outputs.zip"
|
||||
assert result == expected_uri
|
||||
|
||||
assert client_mock.upload_file.call_count == 2
|
||||
|
||||
@patch("tasks.jobs.export.get_s3_client")
|
||||
@@ -84,12 +85,14 @@ class TestOutputs:
|
||||
|
||||
@patch("tasks.jobs.export.get_s3_client")
|
||||
@patch("tasks.jobs.export.base")
|
||||
def test_upload_to_s3_skips_non_files(self, mock_base, mock_get_client, tmp_path):
|
||||
def test_upload_to_s3_skips_non_files(self, mock_base, mock_get_client, tmpdir):
|
||||
mock_base.DJANGO_OUTPUT_S3_AWS_OUTPUT_BUCKET = "test-bucket"
|
||||
zip_path = tmp_path / "results.zip"
|
||||
base_tmp = Path(str(tmpdir.mkdir("upload_skips_non_files")))
|
||||
|
||||
zip_path = base_tmp / "results.zip"
|
||||
zip_path.write_bytes(b"zip")
|
||||
|
||||
compliance_dir = tmp_path / "compliance"
|
||||
compliance_dir = base_tmp / "compliance"
|
||||
compliance_dir.mkdir()
|
||||
(compliance_dir / "subdir").mkdir()
|
||||
|
||||
@@ -100,7 +103,6 @@ class TestOutputs:
|
||||
|
||||
expected_uri = "s3://test-bucket/tenant/scan/results.zip"
|
||||
assert result == expected_uri
|
||||
|
||||
client_mock.upload_file.assert_called_once()
|
||||
|
||||
@patch(
|
||||
@@ -110,23 +112,26 @@ class TestOutputs:
|
||||
@patch("tasks.jobs.export.base")
|
||||
@patch("tasks.jobs.export.logger.error")
|
||||
def test_upload_to_s3_failure_logs_error(
|
||||
self, mock_logger, mock_base, mock_get_client, tmp_path
|
||||
self, mock_logger, mock_base, mock_get_client, tmpdir
|
||||
):
|
||||
mock_base.DJANGO_OUTPUT_S3_AWS_OUTPUT_BUCKET = "bucket"
|
||||
zip_path = tmp_path / "zipfile.zip"
|
||||
|
||||
base_tmp = Path(str(tmpdir.mkdir("upload_failure_logs")))
|
||||
zip_path = base_tmp / "zipfile.zip"
|
||||
zip_path.write_bytes(b"zip")
|
||||
|
||||
compliance_dir = tmp_path / "compliance"
|
||||
compliance_dir = base_tmp / "compliance"
|
||||
compliance_dir.mkdir()
|
||||
(compliance_dir / "report.csv").write_text("csv")
|
||||
|
||||
_upload_to_s3("tenant", str(zip_path), "scan")
|
||||
mock_logger.assert_called()
|
||||
|
||||
def test_generate_output_directory_creates_paths(self, tmp_path):
|
||||
def test_generate_output_directory_creates_paths(self, tmpdir):
|
||||
from prowler.config.config import output_file_timestamp
|
||||
|
||||
base_dir = str(tmp_path)
|
||||
base_tmp = Path(str(tmpdir.mkdir("generate_output")))
|
||||
base_dir = str(base_tmp)
|
||||
tenant_id = "t1"
|
||||
scan_id = "s1"
|
||||
provider = "aws"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
@@ -467,3 +467,19 @@ The required modules are:
|
||||
|
||||
- [ExchangeOnlineManagement](https://www.powershellgallery.com/packages/ExchangeOnlineManagement/3.6.0): Minimum version 3.6.0. Required for several checks across Exchange, Defender, and Purview.
|
||||
- [MicrosoftTeams](https://www.powershellgallery.com/packages/MicrosoftTeams/6.6.0): Minimum version 6.6.0. Required for all Teams checks.
|
||||
|
||||
## GitHub
|
||||
### Authentication
|
||||
|
||||
Prowler supports multiple methods to [authenticate with GitHub](https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api). These include:
|
||||
|
||||
- **Personal Access Token (PAT)**
|
||||
- **OAuth App Token**
|
||||
- **GitHub App Credentials**
|
||||
|
||||
This flexibility allows you to scan and analyze your GitHub account, including repositories, organizations, and applications, using the method that best suits your use case.
|
||||
|
||||
The provided credentials must have the appropriate permissions to perform all the required checks.
|
||||
|
||||
???+ note
|
||||
GitHub App Credentials support less checks than other authentication methods.
|
||||
@@ -565,6 +565,7 @@ kubectl logs prowler-XXXXX --namespace prowler-ns
|
||||
???+ note
|
||||
By default, `prowler` will scan all namespaces in your active Kubernetes context. Use the flag `--context` to specify the context to be scanned and `--namespaces` to specify the namespaces to be scanned.
|
||||
|
||||
|
||||
#### Microsoft 365
|
||||
|
||||
With M365 you need to specify which auth method is going to be used:
|
||||
@@ -587,5 +588,29 @@ prowler m365 --browser-auth --tenant-id "XXXXXXXX"
|
||||
|
||||
See more details about M365 Authentication in [Requirements](getting-started/requirements.md#microsoft-365)
|
||||
|
||||
#### GitHub
|
||||
|
||||
Prowler allows you to scan your GitHub account, including your repositories, organizations or applications.
|
||||
|
||||
There are several supported login methods:
|
||||
|
||||
```console
|
||||
# Personal Access Token (PAT):
|
||||
prowler github --personal-access-token pat
|
||||
|
||||
# OAuth App Token:
|
||||
prowler github --oauth-app-token oauth_token
|
||||
|
||||
# GitHub App Credentials:
|
||||
prowler github --github-app-id app_id --github-app-key app_key
|
||||
```
|
||||
|
||||
???+ note
|
||||
If no login method is explicitly provided, Prowler will automatically attempt to authenticate using environment variables in the following order of precedence:
|
||||
|
||||
1. `GITHUB_PERSONAL_ACCESS_TOKEN`
|
||||
2. `OAUTH_APP_TOKEN`
|
||||
3. `GITHUB_APP_ID` and `GITHUB_APP_KEY`
|
||||
|
||||
## Prowler v2 Documentation
|
||||
For **Prowler v2 Documentation**, please check it out [here](https://github.com/prowler-cloud/prowler/blob/8818f47333a0c1c1a457453c87af0ea5b89a385f/README.md).
|
||||
@@ -0,0 +1,44 @@
|
||||
# GitHub Authentication
|
||||
|
||||
Prowler supports multiple methods to [authenticate with GitHub](https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api). These include:
|
||||
|
||||
- **Personal Access Token (PAT)**
|
||||
- **OAuth App Token**
|
||||
- **GitHub App Credentials**
|
||||
|
||||
This flexibility allows you to scan and analyze your GitHub account, including repositories, organizations, and applications, using the method that best suits your use case.
|
||||
|
||||
## Supported Login Methods
|
||||
|
||||
Here are the available login methods and their respective flags:
|
||||
|
||||
### Personal Access Token (PAT)
|
||||
Use this method by providing your personal access token directly.
|
||||
|
||||
```console
|
||||
prowler github --personal-access-token pat
|
||||
```
|
||||
|
||||
### OAuth App Token
|
||||
Authenticate using an OAuth app token.
|
||||
|
||||
```console
|
||||
prowler github --oauth-app-token oauth_token
|
||||
```
|
||||
|
||||
### GitHub App Credentials
|
||||
Use GitHub App credentials by specifying the App ID and the private key.
|
||||
|
||||
```console
|
||||
prowler github --github-app-id app_id --github-app-key app_key
|
||||
```
|
||||
|
||||
### Automatic Login Method Detection
|
||||
If no login method is explicitly provided, Prowler will automatically attempt to authenticate using environment variables in the following order of precedence:
|
||||
|
||||
1. `GITHUB_PERSONAL_ACCESS_TOKEN`
|
||||
2. `OAUTH_APP_TOKEN`
|
||||
3. `GITHUB_APP_ID` and `GITHUB_APP_KEY`
|
||||
|
||||
???+ note
|
||||
Ensure the corresponding environment variables are set up before running Prowler for automatic detection if you don't plan to specify the login method.
|
||||
@@ -38,11 +38,11 @@ prowler <provider> --list-checks
|
||||
```
|
||||
- Execute specific check(s):
|
||||
```console
|
||||
prowler <provider> -c/--checks s3_bucket_public_access
|
||||
prowler <provider> -c/--checks s3_bucket_public_access iam_root_mfa_enabled
|
||||
```
|
||||
- Exclude specific check(s):
|
||||
```console
|
||||
prowler <provider> -e/--excluded-checks ec2 rds
|
||||
prowler <provider> -e/--excluded-checks s3_bucket_public_access iam_root_mfa_enabled
|
||||
```
|
||||
- Execute checks that appears in a json file:
|
||||
```json
|
||||
|
||||
Generated
+26
@@ -3969,6 +3969,32 @@ cffi = ">=1.4.1"
|
||||
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
|
||||
tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pynacl"
|
||||
version = "1.5.0"
|
||||
description = "Python binding to the Networking and Cryptography (NaCl) library"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"},
|
||||
{file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cffi = ">=1.4.1"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
|
||||
tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.2.3"
|
||||
|
||||
@@ -10,10 +10,25 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- Add Prowler ThreatScore for M365 provider. [(#7692)](https://github.com/prowler-cloud/prowler/pull/7692)
|
||||
- Add new check `defender_domain_spf_records_published`. [(#7724)](https://github.com/prowler-cloud/prowler/pull/7724)
|
||||
- Add GitHub provider. [(#5787)](https://github.com/prowler-cloud/prowler/pull/5787)
|
||||
- Add `repository_default_branch_requires_multiple_approvals` check for GitHub provider. [(#6160)](https://github.com/prowler-cloud/prowler/pull/6160)
|
||||
- Add `repository_default_branch_protection_enabled` check for GitHub provider. [(#6161)](https://github.com/prowler-cloud/prowler/pull/6161)
|
||||
- Add `repository_default_branch_requires_linear_history` check for GitHub provider. [(#6162)](https://github.com/prowler-cloud/prowler/pull/6162)
|
||||
- Add `repository_default_branch_disallows_force_push` check for GitHub provider. [(#6197)](https://github.com/prowler-cloud/prowler/pull/6197)
|
||||
- Add `repository_default_branch_deletion_disabled` check for GitHub provider. [(#6200)](https://github.com/prowler-cloud/prowler/pull/6200)
|
||||
- Add `repository_default_branch_status_checks_required` check for GitHub provider. [(#6204)](https://github.com/prowler-cloud/prowler/pull/6204)
|
||||
- Add `repository_default_branch_protection_applies_to_admins` check for GitHub provider. [(#6205)](https://github.com/prowler-cloud/prowler/pull/6205)
|
||||
- Add `repository_branch_delete_on_merge_enabled` check for GitHub provider. [(#6209)](https://github.com/prowler-cloud/prowler/pull/6209)
|
||||
- Add `repository_default_branch_requires_conversation_resolution` check for GitHub provider. [(#6208)](https://github.com/prowler-cloud/prowler/pull/6208)
|
||||
- Add `organization_members_mfa_required` check for GitHub provider. [(#6304)](https://github.com/prowler-cloud/prowler/pull/6304)
|
||||
- Add GitHub provider documentation and CIS v1.0.0 compliance. [(#6116)](https://github.com/prowler-cloud/prowler/pull/6116)
|
||||
- Add CIS 5.0 compliance framework for AWS. [(7766)](https://github.com/prowler-cloud/prowler/pull/7766)
|
||||
|
||||
### Fixed
|
||||
- Update CIS 4.0 for M365 provider. [(#7699)](https://github.com/prowler-cloud/prowler/pull/7699)
|
||||
- Enhance defender policies checks logic. [(#7719)](https://github.com/prowler-cloud/prowler/pull/7719)
|
||||
- Update and upgrade CIS for all the providers [(#7738)](https://github.com/prowler-cloud/prowler/pull/7738)
|
||||
- Cover policies with conditions with SNS endpoint in `sns_topics_not_publicly_accessible`. [(#7750)](https://github.com/prowler-cloud/prowler/pull/7750)
|
||||
- Change severity logic for `ec2_securitygroup_allow_ingress_from_internet_to_all_ports` check. [(#7764)](https://github.com/prowler-cloud/prowler/pull/7764)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected im
|
||||
from prowler.lib.outputs.compliance.cis.cis_aws import AWSCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_azure import AzureCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_github import GithubCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_m365 import M365CIS
|
||||
from prowler.lib.outputs.compliance.compliance import display_compliance_table
|
||||
@@ -787,6 +788,35 @@ def prowler():
|
||||
generated_outputs["compliance"].append(generic_compliance)
|
||||
generic_compliance.batch_write_data_to_file()
|
||||
|
||||
elif provider == "github":
|
||||
for compliance_name in input_compliance_frameworks:
|
||||
if compliance_name.startswith("cis_"):
|
||||
# Generate CIS Finding Object
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
cis = GithubCIS(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(cis)
|
||||
cis.batch_write_data_to_file()
|
||||
else:
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
generic_compliance = GenericCompliance(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
create_file_descriptor=True,
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(generic_compliance)
|
||||
generic_compliance.batch_write_data_to_file()
|
||||
|
||||
# AWS Security Hub Integration
|
||||
if provider == "aws":
|
||||
# Send output to S3 if needed (-B / -D) for all the output formats
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure contact email and telephone details for AWS accounts are current and map to more than one individual in your organization. An AWS account supports a number of contact details, and AWS will use these to contact the account owner if activity judged to be in breach of Acceptable Use Policy or indicative of likely security compromise is observed by the AWS Abuse team. Contact details should not be for a single individual, as circumstances may arise where that individual is unavailable. Email contact details should point to a mail alias which forwards email to multiple individuals within the organization; where feasible, phone contact details should point to a PABX hunt group or other call-forwarding system.",
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Multi-Factor Authentication (MFA) adds an extra layer of authentication assurance beyond traditional credentials. With MFA enabled, when a user signs in to the AWS Console, they will be prompted for their user name and password as well as for an authentication code from their physical or virtual MFA token. It is recommended that MFA be enabled for all accounts that have a console password.",
|
||||
@@ -54,7 +54,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS console defaults to no check boxes selected when creating a new IAM user. When cerating the IAM User credentials you have to determine what type of access they require. Programmatic access: The IAM user might need to make API calls, use the AWS CLI, or use the Tools for Windows PowerShell. In that case, create an access key (access key ID and a secret access key) for that user. AWS Management Console access: If the user needs to access the AWS Management Console, create a password for the user.",
|
||||
@@ -76,7 +76,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS IAM users can access AWS resources using different types of credentials, such as passwords or access keys. It is recommended that all credentials that have been unused in 45 or greater days be deactivated or removed.",
|
||||
@@ -97,7 +97,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys are long-term credentials for an IAM user or the AWS account 'root' user. You can use access keys to sign programmatic requests to the AWS CLI or AWS API (directly or using the AWS SDK)",
|
||||
@@ -118,7 +118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys consist of an access key ID and secret access key, which are used to sign programmatic requests that you make to AWS. AWS users need their own access keys to make programmatic calls to AWS from the AWS Command Line Interface (AWS CLI), Tools for Windows PowerShell, the AWS SDKs, or direct HTTP calls using the APIs for individual AWS services. It is recommended that all access keys be regularly rotated.",
|
||||
@@ -139,7 +139,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM users are granted access to services, functions, and data through IAM policies. There are three ways to define policies for a user: 1) Edit the user policy directly, aka an inline, or user, policy; 2) attach a policy directly to a user; 3) add the user to an IAM group that has an attached policy. Only the third implementation is recommended.",
|
||||
@@ -161,7 +161,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM policies are the means by which privileges are granted to users, groups, or roles. It is recommended and considered a standard security advice to grant _least privilege_ -that is, granting only the permissions required to perform a task. Determine what users need to do and then craft policies for them that let the users perform _only_ those tasks, instead of allowing full administrative privileges.",
|
||||
@@ -182,7 +182,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS provides a support center that can be used for incident notification and response, as well as technical support and customer services. Create an IAM Role to allow authorized users to manage incidents with AWS Support.",
|
||||
@@ -203,7 +203,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS access from within AWS instances can be done by either encoding AWS keys into AWS API calls or by assigning the instance to a role which has an appropriate permissions policy for the required access. \"AWS Access\" means accessing the APIs of AWS in order to access AWS resources or manage AWS account resources.",
|
||||
@@ -224,7 +224,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To enable HTTPS connections to your website or application in AWS, you need an SSL/TLS server certificate. You can use ACM or IAM to store and deploy server certificates. Use IAM as a certificate manager only when you must support HTTPS connections in a region that is not supported by ACM. IAM securely encrypts your private keys and stores the encrypted version in IAM SSL certificate storage. IAM supports deploying server certificates in all regions, but you must obtain your certificate from an external provider for use with AWS. You cannot upload an ACM certificate to IAM. Additionally, you cannot manage your certificates from the IAM Console.",
|
||||
@@ -245,7 +245,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS provides customers with the option of specifying the contact information for account's security team. It is recommended that this information be provided.",
|
||||
@@ -266,7 +266,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable IAM Access analyzer for IAM policies about all resources in each region. IAM Access Analyzer is a technology introduced at AWS reinvent 2019. After the Analyzer is enabled in IAM, scan results are displayed on the console showing the accessible resources. Scans show resources that other accounts and federated users can access, such as KMS keys and IAM roles. So the results allow you to determine if an unintended user is allowed, making it easier for administrators to monitor least privileges access. Access Analyzer analyzes only policies that are applied to resources in the same AWS Region.",
|
||||
@@ -287,7 +287,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In multi-account environments, IAM user centralization facilitates greater user control. User access beyond the initial account is then provided via role assumption. Centralization of users can be accomplished through federation with an external identity provider or through the use of AWS Organizations.",
|
||||
@@ -308,7 +308,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The AWS support portal allows account owners to establish security questions that can be used to authenticate individuals calling AWS customer service for support. It is recommended that security questions be established.",
|
||||
@@ -329,7 +329,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. AWS Access Keys provide programmatic access to a given AWS account. It is recommended that all access keys associated with the 'root' user account be removed.",
|
||||
@@ -350,7 +350,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. Multi-factor Authentication (MFA) adds an extra layer of protection on top of a username and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their username and password as well as for an authentication code from their AWS MFA device. **Note:** When virtual MFA is used for 'root' accounts, it is recommended that the device used is NOT a personal device, but rather a dedicated mobile device (tablet or phone) that is managed to be kept charged and secured independent of any individual personal devices. (\"non-personal virtual MFA\") This lessens the risks of losing access to the MFA due to device loss, device trade-in or if the individual owning the device is no longer employed at the company.",
|
||||
@@ -371,7 +371,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their user name and password as well as for an authentication code from their AWS MFA device. For Level 2, it is recommended that the 'root' user account be protected with a hardware MFA.",
|
||||
@@ -392,7 +392,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "With the creation of an AWS account, a 'root user' is created that cannot be disabled or deleted. That user has unrestricted access to and control over all resources in the AWS account. It is highly recommended that the use of this account be avoided for everyday tasks.",
|
||||
@@ -413,7 +413,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Password policies are, in part, used to enforce password complexity requirements. IAM password policies can be used to ensure password are at least a given length. It is recommended that the password policy require a minimum password length 14.",
|
||||
@@ -434,7 +434,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM password policies can prevent the reuse of a given password by the same user. It is recommended that the password policy prevent the reuse of passwords.",
|
||||
@@ -455,8 +455,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides a variety of no, or low, cost encryption options to protect data at rest.",
|
||||
@@ -477,8 +477,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -499,8 +499,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -521,8 +521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -544,8 +544,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -566,7 +566,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -589,8 +589,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -611,7 +611,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for your account and delivers log files to you. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail provides a history of AWS API calls for an account, including API calls made via the Management Console, SDKs, command line tools, and higher-level AWS services (such as CloudFormation).",
|
||||
@@ -632,7 +632,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -653,7 +653,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -674,7 +674,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail log file validation creates a digitally signed digest file containing a hash of each log that CloudTrail writes to S3. These digest files can be used to determine whether a log file was changed, deleted, or unchanged after CloudTrail delivered the log. It is recommended that file validation be enabled on all CloudTrails.",
|
||||
@@ -695,7 +695,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail logs a record of every API call made in your AWS account. These logs file are stored in an S3 bucket. It is recommended that the bucket policy or access control list (ACL) applied to the S3 bucket that CloudTrail logs to prevent public access to the CloudTrail logs.",
|
||||
@@ -716,7 +716,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls made in a given AWS account. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail uses Amazon S3 for log file storage and delivery, so log files are stored durably. In addition to capturing CloudTrail logs within a specified S3 bucket for long term analysis, realtime analysis can be performed by configuring CloudTrail to send logs to CloudWatch Logs. For a trail that is enabled in all regions in an account, CloudTrail sends log files from all those regions to a CloudWatch Logs log group. It is recommended that CloudTrail logs be sent to CloudWatch Logs. Note: The intent of this recommendation is to ensure AWS account activity is being captured, monitored, and appropriately alarmed on. CloudWatch Logs is a native way to accomplish this using AWS services but does not preclude the use of an alternate solution.",
|
||||
@@ -737,7 +737,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Config is a web service that performs configuration management of supported AWS resources within your account and delivers log files to you. The recorded information includes the configuration item (AWS resource), relationships between configuration items (AWS resources), any configuration changes between resources. It is recommended AWS Config be enabled in all regions.",
|
||||
@@ -758,7 +758,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 Bucket Access Logging generates a log that contains access records for each request made to your S3 bucket. An access log record contains details about the request, such as the request type, the resources specified in the request worked, and the time and date the request was processed. It is recommended that bucket access logging be enabled on the CloudTrail S3 bucket.",
|
||||
@@ -779,7 +779,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for an account and makes those logs available to users and resources in accordance with IAM policies. AWS Key Management Service (KMS) is a managed service that helps create and control the encryption keys used to encrypt account data, and uses Hardware Security Modules (HSMs) to protect the security of encryption keys. CloudTrail logs can be configured to leverage server side encryption (SSE) and KMS customer created master keys (CMK) to further protect CloudTrail logs. It is recommended that CloudTrail be configured to use SSE-KMS.",
|
||||
@@ -800,7 +800,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Key Management Service (KMS) allows customers to rotate the backing key which is key material stored within the KMS which is tied to the key ID of the Customer Created customer master key (CMK). It is the backing key that is used to perform cryptographic operations such as encryption and decryption. Automated key rotation currently retains all prior backing keys so that decryption of encrypted data can take place transparently. It is recommended that CMK key rotation be enabled for symmetric keys. Key rotation can not be enabled for any asymmetric CMK.",
|
||||
@@ -821,7 +821,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. After you've created a flow log, you can view and retrieve its data in Amazon CloudWatch Logs. It is recommended that VPC Flow Logs be enabled for packet \"Rejects\" for VPCs.",
|
||||
@@ -842,7 +842,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for unauthorized API calls.",
|
||||
@@ -863,7 +863,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Security Groups are a stateful packet filter that controls ingress and egress traffic within a VPC. It is recommended that a metric filter and alarm be established for detecting changes to Security Groups.",
|
||||
@@ -884,7 +884,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. NACLs are used as a stateless packet filter to control ingress and egress traffic for subnets within a VPC. It is recommended that a metric filter and alarm be established for changes made to NACLs.",
|
||||
@@ -905,7 +905,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Network gateways are required to send/receive traffic to a destination outside of a VPC. It is recommended that a metric filter and alarm be established for changes to network gateways.",
|
||||
@@ -926,7 +926,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.",
|
||||
@@ -947,7 +947,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is possible to have more than 1 VPC within an account, in addition it is also possible to create a peer connection between 2 VPCs enabling network traffic to route between VPCs. It is recommended that a metric filter and alarm be established for changes made to VPCs.",
|
||||
@@ -968,7 +968,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for AWS Organizations changes made in the master AWS Account.",
|
||||
@@ -989,7 +989,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for console logins that are not protected by multi-factor authentication (MFA).",
|
||||
@@ -1010,7 +1010,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for 'root' login attempts.",
|
||||
@@ -1031,7 +1031,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established changes made to Identity and Access Management (IAM) policies.",
|
||||
@@ -1052,7 +1052,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1073,7 +1073,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for failed console authentication attempts.",
|
||||
@@ -1094,7 +1094,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for customer created CMKs which have changed state to disabled or scheduled deletion.",
|
||||
@@ -1115,7 +1115,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for changes to S3 bucket policies.",
|
||||
@@ -1136,7 +1136,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1159,7 +1159,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The Network Access Control List (NACL) function provide stateless filtering of ingress and egress network traffic to AWS resources. It is recommended that no NACL allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1182,7 +1182,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1203,7 +1203,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A VPC comes with a default security group whose initial settings deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances assigned to the security group. If you don't specify a security group when you launch an instance, the instance is automatically assigned to this default security group. Security groups provide stateful filtering of ingress/egress network traffic to AWS resources. It is recommended that the default security group restrict all traffic. The default VPC in every region should have its default security group updated to comply. Any newly created VPCs will automatically contain a default security group that will need remediation to comply with this recommendation. **NOTE:** When implementing this recommendation, VPC flow logging is invaluable in determining the least privilege port access required by systems to work properly because it can log all packet acceptances and rejections occurring under the current security groups. This dramatically reduces the primary barrier to least privilege engineering - discovering the minimum ports required by systems in the environment. Even if the VPC flow logging recommendation in this benchmark is not adopted as a permanent security measure, it should be used during any period of discovery and engineering for least privileged security groups.",
|
||||
@@ -1224,7 +1224,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Once a VPC peering connection is established, routing tables must be updated to establish any connections between the peered VPCs. These routes can be as specific as desired - even peering a VPC to only a single host on the other side of the connection.",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure contact email and telephone details for AWS accounts are current and map to more than one individual in your organization. An AWS account supports a number of contact details, and AWS will use these to contact the account owner if activity judged to be in breach of Acceptable Use Policy or indicative of likely security compromise is observed by the AWS Abuse team. Contact details should not be for a single individual, as circumstances may arise where that individual is unavailable. Email contact details should point to a mail alias which forwards email to multiple individuals within the organization; where feasible, phone contact details should point to a PABX hunt group or other call-forwarding system.",
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Multi-Factor Authentication (MFA) adds an extra layer of authentication assurance beyond traditional credentials. With MFA enabled, when a user signs in to the AWS Console, they will be prompted for their user name and password as well as for an authentication code from their physical or virtual MFA token. It is recommended that MFA be enabled for all accounts that have a console password.",
|
||||
@@ -54,7 +54,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS console defaults to no check boxes selected when creating a new IAM user. When cerating the IAM User credentials you have to determine what type of access they require. Programmatic access: The IAM user might need to make API calls, use the AWS CLI, or use the Tools for Windows PowerShell. In that case, create an access key (access key ID and a secret access key) for that user. AWS Management Console access: If the user needs to access the AWS Management Console, create a password for the user.",
|
||||
@@ -76,7 +76,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS IAM users can access AWS resources using different types of credentials, such as passwords or access keys. It is recommended that all credentials that have been unused in 45 or greater days be deactivated or removed.",
|
||||
@@ -97,7 +97,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys are long-term credentials for an IAM user or the AWS account 'root' user. You can use access keys to sign programmatic requests to the AWS CLI or AWS API (directly or using the AWS SDK)",
|
||||
@@ -118,7 +118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys consist of an access key ID and secret access key, which are used to sign programmatic requests that you make to AWS. AWS users need their own access keys to make programmatic calls to AWS from the AWS Command Line Interface (AWS CLI), Tools for Windows PowerShell, the AWS SDKs, or direct HTTP calls using the APIs for individual AWS services. It is recommended that all access keys be regularly rotated.",
|
||||
@@ -139,7 +139,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM users are granted access to services, functions, and data through IAM policies. There are three ways to define policies for a user: 1) Edit the user policy directly, aka an inline, or user, policy; 2) attach a policy directly to a user; 3) add the user to an IAM group that has an attached policy. Only the third implementation is recommended.",
|
||||
@@ -161,7 +161,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM policies are the means by which privileges are granted to users, groups, or roles. It is recommended and considered a standard security advice to grant _least privilege_ -that is, granting only the permissions required to perform a task. Determine what users need to do and then craft policies for them that let the users perform _only_ those tasks, instead of allowing full administrative privileges.",
|
||||
@@ -182,7 +182,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS provides a support center that can be used for incident notification and response, as well as technical support and customer services. Create an IAM Role to allow authorized users to manage incidents with AWS Support.",
|
||||
@@ -203,7 +203,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS access from within AWS instances can be done by either encoding AWS keys into AWS API calls or by assigning the instance to a role which has an appropriate permissions policy for the required access. \"AWS Access\" means accessing the APIs of AWS in order to access AWS resources or manage AWS account resources.",
|
||||
@@ -224,7 +224,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To enable HTTPS connections to your website or application in AWS, you need an SSL/TLS server certificate. You can use ACM or IAM to store and deploy server certificates. Use IAM as a certificate manager only when you must support HTTPS connections in a region that is not supported by ACM. IAM securely encrypts your private keys and stores the encrypted version in IAM SSL certificate storage. IAM supports deploying server certificates in all regions, but you must obtain your certificate from an external provider for use with AWS. You cannot upload an ACM certificate to IAM. Additionally, you cannot manage your certificates from the IAM Console.",
|
||||
@@ -245,7 +245,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS provides customers with the option of specifying the contact information for account's security team. It is recommended that this information be provided.",
|
||||
@@ -266,7 +266,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable IAM Access analyzer for IAM policies about all resources in each region. IAM Access Analyzer is a technology introduced at AWS reinvent 2019. After the Analyzer is enabled in IAM, scan results are displayed on the console showing the accessible resources. Scans show resources that other accounts and federated users can access, such as KMS keys and IAM roles. So the results allow you to determine if an unintended user is allowed, making it easier for administrators to monitor least privileges access. Access Analyzer analyzes only policies that are applied to resources in the same AWS Region.",
|
||||
@@ -287,7 +287,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In multi-account environments, IAM user centralization facilitates greater user control. User access beyond the initial account is then provided via role assumption. Centralization of users can be accomplished through federation with an external identity provider or through the use of AWS Organizations.",
|
||||
@@ -308,7 +308,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The AWS support portal allows account owners to establish security questions that can be used to authenticate individuals calling AWS customer service for support. It is recommended that security questions be established.",
|
||||
@@ -329,7 +329,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. AWS Access Keys provide programmatic access to a given AWS account. It is recommended that all access keys associated with the 'root' user account be removed.",
|
||||
@@ -350,7 +350,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. Multi-factor Authentication (MFA) adds an extra layer of protection on top of a username and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their username and password as well as for an authentication code from their AWS MFA device. **Note:** When virtual MFA is used for 'root' accounts, it is recommended that the device used is NOT a personal device, but rather a dedicated mobile device (tablet or phone) that is managed to be kept charged and secured independent of any individual personal devices. (\"non-personal virtual MFA\") This lessens the risks of losing access to the MFA due to device loss, device trade-in or if the individual owning the device is no longer employed at the company.",
|
||||
@@ -371,7 +371,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their user name and password as well as for an authentication code from their AWS MFA device. For Level 2, it is recommended that the 'root' user account be protected with a hardware MFA.",
|
||||
@@ -392,7 +392,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "With the creation of an AWS account, a 'root user' is created that cannot be disabled or deleted. That user has unrestricted access to and control over all resources in the AWS account. It is highly recommended that the use of this account be avoided for everyday tasks.",
|
||||
@@ -413,7 +413,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Password policies are, in part, used to enforce password complexity requirements. IAM password policies can be used to ensure password are at least a given length. It is recommended that the password policy require a minimum password length 14.",
|
||||
@@ -434,7 +434,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM password policies can prevent the reuse of a given password by the same user. It is recommended that the password policy prevent the reuse of passwords.",
|
||||
@@ -455,8 +455,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides a variety of no, or low, cost encryption options to protect data at rest.",
|
||||
@@ -477,8 +477,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -499,8 +499,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -521,8 +521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -544,8 +544,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -566,8 +566,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.2 Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -589,8 +589,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -611,8 +611,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that RDS database instances have the Auto Minor Version Upgrade flag enabled in order to receive automatically minor engine upgrades during the specified maintenance window. So, RDS instances can get the new features, bug fixes, and security patches for their database engines.",
|
||||
@@ -633,8 +633,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure and verify that RDS database instances provisioned in your AWS account do restrict unauthorized access in order to minimize security risks. To restrict access to any publicly accessible RDS database instance, you must disable the database Publicly Accessible flag and update the VPC security group associated with the instance.",
|
||||
@@ -655,7 +655,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.4 Elastic File System (EFS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -677,7 +677,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for your account and delivers log files to you. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail provides a history of AWS API calls for an account, including API calls made via the Management Console, SDKs, command line tools, and higher-level AWS services (such as CloudFormation).",
|
||||
@@ -698,7 +698,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -719,7 +719,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -740,7 +740,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail log file validation creates a digitally signed digest file containing a hash of each log that CloudTrail writes to S3. These digest files can be used to determine whether a log file was changed, deleted, or unchanged after CloudTrail delivered the log. It is recommended that file validation be enabled on all CloudTrails.",
|
||||
@@ -761,7 +761,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail logs a record of every API call made in your AWS account. These logs file are stored in an S3 bucket. It is recommended that the bucket policy or access control list (ACL) applied to the S3 bucket that CloudTrail logs to prevent public access to the CloudTrail logs.",
|
||||
@@ -782,7 +782,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls made in a given AWS account. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail uses Amazon S3 for log file storage and delivery, so log files are stored durably. In addition to capturing CloudTrail logs within a specified S3 bucket for long term analysis, realtime analysis can be performed by configuring CloudTrail to send logs to CloudWatch Logs. For a trail that is enabled in all regions in an account, CloudTrail sends log files from all those regions to a CloudWatch Logs log group. It is recommended that CloudTrail logs be sent to CloudWatch Logs. Note: The intent of this recommendation is to ensure AWS account activity is being captured, monitored, and appropriately alarmed on. CloudWatch Logs is a native way to accomplish this using AWS services but does not preclude the use of an alternate solution.",
|
||||
@@ -803,7 +803,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Config is a web service that performs configuration management of supported AWS resources within your account and delivers log files to you. The recorded information includes the configuration item (AWS resource), relationships between configuration items (AWS resources), any configuration changes between resources. It is recommended AWS Config be enabled in all regions.",
|
||||
@@ -824,7 +824,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 Bucket Access Logging generates a log that contains access records for each request made to your S3 bucket. An access log record contains details about the request, such as the request type, the resources specified in the request worked, and the time and date the request was processed. It is recommended that bucket access logging be enabled on the CloudTrail S3 bucket.",
|
||||
@@ -845,7 +845,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for an account and makes those logs available to users and resources in accordance with IAM policies. AWS Key Management Service (KMS) is a managed service that helps create and control the encryption keys used to encrypt account data, and uses Hardware Security Modules (HSMs) to protect the security of encryption keys. CloudTrail logs can be configured to leverage server side encryption (SSE) and KMS customer created master keys (CMK) to further protect CloudTrail logs. It is recommended that CloudTrail be configured to use SSE-KMS.",
|
||||
@@ -866,7 +866,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Key Management Service (KMS) allows customers to rotate the backing key which is key material stored within the KMS which is tied to the key ID of the Customer Created customer master key (CMK). It is the backing key that is used to perform cryptographic operations such as encryption and decryption. Automated key rotation currently retains all prior backing keys so that decryption of encrypted data can take place transparently. It is recommended that CMK key rotation be enabled for symmetric keys. Key rotation can not be enabled for any asymmetric CMK.",
|
||||
@@ -887,7 +887,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. After you've created a flow log, you can view and retrieve its data in Amazon CloudWatch Logs. It is recommended that VPC Flow Logs be enabled for packet \"Rejects\" for VPCs.",
|
||||
@@ -908,7 +908,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for unauthorized API calls.",
|
||||
@@ -929,7 +929,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Security Groups are a stateful packet filter that controls ingress and egress traffic within a VPC. It is recommended that a metric filter and alarm be established for detecting changes to Security Groups.",
|
||||
@@ -950,7 +950,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. NACLs are used as a stateless packet filter to control ingress and egress traffic for subnets within a VPC. It is recommended that a metric filter and alarm be established for changes made to NACLs.",
|
||||
@@ -971,7 +971,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Network gateways are required to send/receive traffic to a destination outside of a VPC. It is recommended that a metric filter and alarm be established for changes to network gateways.",
|
||||
@@ -992,7 +992,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.",
|
||||
@@ -1013,7 +1013,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is possible to have more than 1 VPC within an account, in addition it is also possible to create a peer connection between 2 VPCs enabling network traffic to route between VPCs. It is recommended that a metric filter and alarm be established for changes made to VPCs.",
|
||||
@@ -1034,7 +1034,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for AWS Organizations changes made in the master AWS Account.",
|
||||
@@ -1055,7 +1055,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security Hub collects security data from across AWS accounts, services, and supported third-party partner products and helps you analyze your security trends and identify the highest priority security issues. When you enable Security Hub, it begins to consume, aggregate, organize, and prioritize findings from AWS services that you have enabled, such as Amazon GuardDuty, Amazon Inspector, and Amazon Macie. You can also enable integrations with AWS partner security products.",
|
||||
@@ -1076,7 +1076,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for console logins that are not protected by multi-factor authentication (MFA).",
|
||||
@@ -1097,7 +1097,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for 'root' login attempts.",
|
||||
@@ -1118,7 +1118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established changes made to Identity and Access Management (IAM) policies.",
|
||||
@@ -1139,7 +1139,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1160,7 +1160,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for failed console authentication attempts.",
|
||||
@@ -1181,7 +1181,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for customer created CMKs which have changed state to disabled or scheduled deletion.",
|
||||
@@ -1202,7 +1202,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for changes to S3 bucket policies.",
|
||||
@@ -1223,7 +1223,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1246,7 +1246,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The Network Access Control List (NACL) function provide stateless filtering of ingress and egress network traffic to AWS resources. It is recommended that no NACL allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1269,7 +1269,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1292,7 +1292,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1313,7 +1313,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A VPC comes with a default security group whose initial settings deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances assigned to the security group. If you don't specify a security group when you launch an instance, the instance is automatically assigned to this default security group. Security groups provide stateful filtering of ingress/egress network traffic to AWS resources. It is recommended that the default security group restrict all traffic. The default VPC in every region should have its default security group updated to comply. Any newly created VPCs will automatically contain a default security group that will need remediation to comply with this recommendation. **NOTE:** When implementing this recommendation, VPC flow logging is invaluable in determining the least privilege port access required by systems to work properly because it can log all packet acceptances and rejections occurring under the current security groups. This dramatically reduces the primary barrier to least privilege engineering - discovering the minimum ports required by systems in the environment. Even if the VPC flow logging recommendation in this benchmark is not adopted as a permanent security measure, it should be used during any period of discovery and engineering for least privileged security groups.",
|
||||
@@ -1334,7 +1334,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Once a VPC peering connection is established, routing tables must be updated to establish any connections between the peered VPCs. These routes can be as specific as desired - even peering a VPC to only a single host on the other side of the connection.",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure contact email and telephone details for AWS accounts are current and map to more than one individual in your organization. An AWS account supports a number of contact details, and AWS will use these to contact the account owner if activity judged to be in breach of Acceptable Use Policy or indicative of likely security compromise is observed by the AWS Abuse team. Contact details should not be for a single individual, as circumstances may arise where that individual is unavailable. Email contact details should point to a mail alias which forwards email to multiple individuals within the organization; where feasible, phone contact details should point to a PABX hunt group or other call-forwarding system.",
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Multi-Factor Authentication (MFA) adds an extra layer of authentication assurance beyond traditional credentials. With MFA enabled, when a user signs in to the AWS Console, they will be prompted for their user name and password as well as for an authentication code from their physical or virtual MFA token. It is recommended that MFA be enabled for all accounts that have a console password.",
|
||||
@@ -54,7 +54,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS console defaults to no check boxes selected when creating a new IAM user. When cerating the IAM User credentials you have to determine what type of access they require. Programmatic access: The IAM user might need to make API calls, use the AWS CLI, or use the Tools for Windows PowerShell. In that case, create an access key (access key ID and a secret access key) for that user. AWS Management Console access: If the user needs to access the AWS Management Console, create a password for the user.",
|
||||
@@ -76,7 +76,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS IAM users can access AWS resources using different types of credentials, such as passwords or access keys. It is recommended that all credentials that have been unused in 45 or greater days be deactivated or removed.",
|
||||
@@ -97,7 +97,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys are long-term credentials for an IAM user or the AWS account 'root' user. You can use access keys to sign programmatic requests to the AWS CLI or AWS API (directly or using the AWS SDK)",
|
||||
@@ -118,7 +118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys consist of an access key ID and secret access key, which are used to sign programmatic requests that you make to AWS. AWS users need their own access keys to make programmatic calls to AWS from the AWS Command Line Interface (AWS CLI), Tools for Windows PowerShell, the AWS SDKs, or direct HTTP calls using the APIs for individual AWS services. It is recommended that all access keys be regularly rotated.",
|
||||
@@ -139,7 +139,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM users are granted access to services, functions, and data through IAM policies. There are three ways to define policies for a user: 1) Edit the user policy directly, aka an inline, or user, policy; 2) attach a policy directly to a user; 3) add the user to an IAM group that has an attached policy. Only the third implementation is recommended.",
|
||||
@@ -161,7 +161,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM policies are the means by which privileges are granted to users, groups, or roles. It is recommended and considered a standard security advice to grant _least privilege_ -that is, granting only the permissions required to perform a task. Determine what users need to do and then craft policies for them that let the users perform _only_ those tasks, instead of allowing full administrative privileges.",
|
||||
@@ -182,7 +182,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS provides a support center that can be used for incident notification and response, as well as technical support and customer services. Create an IAM Role to allow authorized users to manage incidents with AWS Support.",
|
||||
@@ -203,7 +203,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS access from within AWS instances can be done by either encoding AWS keys into AWS API calls or by assigning the instance to a role which has an appropriate permissions policy for the required access. \"AWS Access\" means accessing the APIs of AWS in order to access AWS resources or manage AWS account resources.",
|
||||
@@ -224,7 +224,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To enable HTTPS connections to your website or application in AWS, you need an SSL/TLS server certificate. You can use ACM or IAM to store and deploy server certificates. Use IAM as a certificate manager only when you must support HTTPS connections in a region that is not supported by ACM. IAM securely encrypts your private keys and stores the encrypted version in IAM SSL certificate storage. IAM supports deploying server certificates in all regions, but you must obtain your certificate from an external provider for use with AWS. You cannot upload an ACM certificate to IAM. Additionally, you cannot manage your certificates from the IAM Console.",
|
||||
@@ -245,7 +245,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS provides customers with the option of specifying the contact information for account's security team. It is recommended that this information be provided.",
|
||||
@@ -266,7 +266,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable IAM Access analyzer for IAM policies about all resources in each region. IAM Access Analyzer is a technology introduced at AWS reinvent 2019. After the Analyzer is enabled in IAM, scan results are displayed on the console showing the accessible resources. Scans show resources that other accounts and federated users can access, such as KMS keys and IAM roles. So the results allow you to determine if an unintended user is allowed, making it easier for administrators to monitor least privileges access. Access Analyzer analyzes only policies that are applied to resources in the same AWS Region.",
|
||||
@@ -287,7 +287,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In multi-account environments, IAM user centralization facilitates greater user control. User access beyond the initial account is then provided via role assumption. Centralization of users can be accomplished through federation with an external identity provider or through the use of AWS Organizations.",
|
||||
@@ -308,7 +308,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS CloudShell is a convenient way of running CLI commands against AWS services; a managed IAM policy ('AWSCloudShellFullAccess') provides full access to CloudShell, which allows file upload and download capability between a user's local system and the CloudShell environment. Within the CloudShell environment a user has sudo permissions, and can access the internet. So it is feasible to install file transfer software (for example) and move data from CloudShell to external internet servers.",
|
||||
@@ -329,7 +329,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The AWS support portal allows account owners to establish security questions that can be used to authenticate individuals calling AWS customer service for support. It is recommended that security questions be established.",
|
||||
@@ -350,7 +350,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. AWS Access Keys provide programmatic access to a given AWS account. It is recommended that all access keys associated with the 'root' user account be removed.",
|
||||
@@ -371,7 +371,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. Multi-factor Authentication (MFA) adds an extra layer of protection on top of a username and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their username and password as well as for an authentication code from their AWS MFA device. **Note:** When virtual MFA is used for 'root' accounts, it is recommended that the device used is NOT a personal device, but rather a dedicated mobile device (tablet or phone) that is managed to be kept charged and secured independent of any individual personal devices. (\"non-personal virtual MFA\") This lessens the risks of losing access to the MFA due to device loss, device trade-in or if the individual owning the device is no longer employed at the company.",
|
||||
@@ -392,7 +392,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their user name and password as well as for an authentication code from their AWS MFA device. For Level 2, it is recommended that the 'root' user account be protected with a hardware MFA.",
|
||||
@@ -413,7 +413,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "With the creation of an AWS account, a 'root user' is created that cannot be disabled or deleted. That user has unrestricted access to and control over all resources in the AWS account. It is highly recommended that the use of this account be avoided for everyday tasks.",
|
||||
@@ -434,7 +434,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Password policies are, in part, used to enforce password complexity requirements. IAM password policies can be used to ensure password are at least a given length. It is recommended that the password policy require a minimum password length 14.",
|
||||
@@ -455,7 +455,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM password policies can prevent the reuse of a given password by the same user. It is recommended that the password policy prevent the reuse of passwords.",
|
||||
@@ -476,7 +476,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -499,8 +499,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -521,8 +521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -544,8 +544,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -566,8 +566,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.2 Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -589,8 +589,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -611,8 +611,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that RDS database instances have the Auto Minor Version Upgrade flag enabled in order to receive automatically minor engine upgrades during the specified maintenance window. So, RDS instances can get the new features, bug fixes, and security patches for their database engines.",
|
||||
@@ -633,8 +633,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure and verify that RDS database instances provisioned in your AWS account do restrict unauthorized access in order to minimize security risks. To restrict access to any publicly accessible RDS database instance, you must disable the database Publicly Accessible flag and update the VPC security group associated with the instance.",
|
||||
@@ -655,7 +655,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.4 Elastic File System (EFS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -677,7 +677,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for your account and delivers log files to you. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail provides a history of AWS API calls for an account, including API calls made via the Management Console, SDKs, command line tools, and higher-level AWS services (such as CloudFormation).",
|
||||
@@ -698,7 +698,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -719,7 +719,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -740,7 +740,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail log file validation creates a digitally signed digest file containing a hash of each log that CloudTrail writes to S3. These digest files can be used to determine whether a log file was changed, deleted, or unchanged after CloudTrail delivered the log. It is recommended that file validation be enabled on all CloudTrails.",
|
||||
@@ -761,7 +761,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail logs a record of every API call made in your AWS account. These logs file are stored in an S3 bucket. It is recommended that the bucket policy or access control list (ACL) applied to the S3 bucket that CloudTrail logs to prevent public access to the CloudTrail logs.",
|
||||
@@ -782,7 +782,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls made in a given AWS account. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail uses Amazon S3 for log file storage and delivery, so log files are stored durably. In addition to capturing CloudTrail logs within a specified S3 bucket for long term analysis, realtime analysis can be performed by configuring CloudTrail to send logs to CloudWatch Logs. For a trail that is enabled in all regions in an account, CloudTrail sends log files from all those regions to a CloudWatch Logs log group. It is recommended that CloudTrail logs be sent to CloudWatch Logs. Note: The intent of this recommendation is to ensure AWS account activity is being captured, monitored, and appropriately alarmed on. CloudWatch Logs is a native way to accomplish this using AWS services but does not preclude the use of an alternate solution.",
|
||||
@@ -803,7 +803,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Config is a web service that performs configuration management of supported AWS resources within your account and delivers log files to you. The recorded information includes the configuration item (AWS resource), relationships between configuration items (AWS resources), any configuration changes between resources. It is recommended AWS Config be enabled in all regions.",
|
||||
@@ -824,7 +824,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 Bucket Access Logging generates a log that contains access records for each request made to your S3 bucket. An access log record contains details about the request, such as the request type, the resources specified in the request worked, and the time and date the request was processed. It is recommended that bucket access logging be enabled on the CloudTrail S3 bucket.",
|
||||
@@ -845,7 +845,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for an account and makes those logs available to users and resources in accordance with IAM policies. AWS Key Management Service (KMS) is a managed service that helps create and control the encryption keys used to encrypt account data, and uses Hardware Security Modules (HSMs) to protect the security of encryption keys. CloudTrail logs can be configured to leverage server side encryption (SSE) and KMS customer created master keys (CMK) to further protect CloudTrail logs. It is recommended that CloudTrail be configured to use SSE-KMS.",
|
||||
@@ -866,7 +866,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Key Management Service (KMS) allows customers to rotate the backing key which is key material stored within the KMS which is tied to the key ID of the Customer Created customer master key (CMK). It is the backing key that is used to perform cryptographic operations such as encryption and decryption. Automated key rotation currently retains all prior backing keys so that decryption of encrypted data can take place transparently. It is recommended that CMK key rotation be enabled for symmetric keys. Key rotation can not be enabled for any asymmetric CMK.",
|
||||
@@ -887,7 +887,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. After you've created a flow log, you can view and retrieve its data in Amazon CloudWatch Logs. It is recommended that VPC Flow Logs be enabled for packet \"Rejects\" for VPCs.",
|
||||
@@ -908,7 +908,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for unauthorized API calls.",
|
||||
@@ -929,7 +929,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Security Groups are a stateful packet filter that controls ingress and egress traffic within a VPC. It is recommended that a metric filter and alarm be established for detecting changes to Security Groups.",
|
||||
@@ -950,7 +950,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. NACLs are used as a stateless packet filter to control ingress and egress traffic for subnets within a VPC. It is recommended that a metric filter and alarm be established for changes made to NACLs.",
|
||||
@@ -971,7 +971,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Network gateways are required to send/receive traffic to a destination outside of a VPC. It is recommended that a metric filter and alarm be established for changes to network gateways.",
|
||||
@@ -992,7 +992,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.",
|
||||
@@ -1013,7 +1013,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is possible to have more than 1 VPC within an account, in addition it is also possible to create a peer connection between 2 VPCs enabling network traffic to route between VPCs. It is recommended that a metric filter and alarm be established for changes made to VPCs.",
|
||||
@@ -1034,7 +1034,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for AWS Organizations changes made in the master AWS Account.",
|
||||
@@ -1055,7 +1055,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security Hub collects security data from across AWS accounts, services, and supported third-party partner products and helps you analyze your security trends and identify the highest priority security issues. When you enable Security Hub, it begins to consume, aggregate, organize, and prioritize findings from AWS services that you have enabled, such as Amazon GuardDuty, Amazon Inspector, and Amazon Macie. You can also enable integrations with AWS partner security products.",
|
||||
@@ -1076,7 +1076,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for console logins that are not protected by multi-factor authentication (MFA).",
|
||||
@@ -1097,7 +1097,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for 'root' login attempts.",
|
||||
@@ -1118,7 +1118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established changes made to Identity and Access Management (IAM) policies.",
|
||||
@@ -1139,7 +1139,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1160,7 +1160,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for failed console authentication attempts.",
|
||||
@@ -1181,7 +1181,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for customer created CMKs which have changed state to disabled or scheduled deletion.",
|
||||
@@ -1202,7 +1202,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for changes to S3 bucket policies.",
|
||||
@@ -1223,7 +1223,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1246,7 +1246,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The Network Access Control List (NACL) function provide stateless filtering of ingress and egress network traffic to AWS resources. It is recommended that no NACL allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1269,7 +1269,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1292,7 +1292,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1313,7 +1313,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A VPC comes with a default security group whose initial settings deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances assigned to the security group. If you don't specify a security group when you launch an instance, the instance is automatically assigned to this default security group. Security groups provide stateful filtering of ingress/egress network traffic to AWS resources. It is recommended that the default security group restrict all traffic. The default VPC in every region should have its default security group updated to comply. Any newly created VPCs will automatically contain a default security group that will need remediation to comply with this recommendation. **NOTE:** When implementing this recommendation, VPC flow logging is invaluable in determining the least privilege port access required by systems to work properly because it can log all packet acceptances and rejections occurring under the current security groups. This dramatically reduces the primary barrier to least privilege engineering - discovering the minimum ports required by systems in the environment. Even if the VPC flow logging recommendation in this benchmark is not adopted as a permanent security measure, it should be used during any period of discovery and engineering for least privileged security groups.",
|
||||
@@ -1334,7 +1334,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Once a VPC peering connection is established, routing tables must be updated to establish any connections between the peered VPCs. These routes can be as specific as desired - even peering a VPC to only a single host on the other side of the connection.",
|
||||
@@ -1356,7 +1356,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "When enabling the Metadata Service on AWS EC2 instances, users have the option of using either Instance Metadata Service Version 1 (IMDSv1; a request/response method) or Instance Metadata Service Version 2 (IMDSv2; a session-oriented method).",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure contact email and telephone details for AWS accounts are current and map to more than one individual in your organization. An AWS account supports a number of contact details, and AWS will use these to contact the account owner if activity judged to be in breach of Acceptable Use Policy or indicative of likely security compromise is observed by the AWS Abuse team. Contact details should not be for a single individual, as circumstances may arise where that individual is unavailable. Email contact details should point to a mail alias which forwards email to multiple individuals within the organization; where feasible, phone contact details should point to a PABX hunt group or other call-forwarding system.",
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Multi-Factor Authentication (MFA) adds an extra layer of authentication assurance beyond traditional credentials. With MFA enabled, when a user signs in to the AWS Console, they will be prompted for their user name and password as well as for an authentication code from their physical or virtual MFA token. It is recommended that MFA be enabled for all accounts that have a console password.",
|
||||
@@ -54,7 +54,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS console defaults to no check boxes selected when creating a new IAM user. When cerating the IAM User credentials you have to determine what type of access they require. Programmatic access: The IAM user might need to make API calls, use the AWS CLI, or use the Tools for Windows PowerShell. In that case, create an access key (access key ID and a secret access key) for that user. AWS Management Console access: If the user needs to access the AWS Management Console, create a password for the user.",
|
||||
@@ -76,7 +76,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS IAM users can access AWS resources using different types of credentials, such as passwords or access keys. It is recommended that all credentials that have been unused in 45 or greater days be deactivated or removed.",
|
||||
@@ -97,7 +97,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys are long-term credentials for an IAM user or the AWS account 'root' user. You can use access keys to sign programmatic requests to the AWS CLI or AWS API (directly or using the AWS SDK)",
|
||||
@@ -118,7 +118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys consist of an access key ID and secret access key, which are used to sign programmatic requests that you make to AWS. AWS users need their own access keys to make programmatic calls to AWS from the AWS Command Line Interface (AWS CLI), Tools for Windows PowerShell, the AWS SDKs, or direct HTTP calls using the APIs for individual AWS services. It is recommended that all access keys be regularly rotated.",
|
||||
@@ -139,7 +139,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM users are granted access to services, functions, and data through IAM policies. There are three ways to define policies for a user: 1) Edit the user policy directly, aka an inline, or user, policy; 2) attach a policy directly to a user; 3) add the user to an IAM group that has an attached policy. Only the third implementation is recommended.",
|
||||
@@ -161,7 +161,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM policies are the means by which privileges are granted to users, groups, or roles. It is recommended and considered a standard security advice to grant _least privilege_ -that is, granting only the permissions required to perform a task. Determine what users need to do and then craft policies for them that let the users perform _only_ those tasks, instead of allowing full administrative privileges.",
|
||||
@@ -182,7 +182,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS provides a support center that can be used for incident notification and response, as well as technical support and customer services. Create an IAM Role to allow authorized users to manage incidents with AWS Support.",
|
||||
@@ -203,7 +203,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS access from within AWS instances can be done by either encoding AWS keys into AWS API calls or by assigning the instance to a role which has an appropriate permissions policy for the required access. \"AWS Access\" means accessing the APIs of AWS in order to access AWS resources or manage AWS account resources.",
|
||||
@@ -224,7 +224,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To enable HTTPS connections to your website or application in AWS, you need an SSL/TLS server certificate. You can use ACM or IAM to store and deploy server certificates. Use IAM as a certificate manager only when you must support HTTPS connections in a region that is not supported by ACM. IAM securely encrypts your private keys and stores the encrypted version in IAM SSL certificate storage. IAM supports deploying server certificates in all regions, but you must obtain your certificate from an external provider for use with AWS. You cannot upload an ACM certificate to IAM. Additionally, you cannot manage your certificates from the IAM Console.",
|
||||
@@ -245,7 +245,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS provides customers with the option of specifying the contact information for account's security team. It is recommended that this information be provided.",
|
||||
@@ -266,7 +266,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable IAM Access analyzer for IAM policies about all resources in each region. IAM Access Analyzer is a technology introduced at AWS reinvent 2019. After the Analyzer is enabled in IAM, scan results are displayed on the console showing the accessible resources. Scans show resources that other accounts and federated users can access, such as KMS keys and IAM roles. So the results allow you to determine if an unintended user is allowed, making it easier for administrators to monitor least privileges access. Access Analyzer analyzes only policies that are applied to resources in the same AWS Region.",
|
||||
@@ -287,7 +287,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In multi-account environments, IAM user centralization facilitates greater user control. User access beyond the initial account is then provided via role assumption. Centralization of users can be accomplished through federation with an external identity provider or through the use of AWS Organizations.",
|
||||
@@ -306,7 +306,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS CloudShell is a convenient way of running CLI commands against AWS services; a managed IAM policy ('AWSCloudShellFullAccess') provides full access to CloudShell, which allows file upload and download capability between a user's local system and the CloudShell environment. Within the CloudShell environment a user has sudo permissions, and can access the internet. So it is feasible to install file transfer software (for example) and move data from CloudShell to external internet servers.",
|
||||
@@ -327,7 +327,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The AWS support portal allows account owners to establish security questions that can be used to authenticate individuals calling AWS customer service for support. It is recommended that security questions be established.",
|
||||
@@ -348,7 +348,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. AWS Access Keys provide programmatic access to a given AWS account. It is recommended that all access keys associated with the 'root' user account be removed.",
|
||||
@@ -369,7 +369,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. Multi-factor Authentication (MFA) adds an extra layer of protection on top of a username and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their username and password as well as for an authentication code from their AWS MFA device. **Note:** When virtual MFA is used for 'root' accounts, it is recommended that the device used is NOT a personal device, but rather a dedicated mobile device (tablet or phone) that is managed to be kept charged and secured independent of any individual personal devices. (\"non-personal virtual MFA\") This lessens the risks of losing access to the MFA due to device loss, device trade-in or if the individual owning the device is no longer employed at the company.",
|
||||
@@ -390,7 +390,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their user name and password as well as for an authentication code from their AWS MFA device. For Level 2, it is recommended that the 'root' user account be protected with a hardware MFA.",
|
||||
@@ -411,7 +411,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "With the creation of an AWS account, a 'root user' is created that cannot be disabled or deleted. That user has unrestricted access to and control over all resources in the AWS account. It is highly recommended that the use of this account be avoided for everyday tasks.",
|
||||
@@ -432,7 +432,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Password policies are, in part, used to enforce password complexity requirements. IAM password policies can be used to ensure password are at least a given length. It is recommended that the password policy require a minimum password length 14.",
|
||||
@@ -453,7 +453,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM password policies can prevent the reuse of a given password by the same user. It is recommended that the password policy prevent the reuse of passwords.",
|
||||
@@ -474,8 +474,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -496,8 +496,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -518,8 +518,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -541,8 +541,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.1 Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -563,8 +563,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.2 Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -585,8 +585,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -607,8 +607,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that RDS database instances have the Auto Minor Version Upgrade flag enabled in order to receive automatically minor engine upgrades during the specified maintenance window. So, RDS instances can get the new features, bug fixes, and security patches for their database engines.",
|
||||
@@ -629,8 +629,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.3 Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure and verify that RDS database instances provisioned in your AWS account do restrict unauthorized access in order to minimize security risks. To restrict access to anypublicly accessible RDS database instance, you must disable the database PubliclyAccessible flag and update the VPC security group associated with the instance",
|
||||
@@ -651,7 +651,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Storage",
|
||||
"Section": "2 Storage",
|
||||
"SubSection": "2.4 Elastic File System (EFS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -673,7 +673,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for your account and delivers log files to you. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail provides a history of AWS API calls for an account, including API calls made via the Management Console, SDKs, command line tools, and higher-level AWS services (such as CloudFormation).",
|
||||
@@ -694,7 +694,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -715,7 +715,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations such as GetObject, DeleteObject, and PutObject are called data events. By default, CloudTrail trails don't log data events and so it is recommended to enable Object-level logging for S3 buckets.",
|
||||
@@ -736,7 +736,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail log file validation creates a digitally signed digest file containing a hash of each log that CloudTrail writes to S3. These digest files can be used to determine whether a log file was changed, deleted, or unchanged after CloudTrail delivered the log. It is recommended that file validation be enabled on all CloudTrails.",
|
||||
@@ -757,7 +757,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Config is a web service that performs configuration management of supported AWS resources within your account and delivers log files to you. The recorded information includes the configuration item (AWS resource), relationships between configuration items (AWS resources), any configuration changes between resources. It is recommended AWS Config be enabled in all regions.",
|
||||
@@ -778,7 +778,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 Bucket Access Logging generates a log that contains access records for each request made to your S3 bucket. An access log record contains details about the request, such as the request type, the resources specified in the request worked, and the time and date the request was processed. It is recommended that bucket access logging be enabled on the CloudTrail S3 bucket.",
|
||||
@@ -799,7 +799,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for an account and makes those logs available to users and resources in accordance with IAM policies. AWS Key Management Service (KMS) is a managed service that helps create and control the encryption keys used to encrypt account data, and uses Hardware Security Modules (HSMs) to protect the security of encryption keys. CloudTrail logs can be configured to leverage server side encryption (SSE) and KMS customer created master keys (CMK) to further protect CloudTrail logs. It is recommended that CloudTrail be configured to use SSE-KMS.",
|
||||
@@ -820,7 +820,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Key Management Service (KMS) allows customers to rotate the backing key which is key material stored within the KMS which is tied to the key ID of the Customer Created customer master key (CMK). It is the backing key that is used to perform cryptographic operations such as encryption and decryption. Automated key rotation currently retains all prior backing keys so that decryption of encrypted data can take place transparently. It is recommended that CMK key rotation be enabled for symmetric keys. Key rotation can not be enabled for any asymmetric CMK.",
|
||||
@@ -841,7 +841,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Logging",
|
||||
"Section": "3 Logging",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. After you've created a flow log, you can view and retrieve its data in Amazon CloudWatch Logs. It is recommended that VPC Flow Logs be enabled for packet \"Rejects\" for VPCs.",
|
||||
@@ -862,7 +862,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for unauthorized API calls.",
|
||||
@@ -883,7 +883,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Security Groups are a stateful packet filter that controls ingress and egress traffic within a VPC. It is recommended that a metric filter and alarm be established for detecting changes to Security Groups.",
|
||||
@@ -904,7 +904,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. NACLs are used as a stateless packet filter to control ingress and egress traffic for subnets within a VPC. It is recommended that a metric filter and alarm be established for changes made to NACLs.",
|
||||
@@ -925,7 +925,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Network gateways are required to send/receive traffic to a destination outside of a VPC. It is recommended that a metric filter and alarm be established for changes to network gateways.",
|
||||
@@ -946,7 +946,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.",
|
||||
@@ -967,7 +967,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is possible to have more than 1 VPC within an account, in addition it is also possible to create a peer connection between 2 VPCs enabling network traffic to route between VPCs. It is recommended that a metric filter and alarm be established for changes made to VPCs.",
|
||||
@@ -988,7 +988,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for AWS Organizations changes made in the master AWS Account.",
|
||||
@@ -1009,7 +1009,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security Hub collects security data from across AWS accounts, services, and supported third-party partner products and helps you analyze your security trends and identify the highest priority security issues. When you enable Security Hub, it begins to consume, aggregate, organize, and prioritize findings from AWS services that you have enabled, such as Amazon GuardDuty, Amazon Inspector, and Amazon Macie. You can also enable integrations with AWS partner security products.",
|
||||
@@ -1030,7 +1030,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for console logins that are not protected by multi-factor authentication (MFA).",
|
||||
@@ -1051,7 +1051,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for 'root' login attempts.",
|
||||
@@ -1072,7 +1072,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established changes made to Identity and Access Management (IAM) policies.",
|
||||
@@ -1093,7 +1093,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1114,7 +1114,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for failed console authentication attempts.",
|
||||
@@ -1135,7 +1135,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for customer created CMKs which have changed state to disabled or scheduled deletion.",
|
||||
@@ -1156,7 +1156,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for changes to S3 bucket policies.",
|
||||
@@ -1177,7 +1177,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Monitoring",
|
||||
"Section": "4 Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to CloudTrail's configurations.",
|
||||
@@ -1200,7 +1200,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The Network Access Control List (NACL) function provide stateless filtering of ingress and egress network traffic to AWS resources. It is recommended that no NACL allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1223,7 +1223,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1246,7 +1246,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port `22` and RDP to port `3389`.",
|
||||
@@ -1267,7 +1267,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A VPC comes with a default security group whose initial settings deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances assigned to the security group. If you don't specify a security group when you launch an instance, the instance is automatically assigned to this default security group. Security groups provide stateful filtering of ingress/egress network traffic to AWS resources. It is recommended that the default security group restrict all traffic. The default VPC in every region should have its default security group updated to comply. Any newly created VPCs will automatically contain a default security group that will need remediation to comply with this recommendation. **NOTE:** When implementing this recommendation, VPC flow logging is invaluable in determining the least privilege port access required by systems to work properly because it can log all packet acceptances and rejections occurring under the current security groups. This dramatically reduces the primary barrier to least privilege engineering - discovering the minimum ports required by systems in the environment. Even if the VPC flow logging recommendation in this benchmark is not adopted as a permanent security measure, it should be used during any period of discovery and engineering for least privileged security groups.",
|
||||
@@ -1288,7 +1288,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Once a VPC peering connection is established, routing tables must be updated to establish any connections between the peered VPCs. These routes can be as specific as desired - even peering a VPC to only a single host on the other side of the connection.",
|
||||
@@ -1309,7 +1309,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Networking",
|
||||
"Section": "5 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "When enabling the Metadata Service on AWS EC2 instances, users have the option of using either Instance Metadata Service Version 1 (IMDSv1; a request/response method) or Instance Metadata Service Version 2 (IMDSv2; a session-oriented method).",
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure contact email and telephone details for AWS accounts are current and map to more than one individual in your organization.An AWS account supports a number of contact details, and AWS will use these to contact the account owner if activity judged to be in breach of the Acceptable Use Policy or indicative of a likely security compromise is observed by the AWS Abuse team. Contact details should not be for a single individual, as circumstances may arise where that individual is unavailable. Email contact details should point to a mail alias which forwards email to multiple individuals within the organization; where feasible, phone contact details should point to a PABX hunt group or other call-forwarding system.",
|
||||
@@ -36,7 +35,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS provides customers with the option of specifying the contact information for account's security team. It is recommended that this information be provided.",
|
||||
@@ -59,7 +57,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The AWS support portal allows account owners to establish security questions that can be used to authenticate individuals calling AWS customer service for support. It is recommended that security questions be established.",
|
||||
@@ -82,7 +79,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. AWS Access Keys provide programmatic access to a given AWS account. It is recommended that all access keys associated with the 'root' user account be deleted.",
|
||||
@@ -105,7 +101,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. Multi-factor Authentication (MFA) adds an extra layer of protection on top of a username and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their username and password as well as for an authentication code from their AWS MFA device.**Note:** When virtual MFA is used for 'root' accounts, it is recommended that the device used is NOT a personal device, but rather a dedicated mobile device (tablet or phone) that is kept charged and secured, independent of any individual personal devices (non-personal virtual MFA). This lessens the risks of losing access to the MFA due to device loss, device trade-in, or if the individual owning the device is no longer employed at the company.",
|
||||
@@ -128,7 +123,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The 'root' user account is the most privileged user in an AWS account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they will be prompted for their user name and password as well as for an authentication code from their AWS MFA device. For Level 2, it is recommended that the 'root' user account be protected with a hardware MFA.",
|
||||
@@ -151,7 +145,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "With the creation of an AWS account, a 'root user' is created that cannot be disabled or deleted. That user has unrestricted access to and control over all resources in the AWS account. It is highly recommended that the use of this account be avoided for everyday tasks.",
|
||||
@@ -174,7 +167,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Password policies are, in part, used to enforce password complexity requirements. IAM password policies can be used to ensure passwords are at least a given length. It is recommended that the password policy require a minimum password length 14.",
|
||||
@@ -197,7 +189,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM password policies can prevent the reuse of a given password by the same user. It is recommended that the password policy prevent the reuse of passwords.",
|
||||
@@ -220,7 +211,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Multi-Factor Authentication (MFA) adds an extra layer of authentication assurance beyond traditional credentials. With MFA enabled, when a user signs in to the AWS Console, they will be prompted for their user name and password as well as for an authentication code from their physical or virtual MFA token. It is recommended that MFA be enabled for all accounts that have a console password.",
|
||||
@@ -243,7 +233,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS console defaults to no check boxes selected when creating a new IAM user. When creating the IAM User credentials you have to determine what type of access they require. Programmatic access: The IAM user might need to make API calls, use the AWS CLI, or use the Tools for Windows PowerShell. In that case, create an access key (access key ID and a secret access key) for that user. AWS Management Console access: If the user needs to access the AWS Management Console, create a password for the user.",
|
||||
@@ -267,7 +256,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS IAM users can access AWS resources using different types of credentials, such as passwords or access keys. It is recommended that all credentials that have been unused for 45 days or more be deactivated or removed.",
|
||||
@@ -290,7 +278,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys are long-term credentials for an IAM user or the AWS account 'root' user. You can use access keys to sign programmatic requests to the AWS CLI or AWS API (directly or using the AWS SDK)",
|
||||
@@ -313,7 +300,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Access keys consist of an access key ID and secret access key, which are used to sign programmatic requests that you make to AWS. AWS users need their own access keys to make programmatic calls to AWS from the AWS Command Line Interface (AWS CLI), Tools for Windows PowerShell, the AWS SDKs, or direct HTTP calls using the APIs for individual AWS services. It is recommended that all access keys be rotated regularly.",
|
||||
@@ -336,7 +322,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM users are granted access to services, functions, and data through IAM policies. There are four ways to define policies for a user: 1) Edit the user policy directly, also known as an inline or user policy; 2) attach a policy directly to a user; 3) add the user to an IAM group that has an attached policy; 4) add the user to an IAM group that has an inline policy.Only the third implementation is recommended.",
|
||||
@@ -360,7 +345,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "IAM policies are the means by which privileges are granted to users, groups, or roles. It is recommended and considered standard security advice to grant least privilege—that is, granting only the permissions required to perform a task. Determine what users need to do, and then craft policies for them that allow the users to perform only those tasks, instead of granting full administrative privileges.",
|
||||
@@ -383,7 +367,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS provides a support center that can be used for incident notification and response, as well as technical support and customer services. Create an IAM Role, with the appropriate policy assigned, to allow authorized users to manage incidents with AWS Support.",
|
||||
@@ -406,7 +389,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS access from within AWS instances can be done by either encoding AWS keys into AWS API calls or by assigning the instance to a role which has an appropriate permissions policy for the required access. AWS Access means accessing the APIs of AWS in order to access AWS resources or manage AWS account resources.",
|
||||
@@ -429,7 +411,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To enable HTTPS connections to your website or application in AWS, you need an SSL/TLS server certificate. You can use AWS Certificate Manager (ACM) or IAM to store and deploy server certificates. Use IAM as a certificate manager only when you must support HTTPS connections in a region that is not supported by ACM. IAM securely encrypts your private keys and stores the encrypted version in IAM SSL certificate storage. IAM supports deploying server certificates in all regions, but you must obtain your certificate from an external provider for use with AWS. You cannot upload an ACM certificate to IAM. Additionally, you cannot manage your certificates from the IAM Console.",
|
||||
@@ -452,7 +433,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable the IAM Access Analyzer for IAM policies regarding all resources in each active AWS region.IAM Access Analyzer is a technology introduced at AWS reinvent 2019. After the Analyzer is enabled in IAM, scan results are displayed on the console showing the accessible resources. Scans show resources that other accounts and federated users can access, such as KMS keys and IAM roles. The results allow you to determine whether an unintended user is permitted, making it easier for administrators to monitor least privilege access. Access Analyzer analyzes only the policies that are applied to resources in the same AWS Region.",
|
||||
@@ -475,7 +455,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In multi-account environments, IAM user centralization facilitates greater user control. User access beyond the initial account is then provided via role assumption. Centralization of users can be accomplished through federation with an external identity provider or through the use of AWS Organizations.",
|
||||
@@ -498,7 +477,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1 Identity and Access Management",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "AWS CloudShell is a convenient way of running CLI commands against AWS services; a managed IAM policy ('AWSCloudShellFullAccess') provides full access to CloudShell, which allows file upload and download capability between a user's local system and the CloudShell environment. Within the CloudShell environment, a user has sudo permissions and can access the internet. Therefore, it is feasible to install file transfer software, for example, and move data from CloudShell to external internet servers.",
|
||||
@@ -730,7 +708,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for your account and delivers log files to you. The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service. CloudTrail provides a history of AWS API calls for an account, including API calls made via the Management Console, SDKs, command line tools, and higher-level AWS services (such as CloudFormation).",
|
||||
@@ -753,7 +730,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "CloudTrail log file validation creates a digitally signed digest file containing a hash of each log that CloudTrail writes to S3. These digest files can be used to determine whether a log file was changed, deleted, or remained unchanged after CloudTrail delivered the log. It is recommended that file validation be enabled for all CloudTrails.",
|
||||
@@ -776,7 +752,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Config is a web service that performs configuration management of supported AWS resources within your account and delivers log files to you. The recorded information includes the configuration items (AWS resources), relationships between configuration items (AWS resources), and any configuration changes between resources. It is recommended that AWS Config be enabled in all regions.",
|
||||
@@ -799,7 +774,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Server access logging generates a log that contains access records for each request made to your S3 bucket. An access log record contains details about the request, such as the request type, the resources specified in the request worked, and the time and date the request was processed. It is recommended that server access logging be enabled on the CloudTrail S3 bucket.",
|
||||
@@ -822,7 +796,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS CloudTrail is a web service that records AWS API calls for an account and makes those logs available to users and resources in accordance with IAM policies. AWS Key Management Service (KMS) is a managed service that helps create and control the encryption keys used to encrypt account data, and uses Hardware Security Modules (HSMs) to protect the security of encryption keys. CloudTrail logs can be configured to leverage server side encryption (SSE) and KMS customer-created master keys (CMK) to further protect CloudTrail logs. It is recommended that CloudTrail be configured to use SSE-KMS.",
|
||||
@@ -845,7 +818,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "AWS Key Management Service (KMS) allows customers to rotate the backing key, which is key material stored within the KMS that is tied to the key ID of the customer-created customer master key (CMK). The backing key is used to perform cryptographic operations such as encryption and decryption. Automated key rotation currently retains all prior backing keys so that decryption of encrypted data can occur transparently. It is recommended that CMK key rotation be enabled for symmetric keys. Key rotation cannot be enabled for any asymmetric CMK.",
|
||||
@@ -868,7 +840,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. After you've created a flow log, you can view and retrieve its data in Amazon CloudWatch Logs. It is recommended that VPC Flow Logs be enabled for packet Rejects for VPCs.",
|
||||
@@ -891,7 +862,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations, such as GetObject, DeleteObject, and PutObject, are referred to as data events. By default, CloudTrail trails do not log data events, so it is recommended to enable object-level logging for S3 buckets.",
|
||||
@@ -914,7 +884,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3 Logging",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "S3 object-level API operations, such as GetObject, DeleteObject, and PutObject, are referred to as data events. By default, CloudTrail trails do not log data events, so it is recommended to enable object-level logging for S3 buckets.",
|
||||
@@ -937,7 +906,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for unauthorized API calls.",
|
||||
@@ -960,7 +928,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for console logins that are not protected by multi-factor authentication (MFA).",
|
||||
@@ -983,7 +950,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for 'root' login attempts to detect unauthorized use or attempts to use the root account.",
|
||||
@@ -1006,7 +972,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms.It is recommended that a metric filter and alarm be established for changes made to Identity and Access Management (IAM) policies.",
|
||||
@@ -1029,7 +994,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be used to detect changes to CloudTrail's configurations.",
|
||||
@@ -1052,7 +1016,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for failed console authentication attempts.",
|
||||
@@ -1075,7 +1038,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for customer-created CMKs that have changed state to disabled or are scheduled for deletion.",
|
||||
@@ -1098,7 +1060,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for changes to S3 bucket policies.",
|
||||
@@ -1121,7 +1082,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for detecting changes to AWS Config's configurations.",
|
||||
@@ -1144,7 +1104,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. Security groups are stateful packet filters that control ingress and egress traffic within a VPC.It is recommended that a metric filter and alarm be established to detect changes to security groups.",
|
||||
@@ -1167,7 +1126,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. NACLs are used as a stateless packet filter to control ingress and egress traffic for subnets within a VPC. It is recommended that a metric filter and alarm be established for any changes made to NACLs.",
|
||||
@@ -1190,7 +1148,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. Network gateways are required to send and receive traffic to a destination outside of a VPC. It is recommended that a metric filter and alarm be established for changes to network gateways.",
|
||||
@@ -1213,7 +1170,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways.It is recommended that a metric filter and alarm be established for changes to route tables.",
|
||||
@@ -1236,7 +1192,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is possible to have more than one VPC within an account; additionally, it is also possible to create a peer connection between two VPCs, enabling network traffic to route between them.It is recommended that a metric filter and alarm be established for changes made to VPCs.",
|
||||
@@ -1259,7 +1214,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs or an external Security Information and Event Management (SIEM) environment, and establishing corresponding metric filters and alarms. It is recommended that a metric filter and alarm be established for changes made to AWS Organizations in the master AWS account.",
|
||||
@@ -1282,7 +1236,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4 Monitoring",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security Hub collects security data from various AWS accounts, services, and supported third-party partner products, helping you analyze your security trends and identify the highest-priority security issues. When you enable Security Hub, it begins to consume, aggregate, organize, and prioritize findings from the AWS services that you have enabled, such as Amazon GuardDuty, Amazon Inspector, and Amazon Macie. You can also enable integrations with AWS partner security products.",
|
||||
@@ -1307,7 +1260,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5 Networking",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The Network Access Control List (NACL) function provides stateless filtering of ingress and egress network traffic to AWS resources. It is recommended that no NACL allows unrestricted ingress access to remote server administration ports, such as SSH on port `22` and RDP on port `3389`, using either the TCP (6), UDP (17), or ALL (-1) protocols.",
|
||||
@@ -1332,7 +1284,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5 Networking",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH on port `22` and RDP on port `3389`, using either the TCP (6), UDP (17), or ALL (-1) protocols.",
|
||||
@@ -1357,7 +1308,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5 Networking",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH on port `22` and RDP on port `3389`.",
|
||||
@@ -1380,7 +1330,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5 Networking",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A VPC comes with a default security group whose initial settings deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances assigned to the security group. If a security group is not specified when an instance is launched, it is automatically assigned to this default security group. Security groups provide stateful filtering of ingress/egress network traffic to AWS resources. It is recommended that the default security group restrict all traffic, both inbound and outbound.The default VPC in every region should have its default security group updated to comply with the following: - No inbound rules. - No outbound rules.Any newly created VPCs will automatically contain a default security group that will need remediation to comply with this recommendation.**Note:** When implementing this recommendation, VPC flow logging is invaluable in determining the least privilege port access required by systems to work properly, as it can log all packet acceptances and rejections occurring under the current security groups. This dramatically reduces the primary barrier to least privilege engineering by discovering the minimum ports required by systems in the environment. Even if the VPC flow logging recommendation in this benchmark is not adopted as a permanent security measure, it should be used during any period of discovery and engineering for least privileged security groups.",
|
||||
@@ -1403,7 +1352,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5 Networking",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Once a VPC peering connection is established, routing tables must be updated to enable any connections between the peered VPCs. These routes can be as specific as desired, even allowing for the peering of a VPC to only a single host on the other side of the connection.",
|
||||
@@ -1426,7 +1374,6 @@
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5 Networking",
|
||||
"SubSection": "",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "When enabling the Metadata Service on AWS EC2 instances, users have the option of using either Instance Metadata Service Version 1 (IMDSv1; a request/response method) or Instance Metadata Service Version 2 (IMDSv2; a session-oriented method).",
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -10,7 +10,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Use corporate login credentials instead of personal accounts, such as Gmail accounts.",
|
||||
@@ -29,7 +29,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Setup multi-factor authentication for Google Cloud Platform accounts.",
|
||||
@@ -48,7 +48,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Setup Security Key Enforcement for Google Cloud Platform admin accounts.",
|
||||
@@ -69,7 +69,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. API keys are always at risk because they can be viewed publicly, such as from within a browser, or they can be accessed on a device where the key resides. It is recommended to restrict API keys to use (call) only APIs required by an application.",
|
||||
@@ -90,7 +90,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. If they are in use it is recommended to rotate API keys every 90 days.",
|
||||
@@ -111,7 +111,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. Unused keys with their permissions in tact may still exist within a project. Keys are insecure because they can be viewed publicly, such as from within a browser, or they can be accessed on a device where the key resides. It is recommended to use standard authentication flow instead.",
|
||||
@@ -132,7 +132,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that Essential Contacts is configured to designate email addresses for Google Cloud services to notify of important technical or security information.",
|
||||
@@ -153,7 +153,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Google Cloud Key Management Service stores cryptographic keys in a hierarchical structure designed for useful and elegant access control management. The format for the rotation schedule depends on the client library that is used. For the gcloud command-line tool, the next rotation time must be in `ISO` or `RFC3339` format, and the rotation period must be in the form `INTEGERUNIT`, where units can be one of seconds (s), minutes (m), hours (h) or days (d).",
|
||||
@@ -174,7 +174,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the IAM policy on Cloud KMS `cryptokeys` should restrict anonymous and/or public access.",
|
||||
@@ -195,7 +195,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "When you use Dataproc, cluster and job data is stored on Persistent Disks (PDs) associated with the Compute Engine VMs in your cluster and in a Cloud Storage staging bucket. This PD and bucket data is encrypted using a Google-generated data encryption key (DEK) and key encryption key (KEK). The CMEK feature allows you to create, use, and revoke the key encryption key (KEK). Google still controls the data encryption key (DEK).",
|
||||
@@ -216,7 +216,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to assign the `Service Account User (iam.serviceAccountUser)` and `Service Account Token Creator (iam.serviceAccountTokenCreator)` roles to a user for a specific service account rather than assigning the role to a user at project level.",
|
||||
@@ -237,7 +237,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the principle of 'Separation of Duties' is enforced while assigning KMS related roles to users.",
|
||||
@@ -256,7 +256,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. In this case, unrestricted keys are insecure because they can be viewed publicly, such as from within a browser, or they can be accessed on a device where the key resides. It is recommended to restrict API key usage to trusted hosts, HTTP referrers and apps. It is recommended to use the more secure standard authentication flow instead.",
|
||||
@@ -277,7 +277,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the principle of 'Separation of Duties' is enforced while assigning service-account related roles to users.",
|
||||
@@ -298,7 +298,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A service account is a special Google account that belongs to an application or a VM, instead of to an individual end-user. The application uses the service account to call the service's Google API so that users aren't directly involved. It's recommended not to use admin access for ServiceAccount.",
|
||||
@@ -319,7 +319,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "User managed service accounts should not have user-managed keys.",
|
||||
@@ -340,7 +340,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Service Account keys consist of a key ID (Private_key_Id) and Private key, which are used to sign programmatic requests users make to Google cloud services accessible to that particular service account. It is recommended that all Service Account keys are regularly rotated.",
|
||||
@@ -359,7 +359,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Google Cloud Functions allow you to host serverless code that is executed when an event is triggered, without the requiring the management a host operating system. These functions can also store environment variables to be used by the code that may contain authentication or other information that needs to remain confidential.",
|
||||
@@ -380,7 +380,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP Access Approval enables you to require your organizations' explicit approval whenever Google support try to access your projects. You can then select users within your organization who can approve these requests through giving them a security role in IAM. All access requests display which Google Employee requested them in an email or Pub/Sub message that you can choose to Approve. This adds an additional control and logging of who in your organization approved/denied these requests.",
|
||||
@@ -401,7 +401,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP Cloud Asset Inventory is services that provides a historical view of GCP resources and IAM policies through a time-series database. The information recorded includes metadata on Google Cloud resources, metadata on policies set on Google Cloud projects or resources, and runtime information gathered within a Google Cloud resource.",
|
||||
@@ -422,7 +422,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "In order to prevent unnecessary project ownership assignments to users/service-accounts and further misuses of projects and resources, all `roles/Owner` assignments should be monitored. Members (users/Service-Accounts) with a role assignment to primitive role `roles/Owner` are project owners. The project owner has all the privileges on the project the role belongs to. These are summarized below: - All viewer permissions on all GCP Services within the project - Permissions for actions that modify the state of all GCP services within the project - Manage roles and permissions for a project and all resources within the project - Set up billing for a project Granting the owner role to a member (user/Service-Account) will allow that member to modify the Identity and Access Management (IAM) policy. Therefore, grant the owner role only if the member has a legitimate purpose to manage the IAM policy. This is because the project IAM policy contains sensitive access control data. Having a minimal set of users allowed to manage IAM policy will simplify any auditing that may be necessary.",
|
||||
@@ -443,7 +443,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Logging enabled on a HTTPS Load Balancer will show all network traffic and its destination.",
|
||||
@@ -464,7 +464,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that Cloud Audit Logging is configured to track all admin activities and read, write access to user data.",
|
||||
@@ -485,7 +485,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Cloud DNS logging records the queries from the name servers within your VPC to Stackdriver. Logged queries can come from Compute Engine VMs, GKE containers, or other GCP resources provisioned within the VPC.",
|
||||
@@ -506,7 +506,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling retention policies on log buckets will protect logs stored in cloud storage buckets from being overwritten or accidentally deleted. It is recommended to set up retention policies and configure Bucket Lock on all storage buckets that are used as log sinks.",
|
||||
@@ -527,7 +527,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to create a sink that will export copies of all the log entries. This can help aggregate logs from multiple projects and export them to a Security Information and Event Management (SIEM).",
|
||||
@@ -548,7 +548,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Google Cloud Platform (GCP) services write audit log entries to the Admin Activity and Data Access logs to help answer the questions of, \"who did what, where, and when?\" within GCP projects. Cloud audit logging records information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by GCP services. Cloud audit logging provides a history of GCP API calls for an account, including API calls made via the console, SDKs, command-line tools, and other GCP services.",
|
||||
@@ -569,7 +569,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Cloud Storage Bucket IAM changes.",
|
||||
@@ -590,7 +590,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for changes to Identity and Access Management (IAM) role creation, deletion and updating activities.",
|
||||
@@ -611,7 +611,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for SQL instance configuration changes.",
|
||||
@@ -632,7 +632,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Virtual Private Cloud (VPC) network changes.",
|
||||
@@ -651,7 +651,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "GCP Access Transparency provides audit logs for all actions that Google personnel take in your Google Cloud resources.",
|
||||
@@ -672,7 +672,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Virtual Private Cloud (VPC) Network Firewall rule changes.",
|
||||
@@ -693,7 +693,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Virtual Private Cloud (VPC) network route changes.",
|
||||
@@ -714,7 +714,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "In order to prevent use of legacy networks, a project should not have a legacy network configured. As of now, Legacy Networks are gradually being phased out, and you can no longer create projects with them. This recommendation is to check older projects to ensure that they are not using Legacy Networks.",
|
||||
@@ -735,7 +735,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Cloud Domain Name System (DNS) is a fast, reliable and cost-effective domain name system that powers millions of domains on the internet. Domain Name System Security Extensions (DNSSEC) in Cloud DNS enables domain owners to take easy steps to protect their domains against DNS hijacking and man-in-the-middle and other attacks.",
|
||||
@@ -756,7 +756,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP `Firewall Rules` are specific to a `VPC Network`. Each rule either `allows` or `denies` traffic when its conditions are met. Its conditions allow users to specify the type of traffic, such as ports and protocols, and the source or destination of the traffic, including IP addresses, subnets, and instances. Firewall rules are defined at the VPC network level and are specific to the network in which they are defined. The rules themselves cannot be shared among networks. Firewall rules only support IPv4 traffic. When specifying a source for an ingress rule or a destination for an egress rule by address, an `IPv4` address or `IPv4 block in CIDR` notation can be used. Generic `(0.0.0.0/0)` incoming traffic from the Internet to a VPC or VM instance using `RDP` on `Port 3389` can be avoided.",
|
||||
@@ -777,7 +777,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "NOTE: Currently, the SHA1 algorithm has been removed from general use by Google, and, if being used, needs to be whitelisted on a project basis by Google and will also, therefore, require a Google Cloud support contract. DNSSEC algorithm numbers in this registry may be used in CERT RRs. Zone signing (DNSSEC) and transaction security mechanisms (SIG(0) and TSIG) make use of particular subsets of these algorithms. The algorithm used for key signing should be a recommended one and it should be strong.",
|
||||
@@ -798,7 +798,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "NOTE: Currently, the SHA1 algorithm has been removed from general use by Google, and, if being used, needs to be whitelisted on a project basis by Google and will also, therefore, require a Google Cloud support contract. DNSSEC algorithm numbers in this registry may be used in CERT RRs. Zone signing (DNSSEC) and transaction security mechanisms (SIG(0) and TSIG) make use of particular subsets of these algorithms. The algorithm used for key signing should be a recommended one and it should be strong.",
|
||||
@@ -819,7 +819,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP `Firewall Rules` are specific to a `VPC Network`. Each rule either `allows` or `denies` traffic when its conditions are met. Its conditions allow the user to specify the type of traffic, such as ports and protocols, and the source or destination of the traffic, including IP addresses, subnets, and instances. Firewall rules are defined at the VPC network level and are specific to the network in which they are defined. The rules themselves cannot be shared among networks. Firewall rules only support IPv4 traffic. When specifying a source for an ingress rule or a destination for an egress rule by address, only an `IPv4` address or `IPv4 block in CIDR` notation can be used. Generic `(0.0.0.0/0)` incoming traffic from the internet to VPC or VM instance using `SSH` on `Port 22` can be avoided.",
|
||||
@@ -840,7 +840,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To prevent use of `default` network, a project should not have a `default` network.",
|
||||
@@ -861,7 +861,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Flow Logs is a feature that enables users to capture information about the IP traffic going to and from network interfaces in the organization's VPC Subnets. Once a flow log is created, the user can view and retrieve its data in Stackdriver Logging. It is recommended that Flow Logs be enabled for every business-critical VPC subnet.",
|
||||
@@ -880,7 +880,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Secure Sockets Layer (SSL) policies determine what port Transport Layer Security (TLS) features clients are permitted to use when connecting to load balancers. To prevent usage of insecure features, SSL policies should use (a) at least TLS 1.2 with the MODERN profile; or (b) the RESTRICTED profile, because it effectively requires clients to use TLS 1.2 regardless of the chosen minimum TLS version; or (3) a CUSTOM profile that does not support any of the following features: ``` TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_3DES_EDE_CBC_SHA ```",
|
||||
@@ -899,7 +899,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "IAP authenticates the user requests to your apps via a Google single sign in. You can then manage these users with permissions to control access. It is recommended to use both IAP permissions and firewalls to restrict this access to your apps with sensitive information.",
|
||||
@@ -920,7 +920,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Interacting with a serial port is often referred to as the serial console, which is similar to using a terminal window, in that input and output is entirely in text mode and there is no graphical interface or mouse support. If you enable the interactive serial console on an instance, clients can attempt to connect to that instance from any IP address. Therefore interactive serial console support should be disabled.",
|
||||
@@ -941,7 +941,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to use Instance specific SSH key(s) instead of using common/shared project-wide SSH key(s) to access Instances.",
|
||||
@@ -962,7 +962,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To defend against advanced threats and ensure that the boot loader and firmware on your VMs are signed and untampered, it is recommended that Compute instances are launched with Shielded VM enabled.",
|
||||
@@ -983,7 +983,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling OS login binds SSH certificates to IAM users and facilitates effective SSH certificate management.",
|
||||
@@ -1004,7 +1004,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Compute instances should not be configured to have external IP addresses.",
|
||||
@@ -1025,7 +1025,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Google Cloud encrypts data at-rest and in-transit, but customer data must be decrypted for processing. Confidential Computing is a breakthrough technology which encrypts data in-use—while it is being processed. Confidential Computing environments keep data encrypted in memory and elsewhere outside the central processing unit (CPU). Confidential VMs leverage the Secure Encrypted Virtualization (SEV) feature of AMD EPYC™ CPUs. Customer data will stay encrypted while it is used, indexed, queried, or trained on. Encryption keys are generated in hardware, per VM, and not exportable. Thanks to built-in hardware optimizations of both performance and security, there is no significant performance penalty to Confidential Computing workloads.",
|
||||
@@ -1046,7 +1046,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to configure your instance to not use the default Compute Engine service account because it has the Editor role on the project.",
|
||||
@@ -1067,7 +1067,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To support principle of least privileges and prevent potential privilege escalation it is recommended that instances are not assigned to default service account `Compute Engine default service account` with Scope `Allow full access to all Cloud APIs`.",
|
||||
@@ -1088,7 +1088,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Compute Engine instance cannot forward a packet unless the source IP address of the packet matches the IP address of the instance. Similarly, GCP won't deliver a packet whose destination IP address is different than the IP address of the instance receiving the packet. However, both capabilities are required if you want to use instances to help route packets. Forwarding of data packets should be disabled to prevent data loss or information disclosure.",
|
||||
@@ -1107,7 +1107,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In order to maintain the highest level of security all connections to an application should be secure by default.",
|
||||
@@ -1128,7 +1128,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Customer-Supplied Encryption Keys (CSEK) are a feature in Google Cloud Storage and Google Compute Engine. If you supply your own encryption keys, Google uses your key to protect the Google-generated keys used to encrypt and decrypt your data. By default, Google Compute Engine encrypts all data at rest. Compute Engine handles and manages this encryption for you without any additional actions on your part. However, if you wanted to control and manage this encryption yourself, you can provide your own encryption keys.",
|
||||
@@ -1147,7 +1147,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Google Cloud Virtual Machines have the ability via an OS Config agent API to periodically (about every 10 minutes) report OS inventory data. A patch compliance API periodically reads this data, and cross references metadata to determine if the latest updates are installed. This is not the only Patch Management solution available to your organization and you should weigh your needs before committing to using this method.",
|
||||
@@ -1168,7 +1168,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Storage",
|
||||
"Section": "5 Storage",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that IAM policy on Cloud Storage bucket does not allows anonymous or public access.",
|
||||
@@ -1189,7 +1189,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Storage",
|
||||
"Section": "5 Storage",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that uniform bucket-level access is enabled on Cloud Storage buckets.",
|
||||
@@ -1210,7 +1210,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to have all SQL database instances set to enable automated backups.",
|
||||
@@ -1231,7 +1231,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to configure Second Generation Sql instance to use private IPs instead of public IPs.",
|
||||
@@ -1252,7 +1252,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Database Server should accept connections only from trusted Network(s)/IP(s) and restrict access from public IP addresses.",
|
||||
@@ -1273,7 +1273,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to enforce all incoming connections to SQL database instance to use SSL.",
|
||||
@@ -1292,8 +1292,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.1 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "It is recommended to set a password for the administrative user (`root` by default) to prevent unauthorized access to the SQL database instances. This recommendation is applicable only for MySQL Instances. PostgreSQL does not offer any setting for No Password from the cloud console.",
|
||||
@@ -1314,8 +1314,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.1 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `skip_show_database` database flag for Cloud SQL Mysql instance to `on`",
|
||||
@@ -1336,8 +1336,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.1 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set the `local_infile` database flag for a Cloud SQL MySQL instance to `off`.",
|
||||
@@ -1358,8 +1358,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_error_verbosity` flag controls the verbosity/details of messages logged. Valid values are: - `TERSE` - `DEFAULT` - `VERBOSE` `TERSE` excludes the logging of `DETAIL`, `HINT`, `QUERY`, and `CONTEXT` error information. `VERBOSE` output includes the `SQLSTATE` error code, source code file name, function name, and line number that generated the error. Ensure an appropriate value is set to 'DEFAULT' or stricter.",
|
||||
@@ -1380,8 +1380,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_error_statement` flag defines the minimum message severity level that are considered as an error statement. Messages for error statements are logged with the SQL statement. Valid values include `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. Each severity level includes the subsequent levels mentioned above. Ensure a value of `ERROR` or stricter is set.",
|
||||
@@ -1402,8 +1402,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The value of `log_statement` flag determined the SQL statements that are logged. Valid values are: - `none` - `ddl` - `mod` - `all` The value `ddl` logs all data definition statements. The value `mod` logs all ddl statements, plus data-modifying statements. The statements are logged after a basic parsing is done and statement type is determined, thus this does not logs statements with errors. When using extended query protocol, logging occurs after an Execute message is received and values of the Bind parameters are included. A value of 'ddl' is recommended unless otherwise directed by your organization's logging policy.",
|
||||
@@ -1424,8 +1424,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Instance addresses can be public IP or private IP. Public IP means that the instance is accessible through the public internet. In contrast, instances using only private IP are not accessible through the public internet, but are accessible through a Virtual Private Cloud (VPC). Limiting network access to your database will limit potential attacks.",
|
||||
@@ -1446,8 +1446,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure `cloudsql.enable_pgaudit` database flag for Cloud SQL PostgreSQL instance is set to `on` to allow for centralized logging.",
|
||||
@@ -1468,8 +1468,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling the `log_connections` setting causes each attempted connection to the server to be logged, along with successful completion of client authentication. This parameter cannot be changed after the session starts.",
|
||||
@@ -1490,8 +1490,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling the `log_disconnections` setting logs the end of each session, including the session duration.",
|
||||
@@ -1512,8 +1512,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_duration_statement` flag defines the minimum amount of execution time of a statement in milliseconds where the total duration of the statement is logged. Ensure that `log_min_duration_statement` is disabled, i.e., a value of `-1` is set.",
|
||||
@@ -1534,8 +1534,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_messages` flag defines the minimum message severity level that is considered as an error statement. Messages for error statements are logged with the SQL statement. Valid values include `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. Each severity level includes the subsequent levels mentioned above. ERROR is considered the best practice setting. Changes should only be made in accordance with the organization's logging policy.",
|
||||
@@ -1556,8 +1556,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `3625 (trace flag)` database flag for Cloud SQL SQL Server instance to `on`.",
|
||||
@@ -1578,8 +1578,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `external scripts enabled` database flag for Cloud SQL SQL Server instance to `off`",
|
||||
@@ -1600,8 +1600,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `remote access` database flag for Cloud SQL SQL Server instance to `off`.",
|
||||
@@ -1622,8 +1622,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to check the `user connections` for a Cloud SQL SQL Server instance to ensure that it is not artificially limiting connections.",
|
||||
@@ -1644,8 +1644,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that, `user options` database flag for Cloud SQL SQL Server instance should not be configured.",
|
||||
@@ -1666,8 +1666,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `contained database authentication` database flag for Cloud SQL on the SQL Server instance to `off`.",
|
||||
@@ -1688,8 +1688,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `cross db ownership chaining` database flag for Cloud SQL SQL Server instance to `off`.",
|
||||
@@ -1710,7 +1710,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "BigQuery by default encrypts the data as rest by employing `Envelope Encryption` using Google managed cryptographic keys. The data is encrypted using the `data encryption keys` and data encryption keys themselves are further encrypted using `key encryption keys`. This is seamless and do not require any additional input from the user. However, if you want to have greater control, Customer-managed encryption keys (CMEK) can be used as encryption key management solution for BigQuery Data Sets.",
|
||||
@@ -1731,7 +1731,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "BigQuery by default encrypts the data as rest by employing `Envelope Encryption` using Google managed cryptographic keys. The data is encrypted using the `data encryption keys` and data encryption keys themselves are further encrypted using `key encryption keys`. This is seamless and do not require any additional input from the user. However, if you want to have greater control, Customer-managed encryption keys (CMEK) can be used as encryption key management solution for BigQuery Data Sets. If CMEK is used, the CMEK is used to encrypt the data encryption keys instead of using google-managed encryption keys.",
|
||||
@@ -1752,7 +1752,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the IAM policy on BigQuery datasets does not allow anonymous and/or public access.",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Use corporate login credentials instead of consumer accounts, such as Gmail accounts.",
|
||||
@@ -30,7 +30,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Setup multi-factor authentication for Google Cloud Platform accounts.",
|
||||
@@ -50,7 +50,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Setup Security Key Enforcement for Google Cloud Platform admin accounts.",
|
||||
@@ -72,7 +72,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "User-managed service accounts should not have user-managed keys.",
|
||||
@@ -94,7 +94,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "A service account is a special Google account that belongs to an application or a VM, instead of to an individual end-user. The application uses the service account to call the service's Google API so that users aren't directly involved. It's recommended not to use admin access for ServiceAccount.",
|
||||
@@ -116,7 +116,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to assign the `Service Account User (iam.serviceAccountUser)` and `Service Account Token Creator (iam.serviceAccountTokenCreator)` roles to a user for a specific service account rather than assigning the role to a user at project level.",
|
||||
@@ -138,7 +138,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Service Account keys consist of a key ID (Private_key_Id) and Private key, which are used to sign programmatic requests users make to Google cloud services accessible to that particular service account. It is recommended that all Service Account keys are regularly rotated.",
|
||||
@@ -160,7 +160,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the principle of 'Separation of Duties' is enforced while assigning service-account related roles to users.",
|
||||
@@ -182,7 +182,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the IAM policy on Cloud KMS `cryptokeys` should restrict anonymous and/or public access.",
|
||||
@@ -204,7 +204,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Google Cloud Key Management Service stores cryptographic keys in a hierarchical structure designed for useful and elegant access control management. The format for the rotation schedule depends on the client library that is used. For the gcloud command-line tool, the next rotation time must be in `ISO` or `RFC3339` format, and the rotation period must be in the form `INTEGER[UNIT]`, where units can be one of seconds (s), minutes (m), hours (h) or days (d).",
|
||||
@@ -226,7 +226,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the principle of 'Separation of Duties' is enforced while assigning KMS related roles to users.",
|
||||
@@ -248,7 +248,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. Unused keys with their permissions in tact may still exist within a project. Keys are insecure because they can be viewed publicly, such as from within a browser, or they can be accessed on a device where the key resides. It is recommended to use standard authentication flow instead.",
|
||||
@@ -268,7 +268,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. In this case, unrestricted keys are insecure because they can be viewed publicly, such as from within a browser, or they can be accessed on a device where the key resides. It is recommended to restrict API key usage to trusted hosts, HTTP referrers and apps. It is recommended to use the more secure standard authentication flow instead.",
|
||||
@@ -290,7 +290,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. API keys are always at risk because they can be viewed publicly, such as from within a browser, or they can be accessed on a device where the key resides. It is recommended to restrict API keys to use (call) only APIs required by an application.",
|
||||
@@ -312,7 +312,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "API Keys should only be used for services in cases where other authentication methods are unavailable. If they are in use it is recommended to rotate API keys every 90 days.",
|
||||
@@ -334,7 +334,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that Essential Contacts is configured to designate email addresses for Google Cloud services to notify of important technical or security information.",
|
||||
@@ -354,7 +354,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Section": "1 Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Google Cloud Functions allow you to host serverless code that is executed when an event is triggered, without the requiring the management a host operating system. These functions can also store environment variables to be used by the code that may contain authentication or other information that needs to remain confidential.",
|
||||
@@ -376,7 +376,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that Cloud Audit Logging is configured to track all admin activities and read, write access to user data.",
|
||||
@@ -398,7 +398,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to create a sink that will export copies of all the log entries. This can help aggregate logs from multiple projects and export them to a Security Information and Event Management (SIEM).",
|
||||
@@ -420,7 +420,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling retention policies on log buckets will protect logs stored in cloud storage buckets from being overwritten or accidentally deleted. It is recommended to set up retention policies and configure Bucket Lock on all storage buckets that are used as log sinks.",
|
||||
@@ -442,7 +442,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "In order to prevent unnecessary project ownership assignments to users/service-accounts and further misuses of projects and resources, all `roles/Owner` assignments should be monitored.Members (users/Service-Accounts) with a role assignment to primitive role `roles/Owner` are project owners.The project owner has all the privileges on the project the role belongs to. These are summarized below:- All viewer permissions on all GCP Services within the project- Permissions for actions that modify the state of all GCP services within the project- Manage roles and permissions for a project and all resources within the project- Set up billing for a projectGranting the owner role to a member (user/Service-Account) will allow that member to modify the Identity and Access Management (IAM) policy. Therefore, grant the owner role only if the member has a legitimate purpose to manage the IAM policy. This is because the project IAM policy contains sensitive access control data. Having a minimal set of users allowed to manage IAM policy will simplify any auditing that may be necessary.",
|
||||
@@ -464,7 +464,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Google Cloud Platform (GCP) services write audit log entries to the Admin Activity and Data Access logs to help answer the questions of, \"who did what, where, and when?\" within GCP projects.Cloud audit logging records information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by GCP services. Cloud audit logging provides a history of GCP API calls for an account, including API calls made via the console, SDKs, command-line tools, and other GCP services.",
|
||||
@@ -486,7 +486,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for changes to Identity and Access Management (IAM) role creation, deletion and updating activities.",
|
||||
@@ -508,7 +508,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Virtual Private Cloud (VPC) Network Firewall rule changes.",
|
||||
@@ -530,7 +530,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Virtual Private Cloud (VPC) network route changes.",
|
||||
@@ -552,7 +552,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Virtual Private Cloud (VPC) network changes.",
|
||||
@@ -574,7 +574,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for Cloud Storage Bucket IAM changes.",
|
||||
@@ -596,7 +596,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that a metric filter and alarm be established for SQL instance configuration changes.",
|
||||
@@ -616,7 +616,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Cloud DNS logging records the queries from the name servers within your VPC to Stackdriver. Logged queries can come from Compute Engine VMs, GKE containers, or other GCP resources provisioned within the VPC.",
|
||||
@@ -638,7 +638,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP Cloud Asset Inventory is services that provides a historical view of GCP resources and IAM policies through a time-series database. The information recorded includes metadata on Google Cloud resources, metadata on policies set on Google Cloud projects or resources, and runtime information gathered within a Google Cloud resource.Cloud Asset Inventory Service (CAIS) API enablement is not required for operation of the service, but rather enables the mechanism for searching/exporting CAIS asset data directly.",
|
||||
@@ -658,7 +658,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "GCP Access Transparency provides audit logs for all actions that Google personnel take in your Google Cloud resources.",
|
||||
@@ -680,7 +680,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP Access Approval enables you to require your organizations' explicit approval whenever Google support try to access your projects. You can then select users within your organization who can approve these requests through giving them a security role in IAM. All access requests display which Google Employee requested them in an email or Pub/Sub message that you can choose to Approve. This adds an additional control and logging of who in your organization approved/denied these requests.",
|
||||
@@ -702,7 +702,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2. Logging and Monitoring",
|
||||
"Section": "2 Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Logging enabled on a HTTPS Load Balancer will show all network traffic and its destination.",
|
||||
@@ -724,7 +724,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To prevent use of `default` network, a project should not have a `default` network.",
|
||||
@@ -746,7 +746,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "In order to prevent use of legacy networks, a project should not have a legacy network configured. As of now, Legacy Networks are gradually being phased out, and you can no longer create projects with them. This recommendation is to check older projects to ensure that they are not using Legacy Networks.",
|
||||
@@ -768,7 +768,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Cloud Domain Name System (DNS) is a fast, reliable and cost-effective domain name system that powers millions of domains on the internet. Domain Name System Security Extensions (DNSSEC) in Cloud DNS enables domain owners to take easy steps to protect their domains against DNS hijacking and man-in-the-middle and other attacks.",
|
||||
@@ -790,7 +790,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "NOTE: Currently, the SHA1 algorithm has been removed from general use by Google, and, if being used, needs to be whitelisted on a project basis by Google and will also, therefore, require a Google Cloud support contract.DNSSEC algorithm numbers in this registry may be used in CERT RRs. Zone signing (DNSSEC) and transaction security mechanisms (SIG(0) and TSIG) make use of particular subsets of these algorithms. The algorithm used for key signing should be a recommended one and it should be strong.",
|
||||
@@ -812,7 +812,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "NOTE: Currently, the SHA1 algorithm has been removed from general use by Google, and, if being used, needs to be whitelisted on a project basis by Google and will also, therefore, require a Google Cloud support contract.DNSSEC algorithm numbers in this registry may be used in CERT RRs. Zone signing (DNSSEC) and transaction security mechanisms (SIG(0) and TSIG) make use of particular subsets of these algorithms. The algorithm used for key signing should be a recommended one and it should be strong.",
|
||||
@@ -834,7 +834,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP `Firewall Rules` are specific to a `VPC Network`. Each rule either `allows` or `denies` traffic when its conditions are met. Its conditions allow the user to specify the type of traffic, such as ports and protocols, and the source or destination of the traffic, including IP addresses, subnets, and instances.Firewall rules are defined at the VPC network level and are specific to the network in which they are defined. The rules themselves cannot be shared among networks. Firewall rules only support IPv4 traffic. When specifying a source for an ingress rule or a destination for an egress rule by address, only an `IPv4` address or `IPv4 block in CIDR` notation can be used. Generic `(0.0.0.0/0)` incoming traffic from the internet to VPC or VM instance using `SSH` on `Port 22` can be avoided.",
|
||||
@@ -856,7 +856,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "GCP `Firewall Rules` are specific to a `VPC Network`. Each rule either `allows` or `denies` traffic when its conditions are met. Its conditions allow users to specify the type of traffic, such as ports and protocols, and the source or destination of the traffic, including IP addresses, subnets, and instances.Firewall rules are defined at the VPC network level and are specific to the network in which they are defined. The rules themselves cannot be shared among networks. Firewall rules only support IPv4 traffic. When specifying a source for an ingress rule or a destination for an egress rule by address, an `IPv4` address or `IPv4 block in CIDR` notation can be used. Generic `(0.0.0.0/0)` incoming traffic from the Internet to a VPC or VM instance using `RDP` on `Port 3389` can be avoided.",
|
||||
@@ -878,7 +878,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Flow Logs is a feature that enables users to capture information about the IP traffic going to and from network interfaces in the organization's VPC Subnets. Once a flow log is created, the user can view and retrieve its data in Stackdriver Logging. It is recommended that Flow Logs be enabled for every business-critical VPC subnet.",
|
||||
@@ -898,7 +898,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Secure Sockets Layer (SSL) policies determine what port Transport Layer Security (TLS) features clients are permitted to use when connecting to load balancers. To prevent usage of insecure features, SSL policies should use (a) at least TLS 1.2 with the MODERN profile; or (b) the RESTRICTED profile, because it effectively requires clients to use TLS 1.2 regardless of the chosen minimum TLS version; or (3) a CUSTOM profile that does not support any of the following features: ```TLS_RSA_WITH_AES_128_GCM_SHA256TLS_RSA_WITH_AES_256_GCM_SHA384TLS_RSA_WITH_AES_128_CBC_SHATLS_RSA_WITH_AES_256_CBC_SHATLS_RSA_WITH_3DES_EDE_CBC_SHA```",
|
||||
@@ -918,7 +918,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Networking",
|
||||
"Section": "3 Networking",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "IAP authenticates the user requests to your apps via a Google single sign in. You can then manage these users with permissions to control access. It is recommended to use both IAP permissions and firewalls to restrict this access to your apps with sensitive information.",
|
||||
@@ -940,7 +940,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to configure your instance to not use the default Compute Engine service account because it has the Editor role on the project.",
|
||||
@@ -962,7 +962,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To support principle of least privileges and prevent potential privilege escalation it is recommended that instances are not assigned to default service account `Compute Engine default service account` with Scope `Allow full access to all Cloud APIs`.",
|
||||
@@ -984,7 +984,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to use Instance specific SSH key(s) instead of using common/shared project-wide SSH key(s) to access Instances.",
|
||||
@@ -1006,7 +1006,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling OS login binds SSH certificates to IAM users and facilitates effective SSH certificate management.",
|
||||
@@ -1028,7 +1028,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Interacting with a serial port is often referred to as the serial console, which is similar to using a terminal window, in that input and output is entirely in text mode and there is no graphical interface or mouse support.If you enable the interactive serial console on an instance, clients can attempt to connect to that instance from any IP address. Therefore interactive serial console support should be disabled.",
|
||||
@@ -1050,7 +1050,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Compute Engine instance cannot forward a packet unless the source IP address of the packet matches the IP address of the instance. Similarly, GCP won't deliver a packet whose destination IP address is different than the IP address of the instance receiving the packet. However, both capabilities are required if you want to use instances to help route packets.Forwarding of data packets should be disabled to prevent data loss or information disclosure.",
|
||||
@@ -1072,7 +1072,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Customer-Supplied Encryption Keys (CSEK) are a feature in Google Cloud Storage and Google Compute Engine. If you supply your own encryption keys, Google uses your key to protect the Google-generated keys used to encrypt and decrypt your data. By default, Google Compute Engine encrypts all data at rest. Compute Engine handles and manages this encryption for you without any additional actions on your part. However, if you wanted to control and manage this encryption yourself, you can provide your own encryption keys.",
|
||||
@@ -1094,7 +1094,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "To defend against advanced threats and ensure that the boot loader and firmware on your VMs are signed and untampered, it is recommended that Compute instances are launched with Shielded VM enabled.",
|
||||
@@ -1116,7 +1116,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Compute instances should not be configured to have external IP addresses.",
|
||||
@@ -1136,7 +1136,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "In order to maintain the highest level of security all connections to an application should be secure by default.",
|
||||
@@ -1158,7 +1158,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Google Cloud encrypts data at-rest and in-transit, but customer data must be decrypted for processing. Confidential Computing is a breakthrough technology which encrypts data in-use—while it is being processed. Confidential Computing environments keep data encrypted in memory and elsewhere outside the central processing unit (CPU). Confidential VMs leverage the Secure Encrypted Virtualization (SEV) feature of AMD EPYC™ CPUs. Customer data will stay encrypted while it is used, indexed, queried, or trained on. Encryption keys are generated in hardware, per VM, and not exportable. Thanks to built-in hardware optimizations of both performance and security, there is no significant performance penalty to Confidential Computing workloads.",
|
||||
@@ -1178,7 +1178,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Virtual Machines",
|
||||
"Section": "4 Virtual Machines",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Google Cloud Virtual Machines have the ability via an OS Config agent API to periodically (about every 10 minutes) report OS inventory data. A patch compliance API periodically reads this data, and cross references metadata to determine if the latest updates are installed.This is not the only Patch Management solution available to your organization and you should weigh your needs before committing to using this method.",
|
||||
@@ -1200,7 +1200,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Storage",
|
||||
"Section": "5 Storage",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that IAM policy on Cloud Storage bucket does not allows anonymous or public access.",
|
||||
@@ -1222,7 +1222,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Storage",
|
||||
"Section": "5 Storage",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that uniform bucket-level access is enabled on Cloud Storage buckets.",
|
||||
@@ -1244,7 +1244,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to enforce all incoming connections to SQL database instance to use SSL.",
|
||||
@@ -1266,7 +1266,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Database Server should accept connections only from trusted Network(s)/IP(s) and restrict access from public IP addresses.",
|
||||
@@ -1288,7 +1288,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to configure Second Generation Sql instance to use private IPs instead of public IPs.",
|
||||
@@ -1310,7 +1310,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to have all SQL database instances set to enable automated backups.",
|
||||
@@ -1330,8 +1330,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.1 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "It is recommended to set a password for the administrative user (`root` by default) to prevent unauthorized access to the SQL database instances.This recommendation is applicable only for MySQL Instances. PostgreSQL does not offer any setting for No Password from the cloud console.",
|
||||
@@ -1353,8 +1353,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.1 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `skip_show_database` database flag for Cloud SQL Mysql instance to `on`",
|
||||
@@ -1376,8 +1376,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.1 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set the `local_infile` database flag for a Cloud SQL MySQL instance to `off`.",
|
||||
@@ -1399,8 +1399,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_error_verbosity` flag controls the verbosity/details of messages logged. Valid values are:- `TERSE`- `DEFAULT`- `VERBOSE``TERSE` excludes the logging of `DETAIL`, `HINT`, `QUERY`, and `CONTEXT` error information.`VERBOSE` output includes the `SQLSTATE` error code, source code file name, function name, and line number that generated the error.Ensure an appropriate value is set to 'DEFAULT' or stricter.",
|
||||
@@ -1422,8 +1422,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling the `log_connections` setting causes each attempted connection to the server to be logged, along with successful completion of client authentication. This parameter cannot be changed after the session starts.",
|
||||
@@ -1445,8 +1445,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling the `log_disconnections` setting logs the end of each session, including the session duration.",
|
||||
@@ -1468,8 +1468,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The value of `log_statement` flag determined the SQL statements that are logged. Valid values are:- `none`- `ddl`- `mod`- `all`The value `ddl` logs all data definition statements.The value `mod` logs all ddl statements, plus data-modifying statements.The statements are logged after a basic parsing is done and statement type is determined, thus this does not logs statements with errors. When using extended query protocol, logging occurs after an Execute message is received and values of the Bind parameters are included.A value of 'ddl' is recommended unless otherwise directed by your organization's logging policy.",
|
||||
@@ -1491,8 +1491,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_messages` flag defines the minimum message severity level that is considered as an error statement. Messages for error statements are logged with the SQL statement. Valid values include (from lowest to highest severity) `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`.Each severity level includes the subsequent levels mentioned above. ERROR is considered the best practice setting. Changes should only be made in accordance with the organization's logging policy.",
|
||||
@@ -1514,8 +1514,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_error_statement` flag defines the minimum message severity level that are considered as an error statement. Messages for error statements are logged with the SQL statement. Valid values include (from lowest to highest severity) `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`.Each severity level includes the subsequent levels mentioned above. Ensure a value of `ERROR` or stricter is set.",
|
||||
@@ -1537,8 +1537,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_duration_statement` flag defines the minimum amount of execution time of a statement in milliseconds where the total duration of the statement is logged. Ensure that `log_min_duration_statement` is disabled, i.e., a value of `-1` is set.",
|
||||
@@ -1560,8 +1560,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.2 PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure `cloudsql.enable_pgaudit` database flag for Cloud SQL PostgreSQL instance is set to `on` to allow for centralized logging.",
|
||||
@@ -1583,8 +1583,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `external scripts enabled` database flag for Cloud SQL SQL Server instance to `off`",
|
||||
@@ -1606,8 +1606,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `cross db ownership chaining` database flag for Cloud SQL SQL Server instance to `off`.This flag is deprecated for all SQL Server versions in CGP. Going forward, you can't set its value to on. However, if you have this flag enabled, we strongly recommend that you either remove the flag from your database or set it to off. For cross-database access, use the [Microsoft tutorial for signing stored procedures with a certificate](https://learn.microsoft.com/en-us/sql/relational-databases/tutorial-signing-stored-procedures-with-a-certificate?view=sql-server-ver16).",
|
||||
@@ -1629,8 +1629,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to check the `user connections` for a Cloud SQL SQL Server instance to ensure that it is not artificially limiting connections.",
|
||||
@@ -1652,8 +1652,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that, `user options` database flag for Cloud SQL SQL Server instance should not be configured.",
|
||||
@@ -1675,8 +1675,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `remote access` database flag for Cloud SQL SQL Server instance to `off`.",
|
||||
@@ -1694,12 +1694,12 @@
|
||||
"Id": "6.3.6",
|
||||
"Description": "Ensure '3625 (trace flag)' database flag for all Cloud SQL Server instances is set to 'on'",
|
||||
"Checks": [
|
||||
"cloudsql_instance_sqlserver_trace_flag\""
|
||||
"cloudsql_instance_sqlserver_trace_flag"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `3625 (trace flag)` database flag for Cloud SQL SQL Server instance to `on`.",
|
||||
@@ -1721,8 +1721,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Section": "6 Cloud SQL Database Services",
|
||||
"SubSection": "6.3 SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended not to set `contained database authentication` database flag for Cloud SQL on the SQL Server instance to `on`.",
|
||||
@@ -1744,7 +1744,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that the IAM policy on BigQuery datasets does not allow anonymous and/or public access.",
|
||||
@@ -1766,7 +1766,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "BigQuery by default encrypts the data as rest by employing `Envelope Encryption` using Google managed cryptographic keys. The data is encrypted using the `data encryption keys` and data encryption keys themselves are further encrypted using `key encryption keys`. This is seamless and do not require any additional input from the user. However, if you want to have greater control, Customer-managed encryption keys (CMEK) can be used as encryption key management solution for BigQuery Data Sets. If CMEK is used, the CMEK is used to encrypt the data encryption keys instead of using google-managed encryption keys.",
|
||||
@@ -1788,7 +1788,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "BigQuery by default encrypts the data as rest by employing `Envelope Encryption` using Google managed cryptographic keys. The data is encrypted using the `data encryption keys` and data encryption keys themselves are further encrypted using `key encryption keys`. This is seamless and do not require any additional input from the user. However, if you want to have greater control, Customer-managed encryption keys (CMEK) can be used as encryption key management solution for BigQuery Data Sets.",
|
||||
@@ -1808,7 +1808,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "7. BigQuery",
|
||||
"Section": "7 BigQuery",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "BigQuery tables can contain sensitive data that for security purposes should be discovered, monitored, classified, and protected. Google Cloud's Sensitive Data Protection tools can automatically provide data classification of all BigQuery data across an organization.",
|
||||
@@ -1830,7 +1830,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "8. Dataproc",
|
||||
"Section": "8 Dataproc",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "When you use Dataproc, cluster and job data is stored on Persistent Disks (PDs) associated with the Compute Engine VMs in your cluster and in a Cloud Storage staging bucket. This PD and bucket data is encrypted using a Google-generated data encryption key (DEK) and key encryption key (KEK). The CMEK feature allows you to create, use, and revoke the key encryption key (KEK). Google still controls the data encryption key (DEK).",
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -10,7 +10,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -31,7 +31,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -52,7 +52,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -73,7 +73,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -94,7 +94,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -115,7 +115,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -136,7 +136,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -157,7 +157,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -178,7 +178,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -199,7 +199,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -220,7 +220,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -241,7 +241,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -262,7 +262,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -283,7 +283,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -304,7 +304,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -325,7 +325,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -346,7 +346,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -367,7 +367,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -388,7 +388,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -409,7 +409,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -430,7 +430,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.1 Control Plane Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -453,7 +453,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -476,7 +476,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -499,7 +499,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -522,7 +522,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -545,7 +545,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -568,7 +568,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -591,7 +591,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -614,7 +614,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -637,7 +637,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -660,7 +660,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -683,7 +683,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -706,7 +706,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -729,7 +729,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -752,7 +752,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -775,7 +775,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -798,7 +798,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -821,7 +821,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -844,7 +844,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -867,7 +867,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -890,7 +890,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -913,7 +913,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -936,7 +936,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -959,7 +959,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -982,7 +982,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1005,7 +1005,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1028,7 +1028,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1051,7 +1051,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1074,7 +1074,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1095,7 +1095,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1118,7 +1118,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.2 API Server",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1141,7 +1141,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1164,7 +1164,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1187,7 +1187,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1210,7 +1210,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1233,7 +1233,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1256,7 +1256,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1279,7 +1279,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.3 Controller Manager",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1302,7 +1302,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.4 Scheduler",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1325,7 +1325,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Control Plane Components",
|
||||
"Section": "1 Control Plane Components",
|
||||
"SubSection": "1.4 Scheduler",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1500,7 +1500,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Control Plane Configuration",
|
||||
"Section": "3 Control Plane Configuration",
|
||||
"SubSection": "3.1 Authentication and Authorization",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1521,7 +1521,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Control Plane Configuration",
|
||||
"Section": "3 Control Plane Configuration",
|
||||
"SubSection": "3.1 Authentication and Authorization",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1542,7 +1542,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Control Plane Configuration",
|
||||
"Section": "3 Control Plane Configuration",
|
||||
"SubSection": "3.1 Authentication and Authorization",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1563,7 +1563,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Control Plane Configuration",
|
||||
"Section": "3 Control Plane Configuration",
|
||||
"SubSection": "3.2 Logging",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1584,7 +1584,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "3. Control Plane Configuration",
|
||||
"Section": "3 Control Plane Configuration",
|
||||
"SubSection": "3.2 Logging",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1607,7 +1607,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1630,7 +1630,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1651,7 +1651,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1672,7 +1672,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1695,7 +1695,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1718,7 +1718,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1739,7 +1739,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1760,7 +1760,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1783,7 +1783,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1806,7 +1806,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.1 Worker Node Configuration Files",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1829,7 +1829,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1852,7 +1852,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1875,7 +1875,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1898,7 +1898,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1921,7 +1921,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1944,7 +1944,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -1965,7 +1965,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -1988,7 +1988,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 2 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2011,7 +2011,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2034,7 +2034,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2055,7 +2055,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2078,7 +2078,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2099,7 +2099,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4. Worker Nodes",
|
||||
"Section": "4 Worker Nodes",
|
||||
"SubSection": "4.2 Kubelet",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2122,7 +2122,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2145,7 +2145,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2168,7 +2168,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Worker Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2191,7 +2191,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2212,7 +2212,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2233,7 +2233,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2254,7 +2254,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2275,7 +2275,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2298,7 +2298,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2321,7 +2321,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2344,7 +2344,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2367,7 +2367,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2390,7 +2390,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.1 RBAC and Service Accounts",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2411,7 +2411,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2434,7 +2434,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2457,7 +2457,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2480,7 +2480,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2503,7 +2503,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2526,7 +2526,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2549,7 +2549,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2572,7 +2572,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2595,7 +2595,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Automated",
|
||||
@@ -2618,7 +2618,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2641,7 +2641,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2662,7 +2662,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2685,7 +2685,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.2 Pod Security Standards",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2706,7 +2706,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.3 Network Policies and CNI",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2727,7 +2727,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.3 Network Policies and CNI",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2750,7 +2750,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.4 Secrets Management",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2771,7 +2771,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.4 Secrets Management",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2792,7 +2792,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.4 Secrets Management",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2813,7 +2813,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.7 General Policies",
|
||||
"Profile": "Level 1 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2836,7 +2836,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.7 General Policies",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2857,7 +2857,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.7 General Policies",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
@@ -2878,7 +2878,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5. Policies",
|
||||
"Section": "5 Policies",
|
||||
"SubSection": "5.7 General Policies",
|
||||
"Profile": "Level 2 - Master Node",
|
||||
"AssessmentStatus": "Manual",
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -556,7 +556,7 @@ class CheckReportGithub(Check_Report):
|
||||
resource: Any,
|
||||
resource_name: str = None,
|
||||
resource_id: str = None,
|
||||
repository: str = None,
|
||||
repository: str = "global",
|
||||
) -> None:
|
||||
"""Initialize the GitHub Check's finding information.
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ Available Cloud Providers:
|
||||
azure Azure Provider
|
||||
gcp GCP Provider
|
||||
kubernetes Kubernetes Provider
|
||||
github GitHub Provider
|
||||
m365 Microsoft 365 Provider
|
||||
nhn NHN Provider (Unofficial)
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
from datetime import datetime
|
||||
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.cis.models import GithubCISModel
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class GithubCIS(ComplianceOutput):
|
||||
"""
|
||||
This class represents the GitHub CIS compliance output.
|
||||
|
||||
Attributes:
|
||||
- _data (list): A list to store transformed data from findings.
|
||||
- _file_descriptor (TextIOWrapper): A file descriptor to write data to a file.
|
||||
|
||||
Methods:
|
||||
- transform: Transforms findings into GitHub CIS compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into GitHub CIS compliance format.
|
||||
|
||||
Parameters:
|
||||
- findings (list): A list of findings.
|
||||
- compliance (Compliance): A compliance model.
|
||||
- compliance_name (str): The name of the compliance model.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
for finding in findings:
|
||||
# Get the compliance requirements for the finding
|
||||
finding_requirements = finding.compliance.get(compliance_name, [])
|
||||
for requirement in compliance.Requirements:
|
||||
if requirement.Id in finding_requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = GithubCISModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
Account_Id=finding.account_uid,
|
||||
Account_Name=finding.account_name,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_RationaleStatement=attribute.RationaleStatement,
|
||||
Requirements_Attributes_ImpactStatement=attribute.ImpactStatement,
|
||||
Requirements_Attributes_RemediationProcedure=attribute.RemediationProcedure,
|
||||
Requirements_Attributes_AuditProcedure=attribute.AuditProcedure,
|
||||
Requirements_Attributes_AdditionalInformation=attribute.AdditionalInformation,
|
||||
Requirements_Attributes_References=attribute.References,
|
||||
Requirements_Attributes_DefaultValue=attribute.DefaultValue,
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
# Add manual requirements to the compliance output
|
||||
for requirement in compliance.Requirements:
|
||||
if not requirement.Checks:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = GithubCISModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
Account_Id="",
|
||||
Account_Name="",
|
||||
AssessmentDate=str(datetime.now()),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
Requirements_Attributes_RationaleStatement=attribute.RationaleStatement,
|
||||
Requirements_Attributes_ImpactStatement=attribute.ImpactStatement,
|
||||
Requirements_Attributes_RemediationProcedure=attribute.RemediationProcedure,
|
||||
Requirements_Attributes_AuditProcedure=attribute.AuditProcedure,
|
||||
Requirements_Attributes_AdditionalInformation=attribute.AdditionalInformation,
|
||||
Requirements_Attributes_References=attribute.References,
|
||||
Requirements_Attributes_DefaultValue=attribute.DefaultValue,
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
@@ -48,6 +48,7 @@ class M365CIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
@@ -79,6 +80,7 @@ class M365CIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
|
||||
@@ -82,6 +82,7 @@ class M365CISModel(BaseModel):
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_Profile: str
|
||||
Requirements_Attributes_AssessmentStatus: str
|
||||
Requirements_Attributes_Description: str
|
||||
@@ -163,6 +164,37 @@ class KubernetesCISModel(BaseModel):
|
||||
Muted: bool
|
||||
|
||||
|
||||
class GithubCISModel(BaseModel):
|
||||
"""
|
||||
GithubCISModel generates a finding's output in Github CIS Compliance format.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
Account_Name: str
|
||||
Account_Id: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_Profile: str
|
||||
Requirements_Attributes_AssessmentStatus: str
|
||||
Requirements_Attributes_Description: str
|
||||
Requirements_Attributes_RationaleStatement: str
|
||||
Requirements_Attributes_ImpactStatement: str
|
||||
Requirements_Attributes_RemediationProcedure: str
|
||||
Requirements_Attributes_AuditProcedure: str
|
||||
Requirements_Attributes_AdditionalInformation: str
|
||||
Requirements_Attributes_References: str
|
||||
Requirements_Attributes_DefaultValue: str
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
ResourceName: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
|
||||
|
||||
# TODO: Create a parent class for the common fields of CIS and have the specific classes from each provider to inherit from it.
|
||||
# It is not done yet because it is needed to respect the current order of the fields in the output file.
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
"ServiceName": "ec2",
|
||||
"SubServiceName": "securitygroup",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "high",
|
||||
"Severity": "critical",
|
||||
"ResourceType": "AwsEc2SecurityGroup",
|
||||
"Description": "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to all ports.",
|
||||
"Risk": "If Security groups are not properly configured the attack surface is increased. An attacker could exploit this misconfiguration to gain unauthorized access to resources.",
|
||||
|
||||
+6
-3
@@ -1,4 +1,4 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS, Severity
|
||||
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
|
||||
from prowler.providers.aws.services.ec2.lib.security_groups import check_security_group
|
||||
from prowler.providers.aws.services.vpc.vpc_client import vpc_client
|
||||
@@ -9,14 +9,17 @@ class ec2_securitygroup_allow_ingress_from_internet_to_all_ports(Check):
|
||||
findings = []
|
||||
for security_group_arn, security_group in ec2_client.security_groups.items():
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if ec2_client.provider.scan_unused_services or (
|
||||
sg_in_use = (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
):
|
||||
)
|
||||
if ec2_client.provider.scan_unused_services or sg_in_use:
|
||||
report = Check_Report_AWS(
|
||||
metadata=self.metadata(), resource=security_group
|
||||
)
|
||||
if not sg_in_use:
|
||||
report.check_metadata.Severity = Severity.high
|
||||
report.resource_details = security_group.name
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Security group {security_group.name} ({security_group.id}) does not have all ports open to the Internet."
|
||||
|
||||
File renamed without changes.
@@ -1,4 +1,5 @@
|
||||
from ipaddress import ip_address, ip_network
|
||||
import re
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.aws.aws_provider import read_aws_regions_file
|
||||
@@ -415,6 +416,55 @@ def is_condition_block_restrictive_organization(
|
||||
return is_condition_valid
|
||||
|
||||
|
||||
def is_condition_block_restrictive_sns_endpoint(
|
||||
condition_statement: dict,
|
||||
):
|
||||
"""
|
||||
is_condition_block_restrictive_sns_endpoint parses the IAM Condition policy block and returns True if the condition_statement is restrictive for an endpoint, False if not.
|
||||
|
||||
@param condition_statement: dict with an IAM Condition block, e.g.:
|
||||
{
|
||||
"StringLike": {
|
||||
"SNS:Endpoint": "https://events.pagerduty.com/integration/<api-key>/enqueue"
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
is_condition_valid = False
|
||||
|
||||
# The conditions must be defined in lowercase since the context key names are not case-sensitive.
|
||||
# For example, including the aws:PrincipalOrgID context key is equivalent to testing for AWS:PrincipalOrgID
|
||||
# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html
|
||||
valid_condition_options = {
|
||||
"StringEquals": [
|
||||
"sns:endpoint",
|
||||
],
|
||||
"StringLike": [
|
||||
"sns:endpoint",
|
||||
],
|
||||
}
|
||||
|
||||
for condition_operator, condition_operator_key in valid_condition_options.items():
|
||||
if condition_operator in condition_statement:
|
||||
# https://docs.aws.amazon.com/sns/latest/dg/sns-using-identity-based-policies.html#sns-policy-keys
|
||||
# sns:endpoint - The URL, email address, or ARN from a Subscribe request or a previously confirmed subscription.
|
||||
pattern = re.compile(r".+@[^*]+|^https:\/\/[^*]+|^arn:aws:sns:[^*]+")
|
||||
for value in condition_operator_key:
|
||||
# We need to transform the condition_statement into lowercase
|
||||
condition_statement[condition_operator] = {
|
||||
k.lower(): v
|
||||
for k, v in condition_statement[condition_operator].items()
|
||||
}
|
||||
|
||||
if value in condition_statement[condition_operator]:
|
||||
if pattern.fullmatch(
|
||||
condition_statement[condition_operator][value]
|
||||
):
|
||||
is_condition_valid = True
|
||||
|
||||
return is_condition_valid
|
||||
|
||||
|
||||
def process_actions(effect, actions, target_set):
|
||||
"""
|
||||
process_actions processes the actions in the policy.
|
||||
|
||||
Whitespace-only changes.
+11
@@ -2,6 +2,7 @@ from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.iam.lib.policy import (
|
||||
is_condition_block_restrictive,
|
||||
is_condition_block_restrictive_organization,
|
||||
is_condition_block_restrictive_sns_endpoint,
|
||||
)
|
||||
from prowler.providers.aws.services.sns.sns_client import sns_client
|
||||
|
||||
@@ -32,6 +33,7 @@ class sns_topics_not_publicly_accessible(Check):
|
||||
):
|
||||
condition_account = False
|
||||
condition_org = False
|
||||
condition_endpoint = False
|
||||
if (
|
||||
"Condition" in statement
|
||||
and is_condition_block_restrictive(
|
||||
@@ -47,6 +49,13 @@ class sns_topics_not_publicly_accessible(Check):
|
||||
)
|
||||
):
|
||||
condition_org = True
|
||||
if (
|
||||
"Condition" in statement
|
||||
and is_condition_block_restrictive_sns_endpoint(
|
||||
statement["Condition"],
|
||||
)
|
||||
):
|
||||
condition_endpoint = True
|
||||
|
||||
if condition_account and condition_org:
|
||||
report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from the account {sns_client.audited_account} and an organization."
|
||||
@@ -54,6 +63,8 @@ class sns_topics_not_publicly_accessible(Check):
|
||||
report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from the account {sns_client.audited_account}."
|
||||
elif condition_org:
|
||||
report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from an organization."
|
||||
elif condition_endpoint:
|
||||
report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from an endpoint."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"SNS topic {topic.name} is public because its policy allows public access."
|
||||
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -247,7 +247,7 @@ class GithubProvider(Provider):
|
||||
if not session_token:
|
||||
# OAUTH
|
||||
logger.info(
|
||||
"Looking for GITHUB_OAUTH_TOKEN environment variable as user has not provided any token...."
|
||||
"Looking for GITHUB_OAUTH_APP_TOKEN environment variable as user has not provided any token...."
|
||||
)
|
||||
session_token = environ.get("GITHUB_OAUTH_APP_TOKEN", "")
|
||||
if session_token:
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
||||
from prowler.providers.common.provider import Provider
|
||||
from prowler.providers.github.services.organization.organization_service import (
|
||||
Organization,
|
||||
)
|
||||
|
||||
organization_client = Organization(Provider.get_global_provider())
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "organization_members_mfa_required",
|
||||
"CheckTitle": "Check if organization members are required to have MFA enabled.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "organization",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "critical",
|
||||
"ResourceType": "GitHubOrganization",
|
||||
"Description": "Ensure that all organization members are required to have multi-factor authentication (MFA) enabled. Enforcing MFA for all organization members helps protect the organization's resources and data from unauthorized access and security breaches.",
|
||||
"Risk": "Without Multi-Factor Authentication (MFA), user accounts are vulnerable to unauthorized access if their passwords are compromised. This can lead to unauthorized actions such as data theft, malicious code commits, and repository manipulation, potentially compromising the organization's source code and intellectual property.",
|
||||
"RelatedUrl": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Mandate the use of MFA for all organization members. This significantly enhances account security by adding an additional layer of protection beyond a username and password. MFA ensures that even if a password is compromised, unauthorized access to user accounts and repositories is prevented, safeguarding sensitive data and critical assets.",
|
||||
"Url": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/preparing-to-require-two-factor-authentication-in-your-organization"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.organization.organization_client import (
|
||||
organization_client,
|
||||
)
|
||||
|
||||
|
||||
class organization_members_mfa_required(Check):
|
||||
"""Check if organization members are required to have two-factor authentication enabled.
|
||||
|
||||
This class verifies whether each organization requires its members to have two-factor authentication enabled.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Organization Members MFA Required check.
|
||||
|
||||
Iterates over all organizations and checks if members are required to have two-factor authentication enabled.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for org in organization_client.organizations.values():
|
||||
if org.mfa_required is not None:
|
||||
report = CheckReportGithub(metadata=self.metadata(), resource=org)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Organization {org.name} does not require members to have two-factor authentication enabled."
|
||||
|
||||
if org.mfa_required:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Organization {org.name} does require members to have two-factor authentication enabled."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,44 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.github.lib.service.service import GithubService
|
||||
|
||||
|
||||
class Organization(GithubService):
|
||||
def __init__(self, provider):
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.organizations = self._list_organizations()
|
||||
|
||||
def _list_organizations(self):
|
||||
logger.info("Organization - Listing Organizations...")
|
||||
organizations = {}
|
||||
try:
|
||||
for client in self.clients:
|
||||
for org in client.get_user().get_orgs():
|
||||
try:
|
||||
require_mfa = org.two_factor_requirement_enabled
|
||||
except Exception as error:
|
||||
require_mfa = None
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
organizations[org.id] = Org(
|
||||
id=org.id,
|
||||
name=org.login,
|
||||
mfa_required=require_mfa,
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return organizations
|
||||
|
||||
|
||||
class Org(BaseModel):
|
||||
"""Model for Github Organization"""
|
||||
|
||||
id: int
|
||||
name: str
|
||||
mfa_required: Optional[bool] = False
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_branch_delete_on_merge_enabled",
|
||||
"CheckTitle": "Check if a repository deletes the branch after merging",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "GitHubRepository",
|
||||
"Description": "Ensure that the repository deletes the branch after merging.",
|
||||
"Risk": "Inactive branches pose a security risk as they can accumulate outdated code, dependencies, and potential vulnerabilities over time. Malicious actors may exploit these branches, and they can clutter the repository, making it harder to manage and track the active code. Additionally, stale branches may unintentionally be accessed or used inappropriately, leading to potential security breaches.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Regularly review and remove inactive branches from your repositories. This helps reduce the risk of malicious code injection, sensitive data leaks, and unnecessary clutter in the repository. By keeping branches active and up to date, you ensure that your codebase remains secure and manageable.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_branch_delete_on_merge_enabled(Check):
|
||||
"""Check if a repository deletes branches on merge
|
||||
|
||||
This class verifies whether each repository deletes branches on merge.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Deletes Branch On Merge check
|
||||
|
||||
Iterates over all repositories and checks if they delete branches on merge.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does not delete branches on merge."
|
||||
)
|
||||
|
||||
if repo.delete_branch_on_merge:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does delete branches on merge."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_deletion_disabled",
|
||||
"CheckTitle": "Check if a repository denies default branch deletion",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "GitHubRepository",
|
||||
"Description": "Ensure that the repository denies default branch deletion.",
|
||||
"Risk": "Allowing the deletion of protected branches by users with push access increases the risk of accidental or intentional branch removal, potentially resulting in significant data loss or disruption to the development process.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#allow-deletions",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Deny the ability to delete protected branches to ensure the preservation of critical branch data. This prevents accidental or malicious deletions and helps maintain the integrity and stability of the repository.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_deletion_disabled(Check):
|
||||
"""Check if a repository denies branch deletion
|
||||
|
||||
This class verifies whether each repository denies default branch deletion.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Denies Default Branch Deletion check
|
||||
|
||||
Iterates over all repositories and checks if they deny default branch deletion.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.default_branch_deletion is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does allow default branch deletion."
|
||||
)
|
||||
|
||||
if not repo.default_branch_deletion:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does deny default branch deletion."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_disallows_force_push",
|
||||
"CheckTitle": "Check if repository denies force push",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "GithubRepository",
|
||||
"Description": "Ensure that the repository denies force push to protected branches.",
|
||||
"Risk": "Permitting force pushes to branches can lead to accidental or intentional overwrites of the commit history, resulting in potential data loss, code inconsistencies, or the introduction of malicious changes. This compromises the stability and security of the repository.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#allow-force-pushes",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Disable force pushes on protected branches to preserve the commit history and ensure the integrity of the repository. This measure helps prevent unintentional data loss and protects the repository from malicious changes.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_disallows_force_push(Check):
|
||||
"""Check if a repository denies force push
|
||||
|
||||
This class verifies whether each repository denies force push.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Denies Force Push check
|
||||
|
||||
Iterates over all repositories and checks if they deny force push.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.allow_force_pushes is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does allow force push."
|
||||
)
|
||||
|
||||
if not repo.allow_force_pushes:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does deny force push."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_protection_applies_to_admins",
|
||||
"CheckTitle": "Check if repository enforces admin branch protection",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "GithubRepository",
|
||||
"Description": "Ensure that the repository enforces branch protection rules for administrators.",
|
||||
"Risk": "Excluding administrators from branch protection rules introduces a significant risk of unauthorized or unreviewed changes being pushed to protected branches. This can lead to vulnerabilities, including the potential insertion of malicious code, especially if an administrator account is compromised.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#do-not-allow-bypassing-the-above-settings",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enforce branch protection rules for administrators to ensure they adhere to the same security and quality standards as other users. This mitigates the risk of unreviewed or untrusted code being introduced, enhancing the overall integrity of the codebase.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_protection_applies_to_admins(Check):
|
||||
"""Check if a repository enforces administrators to be subject to the same branch protection rules as other users
|
||||
|
||||
This class verifies whether each repository enforces administrators to be subject to the same branch protection rules as other users.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Enforces Admin Branch Protection check
|
||||
|
||||
Iterates over all repositories and checks if they enforce administrators to be subject to the same branch protection rules as other users.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository.
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.enforce_admins is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Repository {repo.name} does not enforce administrators to be subject to the same branch protection rules as other users."
|
||||
|
||||
if repo.enforce_admins:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Repository {repo.name} does enforce administrators to be subject to the same branch protection rules as other users."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_protection_enabled",
|
||||
"CheckTitle": "Check if branch protection is enforced on the default branch ",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "github:user-id:repository/repository-name",
|
||||
"Severity": "critical",
|
||||
"ResourceType": "GitHubRepository",
|
||||
"Description": "Ensure branch protection is enforced on the default branch",
|
||||
"Risk": "The absence of branch protection on the default branch increases the risk of unauthorized, unreviewed, or untested changes being merged. This can compromise the stability, security, and reliability of the codebase, which is especially critical for production deployments.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Apply branch protection rules to the default branch to ensure it is safeguarded against unauthorized or improper modifications. This helps maintain code quality, enforces proper review and testing procedures, and reduces the risk of accidental or malicious changes.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule#creating-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_protection_enabled(Check):
|
||||
"""Check if a repository enforces default branch protection
|
||||
|
||||
This class verifies whether each repository enforces default branch protection.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Enforces Default Branch Protection check
|
||||
|
||||
Iterates over all repositories and checks if they enforce default branch protection.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.default_branch_protection is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Repository {repo.name} does not enforce branch protection on default branch ({repo.default_branch})."
|
||||
|
||||
if repo.default_branch_protection:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Repository {repo.name} does enforce branch protection on default branch ({repo.default_branch})."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_requires_conversation_resolution",
|
||||
"CheckTitle": "Check if repository requires conversation resolution before merging",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "GitHubRepository",
|
||||
"Description": "Ensure that the repository requires conversation resolution before merging.",
|
||||
"Risk": "Leaving comments unresolved before merging code can lead to overlooked issues, including potential bugs or security vulnerabilities, that might affect the quality and security of the codebase. Unaddressed concerns could result in a lower quality of code, increasing the risk of production failures or breaches.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-conversation-resolution-before-merging",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Ensure that all comments in a code change proposal are resolved before merging. This guarantees that every reviewer’s concern is addressed, improving code quality and security by preventing issues from being ignored or overlooked.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_requires_conversation_resolution(Check):
|
||||
"""Check if a repository requires conversation resolution
|
||||
|
||||
This class verifies whether each repository requires conversation resolution.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Merging Requires Conversation Resolution check
|
||||
|
||||
Iterates over all repositories and checks if they require conversation resolution.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.conversation_resolution is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does not require conversation resolution."
|
||||
)
|
||||
|
||||
if repo.conversation_resolution:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does require conversation resolution."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_requires_linear_history",
|
||||
"CheckTitle": "Check if repository default branch requires linear history",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "GithubRepository",
|
||||
"Description": "Ensure that the repository default branch requires linear history.",
|
||||
"Risk": "Allowing non-linear history can result in a cluttered and difficult-to-trace Git history, making it harder to identify specific changes, debug issues, and understand the sequence of development. This increases the risk of errors, inconsistencies, and bugs, especially in production environments.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-linear-history",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enforce a linear history by requiring rebase or squash merges for pull requests. This will create a clean, chronological commit history, making it easier to track changes, revert modifications, and troubleshoot any issues that arise.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_requires_linear_history(Check):
|
||||
"""Check if a repository requires linear history on default branch
|
||||
|
||||
This class verifies whether each repository requires linear history on the default branch.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository Merging Requires Linear History check
|
||||
|
||||
Iterates over all repositories and checks if they require linear history on the default branch.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.required_linear_history is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Repository {repo.name} does not require linear history on default branch ({repo.default_branch})."
|
||||
|
||||
if repo.required_linear_history:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Repository {repo.name} does require linear history on default branch ({repo.default_branch})."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_requires_multiple_approvals",
|
||||
"CheckTitle": "Check if repositories require at least 2 code changes approvals",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "github:user-id:repository/repository-name",
|
||||
"Severity": "high",
|
||||
"ResourceType": "GitHubRepository",
|
||||
"Description": "Ensure that repositories require at least 2 code changes approvals before merging a pull request.",
|
||||
"Risk": "If repositories do not require at least 2 code changes approvals before merging a pull request, it is possible that code changes are not being reviewed by multiple people, which could lead to the introduction of bugs or security vulnerabilities.",
|
||||
"RelatedUrl": "https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/approving-a-pull-request-with-required-reviews",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "To require at least 2 code changes approvals before merging a pull request, navigate to the repository settings, click on 'Branches', and then 'Add rule'.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-pull-request-reviews-before-merging"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_requires_multiple_approvals(Check):
|
||||
"""Check if a repository enforces at least 2 approvals for code changes
|
||||
|
||||
This class verifies whether each repository enforces at least 2 approvals for code changes.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository code changes enforce multi approval requirement check
|
||||
|
||||
Iterates over each repository and checks if the repository enforces at least 2 approvals for code changes.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.approval_count is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Repository {repo.name} does not enforce at least 2 approvals for code changes."
|
||||
|
||||
if repo.approval_count >= 2:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Repository {repo.name} does enforce at least 2 approvals for code changes."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "github",
|
||||
"CheckID": "repository_default_branch_status_checks_required",
|
||||
"CheckTitle": "Check if repository enforces status checks to pass",
|
||||
"CheckType": [],
|
||||
"ServiceName": "repository",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "GithubRepository",
|
||||
"Description": "Ensure that the repository enforces status checks to pass before merging code into the main branch.",
|
||||
"Risk": "Merging code without requiring all checks to pass increases the risk of introducing bugs, vulnerabilities, or unstable changes into the codebase. This can compromise the quality, security, and functionality of the application.",
|
||||
"RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Require all predefined status checks to pass successfully before allowing code changes to be merged. This ensures that all quality, stability, and security conditions are met, reducing the likelihood of errors or vulnerabilities being introduced into the project.",
|
||||
"Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportGithub
|
||||
from prowler.providers.github.services.repository.repository_client import (
|
||||
repository_client,
|
||||
)
|
||||
|
||||
|
||||
class repository_default_branch_status_checks_required(Check):
|
||||
"""Check if a repository enforces status checks.
|
||||
|
||||
This class verifies whether each repository enforces status checks.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportGithub]:
|
||||
"""Execute the Github Repository
|
||||
|
||||
Iterates over all repositories and checks if they enforce status checks.
|
||||
|
||||
Returns:
|
||||
List[CheckReportGithub]: A list of reports for each repository.
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if repo.status_checks is not None:
|
||||
report = CheckReportGithub(
|
||||
self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does not enforce status checks."
|
||||
)
|
||||
|
||||
if repo.status_checks:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Repository {repo.name} does enforce status checks."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "github:user-id:repository/repository-name",
|
||||
"Severity": "low",
|
||||
"ResourceType": "Other",
|
||||
"ResourceType": "GitHubRepository",
|
||||
"Description": "Ensure that public repositories have a SECURITY.md file",
|
||||
"Risk": "Not having a SECURITY.md file in a public repository may lead to security vulnerabilities being overlooked by users and contributors.",
|
||||
"RelatedUrl": "https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository",
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class repository_public_has_securitymd_file(Check):
|
||||
"""
|
||||
findings = []
|
||||
for repo in repository_client.repositories.values():
|
||||
if not repo.private:
|
||||
if not repo.private and repo.securitymd is not None:
|
||||
report = CheckReportGithub(
|
||||
metadata=self.metadata(), resource=repo, repository=repo.name
|
||||
)
|
||||
|
||||
@@ -17,17 +17,99 @@ class Repository(GithubService):
|
||||
try:
|
||||
for client in self.clients:
|
||||
for repo in client.get_user().get_repos():
|
||||
default_branch = repo.default_branch
|
||||
delete_branch_on_merge = (
|
||||
repo.delete_branch_on_merge
|
||||
if repo.delete_branch_on_merge is not None
|
||||
else False
|
||||
)
|
||||
securitymd_exists = False
|
||||
try:
|
||||
securitymd_exists = repo.get_contents("SECURITY.md") is not None
|
||||
except Exception:
|
||||
securitymd_exists = False
|
||||
except Exception as error:
|
||||
if "404" in str(error):
|
||||
securitymd_exists = False
|
||||
else:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
securitymd_exists = None
|
||||
|
||||
require_pr = False
|
||||
approval_cnt = 0
|
||||
branch_protection = False
|
||||
required_linear_history = False
|
||||
allow_force_pushes = True
|
||||
branch_deletion = True
|
||||
status_checks = False
|
||||
enforce_admins = False
|
||||
conversation_resolution = False
|
||||
try:
|
||||
branch = repo.get_branch(default_branch)
|
||||
if branch.protected:
|
||||
protection = branch.get_protection()
|
||||
if protection:
|
||||
require_pr = (
|
||||
protection.required_pull_request_reviews is not None
|
||||
)
|
||||
approval_cnt = (
|
||||
protection.required_pull_request_reviews.required_approving_review_count
|
||||
if require_pr
|
||||
else 0
|
||||
)
|
||||
required_linear_history = (
|
||||
protection.required_linear_history
|
||||
)
|
||||
allow_force_pushes = protection.allow_force_pushes
|
||||
branch_deletion = protection.allow_deletions
|
||||
status_checks = (
|
||||
protection.required_status_checks is not None
|
||||
)
|
||||
enforce_admins = protection.enforce_admins
|
||||
conversation_resolution = (
|
||||
protection.required_conversation_resolution
|
||||
)
|
||||
branch_protection = True
|
||||
except Exception as error:
|
||||
# If the branch is not found, it is not protected
|
||||
if "404" in str(error):
|
||||
logger.warning(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
# Any other error, we cannot know if the branch is protected or not
|
||||
else:
|
||||
require_pr = None
|
||||
approval_cnt = None
|
||||
branch_protection = None
|
||||
required_linear_history = None
|
||||
allow_force_pushes = None
|
||||
branch_deletion = None
|
||||
status_checks = None
|
||||
enforce_admins = None
|
||||
conversation_resolution = None
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
repos[repo.id] = Repo(
|
||||
id=repo.id,
|
||||
name=repo.name,
|
||||
full_name=repo.full_name,
|
||||
default_branch=repo.default_branch,
|
||||
private=repo.private,
|
||||
securitymd=securitymd_exists,
|
||||
require_pull_request=require_pr,
|
||||
approval_count=approval_cnt,
|
||||
required_linear_history=required_linear_history,
|
||||
allow_force_pushes=allow_force_pushes,
|
||||
default_branch_deletion=branch_deletion,
|
||||
status_checks=status_checks,
|
||||
enforce_admins=enforce_admins,
|
||||
conversation_resolution=conversation_resolution,
|
||||
default_branch_protection=branch_protection,
|
||||
delete_branch_on_merge=delete_branch_on_merge,
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
@@ -41,5 +123,16 @@ class Repo(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
full_name: str
|
||||
default_branch_protection: Optional[bool]
|
||||
default_branch: str
|
||||
private: bool
|
||||
securitymd: Optional[bool] = False
|
||||
securitymd: Optional[bool]
|
||||
require_pull_request: Optional[bool]
|
||||
required_linear_history: Optional[bool]
|
||||
allow_force_pushes: Optional[bool]
|
||||
default_branch_deletion: Optional[bool]
|
||||
status_checks: Optional[bool]
|
||||
enforce_admins: Optional[bool]
|
||||
approval_count: Optional[int]
|
||||
delete_branch_on_merge: Optional[bool]
|
||||
conversation_resolution: Optional[bool]
|
||||
@@ -7,7 +7,7 @@ from prowler.lib.powershell.powershell import PowerShellSession
|
||||
from prowler.providers.m365.exceptions.exceptions import (
|
||||
M365UserNotBelongingToTenantError,
|
||||
)
|
||||
from prowler.providers.m365.models import M365Credentials
|
||||
from prowler.providers.m365.models import M365Credentials, M365IdentityInfo
|
||||
|
||||
|
||||
class M365PowerShell(PowerShellSession):
|
||||
@@ -34,7 +34,7 @@ class M365PowerShell(PowerShellSession):
|
||||
to be installed and available in the PowerShell environment.
|
||||
"""
|
||||
|
||||
def __init__(self, credentials: M365Credentials):
|
||||
def __init__(self, credentials: M365Credentials, identity: M365IdentityInfo):
|
||||
"""
|
||||
Initialize a Microsoft 365 PowerShell session.
|
||||
|
||||
@@ -46,6 +46,7 @@ class M365PowerShell(PowerShellSession):
|
||||
for authentication.
|
||||
"""
|
||||
super().__init__()
|
||||
self.tenant_identity = identity
|
||||
self.init_credential(credentials)
|
||||
|
||||
def init_credential(self, credentials: M365Credentials) -> None:
|
||||
@@ -95,12 +96,24 @@ class M365PowerShell(PowerShellSession):
|
||||
'Write-Output "$($credential.GetNetworkCredential().Password)"'
|
||||
)
|
||||
|
||||
# Validate user belongs to tenant
|
||||
user_domain = credentials.user.split("@")[1]
|
||||
if not any(
|
||||
user_domain.endswith(domain)
|
||||
for domain in self.tenant_identity.tenant_domains
|
||||
):
|
||||
raise M365UserNotBelongingToTenantError(
|
||||
file=os.path.basename(__file__),
|
||||
message=f"The user domain {user_domain} does not match any of the tenant domains: {', '.join(self.tenant_identity.tenant_domains)}",
|
||||
)
|
||||
|
||||
app = msal.ConfidentialClientApplication(
|
||||
client_id=credentials.client_id,
|
||||
client_credential=credentials.client_secret,
|
||||
authority=f"https://login.microsoftonline.com/{credentials.tenant_id}",
|
||||
)
|
||||
|
||||
# Validate credentials
|
||||
result = app.acquire_token_by_username_password(
|
||||
username=credentials.user,
|
||||
password=decrypted_password, # Needs to be in plain text
|
||||
@@ -113,14 +126,6 @@ class M365PowerShell(PowerShellSession):
|
||||
if "access_token" not in result:
|
||||
return False
|
||||
|
||||
# Validate user credentials belong to tenant
|
||||
user_domain = credentials.user.split("@")[1]
|
||||
if not credentials.provider_id.endswith(user_domain):
|
||||
raise M365UserNotBelongingToTenantError(
|
||||
file=os.path.basename(__file__),
|
||||
message="The provided M365 User does not belong to the specified tenant.",
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
def connect_microsoft_teams(self) -> dict:
|
||||
|
||||
@@ -15,5 +15,7 @@ class M365Service:
|
||||
|
||||
# Initialize PowerShell client only if credentials are available
|
||||
self.powershell = (
|
||||
M365PowerShell(provider.credentials) if provider.credentials else None
|
||||
M365PowerShell(provider.credentials, provider.identity)
|
||||
if provider.credentials and provider.identity
|
||||
else None
|
||||
)
|
||||
@@ -194,20 +194,17 @@ class M365Provider(Provider):
|
||||
|
||||
# Set up the identity
|
||||
self._identity = self.setup_identity(
|
||||
az_cli_auth,
|
||||
sp_env_auth,
|
||||
env_auth,
|
||||
browser_auth,
|
||||
client_id,
|
||||
self._session,
|
||||
)
|
||||
|
||||
# Set up PowerShell session credentials
|
||||
self._credentials = self.setup_powershell(
|
||||
env_auth=env_auth,
|
||||
m365_credentials=m365_credentials,
|
||||
provider_id=self.identity.tenant_domain,
|
||||
init_modules=init_modules,
|
||||
identity=self.identity,
|
||||
init_modules=init_modules,
|
||||
)
|
||||
|
||||
# Audit Config
|
||||
@@ -381,9 +378,8 @@ class M365Provider(Provider):
|
||||
def setup_powershell(
|
||||
env_auth: bool = False,
|
||||
m365_credentials: dict = {},
|
||||
provider_id: str = None,
|
||||
init_modules: bool = False,
|
||||
identity: M365IdentityInfo = None,
|
||||
init_modules: bool = False,
|
||||
) -> M365Credentials:
|
||||
"""Gets the M365 credentials.
|
||||
|
||||
@@ -404,7 +400,7 @@ class M365Provider(Provider):
|
||||
client_id=m365_credentials.get("client_id", ""),
|
||||
client_secret=m365_credentials.get("client_secret", ""),
|
||||
tenant_id=m365_credentials.get("tenant_id", ""),
|
||||
provider_id=provider_id,
|
||||
tenant_domains=identity.tenant_domains,
|
||||
)
|
||||
elif env_auth:
|
||||
m365_user = getenv("M365_USER")
|
||||
@@ -422,19 +418,18 @@ class M365Provider(Provider):
|
||||
message="Missing M365_USER or M365_ENCRYPTED_PASSWORD environment variables required for credentials authentication.",
|
||||
)
|
||||
credentials = M365Credentials(
|
||||
user=m365_user,
|
||||
passwd=m365_password,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
tenant_id=tenant_id,
|
||||
provider_id=provider_id,
|
||||
tenant_domains=identity.tenant_domains,
|
||||
user=m365_user,
|
||||
passwd=m365_password,
|
||||
)
|
||||
|
||||
if credentials:
|
||||
if identity:
|
||||
identity.identity_type = "Service Principal and User Credentials"
|
||||
identity.user = credentials.user
|
||||
test_session = M365PowerShell(credentials)
|
||||
test_session = M365PowerShell(credentials, identity)
|
||||
try:
|
||||
if test_session.test_credentials(credentials):
|
||||
if init_modules:
|
||||
@@ -704,7 +699,7 @@ class M365Provider(Provider):
|
||||
)
|
||||
|
||||
# Set up the M365 session
|
||||
credentials = M365Provider.setup_session(
|
||||
session = M365Provider.setup_session(
|
||||
az_cli_auth,
|
||||
sp_env_auth,
|
||||
env_auth,
|
||||
@@ -714,16 +709,35 @@ class M365Provider(Provider):
|
||||
region_config,
|
||||
)
|
||||
|
||||
GraphServiceClient(credentials=credentials)
|
||||
GraphServiceClient(credentials=session)
|
||||
|
||||
logger.info("M365 provider: Connection to MSGraph successful")
|
||||
|
||||
# Set up Identity
|
||||
identity = M365Provider.setup_identity(
|
||||
sp_env_auth,
|
||||
env_auth,
|
||||
session,
|
||||
)
|
||||
|
||||
if not identity:
|
||||
raise M365GetTokenIdentityError(
|
||||
file=os.path.basename(__file__),
|
||||
message="Failed to retrieve M365 identity",
|
||||
)
|
||||
|
||||
if provider_id not in identity.tenant_domains:
|
||||
raise M365InvalidProviderIdError(
|
||||
file=os.path.basename(__file__),
|
||||
message=f"The provider ID {provider_id} does not match any of the service principal tenant domains: {', '.join(identity.tenant_domains)}",
|
||||
)
|
||||
|
||||
# Set up PowerShell credentials
|
||||
if user and encrypted_password:
|
||||
M365Provider.setup_powershell(
|
||||
env_auth,
|
||||
m365_credentials,
|
||||
provider_id,
|
||||
identity,
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
@@ -732,15 +746,6 @@ class M365Provider(Provider):
|
||||
|
||||
logger.info("M365 provider: Connection to PowerShell successful")
|
||||
|
||||
# Check that user domain, provider_id and Graph client tenant_domain are the same
|
||||
if user and encrypted_password:
|
||||
user_domain = user.split("@")[1]
|
||||
if provider_id and user_domain != provider_id:
|
||||
raise M365InvalidProviderIdError(
|
||||
file=os.path.basename(__file__),
|
||||
message=f"Provider ID {provider_id} does not match Application tenant domain {user_domain}",
|
||||
)
|
||||
|
||||
return Connection(is_connected=True)
|
||||
|
||||
# Exceptions from setup_region_config
|
||||
@@ -867,13 +872,11 @@ class M365Provider(Provider):
|
||||
message=f"Missing environment variable {env_var} required to authenticate.",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def setup_identity(
|
||||
self,
|
||||
az_cli_auth,
|
||||
sp_env_auth,
|
||||
env_auth,
|
||||
browser_auth,
|
||||
client_id,
|
||||
session,
|
||||
):
|
||||
"""
|
||||
Sets up the identity for the M365 provider.
|
||||
@@ -888,7 +891,7 @@ class M365Provider(Provider):
|
||||
Returns:
|
||||
M365IdentityInfo: An instance of M365IdentityInfo containing the identity information.
|
||||
"""
|
||||
credentials = self.session
|
||||
logger.info("M365 provider: Setting up identity ...")
|
||||
# TODO: fill this object with real values not default and set to none
|
||||
identity = M365IdentityInfo()
|
||||
|
||||
@@ -896,74 +899,75 @@ class M365Provider(Provider):
|
||||
# the identity can access AAD and retrieve the tenant domain name.
|
||||
# With cli also should be possible but right now it does not work, m365 python package issue is coming
|
||||
# At the time of writting this with az cli creds is not working, despite that is included
|
||||
if env_auth or az_cli_auth or sp_env_auth or browser_auth or client_id:
|
||||
|
||||
async def get_m365_identity():
|
||||
# Trying to recover tenant domain info
|
||||
async def get_m365_identity(identity):
|
||||
# Trying to recover tenant domain info
|
||||
try:
|
||||
logger.info(
|
||||
"Trying to retrieve tenant domain from AAD to populate identity structure ..."
|
||||
)
|
||||
client = GraphServiceClient(credentials=session)
|
||||
|
||||
domain_result = await client.domains.get()
|
||||
if getattr(domain_result, "value"):
|
||||
if getattr(domain_result.value[0], "id"):
|
||||
identity.tenant_domain = domain_result.value[0].id
|
||||
for domain in domain_result.value:
|
||||
identity.tenant_domains.append(domain.id)
|
||||
|
||||
except HttpResponseError as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
raise M365HTTPResponseError(
|
||||
file=os.path.basename(__file__),
|
||||
original_exception=error,
|
||||
)
|
||||
except ClientAuthenticationError as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
raise M365GetTokenIdentityError(
|
||||
file=os.path.basename(__file__),
|
||||
original_exception=error,
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
# since that exception is not considered as critical, we keep filling another identity fields
|
||||
identity.identity_id = (
|
||||
getenv("AZURE_CLIENT_ID") or "Unknown user id (Missing AAD permissions)"
|
||||
)
|
||||
if sp_env_auth:
|
||||
identity.identity_type = "Service Principal"
|
||||
elif env_auth:
|
||||
identity.identity_type = "Service Principal and User Credentials"
|
||||
else:
|
||||
identity.identity_type = "User"
|
||||
try:
|
||||
logger.info(
|
||||
"Trying to retrieve tenant domain from AAD to populate identity structure ..."
|
||||
"Trying to retrieve user information from AAD to populate identity structure ..."
|
||||
)
|
||||
client = GraphServiceClient(credentials=credentials)
|
||||
client = GraphServiceClient(credentials=session)
|
||||
|
||||
domain_result = await client.domains.get()
|
||||
if getattr(domain_result, "value"):
|
||||
if getattr(domain_result.value[0], "id"):
|
||||
identity.tenant_domain = domain_result.value[0].id
|
||||
me = await client.me.get()
|
||||
if me:
|
||||
if getattr(me, "user_principal_name"):
|
||||
identity.identity_id = me.user_principal_name
|
||||
|
||||
except HttpResponseError as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
raise M365HTTPResponseError(
|
||||
file=os.path.basename(__file__),
|
||||
original_exception=error,
|
||||
)
|
||||
except ClientAuthenticationError as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
raise M365GetTokenIdentityError(
|
||||
file=os.path.basename(__file__),
|
||||
original_exception=error,
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
# since that exception is not considered as critical, we keep filling another identity fields
|
||||
if sp_env_auth or env_auth or client_id:
|
||||
# The id of the sp can be retrieved from environment variables
|
||||
identity.identity_id = getenv("AZURE_CLIENT_ID")
|
||||
identity.identity_type = "Service Principal"
|
||||
# Same here, if user can access AAD, some fields are retrieved if not, default value, for az cli
|
||||
# should work but it doesn't, pending issue
|
||||
else:
|
||||
identity.identity_id = "Unknown user id (Missing AAD permissions)"
|
||||
identity.identity_type = "User"
|
||||
try:
|
||||
logger.info(
|
||||
"Trying to retrieve user information from AAD to populate identity structure ..."
|
||||
)
|
||||
client = GraphServiceClient(credentials=credentials)
|
||||
|
||||
me = await client.me.get()
|
||||
if me:
|
||||
if getattr(me, "user_principal_name"):
|
||||
identity.identity_id = me.user_principal_name
|
||||
# Retrieve tenant id from the client
|
||||
client = GraphServiceClient(credentials=session)
|
||||
organization_info = await client.organization.get()
|
||||
identity.tenant_id = organization_info.value[0].id
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
|
||||
# Retrieve tenant id from the client
|
||||
client = GraphServiceClient(credentials=credentials)
|
||||
organization_info = await client.organization.get()
|
||||
identity.tenant_id = organization_info.value[0].id
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(get_m365_identity())
|
||||
return identity
|
||||
asyncio.get_event_loop().run_until_complete(get_m365_identity(identity))
|
||||
return identity
|
||||
|
||||
@staticmethod
|
||||
def validate_static_credentials(
|
||||
|
||||
@@ -8,7 +8,8 @@ class M365IdentityInfo(BaseModel):
|
||||
identity_id: str = ""
|
||||
identity_type: str = ""
|
||||
tenant_id: str = ""
|
||||
tenant_domain: str = "Unknown tenant domain (missing AAD permissions)"
|
||||
tenant_domain: str = "Unknown tenant domain (missing Entra permissions)"
|
||||
tenant_domains: list[str] = []
|
||||
location: str = ""
|
||||
user: str = None
|
||||
|
||||
@@ -21,12 +22,12 @@ class M365RegionConfig(BaseModel):
|
||||
|
||||
|
||||
class M365Credentials(BaseModel):
|
||||
user: str = ""
|
||||
passwd: str = ""
|
||||
client_id: str = ""
|
||||
client_secret: str = ""
|
||||
tenant_id: str = ""
|
||||
provider_id: str = ""
|
||||
tenant_domains: list[str] = []
|
||||
user: str = ""
|
||||
passwd: str = ""
|
||||
|
||||
|
||||
class M365OutputOptions(ProviderOutputOptions):
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
|
||||
from freezegun import freeze_time
|
||||
from mock import patch
|
||||
|
||||
from prowler.lib.outputs.compliance.cis.cis_m365 import M365CIS
|
||||
from prowler.lib.outputs.compliance.cis.models import M365CISModel
|
||||
from tests.lib.outputs.compliance.fixtures import CIS_4_0_M365
|
||||
from tests.lib.outputs.fixtures.fixtures import generate_finding_output
|
||||
from tests.providers.m365.m365_fixtures import DOMAIN, LOCATION, TENANT_ID
|
||||
|
||||
|
||||
class TestM365CIS:
|
||||
def test_output_transform(self):
|
||||
findings = [
|
||||
generate_finding_output(
|
||||
provider="m365",
|
||||
compliance={"CIS-4.0": "2.1.3"},
|
||||
account_name=DOMAIN,
|
||||
account_uid=TENANT_ID,
|
||||
region=LOCATION,
|
||||
)
|
||||
]
|
||||
# Clear the data from CSV class
|
||||
output = M365CIS(findings, CIS_4_0_M365)
|
||||
output_data = output.data[0]
|
||||
assert isinstance(output_data, M365CISModel)
|
||||
assert output_data.Provider == "m365"
|
||||
assert output_data.TenantId == TENANT_ID
|
||||
assert output_data.Location == LOCATION
|
||||
assert output_data.Description == CIS_4_0_M365.Description
|
||||
assert output_data.Requirements_Id == CIS_4_0_M365.Requirements[0].Id
|
||||
assert (
|
||||
output_data.Requirements_Description
|
||||
== CIS_4_0_M365.Requirements[0].Description
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_Section
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].Section
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_SubSection
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].SubSection
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_Profile
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].Profile
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_AssessmentStatus
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].AssessmentStatus
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_Description
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].Description
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_RationaleStatement
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].RationaleStatement
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_ImpactStatement
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].ImpactStatement
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_RemediationProcedure
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].RemediationProcedure
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_AuditProcedure
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].AuditProcedure
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_AdditionalInformation
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].AdditionalInformation
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_References
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].References
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_DefaultValue
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].DefaultValue
|
||||
)
|
||||
assert output_data.Status == "PASS"
|
||||
assert output_data.StatusExtended == ""
|
||||
assert output_data.ResourceId == ""
|
||||
assert output_data.ResourceName == ""
|
||||
assert output_data.CheckId == "test-check-id"
|
||||
assert output_data.Muted is False
|
||||
# Test manual check
|
||||
output_data_manual = output.data[1]
|
||||
assert output_data_manual.Provider == "m365"
|
||||
assert output_data_manual.TenantId == TENANT_ID
|
||||
assert output_data_manual.Location == LOCATION
|
||||
assert output_data_manual.Description == CIS_4_0_M365.Description
|
||||
assert output_data_manual.Requirements_Id == CIS_4_0_M365.Requirements[1].Id
|
||||
assert (
|
||||
output_data_manual.Requirements_Description
|
||||
== CIS_4_0_M365.Requirements[1].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Section
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].Section
|
||||
)
|
||||
assert (
|
||||
output_data.Requirements_Attributes_SubSection
|
||||
== CIS_4_0_M365.Requirements[0].Attributes[0].SubSection
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Profile
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].Profile
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AssessmentStatus
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].AssessmentStatus
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_Description
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].Description
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_RationaleStatement
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].RationaleStatement
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_ImpactStatement
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].ImpactStatement
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_RemediationProcedure
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].RemediationProcedure
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AuditProcedure
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].AuditProcedure
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_AdditionalInformation
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].AdditionalInformation
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_References
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].References
|
||||
)
|
||||
assert (
|
||||
output_data_manual.Requirements_Attributes_DefaultValue
|
||||
== CIS_4_0_M365.Requirements[1].Attributes[0].DefaultValue
|
||||
)
|
||||
assert output_data_manual.Status == "MANUAL"
|
||||
assert output_data_manual.StatusExtended == "Manual check"
|
||||
assert output_data_manual.ResourceId == "manual_check"
|
||||
assert output_data_manual.ResourceName == "Manual check"
|
||||
assert output_data_manual.CheckId == "manual"
|
||||
assert output_data_manual.Muted is False
|
||||
|
||||
@freeze_time(datetime.now())
|
||||
def test_batch_write_data_to_file(self):
|
||||
mock_file = StringIO()
|
||||
findings = [
|
||||
generate_finding_output(
|
||||
provider="m365",
|
||||
compliance={"CIS-4.0": "2.1.3"},
|
||||
account_name=DOMAIN,
|
||||
account_uid=TENANT_ID,
|
||||
region=LOCATION,
|
||||
)
|
||||
]
|
||||
# Clear the data from CSV class
|
||||
output = M365CIS(findings, CIS_4_0_M365)
|
||||
output._file_descriptor = mock_file
|
||||
|
||||
with patch.object(mock_file, "close", return_value=None):
|
||||
output.batch_write_data_to_file()
|
||||
|
||||
mock_file.seek(0)
|
||||
content = mock_file.read()
|
||||
|
||||
expected_csv = f"PROVIDER;DESCRIPTION;TENANTID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_SECTION;REQUIREMENTS_ATTRIBUTES_SUBSECTION;REQUIREMENTS_ATTRIBUTES_PROFILE;REQUIREMENTS_ATTRIBUTES_ASSESSMENTSTATUS;REQUIREMENTS_ATTRIBUTES_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_RATIONALESTATEMENT;REQUIREMENTS_ATTRIBUTES_IMPACTSTATEMENT;REQUIREMENTS_ATTRIBUTES_REMEDIATIONPROCEDURE;REQUIREMENTS_ATTRIBUTES_AUDITPROCEDURE;REQUIREMENTS_ATTRIBUTES_ADDITIONALINFORMATION;REQUIREMENTS_ATTRIBUTES_DEFAULTVALUE;REQUIREMENTS_ATTRIBUTES_REFERENCES;STATUS;STATUSEXTENDED;RESOURCEID;RESOURCENAME;CHECKID;MUTED\r\nm365;The CIS Microsoft 365 Foundations Benchmark provides prescriptive guidance for configuring security options for Microsoft 365 with an emphasis on foundational, testable, and architecture agnostic settings.;00000000-0000-0000-0000-000000000000;global;{datetime.now()};2.1.3;Ensure MFA Delete is enabled on S3 buckets;2.1. Simple Storage Service (S3);;Level 1;Automated;Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.;Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.;;Perform the steps below to enable MFA delete on an S3 bucket.Note:-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.-You must use your 'root' account to enable MFA Delete on S3 buckets.**From Command line:**1. Run the s3api put-bucket-versioning command aws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode;Perform the steps below to confirm MFA delete is configured on an S3 Bucket**From Console:**1. Login to the S3 console at `https://console.aws.amazon.com/s3/`2. Click the `Check` box next to the Bucket name you want to confirm3. In the window under `Properties`4. Confirm that Versioning is `Enabled`5. Confirm that MFA Delete is `Enabled`**From Command Line:**1. Run the `get-bucket-versioning aws s3api get-bucket-versioning --bucket my-bucket Output example: <VersioningConfiguration xmlns=`http://s3.amazonaws.com/doc/2006-03-01/`> <Status>Enabled</Status> <MfaDelete>Enabled</MfaDelete></VersioningConfiguration>\ If the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.;;By default, MFA Delete is not enabled on S3 buckets.;https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html;PASS;;;;test-check-id;False\r\nm365;The CIS Microsoft 365 Foundations Benchmark provides prescriptive guidance for configuring security options for Microsoft 365 with an emphasis on foundational, testable, and architecture agnostic settings.;00000000-0000-0000-0000-000000000000;global;{datetime.now()};2.1.4;Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive;1.1 Control Plane Node Configuration Files;;Level 1 - Master Node;Automated;Ensure that the controller manager pod specification file has permissions of `600` or more restrictive.;The controller manager pod specification file controls various parameters that set the behavior of the Controller Manager on the master node. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.;;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml ```;Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` stat -c %a /etc/kubernetes/manifests/kube-controller-manager.yaml ``` Verify that the permissions are `600` or more restrictive.;;By default, the `kube-controller-manager.yaml` file has permissions of `640`.;https://kubernetes.io/docs/admin/kube-apiserver/;MANUAL;Manual check;manual_check;Manual check;manual;False\r\n"
|
||||
|
||||
assert content == expected_csv
|
||||
@@ -330,3 +330,55 @@ class TestCompliance:
|
||||
"CIS-2.0": ["2.1.3"],
|
||||
"CIS-2.1": ["2.1.3"],
|
||||
}
|
||||
|
||||
def test_get_check_compliance_github(self):
|
||||
check_compliance = [
|
||||
Compliance(
|
||||
Framework="CIS",
|
||||
Provider="Github",
|
||||
Version="1.0",
|
||||
Description="This document provides prescriptive guidance for establishing a secure configuration posture for securing GitHub.",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="1.1.11",
|
||||
Description="Ensure all open comments are resolved before allowing code change merging",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="1.1",
|
||||
Profile="Level 2",
|
||||
AssessmentStatus="Manual",
|
||||
Description='Organizations should enforce a "no open comments" policy before allowing code change merging.',
|
||||
RationaleStatement="In an open code change proposal, reviewers can leave comments containing their questions and suggestions. These comments can also include potential bugs and security issues. Requiring all comments on a code change proposal to be resolved before it can be merged ensures that every concern is properly addressed or acknowledged before the new code changes are introduced to the code base.",
|
||||
ImpactStatement="Code change proposals containing open comments would not be able to be merged into the code base.",
|
||||
RemediationProcedure='For each code repository in use, require open comments to be resolved before the relevant code change can be merged by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the "Code and automation" section of the sidebar, click **Branches**.\n 4. Next to "Branch protection rules", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn\'t, click **Add rule**.\n 5. If you add the rule, under "Branch name pattern", type the branch name or pattern you want to protect.\n 6. Select **Require conversation resolution before merging**.\n 7. Click **Create** or **Save changes**.',
|
||||
AuditProcedure='For every code repository in use, verify that each merged code change does not contain open, unattended comments by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the "Code and automation" section of the sidebar, click **Branches**.\n 4. Next to "Branch protection rules", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn\'t, you are not compliant.\n 5. Ensure that **Require conversation resolution before merging** is checked.',
|
||||
AdditionalInformation="",
|
||||
References="",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
finding = Check_Report(
|
||||
metadata=load_check_metadata(
|
||||
f"{path.dirname(path.realpath(__file__))}/../fixtures/metadata.json"
|
||||
).json(),
|
||||
resource={},
|
||||
)
|
||||
finding.resource_details = "Test resource details"
|
||||
finding.resource_id = "test-resource"
|
||||
finding.resource_arn = "test-arn"
|
||||
finding.region = "eu-west-1"
|
||||
finding.status = "PASS"
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
bulk_checks_metadata = {}
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"] = mock.MagicMock()
|
||||
bulk_checks_metadata["iam_user_accesskey_unused"].Compliance = check_compliance
|
||||
|
||||
assert get_check_compliance(finding, "github", bulk_checks_metadata) == {
|
||||
"CIS-1.0": ["1.1.11"],
|
||||
}
|
||||
@@ -243,6 +243,58 @@ CIS_1_5_AWS = Compliance(
|
||||
],
|
||||
)
|
||||
|
||||
CIS_4_0_M365_NAME = "cis_4.0_m365"
|
||||
CIS_4_0_M365 = Compliance(
|
||||
Framework="CIS",
|
||||
Provider="M365",
|
||||
Version="4.0",
|
||||
Description="The CIS Microsoft 365 Foundations Benchmark provides prescriptive guidance for configuring security options for Microsoft 365 with an emphasis on foundational, testable, and architecture agnostic settings.",
|
||||
Requirements=[
|
||||
Compliance_Requirement(
|
||||
Checks=[
|
||||
"mfa_delete_enabled",
|
||||
],
|
||||
Id="2.1.3",
|
||||
Description="Ensure MFA Delete is enabled on S3 buckets",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="2.1. Simple Storage Service (S3)",
|
||||
Profile="Level 1",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
RationaleStatement="Adding MFA delete to an S3 bucket, requires additional authentication when you change the version state of your bucket or you delete and object version adding another layer of security in the event your security credentials are compromised or unauthorized access is granted.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Perform the steps below to enable MFA delete on an S3 bucket.Note:-You cannot enable MFA Delete using the AWS Management Console. You must use the AWS CLI or API.-You must use your 'root' account to enable MFA Delete on S3 buckets.**From Command line:**1. Run the s3api put-bucket-versioning command aws s3api put-bucket-versioning --profile my-root-profile --bucket Bucket_Name --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa arn:aws:iam::aws_account_id:mfa/root-account-mfa-device passcode",
|
||||
AuditProcedure="Perform the steps below to confirm MFA delete is configured on an S3 Bucket**From Console:**1. Login to the S3 console at `https://console.aws.amazon.com/s3/`2. Click the `Check` box next to the Bucket name you want to confirm3. In the window under `Properties`4. Confirm that Versioning is `Enabled`5. Confirm that MFA Delete is `Enabled`**From Command Line:**1. Run the `get-bucket-versioning aws s3api get-bucket-versioning --bucket my-bucket Output example: <VersioningConfiguration xmlns=`http://s3.amazonaws.com/doc/2006-03-01/`> <Status>Enabled</Status> <MfaDelete>Enabled</MfaDelete></VersioningConfiguration>\ If the Console or the CLI output does not show Versioning and MFA Delete `enabled` refer to the remediation below.",
|
||||
AdditionalInformation="",
|
||||
References="https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html:https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html",
|
||||
DefaultValue="By default, MFA Delete is not enabled on S3 buckets.",
|
||||
)
|
||||
],
|
||||
),
|
||||
Compliance_Requirement(
|
||||
Checks=[],
|
||||
Id="2.1.4",
|
||||
Description="Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive",
|
||||
Attributes=[
|
||||
CIS_Requirement_Attribute(
|
||||
Section="1.1 Control Plane Node Configuration Files",
|
||||
Profile="Level 1 - Master Node",
|
||||
AssessmentStatus="Automated",
|
||||
Description="Ensure that the controller manager pod specification file has permissions of `600` or more restrictive.",
|
||||
RationaleStatement="The controller manager pod specification file controls various parameters that set the behavior of the Controller Manager on the master node. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.",
|
||||
ImpactStatement="",
|
||||
RemediationProcedure="Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` chmod 600 /etc/kubernetes/manifests/kube-controller-manager.yaml ```",
|
||||
AuditProcedure="Run the below command (based on the file location on your system) on the Control Plane node. For example, ``` stat -c %a /etc/kubernetes/manifests/kube-controller-manager.yaml ``` Verify that the permissions are `600` or more restrictive.",
|
||||
AdditionalInformation="",
|
||||
References="https://kubernetes.io/docs/admin/kube-apiserver/",
|
||||
DefaultValue="By default, the `kube-controller-manager.yaml` file has permissions of `640`.",
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
MITRE_ATTACK_AWS_NAME = "mitre_attack_aws"
|
||||
MITRE_ATTACK_AWS = Compliance(
|
||||
Framework="MITRE-ATTACK",
|
||||
|
||||
+2
-1
@@ -269,6 +269,7 @@ class Test_ec2_securitygroup_allow_ingress_from_internet_to_all_ports:
|
||||
== f"arn:{aws_provider.identity.partition}:ec2:{AWS_REGION_US_EAST_1}:{aws_provider.identity.account}:security-group/{default_sg_id}"
|
||||
)
|
||||
assert sg.resource_details == default_sg_name
|
||||
assert sg.check_metadata.Severity == "high"
|
||||
assert sg.resource_tags == []
|
||||
|
||||
@mock_aws
|
||||
@@ -361,6 +362,7 @@ class Test_ec2_securitygroup_allow_ingress_from_internet_to_all_ports:
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].check_metadata.Severity == "critical"
|
||||
|
||||
@mock_aws
|
||||
def test_set_failed_check_called_correctly(self):
|
||||
@@ -409,7 +411,6 @@ class Test_ec2_securitygroup_allow_ingress_from_internet_to_all_ports:
|
||||
"prowler.providers.aws.lib.service.service.AWSService.set_failed_check"
|
||||
) as mock_set_failed_check,
|
||||
):
|
||||
|
||||
from prowler.providers.aws.services.ec2.ec2_securitygroup_allow_ingress_from_internet_to_all_ports.ec2_securitygroup_allow_ingress_from_internet_to_all_ports import (
|
||||
ec2_securitygroup_allow_ingress_from_internet_to_all_ports,
|
||||
)
|
||||
|
||||
@@ -3,9 +3,11 @@ from prowler.providers.aws.services.iam.lib.policy import (
|
||||
check_full_service_access,
|
||||
is_condition_block_restrictive,
|
||||
is_condition_block_restrictive_organization,
|
||||
is_condition_block_restrictive_sns_endpoint,
|
||||
is_condition_restricting_from_private_ip,
|
||||
is_policy_public,
|
||||
)
|
||||
import pytest
|
||||
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER = "123456789012"
|
||||
NON_TRUSTED_AWS_ACCOUNT_NUMBER = "111222333444"
|
||||
@@ -1442,6 +1444,39 @@ class Test_Policy:
|
||||
condition_statement = {"StringEquals": {"aws:PrincipalOrgID": ALL_ORGS}}
|
||||
assert not is_condition_block_restrictive_organization(condition_statement)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"condition_value,expected",
|
||||
[
|
||||
("*@example.com", True),
|
||||
("https://events.pagerduty.com/integration/<api-key>/enqueue", True),
|
||||
(
|
||||
"arn:aws:sns:eu-west-2:123456789012:example-topic:995be20c-a7e3-44ca-8c18-77cb263d15e7",
|
||||
True,
|
||||
),
|
||||
("*@*.com", False),
|
||||
("*@*", False),
|
||||
("*@example.*", False),
|
||||
("https://events.pagerduty.com/integration/*/enqueue", False),
|
||||
("arn:aws:sns:eu-west-2:123456789012:example-topic:*", False),
|
||||
(
|
||||
"arn:aws:sns:eu-west-2:*:example-topic:995be20c-a7e3-44ca-8c18-77cb263d15e7",
|
||||
False,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_condition_parser_string_equals_sns_endpoint_str(
|
||||
self, condition_value: str, expected: bool
|
||||
):
|
||||
condition_statement = {"StringEquals": {"SNS:Endpoint": condition_value}}
|
||||
assert (
|
||||
is_condition_block_restrictive_sns_endpoint(condition_statement) == expected
|
||||
)
|
||||
|
||||
condition_statement = {"StringLike": {"SNS:Endpoint": condition_value}}
|
||||
assert (
|
||||
is_condition_block_restrictive_sns_endpoint(condition_statement) == expected
|
||||
)
|
||||
|
||||
def test_policy_allows_cross_account_access_with_root_and_wildcard_principal(self):
|
||||
policy_allow_root_and_wildcard_principal = {
|
||||
"Statement": [
|
||||
|
||||
+107
@@ -1,8 +1,10 @@
|
||||
from typing import Any, Dict
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.aws.services.sns.sns_service import Topic
|
||||
from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1
|
||||
import pytest
|
||||
|
||||
kms_key_id = str(uuid4())
|
||||
topic_name = "test-topic"
|
||||
@@ -97,6 +99,20 @@ test_policy_restricted_principal_account_organization = {
|
||||
}
|
||||
|
||||
|
||||
def generate_policy_restricted_on_sns_endpoint(endpoint: str) -> Dict[str, Any]:
|
||||
return {
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": ["sns:Publish"],
|
||||
"Resource": f"arn:aws:sns:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:{topic_name}",
|
||||
"Condition": {"StringEquals": {"SNS:Endpoint": endpoint}},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
class Test_sns_topics_not_publicly_accessible:
|
||||
def test_no_topics(self):
|
||||
sns_client = mock.MagicMock
|
||||
@@ -379,3 +395,94 @@ class Test_sns_topics_not_publicly_accessible:
|
||||
assert result[0].resource_arn == topic_arn
|
||||
assert result[0].region == AWS_REGION_EU_WEST_1
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"endpoint",
|
||||
[
|
||||
("*@example.com"),
|
||||
("user@example.com"),
|
||||
("https://events.pagerduty.com/integration/987654321/enqueue"),
|
||||
(
|
||||
"arn:aws:sns:eu-west-2:123456789012:example-topic:995be20c-a7e3-44ca-8c18-77cb263d15e7"
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_topic_public_with_sns_endpoint(self, endpoint: str):
|
||||
sns_client = mock.MagicMock
|
||||
sns_client.audited_account = AWS_ACCOUNT_NUMBER
|
||||
sns_client.topics = []
|
||||
sns_client.topics.append(
|
||||
Topic(
|
||||
arn=topic_arn,
|
||||
name=topic_name,
|
||||
policy=generate_policy_restricted_on_sns_endpoint(endpoint=endpoint),
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
)
|
||||
)
|
||||
sns_client.provider = mock.MagicMock()
|
||||
sns_client.provider.organizations_metadata = mock.MagicMock()
|
||||
sns_client.provider.organizations_metadata.organization_id = org_id
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.sns.sns_service.SNS",
|
||||
sns_client,
|
||||
):
|
||||
from prowler.providers.aws.services.sns.sns_topics_not_publicly_accessible.sns_topics_not_publicly_accessible import (
|
||||
sns_topics_not_publicly_accessible,
|
||||
)
|
||||
|
||||
check = sns_topics_not_publicly_accessible()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SNS topic {topic_name} is not public because its policy only allows access from an endpoint."
|
||||
)
|
||||
assert result[0].resource_id == topic_name
|
||||
assert result[0].resource_arn == topic_arn
|
||||
assert result[0].region == AWS_REGION_EU_WEST_1
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"endpoint",
|
||||
[
|
||||
("*@*"),
|
||||
("https://events.pagerduty.com/integration/*/enqueue"),
|
||||
("arn:aws:sns:eu-west-2:*:example-topic:*"),
|
||||
],
|
||||
)
|
||||
def test_topic_public_with_unrestricted_sns_endpoint(self, endpoint: str):
|
||||
sns_client = mock.MagicMock
|
||||
sns_client.audited_account = AWS_ACCOUNT_NUMBER
|
||||
sns_client.topics = []
|
||||
sns_client.topics.append(
|
||||
Topic(
|
||||
arn=topic_arn,
|
||||
name=topic_name,
|
||||
policy=generate_policy_restricted_on_sns_endpoint(endpoint=endpoint),
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
)
|
||||
)
|
||||
sns_client.provider = mock.MagicMock()
|
||||
sns_client.provider.organizations_metadata = mock.MagicMock()
|
||||
sns_client.provider.organizations_metadata.organization_id = org_id
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.sns.sns_service.SNS",
|
||||
sns_client,
|
||||
):
|
||||
from prowler.providers.aws.services.sns.sns_topics_not_publicly_accessible.sns_topics_not_publicly_accessible import (
|
||||
sns_topics_not_publicly_accessible,
|
||||
)
|
||||
|
||||
check = sns_topics_not_publicly_accessible()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SNS topic {topic_name} is public because its policy allows public access."
|
||||
)
|
||||
assert result[0].resource_id == topic_name
|
||||
assert result[0].resource_arn == topic_arn
|
||||
assert result[0].region == AWS_REGION_EU_WEST_1
|
||||
assert result[0].resource_tags == []
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.github.services.organization.organization_service import Org
|
||||
from tests.providers.github.github_fixtures import set_mocked_github_provider
|
||||
|
||||
|
||||
class Test_organization_members_mfa_required:
|
||||
def test_no_organizations(self):
|
||||
organization_client = mock.MagicMock
|
||||
organization_client.organizations = {}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.organization.organization_members_mfa_required.organization_members_mfa_required.organization_client",
|
||||
new=organization_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.organization.organization_members_mfa_required.organization_members_mfa_required import (
|
||||
organization_members_mfa_required,
|
||||
)
|
||||
|
||||
check = organization_members_mfa_required()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_organization_mfa_disabled(self):
|
||||
organization_client = mock.MagicMock
|
||||
org_name = "test-organization"
|
||||
organization_client.organizations = {
|
||||
1: Org(
|
||||
id=1,
|
||||
name=org_name,
|
||||
mfa_required=False,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.organization.organization_members_mfa_required.organization_members_mfa_required.organization_client",
|
||||
new=organization_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.organization.organization_members_mfa_required.organization_members_mfa_required import (
|
||||
organization_members_mfa_required,
|
||||
)
|
||||
|
||||
check = organization_members_mfa_required()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "test-organization"
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Organization {org_name} does not require members to have two-factor authentication enabled."
|
||||
)
|
||||
|
||||
def test_one_organization_securitymd(self):
|
||||
organization_client = mock.MagicMock
|
||||
org_name = "test-organization"
|
||||
organization_client.organizations = {
|
||||
1: Org(
|
||||
id=1,
|
||||
name=org_name,
|
||||
mfa_required=True,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.organization.organization_members_mfa_required.organization_members_mfa_required.organization_client",
|
||||
new=organization_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.organization.organization_members_mfa_required.organization_members_mfa_required import (
|
||||
organization_members_mfa_required,
|
||||
)
|
||||
|
||||
check = organization_members_mfa_required()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "test-organization"
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Organization {org_name} does require members to have two-factor authentication enabled."
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from prowler.providers.github.services.organization.organization_service import (
|
||||
Org,
|
||||
Organization,
|
||||
)
|
||||
from tests.providers.github.github_fixtures import set_mocked_github_provider
|
||||
|
||||
|
||||
def mock_list_organizations(_):
|
||||
return {
|
||||
1: Org(
|
||||
id=1,
|
||||
name="test-organization",
|
||||
mfa_required=True,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@patch(
|
||||
"prowler.providers.github.services.organization.organization_service.Organization._list_organizations",
|
||||
new=mock_list_organizations,
|
||||
)
|
||||
class Test_Repository_Service:
|
||||
def test_get_client(self):
|
||||
repository_service = Organization(set_mocked_github_provider())
|
||||
assert repository_service.clients[0].__class__.__name__ == "Github"
|
||||
|
||||
def test_get_service(self):
|
||||
repository_service = Organization(set_mocked_github_provider())
|
||||
assert repository_service.__class__.__name__ == "Organization"
|
||||
|
||||
def test_list_organizations(self):
|
||||
repository_service = Organization(set_mocked_github_provider())
|
||||
assert len(repository_service.organizations) == 1
|
||||
assert repository_service.organizations[1].name == "test-organization"
|
||||
assert repository_service.organizations[1].mfa_required
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.github.services.repository.repository_service import Repo
|
||||
from tests.providers.github.github_fixtures import set_mocked_github_provider
|
||||
|
||||
|
||||
class Test_repository_branch_delete_on_merge_enabled_test:
|
||||
def test_no_repositories(self):
|
||||
repository_client = mock.MagicMock
|
||||
repository_client.repositories = {}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_branch_delete_on_merge_enabled.repository_branch_delete_on_merge_enabled.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_branch_delete_on_merge_enabled.repository_branch_delete_on_merge_enabled import (
|
||||
repository_branch_delete_on_merge_enabled,
|
||||
)
|
||||
|
||||
check = repository_branch_delete_on_merge_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_branch_deletion_disabled(self):
|
||||
repository_client = mock.MagicMock
|
||||
repo_name = "repo1"
|
||||
repository_client.repositories = {
|
||||
1: Repo(
|
||||
id=1,
|
||||
name=repo_name,
|
||||
full_name="account-name/repo1",
|
||||
default_branch="main",
|
||||
private=False,
|
||||
securitymd=False,
|
||||
delete_branch_on_merge=False,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_branch_delete_on_merge_enabled.repository_branch_delete_on_merge_enabled.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_branch_delete_on_merge_enabled.repository_branch_delete_on_merge_enabled import (
|
||||
repository_branch_delete_on_merge_enabled,
|
||||
)
|
||||
|
||||
check = repository_branch_delete_on_merge_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "repo1"
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Repository {repo_name} does not delete branches on merge."
|
||||
)
|
||||
|
||||
def test_branch_deletion_enabled(self):
|
||||
repository_client = mock.MagicMock
|
||||
repo_name = "repo1"
|
||||
repository_client.repositories = {
|
||||
1: Repo(
|
||||
id=1,
|
||||
name=repo_name,
|
||||
full_name="account-name/repo1",
|
||||
default_branch="main",
|
||||
private=False,
|
||||
securitymd=True,
|
||||
delete_branch_on_merge=True,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_branch_delete_on_merge_enabled.repository_branch_delete_on_merge_enabled.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_branch_delete_on_merge_enabled.repository_branch_delete_on_merge_enabled import (
|
||||
repository_branch_delete_on_merge_enabled,
|
||||
)
|
||||
|
||||
check = repository_branch_delete_on_merge_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "repo1"
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Repository {repo_name} does delete branches on merge."
|
||||
)
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.github.services.repository.repository_service import Repo
|
||||
from tests.providers.github.github_fixtures import set_mocked_github_provider
|
||||
|
||||
|
||||
class Test_repository_default_branch_deletion_disabled_test:
|
||||
def test_no_repositories(self):
|
||||
repository_client = mock.MagicMock
|
||||
repository_client.repositories = {}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_default_branch_deletion_disabled.repository_default_branch_deletion_disabled.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_default_branch_deletion_disabled.repository_default_branch_deletion_disabled import (
|
||||
repository_default_branch_deletion_disabled,
|
||||
)
|
||||
|
||||
check = repository_default_branch_deletion_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_allow_branch_deletion_enabled(self):
|
||||
repository_client = mock.MagicMock
|
||||
repo_name = "repo1"
|
||||
default_branch = "main"
|
||||
repository_client.repositories = {
|
||||
1: Repo(
|
||||
id=1,
|
||||
name=repo_name,
|
||||
full_name="account-name/repo1",
|
||||
default_branch=default_branch,
|
||||
default_branch_deletion=True,
|
||||
private=False,
|
||||
securitymd=False,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_default_branch_deletion_disabled.repository_default_branch_deletion_disabled.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_default_branch_deletion_disabled.repository_default_branch_deletion_disabled import (
|
||||
repository_default_branch_deletion_disabled,
|
||||
)
|
||||
|
||||
check = repository_default_branch_deletion_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "repo1"
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Repository {repo_name} does allow default branch deletion."
|
||||
)
|
||||
|
||||
def test_allow_branch_deletion_disabled(self):
|
||||
repository_client = mock.MagicMock
|
||||
repo_name = "repo1"
|
||||
default_branch = "main"
|
||||
repository_client.repositories = {
|
||||
1: Repo(
|
||||
id=1,
|
||||
name=repo_name,
|
||||
full_name="account-name/repo1",
|
||||
private=False,
|
||||
default_branch=default_branch,
|
||||
default_branch_deletion=False,
|
||||
securitymd=True,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_default_branch_deletion_disabled.repository_default_branch_deletion_disabled.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_default_branch_deletion_disabled.repository_default_branch_deletion_disabled import (
|
||||
repository_default_branch_deletion_disabled,
|
||||
)
|
||||
|
||||
check = repository_default_branch_deletion_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "repo1"
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Repository {repo_name} does deny default branch deletion."
|
||||
)
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.github.services.repository.repository_service import Repo
|
||||
from tests.providers.github.github_fixtures import set_mocked_github_provider
|
||||
|
||||
|
||||
class Test_repository_default_branch_disallows_force_push_test:
|
||||
def test_no_repositories(self):
|
||||
repository_client = mock.MagicMock
|
||||
repository_client.repositories = {}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_default_branch_disallows_force_push.repository_default_branch_disallows_force_push.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_default_branch_disallows_force_push.repository_default_branch_disallows_force_push import (
|
||||
repository_default_branch_disallows_force_push,
|
||||
)
|
||||
|
||||
check = repository_default_branch_disallows_force_push()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_allow_force_push_enabled(self):
|
||||
repository_client = mock.MagicMock
|
||||
repo_name = "repo1"
|
||||
default_branch = "main"
|
||||
repository_client.repositories = {
|
||||
1: Repo(
|
||||
id=1,
|
||||
name=repo_name,
|
||||
full_name="account-name/repo1",
|
||||
default_branch=default_branch,
|
||||
allow_force_pushes=True,
|
||||
private=False,
|
||||
securitymd=False,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_default_branch_disallows_force_push.repository_default_branch_disallows_force_push.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_default_branch_disallows_force_push.repository_default_branch_disallows_force_push import (
|
||||
repository_default_branch_disallows_force_push,
|
||||
)
|
||||
|
||||
check = repository_default_branch_disallows_force_push()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "repo1"
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Repository {repo_name} does allow force push."
|
||||
)
|
||||
|
||||
def test_allow_force_push_disabled(self):
|
||||
repository_client = mock.MagicMock
|
||||
repo_name = "repo1"
|
||||
default_branch = "main"
|
||||
repository_client.repositories = {
|
||||
1: Repo(
|
||||
id=1,
|
||||
name=repo_name,
|
||||
full_name="account-name/repo1",
|
||||
private=False,
|
||||
default_branch=default_branch,
|
||||
allow_force_pushes=False,
|
||||
securitymd=True,
|
||||
),
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_github_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.github.services.repository.repository_default_branch_disallows_force_push.repository_default_branch_disallows_force_push.repository_client",
|
||||
new=repository_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.github.services.repository.repository_default_branch_disallows_force_push.repository_default_branch_disallows_force_push import (
|
||||
repository_default_branch_disallows_force_push,
|
||||
)
|
||||
|
||||
check = repository_default_branch_disallows_force_push()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == 1
|
||||
assert result[0].resource_name == "repo1"
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Repository {repo_name} does deny force push."
|
||||
)
|
||||
Loaded 100 of 128 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user