majuna/app/terraform/proxy/azure_cdn.py

203 lines
6.3 KiB
Python
Raw Normal View History

2022-03-10 14:26:22 +00:00
from azure.identity import ClientSecretCredential
from azure.mgmt.alertsmanagement import AlertsManagementClient
from app import app
from app.alarms import get_proxy_alarm
from app.extensions import db
2022-04-25 15:05:28 +01:00
from app.models.mirrors import Proxy
2022-04-22 14:01:16 +01:00
from app.models.alarms import AlarmState
2022-03-10 14:26:22 +00:00
from app.terraform.proxy import ProxyAutomation
class ProxyAzureCdnAutomation(ProxyAutomation):
short_name = "proxy_azure_cdn"
provider = "azure_cdn"
subgroup_max = 25
parallelism = 1
2022-03-10 14:26:22 +00:00
template_parameters = [
"azure_resource_group_name",
"azure_storage_account_name",
"azure_location",
"azure_client_id",
"azure_client_secret",
"azure_subscription_id",
"azure_tenant_id"
]
template = """
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.99.0"
}
}
}
provider "azurerm" {
features {}
client_id = "{{ azure_client_id }}"
client_secret = "{{ azure_client_secret }}"
subscription_id = "{{ azure_subscription_id }}"
tenant_id = "{{ azure_tenant_id }}"
skip_provider_registration = true
}
data "azurerm_resource_group" "this" {
name = "{{ azure_resource_group_name }}"
}
resource "azurerm_storage_account" "this" {
name = "{{ azure_storage_account_name }}"
resource_group_name = data.azurerm_resource_group.this.name
location = "{{ azure_location }}"
account_tier = "Standard"
account_replication_type = "RAGRS"
}
{% for group in groups %}
module "label_{{ group.id }}" {
source = "cloudposse/label/null"
version = "0.25.0"
namespace = "{{ global_namespace }}"
tenant = "{{ group.group_name }}"
label_order = ["namespace", "tenant", "name", "attributes"]
}
2022-04-25 14:56:35 +01:00
{% for subgroup in subgroups[group.id] %}
resource "azurerm_cdn_profile" "profile_{{ group.id }}_{{ subgroup }}" {
2022-04-25 15:08:15 +01:00
name = "${module.label_{{ group.id }}.id}-sub{{ subgroup }}"
2022-03-10 14:26:22 +00:00
location = "{{ azure_location }}"
resource_group_name = data.azurerm_resource_group.this.name
sku = "Standard_Microsoft"
tags = module.label_{{ group.id }}.tags
}
2022-04-25 14:56:35 +01:00
resource "azurerm_monitor_diagnostic_setting" "profile_diagnostic_{{ group.id }}_{{ subgroup }}" {
2022-03-10 14:26:22 +00:00
name = "cdn-diagnostics"
2022-04-25 14:56:35 +01:00
target_resource_id = azurerm_cdn_profile.profile_{{ group.id }}_{{ subgroup }}.id
2022-03-10 14:26:22 +00:00
storage_account_id = azurerm_storage_account.this.id
log {
category = "AzureCDNAccessLog"
enabled = true
retention_policy {
enabled = true
days = 90
}
}
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 90
}
}
}
2022-04-25 14:56:35 +01:00
resource "azurerm_monitor_metric_alert" "response_alert_{{ group.id }}_{{ subgroup }}" {
name = "bandwidth-out-high-${module.label_{{ group.id }}.id}-sub{{ subgroup }}"
2022-03-10 14:26:22 +00:00
resource_group_name = data.azurerm_resource_group.this.name
2022-04-25 14:56:35 +01:00
scopes = [azurerm_cdn_profile.profile_{{ group.id }}_{{ subgroup }}.id]
2022-03-10 14:26:22 +00:00
description = "Action will be triggered when response size is too high."
criteria {
metric_namespace = "Microsoft.Cdn/profiles"
metric_name = "ResponseSize"
aggregation = "Total"
operator = "GreaterThan"
threshold = 21474836481
}
window_size = "PT1H"
}
{% endfor %}
2022-04-25 14:56:35 +01:00
{% endfor %}
2022-03-10 14:26:22 +00:00
{% for proxy in proxies %}
resource "azurerm_cdn_endpoint" "endpoint_{{ proxy.id }}" {
name = "{{ proxy.slug }}"
2022-04-25 14:56:35 +01:00
profile_name = azurerm_cdn_profile.profile_{{ proxy.origin.group.id }}_{{ proxy.psg }}.name
2022-03-10 14:26:22 +00:00
location = "{{ azure_location }}"
resource_group_name = data.azurerm_resource_group.this.name
2022-04-19 14:32:04 +01:00
origin_host_header = "{{ proxy.origin.domain_name }}"
2022-03-10 14:26:22 +00:00
origin {
name = "upstream"
host_name = "{{ proxy.origin.domain_name }}"
}
global_delivery_rule {
modify_request_header_action {
action = "Append"
2022-04-19 14:32:04 +01:00
name = "Bypass-Rate-Limit-Token"
value = "{{ bypass_token }}"
2022-03-10 14:26:22 +00:00
}
}
}
resource "azurerm_monitor_diagnostic_setting" "diagnostic_{{ proxy.id }}" {
name = "cdn-diagnostics"
target_resource_id = azurerm_cdn_endpoint.endpoint_{{ proxy.id }}.id
storage_account_id = azurerm_storage_account.this.id
log {
category = "CoreAnalytics"
enabled = true
retention_policy {
enabled = true
days = 90
}
}
}
{% endfor %}
"""
def import_state(self, state):
proxies = Proxy.query.filter(
Proxy.provider == self.provider,
Proxy.destroyed == None
).all()
for proxy in proxies:
proxy.url = f"https://{proxy.slug}.azureedge.net"
db.session.commit()
2022-03-10 14:26:22 +00:00
def import_monitor_alerts():
credential = ClientSecretCredential(
tenant_id=app.config['AZURE_TENANT_ID'],
client_id=app.config['AZURE_CLIENT_ID'],
client_secret=app.config['AZURE_CLIENT_SECRET'])
client = AlertsManagementClient(
credential,
app.config['AZURE_SUBSCRIPTION_ID']
)
firing = [x.name[len("bandwidth-out-high-bc-"):]
for x in client.alerts.get_all()
if x.name.startswith("bandwidth-out-high-bc-") and x.properties.essentials.monitor_condition == "Fired"]
for proxy in Proxy.query.filter(
Proxy.provider == "azure_cdn",
Proxy.destroyed == None
):
alarm = get_proxy_alarm(proxy.id, "bandwidth-out-high")
if proxy.origin.group.group_name.lower() not in firing:
alarm.update_state(AlarmState.OK, "Azure monitor alert not firing")
else:
alarm.update_state(AlarmState.CRITICAL, "Azure monitor alert firing")
if __name__ == "__main__":
with app.app_context():
auto = ProxyAzureCdnAutomation()
auto.automate()
2022-04-25 15:36:45 +01:00
import_monitor_alerts()