-
Notifications
You must be signed in to change notification settings - Fork 17.2k
Implement is_authorized_variable in AWS auth manager
#35804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, | ||
| # software distributed under the License is distributed on an | ||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, | ||
| # software distributed under the License is distributed on an | ||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
| from __future__ import annotations | ||
|
|
||
| from enum import Enum | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| if TYPE_CHECKING: | ||
| from airflow.auth.managers.base_auth_manager import ResourceMethod | ||
|
|
||
| AVP_PREFIX_ENTITIES = "Airflow::" | ||
|
|
||
|
|
||
| class AvpEntities(Enum): | ||
| """Enum of Amazon Verified Permissions entities.""" | ||
|
|
||
| ACTION = "Action" | ||
| ROLE = "Role" | ||
| VARIABLE = "Variable" | ||
| USER = "User" | ||
|
|
||
|
|
||
| def get_entity_type(resource_type: AvpEntities) -> str: | ||
| """ | ||
| Return entity type. | ||
|
|
||
| :param resource_type: Resource type. | ||
|
|
||
| Example: Airflow::Action, Airflow::Role, Airflow::Variable, Airflow::User. | ||
| """ | ||
| return AVP_PREFIX_ENTITIES + resource_type.value | ||
|
|
||
|
|
||
| def get_action_id(resource_type: AvpEntities, method: ResourceMethod): | ||
| """ | ||
| Return action id. | ||
|
|
||
| Convention for action ID is <resource_type>::<method>. Example: Variable::GET. | ||
|
|
||
| :param resource_type: Resource type. | ||
| :param method: Resource method. | ||
| """ | ||
| return f"{resource_type.value}::{method}" | ||
126 changes: 126 additions & 0 deletions
126
airflow/providers/amazon/aws/auth_manager/avp/facade.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, | ||
| # software distributed under the License is distributed on an | ||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
| from __future__ import annotations | ||
|
|
||
| from functools import cached_property | ||
| from typing import TYPE_CHECKING, Callable | ||
|
|
||
| from airflow.configuration import conf | ||
| from airflow.exceptions import AirflowException | ||
| from airflow.providers.amazon.aws.auth_manager.avp.entities import AvpEntities, get_action_id, get_entity_type | ||
| from airflow.providers.amazon.aws.auth_manager.constants import ( | ||
| CONF_AVP_POLICY_STORE_ID_KEY, | ||
| CONF_CONN_ID_KEY, | ||
| CONF_SECTION_NAME, | ||
| ) | ||
| from airflow.providers.amazon.aws.hooks.verified_permissions import VerifiedPermissionsHook | ||
| from airflow.utils.log.logging_mixin import LoggingMixin | ||
|
|
||
| if TYPE_CHECKING: | ||
| from airflow.auth.managers.base_auth_manager import ResourceMethod | ||
| from airflow.providers.amazon.aws.auth_manager.user import AwsAuthManagerUser | ||
|
|
||
|
|
||
| class AwsAuthManagerAmazonVerifiedPermissionsFacade(LoggingMixin): | ||
|
o-nikolas marked this conversation as resolved.
|
||
| """ | ||
| Facade for Amazon Verified Permissions. | ||
|
|
||
| Used as an intermediate layer between AWS auth manager and Amazon Verified Permissions. | ||
| """ | ||
|
|
||
| @cached_property | ||
| def avp_client(self): | ||
| """Build Amazon Verified Permissions client.""" | ||
| aws_conn_id = conf.get(CONF_SECTION_NAME, CONF_CONN_ID_KEY) | ||
| return VerifiedPermissionsHook(aws_conn_id=aws_conn_id).conn | ||
|
|
||
| @cached_property | ||
| def avp_policy_store_id(self): | ||
| """Get the Amazon Verified Permission policy store ID from config.""" | ||
| return conf.get_mandatory_value(CONF_SECTION_NAME, CONF_AVP_POLICY_STORE_ID_KEY) | ||
|
|
||
| def is_authorized( | ||
| self, | ||
| *, | ||
| method: ResourceMethod, | ||
| entity_type: AvpEntities, | ||
| user: AwsAuthManagerUser, | ||
| entity_id: str | None = None, | ||
| entity_fetcher: Callable | None = None, | ||
| ) -> bool: | ||
| """ | ||
| Make an authorization decision against Amazon Verified Permissions. | ||
|
|
||
| Check whether the user has permissions to access given resource. | ||
|
|
||
| :param method: the method to perform | ||
| :param entity_type: the entity type the user accesses | ||
| :param user: the user | ||
| :param entity_id: the entity ID the user accesses. If not provided, all entities of the type will be | ||
| considered. | ||
| :param entity_fetcher: function that returns list of entities to be passed to Amazon Verified | ||
| Permissions. Only needed if some resource properties are used in the policies (e.g. DAG folder). | ||
| """ | ||
| entity_list = self._get_user_role_entities(user) | ||
| if entity_fetcher and entity_id: | ||
| # If no entity ID is provided, there is no need to fetch entities. | ||
| # We just need to know whether the user has permissions to access all resources from this type | ||
| entity_list += entity_fetcher() | ||
|
|
||
| self.log.debug( | ||
| "Making authorization request for user=%s, method=%s, entity_type=%s, entity_id=%s", | ||
| user.get_id(), | ||
| method, | ||
| entity_type, | ||
| entity_id, | ||
| ) | ||
|
|
||
| resp = self.avp_client.is_authorized( | ||
| policyStoreId=self.avp_policy_store_id, | ||
| principal={"entityType": get_entity_type(AvpEntities.USER), "entityId": user.get_id()}, | ||
| action={ | ||
| "actionType": get_entity_type(AvpEntities.ACTION), | ||
| "actionId": get_action_id(entity_type, method), | ||
| }, | ||
| resource={"entityType": get_entity_type(entity_type), "entityId": entity_id or "*"}, | ||
| entities={"entityList": entity_list}, | ||
| ) | ||
|
|
||
| self.log.debug("Authorization response: %s", resp) | ||
|
|
||
| if len(resp.get("errors", [])) > 0: | ||
| self.log.error( | ||
| "Error occurred while making an authorization decision. Errors: %s", resp["errors"] | ||
| ) | ||
| raise AirflowException("Error occurred while making an authorization decision.") | ||
|
|
||
| return resp["decision"] == "ALLOW" | ||
|
|
||
| @staticmethod | ||
| def _get_user_role_entities(user: AwsAuthManagerUser) -> list[dict]: | ||
| user_entity = { | ||
| "identifier": {"entityType": get_entity_type(AvpEntities.USER), "entityId": user.get_id()}, | ||
| "parents": [ | ||
| {"entityType": get_entity_type(AvpEntities.ROLE), "entityId": group} | ||
| for group in user.get_groups() | ||
| ], | ||
| } | ||
| role_entities = [ | ||
| {"identifier": {"entityType": get_entity_type(AvpEntities.ROLE), "entityId": group}} | ||
| for group in user.get_groups() | ||
| ] | ||
| return [user_entity, *role_entities] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
airflow/providers/amazon/aws/hooks/verified_permissions.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, | ||
| # software distributed under the License is distributed on an | ||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| from airflow.providers.amazon.aws.hooks.base_aws import AwsGenericHook | ||
|
|
||
| if TYPE_CHECKING: | ||
| from mypy_boto3_verifiedpermissions.client import VerifiedPermissionsClient # noqa | ||
|
|
||
|
|
||
| class VerifiedPermissionsHook(AwsGenericHook["VerifiedPermissionsClient"]): | ||
| """ | ||
| Interact with Amazon Verified Permissions. | ||
|
|
||
| Provide thin wrapper around :external+boto3:py:class:`boto3.client("verifiedpermissions") | ||
| <VerifiedPermissions.Client>`. | ||
|
|
||
| Additional arguments (such as ``aws_conn_id``) may be specified and | ||
| are passed down to the underlying AwsBaseHook. | ||
|
|
||
| .. seealso:: | ||
| - :class:`airflow.providers.amazon.aws.hooks.base_aws.AwsBaseHook` | ||
| - `Amazon Appflow API Reference <https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/Welcome.html>`__ | ||
| """ | ||
|
|
||
| def __init__(self, *args, **kwargs) -> None: | ||
| kwargs["client_type"] = "verifiedpermissions" | ||
| super().__init__(*args, **kwargs) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.