Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// Application Insights module
|
||||
|
||||
@description('The environment name (DEV, IAT, Prod)')
|
||||
param environment string
|
||||
|
||||
@description('The location for Application Insights')
|
||||
param location string
|
||||
|
||||
@description('Tags to apply to resources')
|
||||
param tags object
|
||||
|
||||
@description('Unique token for resource naming')
|
||||
param resourceToken string
|
||||
|
||||
@description('Key Vault name for storing connection string')
|
||||
param keyVaultName string
|
||||
|
||||
var appInsightsName = 'appi-dbp-${toLower(environment)}-${resourceToken}'
|
||||
var logAnalyticsWorkspaceName = 'log-dbp-${toLower(environment)}-${resourceToken}'
|
||||
|
||||
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' = {
|
||||
name: logAnalyticsWorkspaceName
|
||||
location: location
|
||||
tags: tags
|
||||
properties: {
|
||||
sku: {
|
||||
name: 'PerGB2018'
|
||||
}
|
||||
retentionInDays: environment == 'Prod' ? 90 : 30
|
||||
features: {
|
||||
enableLogAccessUsingOnlyResourcePermissions: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
|
||||
name: appInsightsName
|
||||
location: location
|
||||
tags: tags
|
||||
kind: 'web'
|
||||
properties: {
|
||||
Application_Type: 'web'
|
||||
WorkspaceResourceId: logAnalyticsWorkspace.id
|
||||
IngestionMode: 'LogAnalytics'
|
||||
publicNetworkAccessForIngestion: 'Enabled'
|
||||
publicNetworkAccessForQuery: 'Enabled'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resource keyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = {
|
||||
name: keyVaultName
|
||||
}
|
||||
|
||||
resource connectionStringSecret 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = {
|
||||
parent: keyVault
|
||||
name: 'applicationinsights-connection-string'
|
||||
properties: {
|
||||
value: applicationInsights.properties.ConnectionString
|
||||
attributes: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output applicationInsightsName string = applicationInsights.name
|
||||
output applicationInsightsId string = applicationInsights.id
|
||||
output connectionString string = applicationInsights.properties.ConnectionString
|
||||
output instrumentationKey string = applicationInsights.properties.InstrumentationKey
|
||||
output logAnalyticsWorkspaceId string = logAnalyticsWorkspace.id
|
||||
output logAnalyticsWorkspaceName string = logAnalyticsWorkspace.name
|
||||
@@ -0,0 +1,18 @@
|
||||
// Container App Environment Certificate module (existing)
|
||||
|
||||
@description('Container App Environment name')
|
||||
param containerAppEnvironmentName string
|
||||
|
||||
@description('Certificate name in the Container App Environment')
|
||||
param certificateName string
|
||||
|
||||
resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2025-01-01' existing = {
|
||||
name: containerAppEnvironmentName
|
||||
}
|
||||
|
||||
resource containerAppCertificate 'Microsoft.App/managedEnvironments/certificates@2025-01-01' existing = {
|
||||
name: certificateName
|
||||
parent: containerAppEnvironment
|
||||
}
|
||||
|
||||
output certificateId string = containerAppCertificate.id
|
||||
@@ -0,0 +1,206 @@
|
||||
// Container App module for DB Planet MCP Server
|
||||
|
||||
@description('The environment name (DEV, IAT, Prod)')
|
||||
param environment string
|
||||
|
||||
@description('The location for the Container App')
|
||||
param location string
|
||||
|
||||
@description('Tags to apply to resources')
|
||||
param tags object
|
||||
|
||||
@description('Unique token for resource naming')
|
||||
param resourceToken string
|
||||
|
||||
@description('Existing central Key Vault name (shared secrets)')
|
||||
param centralKeyVaultName string
|
||||
|
||||
@description('Existing central Key Vault resource group')
|
||||
param centralKeyVaultResourceGroup string
|
||||
|
||||
@description('App-specific Key Vault URI (created by keyvault.bicep)')
|
||||
param appKeyVaultUri string
|
||||
|
||||
@description('Existing Container App Environment name')
|
||||
param containerAppEnvironmentName string
|
||||
|
||||
@description('Existing Container App Environment resource group')
|
||||
param containerAppEnvironmentResourceGroup string
|
||||
|
||||
@description('Artifactory server URL for container registry')
|
||||
param artifactoryServer string
|
||||
|
||||
@description('Registry username for container registry authentication')
|
||||
param registryUsername string
|
||||
|
||||
@description('Managed Identity ID for Key Vault access')
|
||||
param managedIdentityId string
|
||||
|
||||
@description('Container image tag/version')
|
||||
param imageTag string = 'latest'
|
||||
|
||||
@description('DB Planet base URL (staging vs production)')
|
||||
param dbplanetBaseUrl string
|
||||
|
||||
@description('Custom domain name for the Container App')
|
||||
param customDomainName string = ''
|
||||
|
||||
@description('Container App Certificate ID (if custom domain is configured)')
|
||||
param containerAppCertificateId string = ''
|
||||
|
||||
var containerAppName = 'ca-dbp-${toLower(environment)}-${take(resourceToken, 8)}'
|
||||
|
||||
// Custom domain configuration
|
||||
var customDomain = !empty(customDomainName) && !empty(containerAppCertificateId) ? [
|
||||
{
|
||||
name: customDomainName
|
||||
certificateId: containerAppCertificateId
|
||||
bindingType: 'SniEnabled'
|
||||
}
|
||||
] : []
|
||||
|
||||
// Reference existing central Key Vault
|
||||
resource centralKeyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = {
|
||||
name: centralKeyVaultName
|
||||
scope: resourceGroup(centralKeyVaultResourceGroup)
|
||||
}
|
||||
|
||||
|
||||
// Reference existing Container App Environment
|
||||
resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2025-01-01' existing = {
|
||||
name: containerAppEnvironmentName
|
||||
scope: resourceGroup(containerAppEnvironmentResourceGroup)
|
||||
}
|
||||
|
||||
// Container App
|
||||
resource containerApp 'Microsoft.App/containerApps@2025-01-01' = {
|
||||
name: containerAppName
|
||||
location: location
|
||||
tags: tags
|
||||
identity: {
|
||||
type: 'SystemAssigned, UserAssigned'
|
||||
userAssignedIdentities: {
|
||||
'${managedIdentityId}': {}
|
||||
}
|
||||
}
|
||||
properties: {
|
||||
managedEnvironmentId: containerAppEnvironment.id
|
||||
workloadProfileName: 'Consumption'
|
||||
configuration: {
|
||||
ingress: {
|
||||
external: true
|
||||
targetPort: 4000
|
||||
allowInsecure: false
|
||||
customDomains: customDomain
|
||||
traffic: [
|
||||
{
|
||||
weight: 100
|
||||
latestRevision: true
|
||||
}
|
||||
]
|
||||
}
|
||||
secrets: [
|
||||
{
|
||||
name: 'artifactory-token'
|
||||
keyVaultUrl: '${centralKeyVault.properties.vaultUri}secrets/artifactory-registry-token'
|
||||
identity: managedIdentityId
|
||||
}
|
||||
{
|
||||
name: 'appinsights-connection-string'
|
||||
keyVaultUrl: '${appKeyVaultUri}secrets/applicationinsights-connection-string'
|
||||
identity: 'system'
|
||||
}
|
||||
{
|
||||
name: 'dbplanet-username'
|
||||
keyVaultUrl: '${appKeyVaultUri}secrets/DBPLANET-USERNAME'
|
||||
identity: 'system'
|
||||
}
|
||||
{
|
||||
name: 'dbplanet-password'
|
||||
keyVaultUrl: '${appKeyVaultUri}secrets/DBPLANET-PASSWORD'
|
||||
identity: 'system'
|
||||
}
|
||||
{
|
||||
name: 'dbplanet-client-id'
|
||||
keyVaultUrl: '${appKeyVaultUri}secrets/DBPLANET-CLIENT-ID'
|
||||
identity: 'system'
|
||||
}
|
||||
{
|
||||
name: 'dbplanet-client-secret'
|
||||
keyVaultUrl: '${appKeyVaultUri}secrets/DBPLANET-CLIENT-SECRET'
|
||||
identity: 'system'
|
||||
}
|
||||
]
|
||||
registries: [
|
||||
{
|
||||
server: artifactoryServer
|
||||
username: registryUsername
|
||||
passwordSecretRef: 'artifactory-token'
|
||||
}
|
||||
]
|
||||
}
|
||||
template: {
|
||||
containers: [
|
||||
{
|
||||
name: 'dbplanet-mcp'
|
||||
image: '${artifactoryServer}/db-planet-mcp-server:${imageTag}'
|
||||
resources: {
|
||||
cpu: json(environment == 'Prod' ? '1.0' : '0.5')
|
||||
memory: environment == 'Prod' ? '2Gi' : '1Gi'
|
||||
}
|
||||
env: [
|
||||
{ name: 'DBPLANET_BASE_URL', value: dbplanetBaseUrl }
|
||||
{ name: 'DBPLANET_USERNAME', secretRef: 'dbplanet-username' }
|
||||
{ name: 'DBPLANET_PASSWORD', secretRef: 'dbplanet-password' }
|
||||
{ name: 'DBPLANET_CLIENT_ID', secretRef: 'dbplanet-client-id' }
|
||||
{ name: 'DBPLANET_CLIENT_SECRET', secretRef: 'dbplanet-client-secret' }
|
||||
{ name: 'NODE_ENV', value: environment == 'Prod' ? 'production' : 'development' }
|
||||
{ name: 'HTTP_PROXY', value: 'http://webproxy.comp.db.de:8080' }
|
||||
{ name: 'HTTPS_PROXY', value: 'http://webproxy.comp.db.de:8080' }
|
||||
{ name: 'http_proxy', value: 'http://webproxy.comp.db.de:8080' }
|
||||
{ name: 'https_proxy', value: 'http://webproxy.comp.db.de:8080' }
|
||||
{ name: 'NO_PROXY', value: '169.254.169.254,169.254.170.2,cognitiveservices.azure.com,internal.deutschebahn.com,db.de' }
|
||||
{ name: 'no_proxy', value: '169.254.169.254,169.254.170.2,cognitiveservices.azure.com,internal.deutschebahn.com,db.de' }
|
||||
{ name: 'STREAMABLE_HTTP', value: 'true' }
|
||||
{ name: 'REMOTE_AUTHORIZATION', value: 'true' }
|
||||
{ name: 'HOST', value: '0.0.0.0' }
|
||||
{
|
||||
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
|
||||
secretRef: 'appinsights-connection-string'
|
||||
}
|
||||
]
|
||||
probes: [
|
||||
{
|
||||
type: 'Readiness'
|
||||
httpGet: {
|
||||
path: '/health'
|
||||
port: 4000
|
||||
}
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 30
|
||||
}
|
||||
{
|
||||
type: 'Liveness'
|
||||
httpGet: {
|
||||
path: '/health'
|
||||
port: 4000
|
||||
}
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 60
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
scale: {
|
||||
minReplicas: 1
|
||||
maxReplicas: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output containerAppName string = containerApp.name
|
||||
output containerAppId string = containerApp.id
|
||||
output containerAppFqdn string = containerApp.properties.configuration.ingress.fqdn
|
||||
output systemIdentityPrincipalId string = containerApp.identity.principalId
|
||||
output containerAppEnvironmentStaticIp string = containerAppEnvironment.properties.staticIp
|
||||
@@ -0,0 +1,30 @@
|
||||
// DNS A Record module for Container App access
|
||||
|
||||
@description('Private DNS Zone name')
|
||||
param privateDnsZoneName string
|
||||
|
||||
@description('A Record name (subdomain)')
|
||||
param aRecordName string
|
||||
|
||||
@description('IPv4 address to point to')
|
||||
param ipv4Address string
|
||||
|
||||
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = {
|
||||
name: privateDnsZoneName
|
||||
}
|
||||
|
||||
resource aRecord 'Microsoft.Network/privateDnsZones/A@2020-06-01' = {
|
||||
name: aRecordName
|
||||
parent: privateDnsZone
|
||||
properties: {
|
||||
ttl: 3600
|
||||
aRecords: [
|
||||
{
|
||||
ipv4Address: ipv4Address
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
output recordName string = aRecord.name
|
||||
output fqdn string = '${aRecordName}.${privateDnsZoneName}'
|
||||
@@ -0,0 +1,59 @@
|
||||
// Key Vault permissions module - reusable for different roles and principals
|
||||
|
||||
@description('Key Vault name')
|
||||
param keyVaultName string
|
||||
|
||||
@description('Principal ID for Key Vault access')
|
||||
param principalId string
|
||||
|
||||
@description('Principal type (User, Group, ServicePrincipal)')
|
||||
@allowed(['User', 'Group', 'ServicePrincipal'])
|
||||
param principalType string = 'ServicePrincipal'
|
||||
|
||||
@description('Key Vault role to assign')
|
||||
@allowed([
|
||||
'Key Vault Administrator'
|
||||
'Key Vault Certificates Officer'
|
||||
'Key Vault Crypto Officer'
|
||||
'Key Vault Crypto Service Encryption User'
|
||||
'Key Vault Crypto User'
|
||||
'Key Vault Reader'
|
||||
'Key Vault Secrets Officer'
|
||||
'Key Vault Secrets User'
|
||||
])
|
||||
param roleName string = 'Key Vault Secrets User'
|
||||
|
||||
var roleDefinitions = {
|
||||
// gitleaks:allow
|
||||
'Key Vault Administrator': '00482a5a-887f-4fb3-b363-3b7fe8e74483'
|
||||
'Key Vault Certificates Officer': 'a4417e6f-fecd-4de8-b567-7b0420556985'
|
||||
'Key Vault Crypto Officer': '14b46e9e-c2b7-41b4-b07b-48a6ebf60603'
|
||||
'Key Vault Crypto Service Encryption User': 'e147488a-f6f5-4113-8e2d-b22465e65bf6'
|
||||
// gitleaks:allow
|
||||
'Key Vault Crypto User': '12338af0-0e69-4776-bea7-57ae8d297424'
|
||||
// gitleaks:allow
|
||||
'Key Vault Reader': '21090545-7ca7-4776-b22c-e363652d74d2'
|
||||
// gitleaks:allow
|
||||
'Key Vault Secrets Officer': 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7'
|
||||
// gitleaks:allow
|
||||
'Key Vault Secrets User': '4633458b-17de-408a-b874-0445c86b69e6'
|
||||
}
|
||||
|
||||
var roleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitions[roleName])
|
||||
|
||||
resource keyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = {
|
||||
name: keyVaultName
|
||||
}
|
||||
|
||||
resource keyVaultRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
|
||||
name: guid(keyVault.id, principalId, roleName)
|
||||
scope: keyVault
|
||||
properties: {
|
||||
roleDefinitionId: roleDefinitionId
|
||||
principalId: principalId
|
||||
principalType: principalType
|
||||
}
|
||||
}
|
||||
|
||||
output roleAssignmentId string = keyVaultRoleAssignment.id
|
||||
output roleAssignmentName string = keyVaultRoleAssignment.name
|
||||
@@ -0,0 +1,47 @@
|
||||
// Azure Key Vault module (public access, no Private Endpoint)
|
||||
|
||||
@description('The environment name (DEV, IAT, Prod)')
|
||||
param environment string
|
||||
|
||||
@description('The location for the Key Vault')
|
||||
param location string
|
||||
|
||||
@description('Tags to apply to resources')
|
||||
param tags object
|
||||
|
||||
@description('Unique token for resource naming')
|
||||
param resourceToken string
|
||||
|
||||
@description('The tenant ID for Key Vault access')
|
||||
param tenantId string = subscription().tenantId
|
||||
|
||||
var keyVaultName = 'kv-dbp-${toLower(environment)}-${take(resourceToken, 8)}'
|
||||
|
||||
resource keyVault 'Microsoft.KeyVault/vaults@2024-11-01' = {
|
||||
name: keyVaultName
|
||||
location: location
|
||||
tags: tags
|
||||
properties: {
|
||||
sku: {
|
||||
family: 'A'
|
||||
name: 'standard'
|
||||
}
|
||||
tenantId: tenantId
|
||||
enabledForDeployment: false
|
||||
enabledForDiskEncryption: true
|
||||
enabledForTemplateDeployment: true
|
||||
enableSoftDelete: true
|
||||
softDeleteRetentionInDays: 7
|
||||
enablePurgeProtection: true
|
||||
enableRbacAuthorization: true
|
||||
publicNetworkAccess: 'Enabled'
|
||||
networkAcls: {
|
||||
defaultAction: 'Allow'
|
||||
bypass: 'AzureServices'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output keyVaultName string = keyVault.name
|
||||
output keyVaultId string = keyVault.id
|
||||
output keyVaultUri string = keyVault.properties.vaultUri
|
||||
@@ -0,0 +1,26 @@
|
||||
// User Managed Identity module
|
||||
|
||||
@description('The environment name (DEV, IAT, Prod)')
|
||||
param environment string
|
||||
|
||||
@description('The location for the managed identity')
|
||||
param location string
|
||||
|
||||
@description('Tags to apply to resources')
|
||||
param tags object
|
||||
|
||||
@description('Unique token for resource naming')
|
||||
param resourceToken string
|
||||
|
||||
var managedIdentityName = 'id-dbplanet-${toLower(environment)}-${resourceToken}'
|
||||
|
||||
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = {
|
||||
name: managedIdentityName
|
||||
location: location
|
||||
tags: tags
|
||||
}
|
||||
|
||||
output managedIdentityName string = managedIdentity.name
|
||||
output managedIdentityId string = managedIdentity.id
|
||||
output managedIdentityPrincipalId string = managedIdentity.properties.principalId
|
||||
output managedIdentityClientId string = managedIdentity.properties.clientId
|
||||
@@ -0,0 +1,21 @@
|
||||
// Resource Group module
|
||||
|
||||
targetScope = 'subscription'
|
||||
|
||||
@description('The resource group name')
|
||||
param resourceGroupName string
|
||||
|
||||
@description('The location for the resource group')
|
||||
param location string
|
||||
|
||||
@description('Tags to apply to the resource group')
|
||||
param tags object
|
||||
|
||||
resource resourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' = {
|
||||
name: resourceGroupName
|
||||
location: location
|
||||
tags: tags
|
||||
}
|
||||
|
||||
output resourceGroupName string = resourceGroup.name
|
||||
output resourceGroupId string = resourceGroup.id
|
||||
Reference in New Issue
Block a user