mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-15 19:38:11 +00:00
enable configurable virtual network ranges (#1268)
This commit is contained in:
@ -645,6 +645,10 @@ Each event will be submitted via HTTP POST to the user provided URL.
|
||||
"allowed_aad_tenants": [
|
||||
"00000000-0000-0000-0000-000000000000"
|
||||
],
|
||||
"network_config": {
|
||||
"address_space": "10.0.0.0/8",
|
||||
"subnet": "10.0.0.0/16"
|
||||
},
|
||||
"proxy_vm_sku": "Standard_B2s"
|
||||
}
|
||||
}
|
||||
@ -752,6 +756,9 @@ Each event will be submitted via HTTP POST to the user provided URL.
|
||||
"extensions": {
|
||||
"$ref": "#/definitions/AzureVmExtensionConfig"
|
||||
},
|
||||
"network_config": {
|
||||
"$ref": "#/definitions/NetworkConfig"
|
||||
},
|
||||
"proxy_vm_sku": {
|
||||
"default": "Standard_B2s",
|
||||
"title": "Proxy Vm Sku",
|
||||
@ -791,6 +798,22 @@ Each event will be submitted via HTTP POST to the user provided URL.
|
||||
],
|
||||
"title": "KeyvaultExtensionConfig",
|
||||
"type": "object"
|
||||
},
|
||||
"NetworkConfig": {
|
||||
"properties": {
|
||||
"address_space": {
|
||||
"default": "10.0.0.0/8",
|
||||
"title": "Address Space",
|
||||
"type": "string"
|
||||
},
|
||||
"subnet": {
|
||||
"default": "10.0.0.0/16",
|
||||
"title": "Subnet",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": "NetworkConfig",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
@ -5804,6 +5827,9 @@ Each event will be submitted via HTTP POST to the user provided URL.
|
||||
"extensions": {
|
||||
"$ref": "#/definitions/AzureVmExtensionConfig"
|
||||
},
|
||||
"network_config": {
|
||||
"$ref": "#/definitions/NetworkConfig"
|
||||
},
|
||||
"proxy_vm_sku": {
|
||||
"default": "Standard_B2s",
|
||||
"title": "Proxy Vm Sku",
|
||||
@ -5895,6 +5921,22 @@ Each event will be submitted via HTTP POST to the user provided URL.
|
||||
"title": "KeyvaultExtensionConfig",
|
||||
"type": "object"
|
||||
},
|
||||
"NetworkConfig": {
|
||||
"properties": {
|
||||
"address_space": {
|
||||
"default": "10.0.0.0/8",
|
||||
"title": "Address Space",
|
||||
"type": "string"
|
||||
},
|
||||
"subnet": {
|
||||
"default": "10.0.0.0/16",
|
||||
"title": "Subnet",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": "NetworkConfig",
|
||||
"type": "object"
|
||||
},
|
||||
"NoReproReport": {
|
||||
"properties": {
|
||||
"error": {
|
||||
|
@ -13,10 +13,11 @@ from msrestazure.azure_exceptions import CloudError
|
||||
from msrestazure.tools import parse_resource_id
|
||||
from onefuzztypes.enums import ErrorCode
|
||||
from onefuzztypes.models import Error
|
||||
from onefuzztypes.primitives import Region
|
||||
|
||||
from .creds import get_base_resource_group
|
||||
from .network import Network
|
||||
from .network_mgmt_client import get_network_client
|
||||
from .subnet import create_virtual_network, get_subnet_id
|
||||
from .vmss import get_instance_id
|
||||
|
||||
|
||||
@ -63,12 +64,12 @@ def delete_ip(resource_group: str, name: str) -> Any:
|
||||
return network_client.public_ip_addresses.begin_delete(resource_group, name)
|
||||
|
||||
|
||||
def create_ip(resource_group: str, name: str, location: str) -> Any:
|
||||
logging.info("creating ip for %s:%s in %s", resource_group, name, location)
|
||||
def create_ip(resource_group: str, name: str, region: Region) -> Any:
|
||||
logging.info("creating ip for %s:%s in %s", resource_group, name, region)
|
||||
|
||||
network_client = get_network_client()
|
||||
params: Dict[str, Union[str, Dict[str, str]]] = {
|
||||
"location": location,
|
||||
"location": region,
|
||||
"public_ip_allocation_method": "Dynamic",
|
||||
}
|
||||
if "ONEFUZZ_OWNER" in os.environ:
|
||||
@ -93,21 +94,24 @@ def delete_nic(resource_group: str, name: str) -> Optional[Any]:
|
||||
return network_client.network_interfaces.begin_delete(resource_group, name)
|
||||
|
||||
|
||||
def create_public_nic(resource_group: str, name: str, location: str) -> Optional[Error]:
|
||||
logging.info("creating nic for %s:%s in %s", resource_group, name, location)
|
||||
def create_public_nic(
|
||||
resource_group: str, name: str, region: Region
|
||||
) -> Optional[Error]:
|
||||
logging.info("creating nic for %s:%s in %s", resource_group, name, region)
|
||||
|
||||
network_client = get_network_client()
|
||||
subnet_id = get_subnet_id(resource_group, location)
|
||||
if not subnet_id:
|
||||
return create_virtual_network(resource_group, location, location)
|
||||
network = Network(region)
|
||||
subnet_id = network.get_id()
|
||||
if subnet_id is None:
|
||||
network.create()
|
||||
return None
|
||||
|
||||
ip = get_ip(resource_group, name)
|
||||
if not ip:
|
||||
create_ip(resource_group, name, location)
|
||||
create_ip(resource_group, name, region)
|
||||
return None
|
||||
|
||||
params = {
|
||||
"location": location,
|
||||
"location": region,
|
||||
"ip_configurations": [
|
||||
{
|
||||
"name": "myIPConfig",
|
||||
@ -119,6 +123,7 @@ def create_public_nic(resource_group: str, name: str, location: str) -> Optional
|
||||
if "ONEFUZZ_OWNER" in os.environ:
|
||||
params["tags"] = {"OWNER": os.environ["ONEFUZZ_OWNER"]}
|
||||
|
||||
network_client = get_network_client()
|
||||
try:
|
||||
network_client.network_interfaces.begin_create_or_update(
|
||||
resource_group, name, params
|
||||
|
@ -4,43 +4,68 @@
|
||||
# Licensed under the MIT License.
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
from typing import Optional, Union
|
||||
|
||||
from msrestazure.azure_exceptions import CloudError
|
||||
from onefuzztypes.enums import ErrorCode
|
||||
from onefuzztypes.models import Error
|
||||
from onefuzztypes.models import Error, NetworkConfig
|
||||
from onefuzztypes.primitives import Region
|
||||
|
||||
from ..config import InstanceConfig
|
||||
from .creds import get_base_resource_group
|
||||
from .subnet import create_virtual_network, delete_subnet, get_subnet_id
|
||||
from .subnet import create_virtual_network, get_subnet_id
|
||||
|
||||
# This was generated randomly and should be preserved moving forwards
|
||||
NETWORK_GUID_NAMESPACE = uuid.UUID("372977ad-b533-416a-b1b4-f770898e0b11")
|
||||
|
||||
|
||||
class Network:
|
||||
def __init__(self, region: Region):
|
||||
self.group = get_base_resource_group()
|
||||
self.region = region
|
||||
self.network_config = InstanceConfig.fetch().network_config
|
||||
|
||||
# Network names will be calculated from the address_space/subnet
|
||||
# *except* if they are the original values. This allows backwards
|
||||
# compatibility to existing configs if you don't change the network
|
||||
# configs.
|
||||
if (
|
||||
self.network_config.address_space
|
||||
== NetworkConfig.__fields__["address_space"].default
|
||||
and self.network_config.subnet == NetworkConfig.__fields__["subnet"].default
|
||||
):
|
||||
self.name: str = self.region
|
||||
else:
|
||||
network_id = uuid.uuid5(
|
||||
NETWORK_GUID_NAMESPACE,
|
||||
"|".join(
|
||||
[self.network_config.address_space, self.network_config.subnet]
|
||||
),
|
||||
)
|
||||
self.name = f"{self.region}-{network_id}"
|
||||
|
||||
def exists(self) -> bool:
|
||||
return self.get_id() is not None
|
||||
|
||||
def get_id(self) -> Optional[str]:
|
||||
return get_subnet_id(self.group, self.region)
|
||||
return get_subnet_id(self.group, self.name, self.name)
|
||||
|
||||
def create(self) -> Union[None, Error]:
|
||||
if not self.exists():
|
||||
result = create_virtual_network(self.group, self.region, self.region)
|
||||
result = create_virtual_network(
|
||||
self.group, self.name, self.region, self.network_config
|
||||
)
|
||||
if isinstance(result, CloudError):
|
||||
error = Error(
|
||||
code=ErrorCode.UNABLE_TO_CREATE_NETWORK, errors=[result.message]
|
||||
)
|
||||
logging.error(
|
||||
"network creation failed: %s- %s",
|
||||
"network creation failed: %s:%s- %s",
|
||||
self.name,
|
||||
self.region,
|
||||
error,
|
||||
)
|
||||
return error
|
||||
|
||||
return None
|
||||
|
||||
def delete(self) -> None:
|
||||
delete_subnet(self.group, self.region)
|
||||
|
@ -10,21 +10,23 @@ from typing import Any, Optional, Union, cast
|
||||
from azure.core.exceptions import ResourceNotFoundError
|
||||
from msrestazure.azure_exceptions import CloudError
|
||||
from onefuzztypes.enums import ErrorCode
|
||||
from onefuzztypes.models import Error
|
||||
from onefuzztypes.models import Error, NetworkConfig
|
||||
from onefuzztypes.primitives import Region
|
||||
|
||||
from .network_mgmt_client import get_network_client
|
||||
|
||||
|
||||
def get_subnet_id(resource_group: str, name: str) -> Optional[str]:
|
||||
def get_subnet_id(resource_group: str, name: str, subnet_name: str) -> Optional[str]:
|
||||
network_client = get_network_client()
|
||||
try:
|
||||
subnet = network_client.subnets.get(resource_group, name, name)
|
||||
subnet = network_client.subnets.get(resource_group, name, subnet_name)
|
||||
return cast(str, subnet.id)
|
||||
except (CloudError, ResourceNotFoundError):
|
||||
logging.info(
|
||||
"subnet missing: resource group: %s name: %s",
|
||||
"subnet missing: resource group:%s name:%s subnet_name:%s",
|
||||
resource_group,
|
||||
name,
|
||||
subnet_name,
|
||||
)
|
||||
return None
|
||||
|
||||
@ -43,20 +45,23 @@ def delete_subnet(resource_group: str, name: str) -> Union[None, CloudError, Any
|
||||
|
||||
|
||||
def create_virtual_network(
|
||||
resource_group: str, name: str, location: str
|
||||
resource_group: str,
|
||||
name: str,
|
||||
region: Region,
|
||||
network_config: NetworkConfig,
|
||||
) -> Optional[Error]:
|
||||
logging.info(
|
||||
"creating subnet - resource group: %s name: %s location: %s",
|
||||
"creating subnet - resource group:%s name:%s region:%s",
|
||||
resource_group,
|
||||
name,
|
||||
location,
|
||||
region,
|
||||
)
|
||||
|
||||
network_client = get_network_client()
|
||||
params = {
|
||||
"location": location,
|
||||
"address_space": {"address_prefixes": ["10.0.0.0/8"]},
|
||||
"subnets": [{"name": name, "address_prefix": "10.0.0.0/16"}],
|
||||
"location": region,
|
||||
"address_space": {"address_prefixes": [network_config.address_space]},
|
||||
"subnets": [{"name": name, "address_prefix": network_config.subnet}],
|
||||
}
|
||||
if "ONEFUZZ_OWNER" in os.environ:
|
||||
params["tags"] = {"OWNER": os.environ["ONEFUZZ_OWNER"]}
|
||||
|
@ -399,11 +399,11 @@ def create_vmss(
|
||||
|
||||
@cached(ttl=60)
|
||||
@retry_on_auth_failure()
|
||||
def list_available_skus(location: str) -> List[str]:
|
||||
def list_available_skus(region: Region) -> List[str]:
|
||||
compute_client = get_compute_client()
|
||||
|
||||
skus: List[ResourceSku] = list(
|
||||
compute_client.resource_skus.list(filter="location eq '%s'" % location)
|
||||
compute_client.resource_skus.list(filter="location eq '%s'" % region)
|
||||
)
|
||||
sku_names: List[str] = []
|
||||
for sku in skus:
|
||||
@ -411,7 +411,7 @@ def list_available_skus(location: str) -> List[str]:
|
||||
if sku.restrictions is not None:
|
||||
for restriction in sku.restrictions:
|
||||
if restriction.type == ResourceSkuRestrictionsType.location and (
|
||||
location.upper() in [v.upper() for v in restriction.values]
|
||||
region.upper() in [v.upper() for v in restriction.values]
|
||||
):
|
||||
available = False
|
||||
break
|
||||
|
@ -92,8 +92,8 @@ def not_ok(
|
||||
)
|
||||
|
||||
|
||||
def redirect(location: str) -> HttpResponse:
|
||||
return HttpResponse(status_code=302, headers={"Location": location})
|
||||
def redirect(url: str) -> HttpResponse:
|
||||
return HttpResponse(status_code=302, headers={"Location": url})
|
||||
|
||||
|
||||
def convert_error(err: ValidationError) -> Error:
|
||||
|
@ -794,6 +794,11 @@ class Task(BaseModel):
|
||||
user_info: Optional[UserInfo]
|
||||
|
||||
|
||||
class NetworkConfig(BaseModel):
|
||||
address_space: str = Field(default="10.0.0.0/8")
|
||||
subnet: str = Field(default="10.0.0.0/16")
|
||||
|
||||
|
||||
class KeyvaultExtensionConfig(BaseModel):
|
||||
keyvault_name: str
|
||||
cert_name: str
|
||||
@ -835,9 +840,8 @@ class InstanceConfig(BaseModel):
|
||||
allow_pool_management: bool = Field(default=True)
|
||||
|
||||
allowed_aad_tenants: List[UUID]
|
||||
|
||||
network_config: NetworkConfig = Field(default_factory=NetworkConfig)
|
||||
extensions: Optional[AzureVmExtensionConfig]
|
||||
|
||||
proxy_vm_sku: str = Field(default="Standard_B2s")
|
||||
|
||||
def update(self, config: "InstanceConfig") -> None:
|
||||
|
Reference in New Issue
Block a user