pkg/deploy/generator/resources_dev.go (414 lines of code) (raw):
package generator
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"encoding/base64"
"fmt"
"strings"
mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-12-01/compute"
mgmtkeyvault "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault"
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
"github.com/Azure/go-autorest/autorest/to"
"github.com/Azure/ARO-RP/pkg/util/arm"
"github.com/Azure/ARO-RP/pkg/util/azureclient"
)
// devLBInternal is needed for defining a healthprobe.
// VMSS with auto upgrademode requires a healthprobe from an LB.
func (g *generator) devLBInternal() *arm.Resource {
return &arm.Resource{
Resource: &mgmtnetwork.LoadBalancer{
Sku: &mgmtnetwork.LoadBalancerSku{
Name: mgmtnetwork.LoadBalancerSkuNameBasic,
},
LoadBalancerPropertiesFormat: &mgmtnetwork.LoadBalancerPropertiesFormat{
FrontendIPConfigurations: &[]mgmtnetwork.FrontendIPConfiguration{
{
FrontendIPConfigurationPropertiesFormat: &mgmtnetwork.FrontendIPConfigurationPropertiesFormat{
Subnet: &mgmtnetwork.Subnet{
ID: to.StringPtr("[resourceId('Microsoft.Network/virtualNetworks/subnets', 'rp-vnet', 'rp-subnet')]"),
},
},
Name: to.StringPtr("not-used"),
},
},
BackendAddressPools: &[]mgmtnetwork.BackendAddressPool{
{
Name: to.StringPtr("dev-backend"),
},
},
LoadBalancingRules: &[]mgmtnetwork.LoadBalancingRule{
{
LoadBalancingRulePropertiesFormat: &mgmtnetwork.LoadBalancingRulePropertiesFormat{
FrontendIPConfiguration: &mgmtnetwork.SubResource{
ID: to.StringPtr("[resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', 'dev-lb-internal', 'not-used')]"),
},
BackendAddressPool: &mgmtnetwork.SubResource{
ID: to.StringPtr("[resourceId('Microsoft.Network/loadBalancers/backendAddressPools', 'dev-lb-internal', 'dev-backend')]"),
},
Probe: &mgmtnetwork.SubResource{
ID: to.StringPtr("[resourceId('Microsoft.Network/loadBalancers/probes', 'dev-lb-internal', 'dev-probe')]"),
},
Protocol: mgmtnetwork.TransportProtocolTCP,
LoadDistribution: mgmtnetwork.LoadDistributionDefault,
FrontendPort: to.Int32Ptr(443),
BackendPort: to.Int32Ptr(443),
},
Name: to.StringPtr("dev-lbrule"),
},
},
Probes: &[]mgmtnetwork.Probe{
{
ProbePropertiesFormat: &mgmtnetwork.ProbePropertiesFormat{
Protocol: mgmtnetwork.ProbeProtocolTCP,
Port: to.Int32Ptr(443),
NumberOfProbes: to.Int32Ptr(3),
},
Name: to.StringPtr("dev-probe"),
},
},
},
Name: to.StringPtr("dev-lb-internal"),
Type: to.StringPtr("Microsoft.Network/loadBalancers"),
Location: to.StringPtr("[resourceGroup().location]"),
},
APIVersion: azureclient.APIVersion("Microsoft.Network"),
}
}
func (g *generator) devProxyVMSS() *arm.Resource {
parts := []string{
fmt.Sprintf("base64ToString('%s')", base64.StdEncoding.EncodeToString([]byte("set -ex\n\n"))),
}
for _, variable := range []string{"proxyImage", "proxyImageAuth"} {
parts = append(parts,
fmt.Sprintf("'%s=$(base64 -d <<<'''", strings.ToUpper(variable)),
fmt.Sprintf("base64(parameters('%s'))", variable),
"''')\n'",
)
}
for _, variable := range []string{"proxyCert", "proxyClientCert", "proxyKey"} {
parts = append(parts,
fmt.Sprintf("'%s='''", strings.ToUpper(variable)),
fmt.Sprintf("parameters('%s')", variable),
"'''\n'",
)
}
trailer := base64.StdEncoding.EncodeToString([]byte(scriptDevProxyVMSS))
parts = append(parts, "'\n'", fmt.Sprintf("base64ToString('%s')", trailer))
customScript := fmt.Sprintf("[base64(concat(%s))]", strings.Join(parts, ","))
return &arm.Resource{
Resource: &mgmtcompute.VirtualMachineScaleSet{
Sku: &mgmtcompute.Sku{
Name: to.StringPtr(string(mgmtcompute.VirtualMachineSizeTypesStandardF2sV2)),
Tier: to.StringPtr("Standard"),
Capacity: to.Int64Ptr(1),
},
Identity: &mgmtcompute.VirtualMachineScaleSetIdentity{
Type: mgmtcompute.ResourceIdentityTypeUserAssigned,
UserAssignedIdentities: map[string]*mgmtcompute.VirtualMachineScaleSetIdentityUserAssignedIdentitiesValue{
"[resourceId('AzSecPackAutoConfigRG', 'Microsoft.ManagedIdentity/userAssignedIdentities', 'AzSecPackAutoConfigUA-eastus')]": {},
},
},
VirtualMachineScaleSetProperties: &mgmtcompute.VirtualMachineScaleSetProperties{
UpgradePolicy: &mgmtcompute.UpgradePolicy{
Mode: mgmtcompute.UpgradeModeRolling,
AutomaticOSUpgradePolicy: &mgmtcompute.AutomaticOSUpgradePolicy{
EnableAutomaticOSUpgrade: to.BoolPtr(true),
},
},
VirtualMachineProfile: &mgmtcompute.VirtualMachineScaleSetVMProfile{
OsProfile: &mgmtcompute.VirtualMachineScaleSetOSProfile{
ComputerNamePrefix: to.StringPtr("dev-proxy-"),
AdminUsername: to.StringPtr("cloud-user"),
LinuxConfiguration: &mgmtcompute.LinuxConfiguration{
DisablePasswordAuthentication: to.BoolPtr(true),
SSH: &mgmtcompute.SSHConfiguration{
PublicKeys: &[]mgmtcompute.SSHPublicKey{
{
Path: to.StringPtr("/home/cloud-user/.ssh/authorized_keys"),
KeyData: to.StringPtr("[parameters('sshPublicKey')]"),
},
},
},
},
},
SecurityProfile: &mgmtcompute.SecurityProfile{
SecurityType: mgmtcompute.SecurityTypesTrustedLaunch,
},
StorageProfile: &mgmtcompute.VirtualMachineScaleSetStorageProfile{
ImageReference: &mgmtcompute.ImageReference{
Publisher: to.StringPtr("MicrosoftCBLMariner"),
Offer: to.StringPtr("cbl-mariner"),
Sku: to.StringPtr("cbl-mariner-2-gen2"),
Version: to.StringPtr("latest"),
},
OsDisk: &mgmtcompute.VirtualMachineScaleSetOSDisk{
CreateOption: mgmtcompute.DiskCreateOptionTypesFromImage,
ManagedDisk: &mgmtcompute.VirtualMachineScaleSetManagedDiskParameters{
StorageAccountType: mgmtcompute.StorageAccountTypesPremiumLRS,
},
DiskSizeGB: to.Int32Ptr(64),
},
},
NetworkProfile: &mgmtcompute.VirtualMachineScaleSetNetworkProfile{
HealthProbe: &mgmtcompute.APIEntityReference{
ID: to.StringPtr("[resourceId('Microsoft.Network/loadBalancers/probes', 'dev-lb-internal', 'dev-probe')]"),
},
NetworkInterfaceConfigurations: &[]mgmtcompute.VirtualMachineScaleSetNetworkConfiguration{
{
Name: to.StringPtr("dev-proxy-vmss-nic"),
VirtualMachineScaleSetNetworkConfigurationProperties: &mgmtcompute.VirtualMachineScaleSetNetworkConfigurationProperties{
Primary: to.BoolPtr(true),
IPConfigurations: &[]mgmtcompute.VirtualMachineScaleSetIPConfiguration{
{
Name: to.StringPtr("dev-proxy-vmss-ipconfig"),
VirtualMachineScaleSetIPConfigurationProperties: &mgmtcompute.VirtualMachineScaleSetIPConfigurationProperties{
Subnet: &mgmtcompute.APIEntityReference{
ID: to.StringPtr("[resourceId('Microsoft.Network/virtualNetworks/subnets', 'rp-vnet', 'rp-subnet')]"),
},
Primary: to.BoolPtr(true),
PublicIPAddressConfiguration: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfiguration{
Name: to.StringPtr("dev-proxy-vmss-pip"),
VirtualMachineScaleSetPublicIPAddressConfigurationProperties: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfigurationProperties{
DNSSettings: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfigurationDNSSettings{
DomainNameLabel: to.StringPtr("[parameters('proxyDomainNameLabel')]"),
},
},
},
LoadBalancerBackendAddressPools: &[]mgmtcompute.SubResource{
{
ID: to.StringPtr("[resourceId('Microsoft.Network/loadBalancers/backendAddressPools', 'dev-lb-internal', 'dev-backend')]"),
},
},
},
},
},
},
},
},
},
ExtensionProfile: &mgmtcompute.VirtualMachineScaleSetExtensionProfile{
Extensions: &[]mgmtcompute.VirtualMachineScaleSetExtension{
{
Name: to.StringPtr("dev-proxy-vmss-cse"),
VirtualMachineScaleSetExtensionProperties: &mgmtcompute.VirtualMachineScaleSetExtensionProperties{
Publisher: to.StringPtr("Microsoft.Azure.Extensions"),
Type: to.StringPtr("CustomScript"),
TypeHandlerVersion: to.StringPtr("2.0"),
ProvisionAfterExtensions: &[]string{
"Microsoft.Azure.Monitor.AzureMonitorLinuxAgent",
"Microsoft.Azure.Security.Monitoring.AzureSecurityLinuxAgent",
},
AutoUpgradeMinorVersion: to.BoolPtr(true),
Settings: map[string]interface{}{},
ProtectedSettings: map[string]interface{}{
"script": customScript,
},
},
},
{
Name: to.StringPtr("Microsoft.Azure.Monitor.AzureMonitorLinuxAgent"),
VirtualMachineScaleSetExtensionProperties: &mgmtcompute.VirtualMachineScaleSetExtensionProperties{
Publisher: to.StringPtr("Microsoft.Azure.Monitor"),
Type: to.StringPtr("AzureMonitorLinuxAgent"),
TypeHandlerVersion: to.StringPtr("1.0"),
AutoUpgradeMinorVersion: to.BoolPtr(true),
EnableAutomaticUpgrade: to.BoolPtr(true),
Settings: map[string]interface{}{
"GCS_AUTO_CONFIG": true,
},
},
},
{
Name: to.StringPtr("Microsoft.Azure.Security.Monitoring.AzureSecurityLinuxAgent"),
VirtualMachineScaleSetExtensionProperties: &mgmtcompute.VirtualMachineScaleSetExtensionProperties{
Publisher: to.StringPtr("Microsoft.Azure.Security.Monitoring"),
Type: to.StringPtr("AzureSecurityLinuxAgent"),
TypeHandlerVersion: to.StringPtr("2.0"),
AutoUpgradeMinorVersion: to.BoolPtr(true),
EnableAutomaticUpgrade: to.BoolPtr(true),
Settings: map[string]interface{}{
"enableGenevaUpload": true,
"enableAutoConfig": true,
"reportSuccessOnUnsupportedDistro": true,
},
},
},
},
},
},
Overprovision: to.BoolPtr(false),
},
Name: to.StringPtr("dev-proxy-vmss"),
Type: to.StringPtr("Microsoft.Compute/virtualMachineScaleSets"),
Location: to.StringPtr("[resourceGroup().location]"),
},
APIVersion: azureclient.APIVersion("Microsoft.Compute"),
Tags: map[string]any{
"azsecpack": "nonprod",
},
DependsOn: []string{
"[resourceId('Microsoft.Network/loadBalancers', 'dev-lb-internal')]",
},
}
}
func (g *generator) devVPNPip() *arm.Resource {
return &arm.Resource{
Resource: &mgmtnetwork.PublicIPAddress{
Sku: &mgmtnetwork.PublicIPAddressSku{
Name: "[parameters('publicIPAddressSkuName')]",
},
PublicIPAddressPropertiesFormat: &mgmtnetwork.PublicIPAddressPropertiesFormat{
PublicIPAllocationMethod: "[parameters('publicIPAddressAllocationMethod')]",
},
Name: to.StringPtr("dev-vpn-pip"),
Type: to.StringPtr("Microsoft.Network/publicIPAddresses"),
Location: to.StringPtr("[resourceGroup().location]"),
},
APIVersion: azureclient.APIVersion("Microsoft.Network"),
}
}
func (g *generator) devVnet() *arm.Resource {
return g.virtualNetwork("dev-vnet", "10.0.0.0/16", &[]mgmtnetwork.Subnet{
{
SubnetPropertiesFormat: &mgmtnetwork.SubnetPropertiesFormat{
AddressPrefix: to.StringPtr("10.0.1.0/24"),
NetworkSecurityGroup: &mgmtnetwork.SecurityGroup{
ID: to.StringPtr("[resourceId('Microsoft.Network/networkSecurityGroups', 'rp-nsg')]"),
},
},
Name: to.StringPtr("ToolingSubnet"),
},
}, nil, nil)
}
func (g *generator) devVPNVnet() *arm.Resource {
return g.virtualNetwork("dev-vpn-vnet", "10.2.0.0/24", &[]mgmtnetwork.Subnet{
{
SubnetPropertiesFormat: &mgmtnetwork.SubnetPropertiesFormat{
AddressPrefix: to.StringPtr("10.2.0.0/24"),
},
Name: to.StringPtr("GatewaySubnet"),
},
}, nil, nil)
}
func (g *generator) devVPN() *arm.Resource {
return &arm.Resource{
Resource: &mgmtnetwork.VirtualNetworkGateway{
VirtualNetworkGatewayPropertiesFormat: &mgmtnetwork.VirtualNetworkGatewayPropertiesFormat{
IPConfigurations: &[]mgmtnetwork.VirtualNetworkGatewayIPConfiguration{
{
VirtualNetworkGatewayIPConfigurationPropertiesFormat: &mgmtnetwork.VirtualNetworkGatewayIPConfigurationPropertiesFormat{
Subnet: &mgmtnetwork.SubResource{
ID: to.StringPtr("[resourceId('Microsoft.Network/virtualNetworks/subnets', 'dev-vpn-vnet', 'GatewaySubnet')]"),
},
PublicIPAddress: &mgmtnetwork.SubResource{
ID: to.StringPtr("[resourceId('Microsoft.Network/publicIPAddresses', 'dev-vpn-pip')]"),
},
},
Name: to.StringPtr("default"),
},
},
VpnType: mgmtnetwork.RouteBased,
Sku: &mgmtnetwork.VirtualNetworkGatewaySku{
Name: mgmtnetwork.VirtualNetworkGatewaySkuNameVpnGw1,
Tier: mgmtnetwork.VirtualNetworkGatewaySkuTierVpnGw1,
},
VpnClientConfiguration: &mgmtnetwork.VpnClientConfiguration{
VpnClientAddressPool: &mgmtnetwork.AddressSpace{
AddressPrefixes: &[]string{"192.168.255.0/24"},
},
VpnClientRootCertificates: &[]mgmtnetwork.VpnClientRootCertificate{
{
VpnClientRootCertificatePropertiesFormat: &mgmtnetwork.VpnClientRootCertificatePropertiesFormat{
PublicCertData: to.StringPtr("[parameters('vpnCACertificate')]"),
},
Name: to.StringPtr("dev-vpn-ca"),
},
},
VpnClientProtocols: &[]mgmtnetwork.VpnClientProtocol{
mgmtnetwork.OpenVPN,
},
},
},
Name: to.StringPtr("dev-vpn"),
Type: to.StringPtr("Microsoft.Network/virtualNetworkGateways"),
Location: to.StringPtr("[resourceGroup().location]"),
},
APIVersion: azureclient.APIVersion("Microsoft.Network"),
DependsOn: []string{
"[resourceId('Microsoft.Network/publicIPAddresses', 'dev-vpn-pip')]",
"[resourceId('Microsoft.Network/virtualNetworks', 'dev-vpn-vnet')]",
},
}
}
const (
sharedDiskEncryptionKeyVaultName = "concat(take(resourceGroup().name,10), '" + SharedDiskEncryptionKeyVaultNameSuffix + "')"
sharedDiskEncryptionSetName = "concat(resourceGroup().name, '" + SharedDiskEncryptionSetNameSuffix + "')"
sharedDiskEncryptionKeyName = "concat(resourceGroup().name, '-disk-encryption-key')"
SharedDiskEncryptionKeyVaultNameSuffix = "-dev-disk-enc"
SharedDiskEncryptionSetNameSuffix = "-disk-encryption-set"
)
// shared keyvault for keys used for disk encryption sets when creating clusters locally
func (g *generator) devDiskEncryptionKeyvault() *arm.Resource {
return g.keyVault(fmt.Sprintf("[%s]", sharedDiskEncryptionKeyVaultName), &[]mgmtkeyvault.AccessPolicyEntry{}, nil, false, nil)
}
func (g *generator) devDiskEncryptionKey() *arm.Resource {
key := &mgmtkeyvault.Key{
KeyProperties: &mgmtkeyvault.KeyProperties{
Kty: mgmtkeyvault.RSA,
KeySize: to.Int32Ptr(4096),
},
Name: to.StringPtr(fmt.Sprintf("[concat(%s, '/', %s)]", sharedDiskEncryptionKeyVaultName, sharedDiskEncryptionKeyName)),
Type: to.StringPtr("Microsoft.KeyVault/vaults/keys"),
Location: to.StringPtr("[resourceGroup().location]"),
}
return &arm.Resource{
Resource: key,
APIVersion: azureclient.APIVersion("Microsoft.KeyVault"),
DependsOn: []string{fmt.Sprintf("[resourceId('Microsoft.KeyVault/vaults', %s)]", sharedDiskEncryptionKeyVaultName)},
}
}
func (g *generator) devDiskEncryptionSet() *arm.Resource {
diskEncryptionSet := &mgmtcompute.DiskEncryptionSet{
EncryptionSetProperties: &mgmtcompute.EncryptionSetProperties{
ActiveKey: &mgmtcompute.KeyForDiskEncryptionSet{
KeyURL: to.StringPtr(fmt.Sprintf("[reference(resourceId('Microsoft.KeyVault/vaults/keys', %s, %s), '%s', 'Full').properties.keyUriWithVersion]", sharedDiskEncryptionKeyVaultName, sharedDiskEncryptionKeyName, azureclient.APIVersion("Microsoft.KeyVault"))),
SourceVault: &mgmtcompute.SourceVault{
ID: to.StringPtr(fmt.Sprintf("[resourceId('Microsoft.KeyVault/vaults', %s)]", sharedDiskEncryptionKeyVaultName)),
},
},
},
Name: to.StringPtr(fmt.Sprintf("[%s]", sharedDiskEncryptionSetName)),
Type: to.StringPtr("Microsoft.Compute/diskEncryptionSets"),
Location: to.StringPtr("[resourceGroup().location]"),
Identity: &mgmtcompute.EncryptionSetIdentity{Type: mgmtcompute.DiskEncryptionSetIdentityTypeSystemAssigned},
}
return &arm.Resource{
Resource: diskEncryptionSet,
APIVersion: azureclient.APIVersion("Microsoft.Compute/diskEncryptionSets"),
DependsOn: []string{
fmt.Sprintf("[resourceId('Microsoft.KeyVault/vaults/keys', %s, %s)]", sharedDiskEncryptionKeyVaultName, sharedDiskEncryptionKeyName),
},
}
}
func (g *generator) devDiskEncryptionKeyVaultAccessPolicy() *arm.Resource {
accessPolicy := &mgmtkeyvault.VaultAccessPolicyParameters{
Properties: &mgmtkeyvault.VaultAccessPolicyProperties{
AccessPolicies: &[]mgmtkeyvault.AccessPolicyEntry{
{
TenantID: &tenantUUIDHack,
ObjectID: to.StringPtr(fmt.Sprintf("[reference(resourceId('Microsoft.Compute/diskEncryptionSets', %s), '%s', 'Full').identity.PrincipalId]", sharedDiskEncryptionSetName, azureclient.APIVersion("Microsoft.Compute/diskEncryptionSets"))),
Permissions: &mgmtkeyvault.Permissions{
Keys: &[]mgmtkeyvault.KeyPermissions{
mgmtkeyvault.KeyPermissionsGet,
mgmtkeyvault.KeyPermissionsWrapKey,
mgmtkeyvault.KeyPermissionsUnwrapKey,
},
},
},
},
},
Name: to.StringPtr(fmt.Sprintf("[concat(%s, '/add')]", sharedDiskEncryptionKeyVaultName)),
Type: to.StringPtr("Microsoft.KeyVault/vaults/accessPolicies"),
Location: to.StringPtr("[resourceGroup().location]"),
}
return &arm.Resource{
Resource: accessPolicy,
APIVersion: azureclient.APIVersion("Microsoft.KeyVault"),
DependsOn: []string{fmt.Sprintf("[resourceId('Microsoft.Compute/diskEncryptionSets', %s)]", sharedDiskEncryptionSetName)},
}
}