Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
waddamski authored Feb 12, 2025
2 parents 7e5fb10 + 777ca53 commit 1e5171d
Show file tree
Hide file tree
Showing 13 changed files with 734 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests_sdk_ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@2654679fe7f7c29875c669398a8ec0791b8a64a1
uses: ruby/setup-ruby@d781c1b4ed31764801bfae177617bb0446f5ef8d
with:
ruby-version: ${{ matrix.ruby-version }}
- name: Set up Python 3.8
Expand Down
86 changes: 85 additions & 1 deletion IMPLEMENTATION_COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8232,6 +8232,91 @@
- [ ] validate_resource_policy
</details>

## securityhub
<details>
<summary>2% implemented</summary>

- [ ] accept_administrator_invitation
- [ ] accept_invitation
- [ ] batch_delete_automation_rules
- [ ] batch_disable_standards
- [ ] batch_enable_standards
- [ ] batch_get_automation_rules
- [ ] batch_get_configuration_policy_associations
- [ ] batch_get_security_controls
- [ ] batch_get_standards_control_associations
- [X] batch_import_findings
- [ ] batch_update_automation_rules
- [ ] batch_update_findings
- [ ] batch_update_standards_control_associations
- [ ] create_action_target
- [ ] create_automation_rule
- [ ] create_configuration_policy
- [ ] create_finding_aggregator
- [ ] create_insight
- [ ] create_members
- [ ] decline_invitations
- [ ] delete_action_target
- [ ] delete_configuration_policy
- [ ] delete_finding_aggregator
- [ ] delete_insight
- [ ] delete_invitations
- [ ] delete_members
- [ ] describe_action_targets
- [ ] describe_hub
- [ ] describe_organization_configuration
- [ ] describe_products
- [ ] describe_standards
- [ ] describe_standards_controls
- [ ] disable_import_findings_for_product
- [ ] disable_organization_admin_account
- [ ] disable_security_hub
- [ ] disassociate_from_administrator_account
- [ ] disassociate_from_master_account
- [ ] disassociate_members
- [ ] enable_import_findings_for_product
- [ ] enable_organization_admin_account
- [ ] enable_security_hub
- [ ] get_administrator_account
- [ ] get_configuration_policy
- [ ] get_configuration_policy_association
- [ ] get_enabled_standards
- [ ] get_finding_aggregator
- [ ] get_finding_history
- [X] get_findings
- [ ] get_insight_results
- [ ] get_insights
- [ ] get_invitations_count
- [ ] get_master_account
- [ ] get_members
- [ ] get_security_control_definition
- [ ] invite_members
- [ ] list_automation_rules
- [ ] list_configuration_policies
- [ ] list_configuration_policy_associations
- [ ] list_enabled_products_for_import
- [ ] list_finding_aggregators
- [ ] list_invitations
- [ ] list_members
- [ ] list_organization_admin_accounts
- [ ] list_security_control_definitions
- [ ] list_standards_control_associations
- [ ] list_tags_for_resource
- [ ] start_configuration_policy_association
- [ ] start_configuration_policy_disassociation
- [ ] tag_resource
- [ ] untag_resource
- [ ] update_action_target
- [ ] update_configuration_policy
- [ ] update_finding_aggregator
- [ ] update_findings
- [ ] update_insight
- [ ] update_organization_configuration
- [ ] update_security_control
- [ ] update_security_hub_configuration
- [ ] update_standards_control
</details>

## service-quotas
<details>
<summary>10% implemented</summary>
Expand Down Expand Up @@ -9624,7 +9709,6 @@
- savingsplans
- schemas
- security-ir
- securityhub
- securitylake
- serverlessrepo
- servicecatalog
Expand Down
112 changes: 112 additions & 0 deletions docs/docs/services/securityhub.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
.. _implementedservice_securityhub:

.. |start-h3| raw:: html

<h3>

.. |end-h3| raw:: html

</h3>

===========
securityhub
===========

.. autoclass:: moto.securityhub.models.SecurityHubBackend

|start-h3| Implemented features for this service |end-h3|

- [ ] accept_administrator_invitation
- [ ] accept_invitation
- [ ] batch_delete_automation_rules
- [ ] batch_disable_standards
- [ ] batch_enable_standards
- [ ] batch_get_automation_rules
- [ ] batch_get_configuration_policy_associations
- [ ] batch_get_security_controls
- [ ] batch_get_standards_control_associations
- [X] batch_import_findings

Import findings in batch to SecurityHub.

Args:
findings: List of finding dictionaries to import

Returns:
Tuple of (failed_count, success_count, failed_findings)


- [ ] batch_update_automation_rules
- [ ] batch_update_findings
- [ ] batch_update_standards_control_associations
- [ ] create_action_target
- [ ] create_automation_rule
- [ ] create_configuration_policy
- [ ] create_finding_aggregator
- [ ] create_insight
- [ ] create_members
- [ ] decline_invitations
- [ ] delete_action_target
- [ ] delete_configuration_policy
- [ ] delete_finding_aggregator
- [ ] delete_insight
- [ ] delete_invitations
- [ ] delete_members
- [ ] describe_action_targets
- [ ] describe_hub
- [ ] describe_organization_configuration
- [ ] describe_products
- [ ] describe_standards
- [ ] describe_standards_controls
- [ ] disable_import_findings_for_product
- [ ] disable_organization_admin_account
- [ ] disable_security_hub
- [ ] disassociate_from_administrator_account
- [ ] disassociate_from_master_account
- [ ] disassociate_members
- [ ] enable_import_findings_for_product
- [ ] enable_organization_admin_account
- [ ] enable_security_hub
- [ ] get_administrator_account
- [ ] get_configuration_policy
- [ ] get_configuration_policy_association
- [ ] get_enabled_standards
- [ ] get_finding_aggregator
- [ ] get_finding_history
- [X] get_findings

Returns findings based on optional filters and sort criteria.


- [ ] get_insight_results
- [ ] get_insights
- [ ] get_invitations_count
- [ ] get_master_account
- [ ] get_members
- [ ] get_security_control_definition
- [ ] invite_members
- [ ] list_automation_rules
- [ ] list_configuration_policies
- [ ] list_configuration_policy_associations
- [ ] list_enabled_products_for_import
- [ ] list_finding_aggregators
- [ ] list_invitations
- [ ] list_members
- [ ] list_organization_admin_accounts
- [ ] list_security_control_definitions
- [ ] list_standards_control_associations
- [ ] list_tags_for_resource
- [ ] start_configuration_policy_association
- [ ] start_configuration_policy_disassociation
- [ ] tag_resource
- [ ] untag_resource
- [ ] update_action_target
- [ ] update_configuration_policy
- [ ] update_finding_aggregator
- [ ] update_findings
- [ ] update_insight
- [ ] update_organization_configuration
- [ ] update_security_control
- [ ] update_security_hub_configuration
- [ ] update_standards_control

1 change: 1 addition & 0 deletions moto/backend_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
("scheduler", re.compile("https?://scheduler\\.(.+)\\.amazonaws\\.com")),
("sdb", re.compile("https?://sdb\\.(.+)\\.amazonaws\\.com")),
("secretsmanager", re.compile("https?://secretsmanager\\.(.+)\\.amazonaws\\.com")),
("securityhub", re.compile("https?://securityhub\\.(.+)\\.amazonaws\\.com")),
(
"servicediscovery",
re.compile("https?://(data-)?servicediscovery\\.(.+)\\.amazonaws\\.com"),
Expand Down
59 changes: 41 additions & 18 deletions moto/cognitoidp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ def __init__(
self.groups: Dict[str, CognitoIdpGroup] = OrderedDict()
self.users: Dict[str, CognitoIdpUser] = OrderedDict()
self.resource_servers: Dict[str, CognitoResourceServer] = OrderedDict()
self.refresh_tokens: Dict[str, Optional[Tuple[str, str]]] = {}
self.refresh_tokens: Dict[str, Optional[Tuple[str, str, str]]] = {}
self.access_tokens: Dict[str, Tuple[str, str]] = {}
self.id_tokens: Dict[str, Tuple[str, str]] = {}

Expand Down Expand Up @@ -534,6 +534,7 @@ def create_jwt(
"token_use": token_use,
"auth_time": now,
"exp": now + expires_in,
"jti": str(random.uuid4()),
}
username_is_email = "email" in self.extended_config.get(
"UsernameAttributes", []
Expand Down Expand Up @@ -574,8 +575,14 @@ def add_custom_attributes(self, custom_attributes: List[Dict[str, str]]) -> None
for attribute in attributes:
self.schema_attributes[attribute.name] = attribute

def create_id_token(self, client_id: str, username: str) -> Tuple[str, int]:
def create_id_token(
self, client_id: str, username: str, origin_jti: str
) -> Tuple[str, int]:
"""
:returns: (id_token, expires_in)
"""
extra_data = self.get_user_extra_data_by_client_id(client_id, username)
extra_data["origin_jti"] = origin_jti
user = self._get_user(username)
for attr in user.attributes:
if attr["Name"].startswith("custom:"):
Expand All @@ -588,13 +595,24 @@ def create_id_token(self, client_id: str, username: str) -> Tuple[str, int]:
self.id_tokens[id_token] = (client_id, username)
return id_token, expires_in

def create_refresh_token(self, client_id: str, username: str) -> str:
def create_refresh_token(self, client_id: str, username: str) -> Tuple[str, str]:
"""
:returns: (refresh_token, origin_jti)
"""
refresh_token = str(random.uuid4())
self.refresh_tokens[refresh_token] = (client_id, username)
return refresh_token
origin_jti = str(random.uuid4())
self.refresh_tokens[refresh_token] = (client_id, username, origin_jti)
return refresh_token, origin_jti

def create_access_token(self, client_id: str, username: str) -> Tuple[str, int]:
extra_data = {}
def create_access_token(
self, client_id: str, username: str, origin_jti: str
) -> Tuple[str, int]:
"""
:returns: (access_token, expires_in)
"""
extra_data: Dict[str, Any] = {
"origin_jti": origin_jti,
}
user = self._get_user(username)
if len(user.groups) > 0:
extra_data["cognito:groups"] = [group.group_name for group in user.groups]
Expand All @@ -611,12 +629,14 @@ def create_tokens_from_refresh_token(
res = self.refresh_tokens[refresh_token]
if res is None:
raise NotAuthorizedError(refresh_token)
client_id, username = res
client_id, username, origin_jti = res
if not username:
raise NotAuthorizedError(refresh_token)

access_token, expires_in = self.create_access_token(client_id, username)
id_token, _ = self.create_id_token(client_id, username)
access_token, expires_in = self.create_access_token(
client_id, username, origin_jti=origin_jti
)
id_token, _ = self.create_id_token(client_id, username, origin_jti=origin_jti)
return access_token, id_token, expires_in

def get_user_extra_data_by_client_id(
Expand All @@ -640,11 +660,10 @@ def sign_out(self, username: str) -> None:
for token, token_tuple in list(self.refresh_tokens.items()):
if token_tuple is None:
continue
_, logged_in_user = token_tuple
_, logged_in_user, _ = token_tuple
if username == logged_in_user:
self.refresh_tokens[token] = None
for access_token, token_tuple in list(self.access_tokens.items()):
_, logged_in_user = token_tuple
for access_token, (_, logged_in_user) in list(self.access_tokens.items()):
if username == logged_in_user:
self.access_tokens.pop(access_token)

Expand Down Expand Up @@ -1427,7 +1446,7 @@ def _log_user_in(
client: CognitoIdpUserPoolClient,
username: str,
) -> Dict[str, Dict[str, Any]]:
refresh_token = user_pool.create_refresh_token(client.id, username)
refresh_token, _ = user_pool.create_refresh_token(client.id, username)
access_token, id_token, expires_in = user_pool.create_tokens_from_refresh_token(
refresh_token
)
Expand Down Expand Up @@ -2083,11 +2102,15 @@ def initiate_auth(
"Session": session,
}

access_token, expires_in = user_pool.create_access_token(
new_refresh_token, origin_jti = user_pool.create_refresh_token(
client_id, username
)
id_token, _ = user_pool.create_id_token(client_id, username)
new_refresh_token = user_pool.create_refresh_token(client_id, username)
access_token, expires_in = user_pool.create_access_token(
client_id, username, origin_jti=origin_jti
)
id_token, _ = user_pool.create_id_token(
client_id, username, origin_jti=origin_jti
)

return {
"AuthenticationResult": {
Expand All @@ -2107,7 +2130,7 @@ def initiate_auth(
if res is None:
raise NotAuthorizedError("Refresh Token has been revoked")

client_id, username = res
client_id, username, _ = res
if not username:
raise ResourceNotFoundError(username)

Expand Down
1 change: 1 addition & 0 deletions moto/securityhub/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .models import securityhub_backends # noqa: F401
21 changes: 21 additions & 0 deletions moto/securityhub/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Exceptions raised by the securityhub service."""

from moto.core.exceptions import JsonRESTError


class SecurityHubClientError(JsonRESTError):
code = 400


class _InvalidOperationException(SecurityHubClientError):
def __init__(self, error_type: str, op: str, msg: str):
super().__init__(
error_type,
"An error occurred (%s) when calling the %s operation: %s"
% (error_type, op, msg),
)


class InvalidInputException(_InvalidOperationException):
def __init__(self, op: str, msg: str):
super().__init__("InvalidInputException", op, msg)
Loading

0 comments on commit 1e5171d

Please sign in to comment.