Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/test_container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
docker compose -f ${{ matrix.compose_file }} build

# Get only project-specific images (exclude system/dependency images)
PROJECT_IMAGES="oasismap|frontend|backend|orion|cygnus|mongo|postgres|keycloak|node"
PROJECT_IMAGES="oasismap|frontend|backend|orion|mongo|postgres|keycloak|node"
docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>" | grep -E "($PROJECT_IMAGES)" > images.txt

# Remove duplicates
Expand All @@ -80,7 +80,7 @@ jobs:
severity_level="CRITICAL,HIGH"
severity_description="CRITICAL or HIGH"
else
# Other containers (orion, cygnus, mongo, postgres, keycloak, node, etc.)
# Other containers (orion, mongo, postgres, keycloak, node, etc.)
severity_level="CRITICAL"
severity_description="CRITICAL"
fi
Expand All @@ -93,8 +93,6 @@ jobs:
ignorefile="--ignorefile ./backend/.trivyignore"
elif [[ "$image" == *"orion"* ]]; then
ignorefile="--ignorefile ./fiware/orion/.trivyignore"
elif [[ "$image" == *"cygnus"* ]]; then
ignorefile="--ignorefile ./fiware/cygnus/.trivyignore"
fi

# Get total vulnerabilities based on severity level
Expand Down
2 changes: 1 addition & 1 deletion infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Terraform は次の **3 レイヤー**を **platform → app → keycloak-realm*
| レイヤー | 主なリソース |
| --- | --- |
| **platform** | リソースグループ、Virtual Network(DMZ / App / DB / Application Gateway 用サブネット)、Cosmos DB(Mongo API・サーバーレス)、PostgreSQL Flexible Server、Log Analytics、Key Vault、DNS ゾーン・レコード、ユーザー割り当てマネージド ID など |
| **app** | Azure Container Registry、Linux App Service(**frontend / backend / Keycloak**)、Azure Container Instances(**Orion、Cygnus**、Mongo/PostgreSQL 用ワンショット CLI、**Orion サブスクリプション登録用ワンショット** など)、Application Gateway(WAF)、Let's Encrypt(ACME DNS-01)による証明書 |
| **app** | Azure Container Registry、Linux App Service(**frontend / backend / Keycloak**)、Azure Container Instances(**Orion**、Mongo/PostgreSQL 用ワンショット CLI、**Orion サブスクリプション登録用ワンショット** など)、Application Gateway(WAF)、Let's Encrypt(ACME DNS-01)による証明書 |
| **keycloak-realm** | Keycloak のレルム・クライアント・IdP 等(**Keycloak Terraform プロバイダ**) |

実行時の依存関係のイメージは次のとおりである。
Expand Down
6 changes: 5 additions & 1 deletion infra/arm/_env-azure
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ REVERSE_GEOCODING_URL="https://nominatim.openstreetmap.org/reverse"

# Cluster configuration
NEXT_PUBLIC_MAX_CLUSTER_RADIUS=200
USE_MOCK_DATA=true
USE_MOCK_DATA=true

# User Agentで扱う、メールアドレスの環境変数
USER_AGENT_EMAIL=TISI_WB@ml.tisi.jp

35 changes: 1 addition & 34 deletions infra/arm/docker-compose-azure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ services:
- "POSTGRES_PASSWORD=${POSTGREPASSWORD}"
- "POSTGRES_DATABASE=cygnus"
- "REVERSE_GEOCODING_URL=${REVERSE_GEOCODING_URL}"
- "USER_AGENT_EMAIL=${USER_AGENT_EMAIL}"
networks:
- backend-network
healthcheck:
Expand Down Expand Up @@ -201,40 +202,6 @@ services:
syslog-facility: local0
tag: orion

cygnus:
build:
context: ./fiware/cygnus
dockerfile: Dockerfile
hostname: cygnus
container_name: cygnus
environment:
- "CYGNUS_POSTGRESQL_HOST=${POSTGREHOST}"
- "CYGNUS_POSTGRESQL_PORT=${POSTGREPORT}"
- "CYGNUS_POSTGRESQL_USER=${POSTGREUSER}"
- "CYGNUS_POSTGRESQL_PASS=${POSTGREPASSWORD}"
- "CYGNUS_POSTGRESQL_ENABLE_CACHE=true"
- "CYGNUS_POSTGRESQL_SERVICE_PORT=5055"
- "CYGNUS_POSTGRESQL_DATABASE=cygnus"
- "CYGNUS_POSTGRESQL_DATA_MODEL=dm-by-service-path"
- "CYGNUS_POSTGRESQL_ATTR_PERSISTENCE=column"
- "CYGNUS_LOG_LEVEL=INFO"
- "CYGNUS_SERVICE_PORT=5055"
- "CYGNUS_API_PORT=5080"
networks:
- backend-network
healthcheck:
test: "curl -f http://cygnus:5080/v1/version"
interval: 10s
timeout: 5s
retries: 10
start_period: 10s
restart: always
logging:
driver: syslog
options:
syslog-facility: local0
tag: cygnus

networks:
backend-network:
driver: bridge
Expand Down
111 changes: 5 additions & 106 deletions infra/terraform/app/aci.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Azure Container Instances: Orion, Cygnus。platform の subnet_app を使った VNet 統合。
# Azure Container Instances: Orion。platform の subnet_app を使った VNet 統合。

resource "azurerm_container_group" "orion" {
name = "${local.prefix}-aci-orion"
Expand Down Expand Up @@ -211,108 +211,8 @@ resource "azurerm_container_group" "postgres_cli" {
]
}

resource "azurerm_container_group" "cygnus" {
name = "${local.prefix}-aci-cygnus"
location = local.location
resource_group_name = local.resource_group_name
ip_address_type = "Private"
os_type = "Linux"
subnet_ids = [data.terraform_remote_state.platform.outputs.subnet_app_id]
key_vault_user_assigned_identity_id = data.azurerm_user_assigned_identity.cygnus.id

image_registry_credential {
server = azurerm_container_registry.main.login_server
user_assigned_identity_id = data.azurerm_user_assigned_identity.cygnus.id
}

identity {
type = "UserAssigned"
identity_ids = [data.azurerm_user_assigned_identity.cygnus.id]
}

container {
name = "cygnus"
image = "${azurerm_container_registry.main.login_server}/${var.aci_cygnus_image_tag}"
cpu = "0.5"
memory = "4"

ports {
port = 5055
protocol = "TCP"
}

ports {
port = 5080
protocol = "TCP"
}

environment_variables = {
CYGNUS_POSTGRESQL_ENABLE_CACHE = "true"
CYGNUS_POSTGRESQL_SERVICE_PORT = "5055"
CYGNUS_POSTGRESQL_DATABASE = "cygnus"
CYGNUS_POSTGRESQL_DATA_MODEL = "dm-by-service-path"
CYGNUS_POSTGRESQL_ATTR_PERSISTENCE = "column"
CYGNUS_LOG_LEVEL = "INFO"
CYGNUS_SERVICE_PORT = "5055"
CYGNUS_API_PORT = "5080"
}

secure_environment_variables = {
CYGNUS_POSTGRESQL_HOST = data.azurerm_postgresql_flexible_server.main.fqdn
CYGNUS_POSTGRESQL_PORT = "5432"
CYGNUS_POSTGRESQL_USER = data.azurerm_postgresql_flexible_server.main.administrator_login
CYGNUS_POSTGRESQL_PASS = data.azurerm_key_vault_secret.cygnus_postgres_password.value
}

readiness_probe {
initial_delay_seconds = 30
period_seconds = 10
timeout_seconds = 5
success_threshold = 1
failure_threshold = 3
http_get {
path = "/v1/version"
port = 5080
scheme = "http"
}
}

liveness_probe {
initial_delay_seconds = 30
period_seconds = 10
timeout_seconds = 5
success_threshold = 1
failure_threshold = 3
http_get {
path = "/v1/version"
port = 5080
scheme = "http"
}
}
}

diagnostics {
log_analytics {
workspace_id = data.azurerm_log_analytics_workspace.main.workspace_id
workspace_key = data.azurerm_log_analytics_workspace.main.primary_shared_key
}
}

lifecycle {
action_trigger {
events = [before_create]
actions = [action.local_command.build_cygnus]
}
}

depends_on = [
azurerm_container_group.postgres_cli,
azurerm_role_assignment.acr_rbac_cygnus_pull
]
}

# ワンショット: Orion サブスクリプション登録(happiness エンティティ変更 → Cygnus 通知)。
# VNet 内で実行し、プライベート IP で Orion / Cygnus に到達する。パブリックイメージのみ使用。
# ワンショット: Orion サブスクリプション登録(happiness エンティティ変更 → Backend 通知)。
# VNet 内で実行し、プライベート IP で Orion に到達する。パブリックイメージのみ使用。
resource "azurerm_container_group" "orion_subscription" {
name = "${local.prefix}-aci-orion-subscription"
location = local.location
Expand All @@ -335,7 +235,6 @@ resource "azurerm_container_group" "orion_subscription" {

environment_variables = {
ORION_IP = azurerm_container_group.orion.ip_address
CYGNUS_IP = azurerm_container_group.cygnus.ip_address
FIWARE_SERVICE = var.orion_fiware_service
FIWARE_SERVICE_PATH = var.orion_fiware_service_path
SUBSCRIPTION_BODY = jsonencode({
Expand All @@ -346,7 +245,7 @@ resource "azurerm_container_group" "orion_subscription" {
}
notification = {
http = {
url = "http://${azurerm_container_group.cygnus.ip_address}:5055/notify"
url = "https://backend.${local.root_domain_name}/change-histories/notify"
}
}
})
Expand All @@ -357,6 +256,6 @@ resource "azurerm_container_group" "orion_subscription" {

depends_on = [
azurerm_container_group.orion,
azurerm_container_group.cygnus
azurerm_linux_web_app.backend
]
}
18 changes: 0 additions & 18 deletions infra/terraform/app/acr.tf
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,6 @@ action "local_command" "build_mongo_cli" {
}
}

data "azurerm_user_assigned_identity" "cygnus" {
name = data.terraform_remote_state.platform.outputs.user_assigned_identity_cygnus_name
resource_group_name = local.resource_group_name
}

resource "azurerm_role_assignment" "acr_rbac_cygnus_pull" {
principal_id = data.azurerm_user_assigned_identity.cygnus.principal_id
role_definition_name = "AcrPull"
scope = azurerm_container_registry.main.id
}

action "local_command" "build_cygnus" {
config {
command = "az"
arguments = ["acr", "build", "--no-logs", "-r", azurerm_container_registry.main.name, "-t", var.aci_cygnus_image_tag, "../../../fiware/cygnus"]
}
}

data "azurerm_user_assigned_identity" "postgres_cli" {
name = data.terraform_remote_state.platform.outputs.user_assigned_identity_postgres_cli_name
resource_group_name = local.resource_group_name
Expand Down
1 change: 1 addition & 0 deletions infra/terraform/app/app_services.tf
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ resource "azurerm_linux_web_app" "backend" {
POSTGRES_PASSWORD = "@Microsoft.KeyVault(SecretUri=${data.azurerm_key_vault.main.vault_uri}secrets/${data.azurerm_key_vault_secret.cygnus_postgres_password.name})"
POSTGRES_DATABASE = "cygnus"
REVERSE_GEOCODING_URL = var.reverse_geocoding_url
USER_AGENT_EMAIL = var.user_agent_email
}

https_only = true
Expand Down
55 changes: 4 additions & 51 deletions infra/terraform/app/monitor_alerts_orion_cygnus.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Log Analytics スケジュールクエリアラート: Orion(Cygnus 通知経路)と Cygnus(PostgreSQL 永続化)。
# Log Analytics スケジュールクエリアラート: Orion(履歴通知経路)。
# プラットフォームのアクショングループが存在する場合のみ作成(monitor_alerts.tf と同様)。

locals {
orion_cygnus_alert_count = length(data.terraform_remote_state.platform.outputs.action_group_id) > 0 ? 1 : 0
orion_alert_count = length(data.terraform_remote_state.platform.outputs.action_group_id) > 0 ? 1 : 0
}

resource "time_sleep" "wait_for_orion_logs" {
Expand All @@ -11,12 +11,12 @@ resource "time_sleep" "wait_for_orion_logs" {
}

resource "azurerm_monitor_scheduled_query_rules_alert_v2" "orion_history_notify_failure" {
count = local.orion_cygnus_alert_count
count = local.orion_alert_count

name = "${azurerm_container_group.orion.name}-ALERT-HistoryNotifyFailure"
resource_group_name = local.resource_group_name
location = data.azurerm_log_analytics_workspace.main.location
description = "Orion: notification to Cygnus failed or non-numeric HTTP response on Notif delivered (history pipeline)."
description = "Orion: notification delivery failure on history pipeline."
display_name = "${azurerm_container_group.orion.name} History notify failure"
severity = 1
enabled = true
Expand Down Expand Up @@ -53,50 +53,3 @@ resource "azurerm_monitor_scheduled_query_rules_alert_v2" "orion_history_notify_

depends_on = [time_sleep.wait_for_orion_logs]
}

resource "time_sleep" "wait_for_cygnus_logs" {
depends_on = [azurerm_container_group.cygnus]
create_duration = "180s"
}

resource "azurerm_monitor_scheduled_query_rules_alert_v2" "cygnus_history_persistence_failure" {
count = local.orion_cygnus_alert_count

name = "${azurerm_container_group.cygnus.name}-ALERT-HistoryPersistenceFailure"
resource_group_name = local.resource_group_name
location = data.azurerm_log_analytics_workspace.main.location
description = "Cygnus: PostgreSQL persistence error (CygnusPersistenceError / connection error) on history sink."
display_name = "${azurerm_container_group.cygnus.name} History persistence failure"
severity = 1
enabled = true
evaluation_frequency = "PT5M"
window_duration = "PT10M"
scopes = [data.azurerm_log_analytics_workspace.main.id]

criteria {
query = <<-KQL
ContainerInstanceLog_CL
| where TimeGenerated > ago(10m)
| where ContainerName_s == 'cygnus'
| where Message has 'CygnusPersistenceError' or Message has 'POSTGRESQL Connection error'
| summarize count()
KQL

time_aggregation_method = "Count"
threshold = 0
operator = "GreaterThan"

failing_periods {
minimum_failing_periods_to_trigger_alert = 1
number_of_evaluation_periods = 1
}
}

action {
action_groups = [data.terraform_remote_state.platform.outputs.action_group_id]
}

auto_mitigation_enabled = true

depends_on = [time_sleep.wait_for_cygnus_logs]
}
1 change: 0 additions & 1 deletion infra/terraform/app/terraform.tfvars.example
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ acme_server_url = "https://acme-v02.api.letsencrypt.org/directory"
# acme_server_url = "https://acme-staging-v02.api.letsencrypt.org/directory"

aci_orion_image_tag = "orion:latest"
aci_cygnus_image_tag = "cygnus:latest"
aci_mongo_cli_image_tag = "mongo-cli:latest"
aci_postgres_cli_image_tag = "postgres-cli:latest"

Expand Down
14 changes: 7 additions & 7 deletions infra/terraform/app/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ variable "reverse_geocoding_url" {
default = "https://nominatim.openstreetmap.org/reverse"
}

variable "user_agent_email" {
description = "User Agent Email for backend"
type = string
default = "TISI_WB@ml.tisi.jp"
}

variable "app_keycloak_name" {
description = "App Service name for Keycloak (globally unique)."
type = string
Expand Down Expand Up @@ -154,19 +160,13 @@ variable "app_keycloak_admin_password" {
sensitive = true
}

# --- ACI(Orion, Cygnus)---
# --- ACI(Orion)---
variable "aci_orion_image_tag" {
description = "Container image tag for Orion ACI."
type = string
default = "orion:latest"
}

variable "aci_cygnus_image_tag" {
description = "Container image tag for Cygnus ACI."
type = string
default = "cygnus:latest"
}

# --- ACI mongo-cli(ワンショット MongoDB インデックス作成)---
variable "aci_mongo_cli_image_tag" {
description = "Container image tag for mongo-cli ACI (one-shot MongoDB index creation)."
Expand Down
Loading