Skip to content

Commit

Permalink
chore: Refactor IAC (#644)
Browse files Browse the repository at this point in the history
- [ ] ~~New feature~~
- [ ] ~~Bug fix~~
- [ ] ~~High impact~~

**Description of work:**
Refactor pipelines and move to seperate devops project. 
Will require some adjustments to align with more segregated service
principal structure.


**Testing:**
- [ ] ~~Can be tested~~
- [ ] ~~Automatic tests created / updated~~
- [ ] ~~Local tests are passing~~

n/a


**Checklist:**
- [ ] Considered automated tests
- [ ] Considered updating specification / documentation
- [ ] Considered work items 
- [ ] Considered security
- [ ] Performed developer testing
- [ ] Checklist finalized / ready for review
  • Loading branch information
HansDahle authored Aug 14, 2024
1 parent fc7ae92 commit c5f8069
Show file tree
Hide file tree
Showing 37 changed files with 1,002 additions and 346 deletions.
52 changes: 52 additions & 0 deletions infrastructure/app-registrations/sp-non-prod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"id": "fab7c06b-0779-4eee-b628-87fd25361f80",
// appId: b6dc16db-85f7-41e4-afad-5f1a07c5961c

"displayName": "DevOps SP - Fusion resource allocation - non-production",
"notes": "DevOps Service Principal - Non-Production\nFusion Resource Allocation solution.\n\nShould have access to non-production environments/resources.",
"serviceManagementReference": "107767",
"tags": ["fra", "fusion", "iac-automation", "production", "backup-enabled"],
"web": {
"homePageUrl": "https://statoil-proview.visualstudio.com/Fusion%20Resource%20Allocation/_build",
"implicitGrantSettings": {
"enableAccessTokenIssuance": false,
"enableIdTokenIssuance": false
},
"logoutUrl": null,
"redirectUriSettings": [],
"redirectUris": []
},
"requiredResourceAccess": [
{
// Statoil ProView Test
"resourceAppId": "5a842df8-3238-415d-b168-9f16a6a6031b",
"resourceAccess": [
{
// Fusion.Apps.Create
"id": "885260ee-8b4c-4841-863f-85f5289fcbfb",
"type": "Role"
}
]
},
{
// Fusion Infrastructure Support
"resourceAppId": "8ab89850-219a-4929-a726-5a7a496efac2",
"resourceAccess": [
{
// Fusion.Infrastructure.Database.Manage
"id": "345143e5-eecd-47ff-a6e5-d8b8f54cad5f",
"type": "Role"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "18a4783c-866b-4cc7-a460-3d5e5662c884",
"type": "Role"
}
]
}
]
}
52 changes: 52 additions & 0 deletions infrastructure/app-registrations/sp-prod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"displayName": "DevOps SP - Fusion resource allocation - production",
"id": "555b9404-0898-421a-b094-41c5b671bc84",
// appId: 3363e160-679c-48c0-8b87-022352cd565c
"notes": "DevOps Service Principal - Non-Production\nFusion Resource Allocation solution.\n\nShould have access to production environments/resources.\n- azure resource groups\n- fusion app creation\n- fusion infra management",
"serviceManagementReference": "107767",
"tags": ["fra", "fusion", "iac-automation", "production", "backup-enabled"],

"web": {
"homePageUrl": "https://statoil-proview.visualstudio.com/Fusion%20Resource%20Allocation/_build",
"implicitGrantSettings": {
"enableAccessTokenIssuance": false,
"enableIdTokenIssuance": false
},
"logoutUrl": null,
"redirectUriSettings": [],
"redirectUris": []
},
"requiredResourceAccess": [
{
// Statoil ProView
"resourceAppId": "97978493-9777-4d48-b38a-67b0b9cd88d2",
"resourceAccess": [
{
// Fusion.Apps.Create
"id": "885260ee-8b4c-4841-863f-85f5289fcbfb",
"type": "Role"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "18a4783c-866b-4cc7-a460-3d5e5662c884",
"type": "Role"
}
]
},
{
// Fusion Infrastructure Support,
"resourceAppId": "8ab89850-219a-4929-a726-5a7a496efac2",
"resourceAccess": [
{
// Fusion.Infrastructure.Database.Manage
"id": "345143e5-eecd-47ff-a6e5-d8b8f54cad5f",
"type": "Role"
}
]
}
]
}
74 changes: 74 additions & 0 deletions infrastructure/arm/database.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"env-name": { "type": "string" },

"sqlserver_name": {
"defaultValue": "fusion-test-sqlserver",
"type": "String"
},
"sql-elastic-pool-id": {
"type": "string"
},
"fcore-env": { "type": "string", "allowedValues": ["test", "prod"] }
},
"variables": {
"db-name": "[concat('Fusion-Apps-Resources-', toUpper(parameters('env-name')), '-DB')]",
"summary-db-name": "[concat('sqldb-fapp-fra-summary-db-', toUpper(parameters('env-name')))]"
},
"resources": [
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2019-06-01-preview",
"name": "[concat(parameters('sqlserver_name'), '/', variables('db-name'))]",
"location": "northeurope",
"tags": {
"fusion-app": "resources",
"fusion-app-env": "[toLower(parameters('env-name'))]",
"fusion-app-component-type": "db",
"fusion-app-component-id": "[concat('resources-api-db-', toLower(parameters('env-name')))]",
"adm-acg": "acg-fusion-resource-allocation",
"dev-acg": "acg-fusion-resource-allocation",
"fcore-env": "[parameters('fcore-env')]"
},
"kind": "v12.0,user,pool",
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": 268435456000,
"elasticPoolId": "[parameters('sql-elastic-pool-id')]",
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"zoneRedundant": false,
"readScale": "Disabled",
"readReplicaCount": 0,
"storageAccountType": "GRS"
}
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2019-06-01-preview",
"name": "[concat(parameters('sqlserver_name'), '/', variables('summary-db-name'))]",
"location": "northeurope",
"tags": {
"fusion-app": "resources",
"fusion-app-env": "[toLower(parameters('env-name'))]",
"fusion-app-component-type": "db",
"fusion-app-component-id": "[concat('summary-api-db-', toLower(parameters('env-name')))]",
"adm-acg": "acg-fusion-resource-allocation",
"dev-acg": "acg-fusion-resource-allocation",
"fcore-env": "[parameters('fcore-env')]"
},
"kind": "v12.0,user,pool",
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": 268435456000,
"elasticPoolId": "[parameters('sql-elastic-pool-id')]",
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"zoneRedundant": false,
"readScale": "Disabled",
"readReplicaCount": 0,
"storageAccountType": "GRS"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"contentVersion": "1.0.0.0",
"parameters": {
"env-name": { "type": "string" },
"sql-connection-string": { "type": "string", "metadata": { "description": "Conection string without username/password"} }
"sql-connection-string": { "type": "string", "metadata": { "description": "Conection string without username/password"} },
"summary-sql-connection-string": { "type": "string", "metadata": { "description": "Conection string without username/password"} }
},
"variables": {
"env-name": "[toLower(parameters('env-name'))]",
Expand Down Expand Up @@ -34,6 +35,7 @@
"enabledForTemplateDeployment": false,
"enabledForDiskEncryption": false,
"enableRbacAuthorization": false,
"enableSoftDelete": true,
"tenantId": "[subscription().tenantId]",
"accessPolicies": [
{
Expand Down Expand Up @@ -219,6 +221,17 @@
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', variables('keyvault-name'))]"
]
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2015-06-01",
"name": "[concat(variables('keyvault-name'), '/', 'Connectionstrings--SummaryDbContext')]",
"properties": {
"value": "[parameters('summary-sql-connection-string')]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', variables('keyvault-name'))]"
]
}
]
}
83 changes: 83 additions & 0 deletions infrastructure/azure-infra-setup.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#
# Idempotent script to ensure relevant baseline-infrastructure is available
#
# This script should be safe to execute multiple times.
# App owners are not removed, only appended.
#
# App registrations should be created be a normal user.
# - Required roles will differ, as non-prod and prod targets different external apis.
#
#
# User running the script must have permissions
# - Owner on subscription -> to set roles
# - Owner on app registrations -> to update
# - Owner on service principals connected to app registrations
#
# https://github.com/equinor/fusion-core-services/pull/969/files

param(
[switch]$ServicePrincipals
)

function Configure-DevOps-AppRegistration($appReg, $owners) {
Write-Host "Patching [$($appReg.name)]"
Write-Host (ConvertTo-Json $appReg)
az rest -m patch -u "https://graph.microsoft.com/v1.0/applications/$($appReg.objectId)" `
--headers 'Content-Type=application/json' `
--body "@$PSScriptRoot\app-registrations\$($appReg.configFile)"

$existingServicePrincipalOwners = (az ad sp owner list --id $appReg.managedIdentity) | ConvertFrom-Json
$existingServicePrincipalOwners

Write-Host "Setting owners"
foreach ($owner in $owners) {
Write-Host "- Adding [$($owner.upn)]"
az ad app owner add --id $appReg.appId --owner-object-id $owner.objectId

if ($existingServicePrincipalOwners | Where-Object { $_.id -eq $owner.objectId }) {
Write-Host "- User is already owner on service principal"
} else {
Write-Host "- Adding [$($owner.upn)] to service principal owner list"

## Construct the payload.
## Shitty stuff.. doublequotes must be escaped for the json to be valid.
$ownerData = @{ "[email protected]" = @("https://graph.microsoft.com/v1.0/users/$($owner.objectId)") } | ConvertTo-Json -Compress

az rest -m patch -u "https://graph.microsoft.com/v1.0/servicePrincipals/$($appReg.managedIdentity)" `
--headers 'Content-Type=application/json' `
--body $ownerData.Replace("`"", "\`"")
}
}
}

# Load infra config.
$infraConfig = ConvertFrom-Json (Get-Content -Raw "$PSScriptRoot\config.json")

##
## Patch app regs to match the defined json in config files `app-registrations/*`.
## - Name, description, CI ++
## - Api permissions
## Adds owners
##
foreach ($appReg in @($infraConfig.spAppRegs.nonProduction, $infraConfig.spAppRegs.production)) {
Configure-DevOps-AppRegistration `
-appReg $appReg `
-owners $infraConfig.appRegOwners
}

if ($ServicePrincipals.IsPresent) {
return
}

##
## Subscription permission setup
## Add roles to resource groups based on config json.
##
foreach ($roleAssignment in $infraConfig.resourceGroups) {
Write-Host "Creating role assignment [$($roleAssignment.roleName)] for rg [$($roleAssignment.name)] to sp [$($roleAssignment.managedIdentity)]"
az role assignment create `
--assignee $roleAssignment.managedIdentity `
--role $roleAssignment.roleName `
--scope "/subscriptions/$($infraConfig.subscriptionId)/resourceGroups/$($roleAssignment.name)"
}

89 changes: 89 additions & 0 deletions infrastructure/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"subscriptionId": "63b791ae-b2bc-41a1-ac66-806c4e69bffe",
"appRegOwners": [
{
"upn": "[email protected]",
"objectId": "f59e967d-8422-41ae-8980-a47f3ac0b70c"
},
{
"upn": "[email protected]",
"objectId": "0a9c3e47-52b3-43fe-ab2c-0c56ffc3155b"
},
{
"upn": "[email protected]",
"objectId": "0bd99c23-64f4-477e-a18c-79a42c4cd709"
},
{
"upn": "[email protected]",
"objectId": "d8d9fa2f-ecee-4cfb-a371-a39e8c1b76aa"
},
{
"upn": "[email protected]",
"objectId": "f9158061-e8e3-494a-acbe-afcb6bc9f7ab"
}
],

"spAppRegs": {
"production": {
"name": "DevOps SP - Fusion resource allocation - production",
"appId": "3363e160-679c-48c0-8b87-022352cd565c",
"objectId": "555b9404-0898-421a-b094-41c5b671bc84",
"managedIdentity": "ad3ca9c7-dd10-423c-96e0-137c8b26ae9f",
"configFile": "sp-prod.json",
"apiPermissions": [
{
"id": "18a4783c-866b-4cc7-a460-3d5e5662c884",
"name": "Application.ReadWrite.OwnedBy",
"type": "graph"
}
]
},
"nonProduction": {
"name": "DevOps SP - Fusion resource allocation - non-production",
"appId": "b6dc16db-85f7-41e4-afad-5f1a07c5961c",
"objectId": "fab7c06b-0779-4eee-b628-87fd25361f80",
"managedIdentity": "6f29795a-2712-4e66-a119-ea082d8b4201",
"configFile": "sp-non-prod.json",
"apiPermissions": [
{
"id": "18a4783c-866b-4cc7-a460-3d5e5662c884",
"name": "Application.ReadWrite.OwnedBy",
"type": "graph"
}
]
}
},

"resourceGroups": [
{
"name": "fusion-apps-resources-ci",
"managedIdentity": "6f29795a-2712-4e66-a119-ea082d8b4201",
"roleName": "Contributor"
},
{
"name": "fusion-apps-resources-fqa",
"managedIdentity": "6f29795a-2712-4e66-a119-ea082d8b4201",
"roleName": "Contributor"
},
{
"name": "fusion-apps-resources-pr",
"managedIdentity": "6f29795a-2712-4e66-a119-ea082d8b4201",
"roleName": "Contributor"
},
{
"name": "fusion-apps-resources-tr",
"managedIdentity": "6f29795a-2712-4e66-a119-ea082d8b4201",
"roleName": "Contributor"
},
{
"name": "fusion-apps-resources-fprd",
"managedIdentity": "ad3ca9c7-dd10-423c-96e0-137c8b26ae9f",
"roleName": "Contributor"
},
{
"name": "fusion-apps-resources-hosting",
"managedIdentity": "ad3ca9c7-dd10-423c-96e0-137c8b26ae9f",
"roleName": "Contributor"
}
]
}
Loading

0 comments on commit c5f8069

Please sign in to comment.