Skip to content

Commit

Permalink
feat(azure): scaffold ssh jumper (#958)
Browse files Browse the repository at this point in the history
<!--- Provide a general summary of your changes in the Title above -->

## Description

A virtual machine that let's us ssh into the `vnet` in order to access
resources in subnets. Next step would be to remove the public IP
entirely and use `Bastion`.

<!--- Describe your changes in detail -->

## Related Issue(s)

- #{issue number}

## Verification

- [ ] **Your** code builds clean without any errors or warnings
- [ ] Manual testing done (required)
- [ ] Relevant automated test added (if you find this hard, leave it and
we'll help out)

## Documentation

- [ ] Documentation is updated (either in `docs`-directory, Altinnpedia
or a separate linked PR in
[altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs), if
applicable)
  • Loading branch information
arealmaas authored Aug 5, 2024
1 parent 6cc234e commit 6228aa2
Show file tree
Hide file tree
Showing 13 changed files with 328 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .azure/infrastructure/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ param sourceKeyVaultResourceGroup string
@minLength(3)
param sourceKeyVaultName string

@description('SSH secret key for the ssh jumper')
@secure()
@minLength(3)
param sourceKeyVaultSshJumperSshSecretKey string

import { Sku as KeyVaultSku } from '../modules/keyvault/create.bicep'
param keyVaultSku KeyVaultSku

Expand Down Expand Up @@ -59,6 +64,7 @@ var secrets = {
sourceKeyVaultSubscriptionId: sourceKeyVaultSubscriptionId
sourceKeyVaultResourceGroup: sourceKeyVaultResourceGroup
sourceKeyVaultName: sourceKeyVaultName
sourceKeyVaultSshSecretKey: sourceKeyVaultSshJumperSshSecretKey
}

var namePrefix = 'dp-be-${environment}'
Expand Down Expand Up @@ -150,6 +156,21 @@ var srcKeyVault = {
resourceGroupName: secrets.sourceKeyVaultResourceGroup
}

module sshJumper '../modules/ssh-jumper/main.bicep' = {
scope: resourceGroup
name: 'sshJumper'
params: {
namePrefix: namePrefix
location: location
subnetId: vnet.outputs.defaultSubnetId
tags: tags
srcKeyVaultName: secrets.sourceKeyVaultName
srcKeyVaultSubId: secrets.sourceKeyVaultSubscriptionId
srcKeyVaultRGNName: secrets.sourceKeyVaultResourceGroup
srcKeyVaultSshSecretKey: secrets.sourceKeyVaultSshSecretKey
}
}

module postgresql '../modules/postgreSql/create.bicep' = {
scope: resourceGroup
name: 'postgresql'
Expand Down
1 change: 1 addition & 0 deletions .azure/infrastructure/production.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ param dialogportenPgAdminPassword = readEnvironmentVariable('PG_ADMIN_PASSWORD')
param sourceKeyVaultSubscriptionId = readEnvironmentVariable('SOURCE_KEY_VAULT_SUBSCRIPTION_ID')
param sourceKeyVaultResourceGroup = readEnvironmentVariable('SOURCE_KEY_VAULT_RESOURCE_GROUP')
param sourceKeyVaultName = readEnvironmentVariable('SOURCE_KEY_VAULT_NAME')
param sourceKeyVaultSshJumperSshSecretKey = readEnvironmentVariable('SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY')

// SKUs
param keyVaultSku = {
Expand Down
1 change: 1 addition & 0 deletions .azure/infrastructure/soak.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ param dialogportenPgAdminPassword = readEnvironmentVariable('PG_ADMIN_PASSWORD')
param sourceKeyVaultSubscriptionId = readEnvironmentVariable('SOURCE_KEY_VAULT_SUBSCRIPTION_ID')
param sourceKeyVaultResourceGroup = readEnvironmentVariable('SOURCE_KEY_VAULT_RESOURCE_GROUP')
param sourceKeyVaultName = readEnvironmentVariable('SOURCE_KEY_VAULT_NAME')
param sourceKeyVaultSshJumperSshSecretKey = readEnvironmentVariable('SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY')

// SKUs
param keyVaultSku = {
Expand Down
1 change: 1 addition & 0 deletions .azure/infrastructure/staging.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ param dialogportenPgAdminPassword = readEnvironmentVariable('PG_ADMIN_PASSWORD')
param sourceKeyVaultSubscriptionId = readEnvironmentVariable('SOURCE_KEY_VAULT_SUBSCRIPTION_ID')
param sourceKeyVaultResourceGroup = readEnvironmentVariable('SOURCE_KEY_VAULT_RESOURCE_GROUP')
param sourceKeyVaultName = readEnvironmentVariable('SOURCE_KEY_VAULT_NAME')
param sourceKeyVaultSshJumperSshSecretKey = readEnvironmentVariable('SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY')

// SKUs
param keyVaultSku = {
Expand Down
1 change: 1 addition & 0 deletions .azure/infrastructure/test.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ param dialogportenPgAdminPassword = readEnvironmentVariable('PG_ADMIN_PASSWORD')
param sourceKeyVaultSubscriptionId = readEnvironmentVariable('SOURCE_KEY_VAULT_SUBSCRIPTION_ID')
param sourceKeyVaultResourceGroup = readEnvironmentVariable('SOURCE_KEY_VAULT_RESOURCE_GROUP')
param sourceKeyVaultName = readEnvironmentVariable('SOURCE_KEY_VAULT_NAME')
param sourceKeyVaultSshJumperSshSecretKey = readEnvironmentVariable('SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY')

// SKUs
param keyVaultSku = {
Expand Down
146 changes: 146 additions & 0 deletions .azure/modules/ssh-jumper/main.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
@description('The name prefix to be used for the resource')
param namePrefix string

@description('The location to deploy the resource to')
param location string

@description('The subnet to deploy the network interface to')
param subnetId string

@description('Tags to be applied to the resource')
param tags object

@description('The name of the source Key Vault')
param srcKeyVaultName string

@description('The subscription ID of the source Key Vault')
param srcKeyVaultSubId string

@description('The resource group name of the source Key Vault')
param srcKeyVaultRGNName string

@description('The SSH secret key to be used to get the ssh key for the virtual machine')
@secure()
param srcKeyVaultSshSecretKey string

var name = '${namePrefix}-ssh-jumper'

resource srcKeyVaultResource 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: srcKeyVaultName
scope: resourceGroup(srcKeyVaultSubId, srcKeyVaultRGNName)
}

resource publicIp 'Microsoft.Network/publicIPAddresses@2023-11-01' = {
name: '${name}-ip'
location: location
sku: {
name: 'Standard'
tier: 'Regional'
}
zones: [
'1'
]
properties: {
publicIPAddressVersion: 'IPv4'
publicIPAllocationMethod: 'Static'
idleTimeoutInMinutes: 4
ipTags: []
}
tags: tags
}

resource networkInterface 'Microsoft.Network/networkInterfaces@2023-11-01' = {
name: name
location: location
properties: {
ipConfigurations: [
{
name: '${name}-ipconfig'
type: 'Microsoft.Network/networkInterfaces/ipConfigurations'
properties: {
privateIPAddress: '10.0.0.5'
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: publicIp.id
properties: {
deleteOption: 'Delete'
}
}
subnet: {
id: subnetId
}
primary: true
privateIPAddressVersion: 'IPv4'
}
}
]
dnsSettings: {
dnsServers: []
}
enableAcceleratedNetworking: false
enableIPForwarding: false
disableTcpStateTracking: false
nicType: 'Standard'
auxiliaryMode: 'None'
auxiliarySku: 'None'
}
}

module virtualMachine '../../modules/virtualMachine/main.bicep' = {
name: name
params: {
name: name
sshKeyData: srcKeyVaultResource.getSecret(srcKeyVaultSshSecretKey)
location: location
tags: tags
hardwareProfile: {
vmSize: 'Standard_B1s'
}
additionalCapabilities: {
hibernationEnabled: false
}
storageProfile: {
imageReference: {
publisher: 'canonical'
offer: '0001-com-ubuntu-server-focal'
sku: '20_04-lts-gen2'
version: 'latest'
}
osDisk: {
osType: 'Linux'
name: '${name}-osdisk'
createOption: 'FromImage'
caching: 'ReadWrite'
managedDisk: {
storageAccountType: 'Premium_LRS'
}
deleteOption: 'Delete'
diskSizeGB: 30
}
dataDisks: []
diskControllerType: 'SCSI'
}
securityProfile: {
uefiSettings: {
secureBootEnabled: true
vTpmEnabled: true
}
securityType: 'TrustedLaunch'
}
networkProfile: {
networkInterfaces: [
{
id: networkInterface.id
properties: {
deleteOption: 'Delete'
}
}
]
}
diagnosticsProfile: {
bootDiagnostics: {
enabled: true
}
}
}
}
132 changes: 132 additions & 0 deletions .azure/modules/virtualMachine/main.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
param name string
param location string
param tags object

type HardwareProfile = {
vmSize: string
}
@description('Specifies the hardware profile for the virtual machine')
param hardwareProfile HardwareProfile

type AdditionalCapabilities = {
hibernationEnabled: bool
}
@description('Specifies the additional capabilities for the virtual machine')
param additionalCapabilities AdditionalCapabilities

type SecurityProfile = {
uefiSettings: {
secureBootEnabled: bool
vTpmEnabled: bool
}
securityType: string
}
@description('Specifies the security profile for the virtual machine')
param securityProfile SecurityProfile

type NetworkInterface = {
id: string
properties: {
deleteOption: string
}
}
type NetworkProfile = {
networkInterfaces: NetworkInterface[]
}
@description('Specifies the network profile for the virtual machine')
param networkProfile NetworkProfile

type DiagnosticsProfile = {
bootDiagnostics: {
enabled: bool
}
}
@description('Specifies the diagnostics profile for the virtual machine')
param diagnosticsProfile DiagnosticsProfile

type StorageProfile = {
imageReference: {
publisher: string
offer: string
sku: string
version: string
}
osDisk: {
osType: string
name: string
createOption: string
caching: string
managedDisk: {
storageAccountType: string
}
deleteOption: string
diskSizeGB: int
}
dataDisks: array
diskControllerType: string
}
@description('Specifies the storage profile for the virtual machine')
param storageProfile StorageProfile

@description('Specifies the SSH key data for the virtual machine')
@secure()
param sshKeyData string

resource virtualMachine 'Microsoft.Compute/virtualMachines@2024-03-01' = {
name: name
location: location
zones: [
'1'
]
properties: {
hardwareProfile: hardwareProfile
additionalCapabilities: additionalCapabilities
storageProfile: storageProfile
osProfile: {
computerName: name
adminUsername: name
linuxConfiguration: {
disablePasswordAuthentication: true
ssh: {
publicKeys: [
{
path: '/home/${name}/.ssh/authorized_keys'
keyData: sshKeyData
}
]
}
provisionVMAgent: true
patchSettings: {
patchMode: 'AutomaticByPlatform'
automaticByPlatformSettings: {
rebootSetting: 'IfRequired'
bypassPlatformSafetyChecksOnUserSchedule: false
}
assessmentMode: 'ImageDefault'
}
}
secrets: []
allowExtensionOperations: true
requireGuestProvisionSignal: true
}
securityProfile: securityProfile
networkProfile: networkProfile
diagnosticsProfile: diagnosticsProfile
}
identity: {
type: 'SystemAssigned'
}
tags: tags
}

resource aadLoginExtension 'Microsoft.Compute/virtualMachines/extensions@2023-03-01' = {
parent: virtualMachine
name: 'AADSSHLoginForLinux'
location: location
properties: {
publisher: 'Microsoft.Azure.ActiveDirectory'
type: 'AADSSHLoginForLinux'
typeHandlerVersion: '1.0'
autoUpgradeMinorVersion: true
}
}
3 changes: 3 additions & 0 deletions .github/workflows/action-deploy-infra.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ on:
required: true
AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP:
required: true
AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY:
required: true

inputs:
region:
Expand Down Expand Up @@ -98,6 +100,7 @@ jobs:
SOURCE_KEY_VAULT_SUBSCRIPTION_ID: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID }}
SOURCE_KEY_VAULT_RESOURCE_GROUP: ${{ secrets.AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP }}
SOURCE_KEY_VAULT_NAME: ${{ secrets.AZURE_SOURCE_KEY_VAULT_NAME }}
SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY }}
with:
scope: subscription
template: ./.azure/infrastructure/main.bicep
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-cd-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
AZURE_SOURCE_KEY_VAULT_NAME: ${{ secrets.AZURE_SOURCE_KEY_VAULT_NAME }}
AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID }}
AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP: ${{ secrets.AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP }}
AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY }}
with:
environment: test
region: norwayeast
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-cd-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
AZURE_SOURCE_KEY_VAULT_NAME: ${{ secrets.AZURE_SOURCE_KEY_VAULT_NAME }}
AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID }}
AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP: ${{ secrets.AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP }}
AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY }}
with:
environment: test
region: norwayeast
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-cd-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
AZURE_SOURCE_KEY_VAULT_NAME: ${{ secrets.AZURE_SOURCE_KEY_VAULT_NAME }}
AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SUBSCRIPTION_ID }}
AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP: ${{ secrets.AZURE_SOURCE_KEY_VAULT_RESOURCE_GROUP }}
AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY: ${{ secrets.AZURE_SOURCE_KEY_VAULT_SSH_JUMPER_SSH_SECRET_KEY }}
with:
environment: staging
region: norwayeast
Expand Down
Loading

0 comments on commit 6228aa2

Please sign in to comment.