Skip to content

Commit

Permalink
[azure][feat] Add WebApp (#2164)
Browse files Browse the repository at this point in the history
  • Loading branch information
aquamatthias authored Aug 9, 2024
1 parent 00b9581 commit 4b9b718
Show file tree
Hide file tree
Showing 26 changed files with 2,723 additions and 297 deletions.
23 changes: 13 additions & 10 deletions plugins/azure/fix_plugin_azure/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Any, Optional, Type, List, Dict

from azure.core.utils import CaseInsensitiveDict

from fix_plugin_azure.azure_client import MicrosoftClient, RestApiSpec
from fix_plugin_azure.config import AzureConfig, AzureCredentials
from fix_plugin_azure.resource.authorization import resources as authorization_resources
Expand All @@ -22,27 +23,28 @@
resources as compute_resources,
)
from fix_plugin_azure.resource.containerservice import resources as aks_resources
from fix_plugin_azure.resource.security import resources as security_resources
from fix_plugin_azure.resource.keyvault import resources as keyvault_resources
from fix_plugin_azure.resource.microsoft_graph import (
MicrosoftGraphOrganization,
resources as graph_resources,
MicrosoftGraphOrganizationRoot,
)
from fix_plugin_azure.resource.monitor import resources as monitor_resources
from fix_plugin_azure.resource.mysql import AzureMysqlServerType, resources as mysql_resources
from fix_plugin_azure.resource.network import (
AzureExpressRoutePortsLocation,
AzureNetworkVirtualApplianceSku,
AzureNetworkUsage,
resources as network_resources,
)
from fix_plugin_azure.resource.mysql import AzureMysqlServerType, resources as mysql_resources
from fix_plugin_azure.resource.keyvault import resources as keyvault_resources
from fix_plugin_azure.resource.sql_server import resources as sql_resources
from fix_plugin_azure.resource.postgresql import (
AzurePostgresqlServerType,
resources as postgresql_resources,
)
from fix_plugin_azure.resource.security import resources as security_resources
from fix_plugin_azure.resource.sql_server import resources as sql_resources
from fix_plugin_azure.resource.storage import AzureStorageAccountUsage, AzureStorageSku, resources as storage_resources
from fix_plugin_azure.resource.web import resources as web_resources
from fixlib.baseresources import Cloud, GraphRoot, BaseAccount, BaseRegion
from fixlib.core.actions import CoreFeedback, ErrorAccumulator
from fixlib.graph import Graph
Expand All @@ -61,17 +63,18 @@ def resource_with_params(clazz: Type[MicrosoftResource], param: str) -> bool:

subscription_resources: List[Type[MicrosoftResource]] = (
base_resources
+ aks_resources
+ authorization_resources
+ compute_resources
+ keyvault_resources
+ monitor_resources
+ mysql_resources
+ network_resources
+ aks_resources
+ postgresql_resources
+ security_resources
+ storage_resources
+ sql_resources
+ mysql_resources
+ postgresql_resources
+ monitor_resources
+ keyvault_resources
+ storage_resources
+ web_resources
)
all_resources = subscription_resources + graph_resources # defines all resource kinds. used in model check

Expand Down
38 changes: 37 additions & 1 deletion plugins/azure/fix_plugin_azure/resource/authorization.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
from datetime import datetime
from typing import ClassVar, Dict, Optional, List, Type

Expand All @@ -8,6 +9,7 @@
MicrosoftResource,
GraphBuilder,
AzureSubscription,
AzureSystemData,
)
from fix_plugin_azure.resource.microsoft_graph import (
MicrosoftGraphUser,
Expand All @@ -18,7 +20,7 @@
)
from fixlib.baseresources import BaseRole, ModelReference
from fixlib.graph import BySearchCriteria
from fixlib.json_bender import Bender, S, ForallBend
from fixlib.json_bender import Bender, S, ForallBend, Bend
from fixlib.types import Json


Expand Down Expand Up @@ -239,8 +241,42 @@ class AzureRoleDefinition(MicrosoftResource, BaseRole):
updated_on: Optional[datetime] = field(default=None, metadata={"description": "Time it was updated"})


@define(eq=False, slots=False)
class AzureManagementLock(MicrosoftResource):
kind: ClassVar[str] = "azure_management_lock"
api_spec: ClassVar[AzureResourceSpec] = AzureResourceSpec(
service="resources",
version="2020-05-01",
path="/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/locks",
path_parameters=["subscriptionId"],
query_parameters=["api-version"],
access_path="value",
expect_array=True,
)
mapping: ClassVar[Dict[str, Bender]] = {
"id": S("id"),
"tags": S("tags", default={}),
"name": S("name"),
"ctime": S("systemData", "createdAt"),
"mtime": S("systemData", "lastModifiedAt"),
"level": S("properties", "level"),
"notes": S("properties", "notes"),
"owners": S("properties") >> S("owners", default=[]) >> ForallBend(S("applicationId")),
"system_data": S("systemData") >> Bend(AzureSystemData.mapping),
}
level: Optional[str] = field(default=None, metadata={'description': 'The level of the lock. Possible values are: NotSpecified, CanNotDelete, ReadOnly. CanNotDelete means authorized users are able to read and modify the resources, but not delete. ReadOnly means authorized users can only read from a resource, but they can t modify or delete it.'}) # fmt: skip
notes: Optional[str] = field(default=None, metadata={'description': 'Notes about the lock. Maximum of 512 characters.'}) # fmt: skip
owners: Optional[List[str]] = field(default=None, metadata={"description": "The owners of the lock."})
system_data: Optional[AzureSystemData] = field(default=None, metadata={'description': 'Metadata pertaining to creation and last modification of the resource.'}) # fmt: skip

def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
resource_id = re.sub(r"/providers/Microsoft.Authorization/locks/.*$", "", self.id)
builder.add_edge(self, id=resource_id)


resources: List[Type[MicrosoftResource]] = [
AzureDenyAssignment,
AzureManagementLock,
AzureRoleAssignment,
AzureRoleDefinition,
]
54 changes: 53 additions & 1 deletion plugins/azure/fix_plugin_azure/resource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ class AzureProxyResource:


@define(eq=False, slots=False)
class AzureIdentity:
class AzureManagedServiceIdentity:
kind: ClassVar[str] = "azure_identity"
mapping: ClassVar[Dict[str, Bender]] = {
"client_id": S("clientId"),
Expand All @@ -645,15 +645,44 @@ class AzureIdentity:
user_assigned_identities: Optional[Dict[str, AzureUserAssignedIdentity]] = field(default=None, metadata={'description': 'The list of user identities associated with the resource. The user identity dictionary key references will be ARM resource ids in the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName} .'}) # fmt: skip


@define(eq=False, slots=False)
class AzureSkuCapacity:
kind: ClassVar[str] = "azure_sku_capacity"
mapping: ClassVar[Dict[str, Bender]] = {
"default": S("default"),
"elastic_maximum": S("elasticMaximum"),
"maximum": S("maximum"),
"minimum": S("minimum"),
"scale_type": S("scaleType"),
}
default: Optional[int] = field(default=None, metadata={'description': 'Default number of workers for this App Service plan SKU.'}) # fmt: skip
elastic_maximum: Optional[int] = field(default=None, metadata={'description': 'Maximum number of Elastic workers for this App Service plan SKU.'}) # fmt: skip
maximum: Optional[int] = field(default=None, metadata={'description': 'Maximum number of workers for this App Service plan SKU.'}) # fmt: skip
minimum: Optional[int] = field(default=None, metadata={'description': 'Minimum number of workers for this App Service plan SKU.'}) # fmt: skip
scale_type: Optional[str] = field(default=None, metadata={'description': 'Available scale configurations for an App Service plan.'}) # fmt: skip


@define(eq=False, slots=False)
class AzureCapability:
kind: ClassVar[str] = "azure_capability"
mapping: ClassVar[Dict[str, Bender]] = {"name": S("name"), "reason": S("reason"), "value": S("value")}
name: Optional[str] = field(default=None, metadata={"description": "Name of the SKU capability."})
reason: Optional[str] = field(default=None, metadata={"description": "Reason of the SKU capability."})
value: Optional[str] = field(default=None, metadata={"description": "Value of the SKU capability."})


@define(eq=False, slots=False)
class AzureSku:
kind: ClassVar[str] = "azure_sku"
mapping: ClassVar[Dict[str, Bender]] = {
"capabilities": S("capabilities") >> ForallBend(AzureCapability.mapping),
"capacity": S("capacity"),
"name": S("name"),
"tier": S("tier"),
"family": S("family"),
"size": S("size"),
"locations": S("locations"),
"sku_capacity": S("skuCapacity") >> Bend(AzureSkuCapacity.mapping),
}
capacity: Optional[int] = field(default=None, metadata={'description': 'Specifies the number of virtual machines in the scale set.'}) # fmt: skip
family: Optional[str] = field(default=None, metadata={"description": "The family of the sku."})
Expand All @@ -662,6 +691,29 @@ class AzureSku:
size: Optional[str] = field(default=None, metadata={"description": "Size of the particular SKU"})


@define(eq=False, slots=False)
class AzurePrivateEndpointConnection:
kind: ClassVar[str] = "azure_private_endpoint_connection"
mapping: ClassVar[Dict[str, Bender]] = {
"group_ids": S("properties", "groupIds"),
"id": S("id"),
"name": S("name"),
"private_endpoint": S("properties", "privateEndpoint", "id"),
"private_link_service_connection_state": S("properties", "privateLinkServiceConnectionState")
>> Bend(AzurePrivateLinkServiceConnectionState.mapping),
"provisioning_state": S("properties", "provisioningState"),
"system_data": S("systemData") >> Bend(AzureSystemData.mapping),
"type": S("type"),
}
group_ids: Optional[List[str]] = field(default=None, metadata={'description': 'The group ids for the private endpoint resource.'}) # fmt: skip
id: Optional[str] = field(default=None, metadata={'description': 'Fully qualified resource ID for the resource. E.g. /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} '}) # fmt: skip
name: Optional[str] = field(default=None, metadata={"description": "The name of the resource"})
private_endpoint: Optional[str] = field(default=None, metadata={"description": "The private endpoint resource."})
private_link_service_connection_state: Optional[AzurePrivateLinkServiceConnectionState] = field(default=None, metadata={'description': 'A collection of information about the state of the connection between service consumer and provider.'}) # fmt: skip
system_data: Optional[AzureSystemData] = field(default=None, metadata={'description': 'Metadata pertaining to creation and last modification of the resource.'}) # fmt: skip
type: Optional[str] = field(default=None, metadata={'description': 'The type of the resource. E.g. Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts '}) # fmt: skip


class GraphBuilder:
def __init__(
self,
Expand Down
26 changes: 3 additions & 23 deletions plugins/azure/fix_plugin_azure/resource/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
AzureSku,
AzureExtendedLocation,
AzurePrincipalClient,
AzurePrivateLinkServiceConnectionState,
AzurePrivateEndpointConnection,
)
from fix_plugin_azure.resource.metrics import AzureMetricData, AzureMetricQuery, update_resource_metrics
from fix_plugin_azure.resource.network import (
Expand Down Expand Up @@ -1211,26 +1211,6 @@ def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureDiskEncryptionSet, id=disk_en_set_id)


@define(eq=False, slots=False)
class AzureDiskAccessPrivateEndpointConnection:
kind: ClassVar[str] = "azure_disk_access_private_endpoint_connection"
mapping: ClassVar[Dict[str, Bender]] = {
"id": S("id"),
"name": S("name"),
"private_endpoint": S("properties", "privateEndpoint", "id"),
"private_link_service_connection_state": S("properties", "privateLinkServiceConnectionState")
>> Bend(AzurePrivateLinkServiceConnectionState.mapping),
"provisioning_state": S("properties", "provisioningState"),
"type": S("type"),
}
id: Optional[str] = field(default=None, metadata={"description": "Private endpoint connection id."})
name: Optional[str] = field(default=None, metadata={"description": "Private endpoint connection name."})
private_endpoint: Optional[str] = field(default=None, metadata={"description": "The private endpoint resource."})
private_link_service_connection_state: Optional[AzurePrivateLinkServiceConnectionState] = field(default=None, metadata={'description': 'A collection of information about the state of the connection between service consumer and provider.'}) # fmt: skip
provisioning_state: Optional[str] = field(default=None, metadata={'description': 'The current provisioning state.'}) # fmt: skip
type: Optional[str] = field(default=None, metadata={"description": "Private endpoint connection type."})


@define(eq=False, slots=False)
class AzureDiskAccess(MicrosoftResource):
kind: ClassVar[str] = "azure_disk_access"
Expand All @@ -1250,12 +1230,12 @@ class AzureDiskAccess(MicrosoftResource):
"ctime": S("time_created"),
"extended_location": S("extendedLocation") >> Bend(AzureExtendedLocation.mapping),
"private_endpoint_connections": S("properties", "privateEndpointConnections")
>> ForallBend(AzureDiskAccessPrivateEndpointConnection.mapping),
>> ForallBend(AzurePrivateEndpointConnection.mapping),
"provisioning_state": S("properties", "provisioningState"),
"time_created": S("properties", "timeCreated"),
}
extended_location: Optional[AzureExtendedLocation] = field(default=None, metadata={'description': 'The complex type of the extended location.'}) # fmt: skip
private_endpoint_connections: Optional[List[AzureDiskAccessPrivateEndpointConnection]] = field(default=None, metadata={'description': 'A readonly collection of private endpoint connections created on the disk. Currently only one endpoint connection is supported.'}) # fmt: skip
private_endpoint_connections: Optional[List[AzurePrivateEndpointConnection]] = field(default=None, metadata={'description': 'A readonly collection of private endpoint connections created on the disk. Currently only one endpoint connection is supported.'}) # fmt: skip
time_created: Optional[datetime] = field(default=None, metadata={'description': 'The time when the disk access was created.'}) # fmt: skip


Expand Down
6 changes: 3 additions & 3 deletions plugins/azure/fix_plugin_azure/resource/containerservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
AzureExtendedLocation,
AzureUserAssignedIdentity,
AzurePrincipalClient,
AzureIdentity,
AzureManagedServiceIdentity,
)
from fixlib.baseresources import BaseManagedKubernetesClusterProvider, BaseSnapshot, EdgeType, ModelReference
from fixlib.json_bender import Bender, S, Bend, ForallBend
Expand Down Expand Up @@ -86,12 +86,12 @@ class AzureFleet(MicrosoftResource):
"e_tag": S("eTag"),
"resource_group": S("resourceGroup"),
"hub_profile": S("properties", "hubProfile") >> Bend(AzureFleetHubProfile.mapping),
"azure_fleet_identity": S("identity") >> Bend(AzureIdentity.mapping),
"azure_fleet_identity": S("identity") >> Bend(AzureManagedServiceIdentity.mapping),
"provisioning_state": S("properties", "provisioningState"),
}
e_tag: Optional[str] = field(default=None, metadata={'description': 'If eTag is provided in the response body, it may also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields.'}) # fmt: skip
hub_profile: Optional[AzureFleetHubProfile] = field(default=None, metadata={'description': 'The FleetHubProfile configures the fleet hub.'}) # fmt: skip
azure_fleet_identity: Optional[AzureIdentity] = field(default=None, metadata={'description': 'Managed service identity (system assigned and/or user assigned identities)'}) # fmt: skip
azure_fleet_identity: Optional[AzureManagedServiceIdentity] = field(default=None, metadata={'description': 'Managed service identity (system assigned and/or user assigned identities)'}) # fmt: skip
resource_group: Optional[str] = field(default=None, metadata={"description": "Resource group name"})
_cluster_resource_ids: Optional[List[str]] = field(
default=None, metadata={"description": "Reference to the cluster IDs"}
Expand Down
Loading

0 comments on commit 4b9b718

Please sign in to comment.