Custom Extension Instance Configuration (#1184)

This commit is contained in:
Noah McGregor Harper
2021-09-24 09:27:39 -07:00
committed by GitHub
parent d73981128f
commit 599c400fa0
3 changed files with 385 additions and 5 deletions

View File

@ -655,6 +655,77 @@ Each event will be submitted via HTTP POST to the user provided URL.
```json ```json
{ {
"definitions": { "definitions": {
"AzureMonitorExtensionConfig": {
"properties": {
"config_version": {
"title": "Config Version",
"type": "string"
},
"moniker": {
"title": "Moniker",
"type": "string"
},
"monitoringGCSAccount": {
"title": "Monitoringgcsaccount",
"type": "string"
},
"monitoringGCSAuthId": {
"title": "Monitoringgcsauthid",
"type": "string"
},
"monitoringGCSAuthIdType": {
"title": "Monitoringgcsauthidtype",
"type": "string"
},
"monitoringGSEnvironment": {
"title": "Monitoringgsenvironment",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
}
},
"required": [
"config_version",
"moniker",
"namespace",
"monitoringGSEnvironment",
"monitoringGCSAccount",
"monitoringGCSAuthId",
"monitoringGCSAuthIdType"
],
"title": "AzureMonitorExtensionConfig",
"type": "object"
},
"AzureSecurityExtensionConfig": {
"properties": {},
"title": "AzureSecurityExtensionConfig",
"type": "object"
},
"AzureVmExtensionConfig": {
"properties": {
"azure_monitor": {
"$ref": "#/definitions/AzureMonitorExtensionConfig"
},
"azure_security": {
"$ref": "#/definitions/AzureSecurityExtensionConfig"
},
"geneva": {
"$ref": "#/definitions/GenevaExtensionConfig"
},
"keyvault": {
"$ref": "#/definitions/KeyvaultExtensionConfig"
}
},
"title": "AzureVmExtensionConfig",
"type": "object"
},
"GenevaExtensionConfig": {
"properties": {},
"title": "GenevaExtensionConfig",
"type": "object"
},
"InstanceConfig": { "InstanceConfig": {
"properties": { "properties": {
"admins": { "admins": {
@ -678,6 +749,9 @@ Each event will be submitted via HTTP POST to the user provided URL.
"title": "Allowed Aad Tenants", "title": "Allowed Aad Tenants",
"type": "array" "type": "array"
}, },
"extensions": {
"$ref": "#/definitions/AzureVmExtensionConfig"
},
"proxy_vm_sku": { "proxy_vm_sku": {
"default": "Standard_B2s", "default": "Standard_B2s",
"title": "Proxy Vm Sku", "title": "Proxy Vm Sku",
@ -689,6 +763,34 @@ Each event will be submitted via HTTP POST to the user provided URL.
], ],
"title": "InstanceConfig", "title": "InstanceConfig",
"type": "object" "type": "object"
},
"KeyvaultExtensionConfig": {
"properties": {
"cert_name": {
"title": "Cert Name",
"type": "string"
},
"cert_path": {
"title": "Cert Path",
"type": "string"
},
"extension_store": {
"title": "Extension Store",
"type": "string"
},
"keyvault_name": {
"title": "Keyvault Name",
"type": "string"
}
},
"required": [
"keyvault_name",
"cert_name",
"cert_path",
"extension_store"
],
"title": "KeyvaultExtensionConfig",
"type": "object"
} }
}, },
"properties": { "properties": {
@ -4835,6 +4937,72 @@ Each event will be submitted via HTTP POST to the user provided URL.
"title": "AutoScaleConfig", "title": "AutoScaleConfig",
"type": "object" "type": "object"
}, },
"AzureMonitorExtensionConfig": {
"properties": {
"config_version": {
"title": "Config Version",
"type": "string"
},
"moniker": {
"title": "Moniker",
"type": "string"
},
"monitoringGCSAccount": {
"title": "Monitoringgcsaccount",
"type": "string"
},
"monitoringGCSAuthId": {
"title": "Monitoringgcsauthid",
"type": "string"
},
"monitoringGCSAuthIdType": {
"title": "Monitoringgcsauthidtype",
"type": "string"
},
"monitoringGSEnvironment": {
"title": "Monitoringgsenvironment",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
}
},
"required": [
"config_version",
"moniker",
"namespace",
"monitoringGSEnvironment",
"monitoringGCSAccount",
"monitoringGCSAuthId",
"monitoringGCSAuthIdType"
],
"title": "AzureMonitorExtensionConfig",
"type": "object"
},
"AzureSecurityExtensionConfig": {
"properties": {},
"title": "AzureSecurityExtensionConfig",
"type": "object"
},
"AzureVmExtensionConfig": {
"properties": {
"azure_monitor": {
"$ref": "#/definitions/AzureMonitorExtensionConfig"
},
"azure_security": {
"$ref": "#/definitions/AzureSecurityExtensionConfig"
},
"geneva": {
"$ref": "#/definitions/GenevaExtensionConfig"
},
"keyvault": {
"$ref": "#/definitions/KeyvaultExtensionConfig"
}
},
"title": "AzureVmExtensionConfig",
"type": "object"
},
"BlobRef": { "BlobRef": {
"properties": { "properties": {
"account": { "account": {
@ -5605,6 +5773,11 @@ Each event will be submitted via HTTP POST to the user provided URL.
], ],
"title": "EventType" "title": "EventType"
}, },
"GenevaExtensionConfig": {
"properties": {},
"title": "GenevaExtensionConfig",
"type": "object"
},
"InstanceConfig": { "InstanceConfig": {
"properties": { "properties": {
"admins": { "admins": {
@ -5628,6 +5801,9 @@ Each event will be submitted via HTTP POST to the user provided URL.
"title": "Allowed Aad Tenants", "title": "Allowed Aad Tenants",
"type": "array" "type": "array"
}, },
"extensions": {
"$ref": "#/definitions/AzureVmExtensionConfig"
},
"proxy_vm_sku": { "proxy_vm_sku": {
"default": "Standard_B2s", "default": "Standard_B2s",
"title": "Proxy Vm Sku", "title": "Proxy Vm Sku",
@ -5691,6 +5867,34 @@ Each event will be submitted via HTTP POST to the user provided URL.
"title": "JobTaskStopped", "title": "JobTaskStopped",
"type": "object" "type": "object"
}, },
"KeyvaultExtensionConfig": {
"properties": {
"cert_name": {
"title": "Cert Name",
"type": "string"
},
"cert_path": {
"title": "Cert Path",
"type": "string"
},
"extension_store": {
"title": "Extension Store",
"type": "string"
},
"keyvault_name": {
"title": "Keyvault Name",
"type": "string"
}
},
"required": [
"keyvault_name",
"cert_name",
"cert_path",
"extension_store"
],
"title": "KeyvaultExtensionConfig",
"type": "object"
},
"NoReproReport": { "NoReproReport": {
"properties": { "properties": {
"error": { "error": {

View File

@ -8,7 +8,14 @@ from typing import List, Optional
from uuid import UUID, uuid4 from uuid import UUID, uuid4
from onefuzztypes.enums import OS, AgentMode from onefuzztypes.enums import OS, AgentMode
from onefuzztypes.models import AgentConfig, Pool, ReproConfig, Scaleset from onefuzztypes.models import (
AgentConfig,
AzureMonitorExtensionConfig,
KeyvaultExtensionConfig,
Pool,
ReproConfig,
Scaleset,
)
from onefuzztypes.primitives import Container, Extension, Region from onefuzztypes.primitives import Container, Extension, Region
from .azure.containers import ( from .azure.containers import (
@ -21,14 +28,38 @@ from .azure.creds import get_instance_id, get_instance_url
from .azure.monitor import get_monitor_settings from .azure.monitor import get_monitor_settings
from .azure.queue import get_queue_sas from .azure.queue import get_queue_sas
from .azure.storage import StorageType from .azure.storage import StorageType
from .config import InstanceConfig
from .reports import get_report from .reports import get_report
def generic_extensions(region: Region, vm_os: OS) -> List[Extension]: def generic_extensions(region: Region, vm_os: OS) -> List[Extension]:
instance_config = InstanceConfig.fetch()
extensions = [monitor_extension(region, vm_os)] extensions = [monitor_extension(region, vm_os)]
depedency = dependency_extension(region, vm_os)
if depedency: dependency = dependency_extension(region, vm_os)
extensions.append(depedency) if dependency:
extensions.append(dependency)
if instance_config.extensions:
if instance_config.extensions.keyvault:
keyvault = keyvault_extension(
region, instance_config.extensions.keyvault, vm_os
)
extensions.append(keyvault)
if instance_config.extensions.geneva and vm_os == OS.windows:
geneva = geneva_extension(region)
extensions.append(geneva)
if instance_config.extensions.azure_monitor and vm_os == OS.linux:
azmon = azmon_extension(region, instance_config.extensions.azure_monitor)
extensions.append(azmon)
if instance_config.extensions.azure_security and vm_os == OS.linux:
azsec = azsec_extension(region)
extensions.append(azsec)
return extensions return extensions
@ -85,6 +116,116 @@ def dependency_extension(region: Region, vm_os: OS) -> Optional[Extension]:
return None return None
def geneva_extension(region: Region) -> Extension:
return {
"name": "Microsoft.Azure.Geneva.GenevaMonitoring",
"publisher": "Microsoft.Azure.Geneva",
"type": "GenevaMonitoring",
"typeHandlerVersion": "2.0",
"location": region,
"autoUpgradeMinorVersion": True,
"enableAutomaticUpgrade": True,
"settings": {},
"protectedSettings": {},
}
def azmon_extension(
region: Region, azure_monitor: AzureMonitorExtensionConfig
) -> Extension:
auth_id = azure_monitor.monitoringGCSAuthId
config_version = azure_monitor.config_version
moniker = azure_monitor.moniker
namespace = azure_monitor.namespace
environment = azure_monitor.monitoringGSEnvironment
account = azure_monitor.monitoringGCSAccount
auth_id_type = azure_monitor.monitoringGCSAuthIdType
return {
"name": "AzureMonitorLinuxAgent",
"publisher": "Microsoft.Azure.Monitor",
"location": region,
"type": "AzureMonitorLinuxAgent",
"typeHandlerVersion": "1.9",
"autoUpgradeMinorVersion": False,
"settings": {},
"protectedsettings": {
"configVersion": config_version,
"moniker": moniker,
"namespace": namespace,
"monitoringGCSEnvironment": environment,
"monitoringGCSAccount": account,
"monitoringGCSRegion": region,
"monitoringGCSAuthId": auth_id,
"monitoringGCSAuthIdType": auth_id_type,
},
}
def azsec_extension(region: Region) -> Extension:
return {
"name": "AzureSecurityLinuxAgent",
"publisher": "Microsoft.Azure.Security.Monitoring",
"location": region,
"type": "AzureSecurityLinuxAgent",
"typeHandlerVersion": "2.0",
"autoUpgradeMinorVersion": True,
"settings": {"enableGenevaUpload": True},
}
def keyvault_extension(
region: Region, keyvault: KeyvaultExtensionConfig, vm_os: OS
) -> Extension:
keyvault_name = keyvault.keyvault_name
cert_name = keyvault.cert_name
uri = keyvault_name + cert_name
if vm_os == OS.windows:
return {
"name": "KVVMExtensionForWindows",
"location": region,
"publisher": "Microsoft.Azure.KeyVault",
"type": "KeyVaultForWindows",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": True,
"settings": {
"secretsManagementSettings": {
"pollingIntervalInS": "3600",
"certificateStoreName": "MY",
"linkOnRenewal": False,
"certificateStoreLocation": "LocalMachine",
"requireInitialSync": True,
"observedCertificates": [uri],
}
},
}
elif vm_os == OS.linux:
cert_path = keyvault.cert_path
extension_store = keyvault.extension_store
cert_location = cert_path + extension_store
return {
"name": "KVVMExtensionForLinux",
"location": region,
"publisher": "Microsoft.Azure.KeyVault",
"type": "KeyVaultForLinux",
"typeHandlerVersion": "2.0",
"autoUpgradeMinorVersion": True,
"settings": {
"secretsManagementSettings": {
"pollingIntervalInS": "3600",
"certificateStoreLocation": cert_location,
"observedCertificates": [uri],
},
},
}
raise NotImplementedError("unsupported os: %s" % vm_os)
def build_scaleset_script(pool: Pool, scaleset: Scaleset) -> str: def build_scaleset_script(pool: Pool, scaleset: Scaleset) -> str:
commands = [] commands = []
extension = "ps1" if pool.os == OS.windows else "sh" extension = "ps1" if pool.os == OS.windows else "sh"

View File

@ -794,6 +794,38 @@ class Task(BaseModel):
user_info: Optional[UserInfo] user_info: Optional[UserInfo]
class KeyvaultExtensionConfig(BaseModel):
keyvault_name: str
cert_name: str
cert_path: str
extension_store: str
class AzureMonitorExtensionConfig(BaseModel):
config_version: str
moniker: str
namespace: str
monitoringGSEnvironment: str
monitoringGCSAccount: str
monitoringGCSAuthId: str
monitoringGCSAuthIdType: str
class AzureSecurityExtensionConfig(BaseModel):
pass
class GenevaExtensionConfig(BaseModel):
pass
class AzureVmExtensionConfig(BaseModel):
keyvault: Optional[KeyvaultExtensionConfig]
azure_monitor: Optional[AzureMonitorExtensionConfig]
azure_security: Optional[AzureSecurityExtensionConfig]
geneva: Optional[GenevaExtensionConfig]
class InstanceConfig(BaseModel): class InstanceConfig(BaseModel):
# initial set of admins can only be set during deployment. # initial set of admins can only be set during deployment.
# if admins are set, only admins can update instance configs. # if admins are set, only admins can update instance configs.
@ -802,9 +834,12 @@ class InstanceConfig(BaseModel):
# if set, only admins can manage pools or scalesets # if set, only admins can manage pools or scalesets
allow_pool_management: bool = Field(default=True) allow_pool_management: bool = Field(default=True)
proxy_vm_sku: str = Field(default="Standard_B2s")
allowed_aad_tenants: List[UUID] allowed_aad_tenants: List[UUID]
extensions: Optional[AzureVmExtensionConfig]
proxy_vm_sku: str = Field(default="Standard_B2s")
def update(self, config: "InstanceConfig") -> None: def update(self, config: "InstanceConfig") -> None:
for field in config.__fields__: for field in config.__fields__:
# If no admins are set, then ignore setting admins # If no admins are set, then ignore setting admins