Skip to content

Commit

Permalink
CDPCAM-83 Add cross-account role actions validation for Azure (#61)
Browse files Browse the repository at this point in the history
* CDPCAM-83 Add cross-account role actions validation for Azure

Signed-off-by: Mahendra Korepu <[email protected]>
  • Loading branch information
mahendra-rk authored Nov 17, 2021
1 parent 1b87cc1 commit 6f151ad
Show file tree
Hide file tree
Showing 5 changed files with 568 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cdpctl/templates/config_azure.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ env:
## The Ranger Audit Identity to be used for the environment
# example: azure-cdp-ranger_audit-identity
ranger_audit: {{ info['env:azure:role:name:ranger_audit']|default("", true) }}

## The Cloudera Management Console Operator Identity to be used for the environment
# example: azure-cdp-cross_account-identity
cross_account: {{ info['env:azure:role:name:cross_account']|default("", true) }}
storage:
## The Storage Account used for the environment
name: {{ info['env:azure:storage:name']|default("", true) }}
Expand Down
86 changes: 86 additions & 0 deletions cdpctl/validation/infra/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,89 @@ def azure_assumer_required_resource_group_actions() -> List[str]:
"Microsoft.Support/operationsstatus/read",
"Microsoft.Support/operations/read",
]


@pytest.fixture
def azure_cross_account_required_resource_group_actions() -> List[str]:
"""Get the Azure actions needed for the cross account identity."""
return [
"Microsoft.Storage/storageAccounts/read",
"Microsoft.Storage/storageAccounts/write",
"Microsoft.Storage/storageAccounts/blobServices/write",
"Microsoft.Storage/storageAccounts/blobServices/containers/delete",
"Microsoft.Storage/storageAccounts/blobServices/containers/read",
"Microsoft.Storage/storageAccounts/blobServices/containers/write",
"Microsoft.Storage/storageAccounts/fileServices/write",
"Microsoft.Storage/storageAccounts/listkeys/action",
"Microsoft.Storage/storageAccounts/regeneratekey/action",
"Microsoft.Storage/storageAccounts/delete",
"Microsoft.Storage/locations/deleteVirtualNetworkOrSubnets/action",
"Microsoft.Network/virtualNetworks/read",
"Microsoft.Network/virtualNetworks/write",
"Microsoft.Network/virtualNetworks/delete",
"Microsoft.Network/virtualNetworks/subnets/read",
"Microsoft.Network/virtualNetworks/subnets/write",
"Microsoft.Network/virtualNetworks/subnets/delete",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/publicIPAddresses/read",
"Microsoft.Network/publicIPAddresses/write",
"Microsoft.Network/publicIPAddresses/delete",
"Microsoft.Network/publicIPAddresses/join/action",
"Microsoft.Network/networkInterfaces/read",
"Microsoft.Network/networkInterfaces/write",
"Microsoft.Network/networkInterfaces/delete",
"Microsoft.Network/networkInterfaces/join/action",
"Microsoft.Network/networkInterfaces/ipconfigurations/read",
"Microsoft.Network/networkSecurityGroups/read",
"Microsoft.Network/networkSecurityGroups/write",
"Microsoft.Network/networkSecurityGroups/delete",
"Microsoft.Network/networkSecurityGroups/join/action",
"Microsoft.Network/virtualNetworks/subnets/joinViaServiceEndpoint/action",
"Microsoft.Network/loadBalancers/delete",
"Microsoft.Network/loadBalancers/read",
"Microsoft.Network/loadBalancers/write",
"Microsoft.Network/loadBalancers/backendAddressPools/join/action",
"Microsoft.Compute/availabilitySets/read",
"Microsoft.Compute/availabilitySets/write",
"Microsoft.Compute/availabilitySets/delete",
"Microsoft.Compute/disks/read",
"Microsoft.Compute/disks/write",
"Microsoft.Compute/disks/delete",
"Microsoft.Compute/images/read",
"Microsoft.Compute/images/write",
"Microsoft.Compute/images/delete",
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/write",
"Microsoft.Compute/virtualMachines/delete",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/deallocate/action",
"Microsoft.Compute/virtualMachines/powerOff/action",
"Microsoft.Compute/virtualMachines/vmSizes/read",
"Microsoft.Authorization/roleAssignments/read",
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Resources/deployments/read",
"Microsoft.Resources/deployments/write",
"Microsoft.Resources/deployments/delete",
"Microsoft.Resources/deployments/operations/read",
"Microsoft.Resources/deployments/operationstatuses/read",
"Microsoft.Resources/deployments/exportTemplate/action",
"Microsoft.Resources/subscriptions/read",
"Microsoft.ManagedIdentity/userAssignedIdentities/read",
"Microsoft.ManagedIdentity/userAssignedIdentities/assign/action",
"Microsoft.DBforPostgreSQL/servers/write",
"Microsoft.DBforPostgreSQL/servers/delete",
"Microsoft.DBforPostgreSQL/servers/virtualNetworkRules/write",
"Microsoft.Resources/deployments/cancel/action",
]


@pytest.fixture
def azure_cross_account_required_resource_group_data_actions() -> List[str]:
"""Get the Azure data actions needed for the cross account identity."""
return [
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read",
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write",
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete",
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/add/action",
]
178 changes: 178 additions & 0 deletions cdpctl/validation/infra/validate_azure_cross_account_identity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/usr/bin/env python3
###
# CLOUDERA CDP Control (cdpctl)
#
# (C) Cloudera, Inc. 2021-2021
# All rights reserved.
#
# Applicable Open Source License: GNU AFFERO GENERAL PUBLIC LICENSE
#
# NOTE: Cloudera open source products are modular software products
# made up of hundreds of individual components, each of which was
# individually copyrighted. Each Cloudera open source product is a
# collective work under U.S. Copyright Law. Your license to use the
# collective work is as provided in your written agreement with
# Cloudera. Used apart from the collective work, this file is
# licensed for your use pursuant to the open source license
# identified above.
#
# This code is provided to you pursuant a written agreement with
# (i) Cloudera, Inc. or (ii) a third-party authorized to distribute
# this code. If you do not have a written agreement with Cloudera nor
# with an authorized and properly licensed third party, you do not
# have any rights to access nor to use this code.
#
# Absent a written agreement with Cloudera, Inc. (“Cloudera”) to the
# contrary, A) CLOUDERA PROVIDES THIS CODE TO YOU WITHOUT WARRANTIES OF ANY
# KIND; (B) CLOUDERA DISCLAIMS ANY AND ALL EXPRESS AND IMPLIED
# WARRANTIES WITH RESPECT TO THIS CODE, INCLUDING BUT NOT LIMITED TO
# IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE; (C) CLOUDERA IS NOT LIABLE TO YOU,
# AND WILL NOT DEFEND, INDEMNIFY, NOR HOLD YOU HARMLESS FOR ANY CLAIMS
# ARISING FROM OR RELATED TO THE CODE; AND (D)WITH RESPECT TO YOUR EXERCISE
# OF ANY RIGHTS GRANTED TO YOU FOR THE CODE, CLOUDERA IS NOT LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
# CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, DAMAGES
# RELATED TO LOST REVENUE, LOST PROFITS, LOSS OF INCOME, LOSS OF
# BUSINESS ADVANTAGE OR UNAVAILABILITY, OR LOSS OR CORRUPTION OF
# DATA.
#
# Source File Name: validate_azure_cross_account_identity.py
###
"""Validation of Azure Cross Account Identity."""
# "Cross Account Identity" is equivalent to "Cloudera Management Console Operator Identity" # noqa: D401,E501
# Customer facing text changed to "Cloudera Management Console Operator Identity" to
# match the documentation

from typing import Any, Dict, List

import pytest
from azure.mgmt.authorization import AuthorizationManagementClient
from azure.mgmt.resource import ResourceManagementClient

from cdpctl.validation import fail, get_config_value
from cdpctl.validation.azure_utils import (
check_for_actions,
get_client,
get_resource_group_scope,
get_role_assignments,
)
from cdpctl.validation.infra.issues import (
AZURE_IDENTITY_MISSING_ACTIONS_FOR_LOCATION,
AZURE_IDENTITY_MISSING_DATA_ACTIONS_FOR_LOCATION,
)

_cross_account_info = {}


@pytest.fixture(name="cross_account_info")
def cross_account_info_fixture():
"""Get the info for the Cross Account Identity."""
return _cross_account_info


@pytest.fixture(autouse=True, name="resource_client")
def resource_client_fixture(config: Dict[str, Any]) -> ResourceManagementClient:
"""Return an Azure Resource Client."""
return get_client("resource", config)


@pytest.fixture(autouse=True, name="auth_client")
def auth_client_fixture(config: Dict[str, Any]) -> AuthorizationManagementClient:
"""Return an Azure Auth Client."""
return get_client("auth", config)


@pytest.mark.azure
@pytest.mark.infra
def azure_cross_account_identity_exists_validation(
config: Dict[str, Any],
auth_client: AuthorizationManagementClient,
resource_client: ResourceManagementClient,
) -> None: # pragma: no cover
"""Azure Cloudera Management Console Operator Identity exists."""

_cross_account_info["sub_id"] = get_config_value(
config=config, key="infra:azure:subscription_id"
)
_cross_account_info["rg_name"] = get_config_value(
config=config, key="infra:azure:metagroup:name"
)
_cross_account_info["name"] = get_config_value(
config=config, key="env:azure:role:name:cross_account"
)

_cross_account_info["assignments"] = get_role_assignments(
auth_client=auth_client,
resource_client=resource_client,
identity_name=_cross_account_info["name"],
subscription_id=_cross_account_info["sub_id"],
resource_group=_cross_account_info["rg_name"],
)


@pytest.mark.azure
@pytest.mark.infra
@pytest.mark.dependency(depends=["azure_cross_account_identity_exists_validation"])
def azure_cross_account_rg_actions_validation(
auth_client: AuthorizationManagementClient,
azure_cross_account_required_resource_group_actions: List[str],
cross_account_info,
) -> None: # pragma: no cover
"""Cloudera Management Console Operator Identity has the necessary actions on the resource group.""" # noqa: D401,E501

proper_scope = get_resource_group_scope(
subscription_id=cross_account_info["sub_id"],
resource_group=cross_account_info["rg_name"],
)

missing_actions, _ = check_for_actions(
auth_client=auth_client,
role_assigments=cross_account_info["assignments"],
proper_scope=proper_scope,
required_actions=azure_cross_account_required_resource_group_actions,
required_data_actions=[],
)

if missing_actions:
fail(
AZURE_IDENTITY_MISSING_ACTIONS_FOR_LOCATION,
subjects=[
cross_account_info["name"],
proper_scope, # noqa: E501
],
resources=missing_actions,
)


@pytest.mark.azure
@pytest.mark.infra
@pytest.mark.dependency(depends=["azure_cross_account_identity_exists_validation"])
def azure_cross_account_rg_data_actions_validation(
auth_client: AuthorizationManagementClient,
azure_cross_account_required_resource_group_data_actions: List[str],
cross_account_info,
) -> None: # pragma: no cover
"""Cloudera Management Console Operator Identity has the necessary data actions on the resource group.""" # noqa: D401,E501

proper_scope = get_resource_group_scope(
subscription_id=cross_account_info["sub_id"],
resource_group=cross_account_info["rg_name"],
)

_, missing_data_actions = check_for_actions(
auth_client=auth_client,
role_assigments=cross_account_info["assignments"],
proper_scope=proper_scope,
required_actions=[],
required_data_actions=azure_cross_account_required_resource_group_data_actions,
)
if missing_data_actions:
fail(
AZURE_IDENTITY_MISSING_DATA_ACTIONS_FOR_LOCATION,
subjects=[
cross_account_info["name"],
proper_scope, # noqa: E501
],
resources=missing_data_actions,
)
2 changes: 2 additions & 0 deletions tests/validation/infra/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"""Import validation fixtures."""
from cdpctl.validation.infra.conftest import (
autoscaling_resources_needed_actions,
azure_cross_account_required_resource_group_actions,
azure_cross_account_required_resource_group_data_actions,
azure_data_required_actions,
azure_data_required_data_actions,
cdp_cidrs,
Expand Down
Loading

0 comments on commit 6f151ad

Please sign in to comment.