Adding support for ETCD encryption with KMS (#351)
* various improvements Signed-off-by: Gordonby <gordon.byers@microsoft.com> * kms Signed-off-by: Gordonby <gordon.byers@microsoft.com> * contrib Signed-off-by: Gordonby <gordon.byers@microsoft.com> * KMS working on public kv Signed-off-by: Gordonby <gordon.byers@microsoft.com> * adding support for private kms Signed-off-by: Gordonby <gordon.byers@microsoft.com> * Updating branch to main Signed-off-by: Gordonby <gordon.byers@microsoft.com> * tested and working Signed-off-by: Gordonby <gordon.byers@microsoft.com> * added UI Signed-off-by: Gordonby <gordon.byers@microsoft.com> * Added byoKeyId to the UI Signed-off-by: Gordonby <gordon.byers@microsoft.com> * kms byo key validation Signed-off-by: Gordonby <gordon.byers@microsoft.com> * better error message Signed-off-by: Gordonby <gordon.byers@microsoft.com> * better regex Signed-off-by: Gordonby <gordon.byers@microsoft.com> * regext dot bracket Signed-off-by: Gordonby <gordon.byers@microsoft.com> * better regex still....! (amazing :D ) Signed-off-by: Gordonby <gordon.byers@microsoft.com> * slash dots Signed-off-by: Gordonby <gordon.byers@microsoft.com> * useless-regexp-character Signed-off-by: Gordonby <gordon.byers@microsoft.com> * regex Signed-off-by: Gordonby <gordon.byers@microsoft.com> * byo kms bicep Signed-off-by: Gordonby <gordon.byers@microsoft.com> * UI private link behaviour Signed-off-by: Gordonby <gordon.byers@microsoft.com> * key var conditionality Signed-off-by: Gordonby <gordon.byers@microsoft.com> * metadata Signed-off-by: Gordonby <gordon.byers@microsoft.com> * Add Byo KV RG Signed-off-by: Gordonby <gordon.byers@microsoft.com> * meta Signed-off-by: Gordonby <gordon.byers@microsoft.com> * added ui for rg name Signed-off-by: Gordonby <gordon.byers@microsoft.com> * kms working! Signed-off-by: Gordonby <gordon.byers@microsoft.com> * typos Signed-off-by: Gordonby <gordon.byers@microsoft.com> Signed-off-by: Gordonby <gordon.byers@microsoft.com>
This commit is contained in:
Родитель
c103a28ff1
Коммит
3a5bbcd0f1
|
@ -99,7 +99,7 @@ jobs:
|
|||
}
|
||||
}
|
||||
|
||||
- name: Replace subnet and dnszone param values from secret
|
||||
- name: Replace subnet, dnszone and kv param values from secret
|
||||
shell: pwsh
|
||||
run: |
|
||||
$paramFilePath="${{ env.ParamDir }}${{ matrix.files }}"
|
||||
|
@ -114,6 +114,9 @@ jobs:
|
|||
if($params.parameters.byoAGWSubnetId.value -ne $null) {
|
||||
$params.parameters.byoAGWSubnetId.value = "${{ secrets.ByoAgwSubnetId }}"
|
||||
}
|
||||
if($params.parameters.keyVaultKmsByoKeyId.value -ne $null) {
|
||||
$params.parameters.keyVaultKmsByoKeyId.value = "${{ secrets.ByoKmsKeyId }}"
|
||||
}
|
||||
|
||||
$params | ConvertTo-Json -Depth 4 | Out-File "${{ env.ParamDir }}${{ matrix.files }}"
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"resourceName": {
|
||||
"value": "az-k8s-kmsbyopub"
|
||||
},
|
||||
"agentVMSize": {
|
||||
"value": "Standard_DS3_v2"
|
||||
},
|
||||
"JustUseSystemPool": {
|
||||
"value": true
|
||||
},
|
||||
"keyVaultKmsCreate": {
|
||||
"value": false
|
||||
},
|
||||
"keyVaultKmsByoRG": {
|
||||
"value": "Automation-Actions-AksDeployCI"
|
||||
},
|
||||
"keyVaultKmsByoKeyId": {
|
||||
"value": "https://YOURVAULTNAME.vault.azure.net/keys/YOURKEYNAME/KEYVERSIONSTRING"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"resourceName": {
|
||||
"value": "az-k8s-kmsbyopl"
|
||||
},
|
||||
"agentVMSize": {
|
||||
"value": "Standard_DS3_v2"
|
||||
},
|
||||
"JustUseSystemPool": {
|
||||
"value": true
|
||||
},
|
||||
"custom_vnet": {
|
||||
"value": true
|
||||
},
|
||||
"privateLinks": {
|
||||
"value": true
|
||||
},
|
||||
"bastion": {
|
||||
"value": true
|
||||
},
|
||||
"registries_sku": {
|
||||
"value": "Premium"
|
||||
},
|
||||
"keyVaultKmsCreate": {
|
||||
"value": false
|
||||
},
|
||||
"keyVaultKmsByoRG": {
|
||||
"value": "Automation-Actions-AksDeployCI"
|
||||
},
|
||||
"keyVaultKmsByoKeyId": {
|
||||
"value": "https://YOURVAULTNAME.vault.azure.net/keys/YOURKEYNAME/KEYVERSIONSTRING"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"resourceName": {
|
||||
"value": "az-k8s-kmspp1"
|
||||
},
|
||||
"agentVMSize": {
|
||||
"value": "Standard_DS3_v2"
|
||||
},
|
||||
"JustUseSystemPool": {
|
||||
"value": true
|
||||
},
|
||||
"keyVaultKmsCreate": {
|
||||
"value": true
|
||||
},
|
||||
"keyVaultKmsOfficerRolePrincipalId": {
|
||||
"value": "Make sure to override this value"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -78,7 +78,7 @@ If you're interested in contributing, we have two contribution guides in the rep
|
|||
Guide | Description
|
||||
----- | -----------
|
||||
[Generic Contribution Guide](CONTRIBUTING.md) | Talks about the branching strategy, using CodeSpaces and general guidance
|
||||
[Helper Contribtion Guide](https://github.com/Azure/AKS-Construction/blob/main/docs/ContributingHelper.md) | Talks about the structure of the app and walks through a sample change of adding a new feature to the UI and Bicep
|
||||
[Helper Contribution Guide](https://github.com/Azure/AKS-Construction/blob/main/docs/ContributingHelper.md) | Talks about the structure of the app and walks through a sample change of adding a new feature to the UI and Bicep
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
},
|
||||
"use-stable-vm-image": {
|
||||
"level": "warning"
|
||||
},
|
||||
"secure-secrets-in-params" : {
|
||||
"level": "error"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
param keyVaultName string
|
||||
|
||||
resource kv 'Microsoft.KeyVault/vaults@2021-11-01-preview' existing = {
|
||||
name: keyVaultName
|
||||
}
|
||||
|
||||
resource kvKmsKey 'Microsoft.KeyVault/vaults/keys@2021-11-01-preview' = {
|
||||
name: 'kmskey'
|
||||
parent: kv
|
||||
properties: {
|
||||
kty: 'RSA'
|
||||
keySize: 2048
|
||||
keyOps: [
|
||||
'wrapKey'
|
||||
'unwrapKey'
|
||||
'decrypt'
|
||||
'encrypt'
|
||||
'verify'
|
||||
'sign'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
output keyVaultKmsKeyUri string = kvKmsKey.properties.keyUriWithVersion
|
|
@ -11,6 +11,24 @@ param rbacSecretOfficerSps array = []
|
|||
@description('An array of Service Principal IDs')
|
||||
param rbacCertOfficerSps array = []
|
||||
|
||||
@description('An array of Service Principal IDs')
|
||||
param rbacCryptoUserSps array = []
|
||||
|
||||
@description('An array of Service Principal IDs')
|
||||
param rbacCryptoOfficerSps array = []
|
||||
|
||||
@description('An array of Service Principal IDs')
|
||||
param rbacCryptoServiceEncryptSps array = []
|
||||
|
||||
@description('An array of Service Principal IDs')
|
||||
param rbacKvContributorSps array = []
|
||||
|
||||
@description('An array of Service Principal IDs')
|
||||
param rbacAdminSps array = []
|
||||
|
||||
@description('An array of User IDs')
|
||||
param rbacCryptoOfficerUsers array = []
|
||||
|
||||
@description('An array of User IDs')
|
||||
#disable-next-line secure-secrets-in-params //Disabling validation of this linter rule as param does not contain a secret.
|
||||
param rbacSecretOfficerUsers array = []
|
||||
|
@ -18,9 +36,17 @@ param rbacSecretOfficerUsers array = []
|
|||
@description('An array of User IDs')
|
||||
param rbacCertOfficerUsers array = []
|
||||
|
||||
@description('An array of User IDs')
|
||||
param rbacAdminUsers array = []
|
||||
|
||||
var keyVaultAdministratorRole = resourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')
|
||||
var keyVaultContributorRole = resourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')
|
||||
var keyVaultSecretsUserRole = resourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')
|
||||
var keyVaultSecretsOfficerRole = resourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')
|
||||
var keyVaultCertsOfficerRole = resourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')
|
||||
var keyVaultCryptoUserRole = resourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')
|
||||
var keyVaultCryptoOfficerRole = resourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')
|
||||
var keyVaultCryptoServiceEncrpytionRole = resourceId('Microsoft.Authorization/roleDefinitions','e147488a-f6f5-4113-8e2d-b22465e65bf6')
|
||||
|
||||
resource kv 'Microsoft.KeyVault/vaults@2021-11-01-preview' existing = {
|
||||
name: keyVaultName
|
||||
|
@ -56,6 +82,66 @@ resource rbacCertsOfficerSp 'Microsoft.Authorization/roleAssignments@2022-04-01'
|
|||
}
|
||||
}]
|
||||
|
||||
resource rbacCryptoUserSp 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacCryptoUserSps : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultCryptoUserRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultCryptoUserRole
|
||||
principalType: 'ServicePrincipal'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacCryptoServiceEncryptionSp 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacCryptoServiceEncryptSps : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultCryptoServiceEncrpytionRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultCryptoServiceEncrpytionRole
|
||||
principalType: 'ServicePrincipal'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacKvContributorSp 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacKvContributorSps : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultContributorRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultContributorRole
|
||||
principalType: 'ServicePrincipal'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacCryptoOfficerSp 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacCryptoOfficerSps : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultCryptoUserRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultCryptoOfficerRole
|
||||
principalType: 'ServicePrincipal'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacAdminSp 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacAdminSps : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultAdministratorRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultAdministratorRole
|
||||
principalType: 'ServicePrincipal'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacCryptoOfficerUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacCryptoOfficerUsers : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultCryptoOfficerRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultCryptoOfficerRole
|
||||
principalType: 'User'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacSecretOfficerUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacSecretOfficerUsers : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultSecretsOfficerRole)
|
||||
|
@ -75,3 +161,13 @@ resource rbacCertsOfficerUser 'Microsoft.Authorization/roleAssignments@2022-04-0
|
|||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
||||
resource rbacAdminUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for rbacSp in rbacAdminUsers : if(!empty(rbacSp)) {
|
||||
scope: kv
|
||||
name: guid(kv.id, rbacSp, keyVaultAdministratorRole)
|
||||
properties: {
|
||||
roleDefinitionId: keyVaultAdministratorRole
|
||||
principalType: 'User'
|
||||
principalId: rbacSp
|
||||
}
|
||||
}]
|
||||
|
|
133
bicep/main.bicep
133
bicep/main.bicep
|
@ -38,7 +38,7 @@ param byoAKSSubnetId string = ''
|
|||
param byoAGWSubnetId string = ''
|
||||
|
||||
//--- Custom, BYO networking and PrivateApiZones requires BYO AKS User Identity
|
||||
var createAksUai = custom_vnet || !empty(byoAKSSubnetId) || !empty(dnsApiPrivateZoneId)
|
||||
var createAksUai = custom_vnet || !empty(byoAKSSubnetId) || !empty(dnsApiPrivateZoneId) || keyVaultKmsCreateAndPrereqs || !empty(keyVaultKmsByoKeyId)
|
||||
resource aksUai 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = if (createAksUai) {
|
||||
name: 'id-aks-${resourceName}'
|
||||
location: location
|
||||
|
@ -95,7 +95,7 @@ param privateLinkSubnetAddressPrefix string = '10.240.4.192/26'
|
|||
@description('The address range for Azure Firewall in your custom vnet')
|
||||
param vnetFirewallSubnetAddressPrefix string = '10.240.50.0/24'
|
||||
|
||||
@description('Enable support for private links')
|
||||
@description('Enable support for private links (required custom_vnet)')
|
||||
param privateLinks bool = false
|
||||
|
||||
@description('Enable support for ACR private pool')
|
||||
|
@ -194,8 +194,9 @@ param keyVaultAksCSI bool = false
|
|||
@description('Rotation poll interval for the AKS KV CSI provider')
|
||||
param keyVaultAksCSIPollInterval string = '2m'
|
||||
|
||||
@description('Creates a KeyVault for application secrets (eg. CSI)')
|
||||
module kv 'keyvault.bicep' = if(keyVaultCreate) {
|
||||
name: 'keyvault'
|
||||
name: 'keyvaultApps'
|
||||
params: {
|
||||
resourceName: resourceName
|
||||
keyVaultPurgeProtection: keyVaultPurgeProtection
|
||||
|
@ -217,7 +218,7 @@ var rbacSecretUserSps = union([deployAppGw && appgwKVIntegration ? appGwIdentity
|
|||
|
||||
@description('A seperate module is used for RBAC to avoid delaying the KeyVault creation and causing a circular reference.')
|
||||
module kvRbac 'keyvaultrbac.bicep' = if (keyVaultCreate) {
|
||||
name: 'KeyVaultRbac'
|
||||
name: 'KeyVaultAppsRbac'
|
||||
params: {
|
||||
keyVaultName: keyVaultCreate ? kv.outputs.keyVaultName : ''
|
||||
|
||||
|
@ -236,6 +237,125 @@ output keyVaultName string = keyVaultCreate ? kv.outputs.keyVaultName : ''
|
|||
output keyVaultId string = keyVaultCreate ? kv.outputs.keyVaultId : ''
|
||||
|
||||
|
||||
/* KeyVault for KMS Etcd*/
|
||||
|
||||
@description('Enable encryption at rest for Kubernetes etcd data')
|
||||
param keyVaultKmsCreate bool = false
|
||||
|
||||
@description('Bring an existing Key from an existing Key Vault')
|
||||
param keyVaultKmsByoKeyId string = ''
|
||||
|
||||
@description('The resource group for the existing KMS Key Vault')
|
||||
param keyVaultKmsByoRG string = resourceGroup().name
|
||||
|
||||
@description('The PrincipalId of the deploying user, which is necessary when creating a Kms Key')
|
||||
param keyVaultKmsOfficerRolePrincipalId string = ''
|
||||
|
||||
@description('The extracted name of the existing Key Vault')
|
||||
var keyVaultKmsByoName = !empty(keyVaultKmsByoKeyId) ? split(split(keyVaultKmsByoKeyId,'/')[2],'.')[0] : ''
|
||||
|
||||
@description('The deployment delay to introduce when creating a new keyvault for kms key')
|
||||
var kmsRbacWaitSeconds=30
|
||||
|
||||
@description('This indicates if the deploying user has provided their PrincipalId in order for the key to be created')
|
||||
var keyVaultKmsCreateAndPrereqs = keyVaultKmsCreate && !empty(keyVaultKmsOfficerRolePrincipalId) && privateLinks == false
|
||||
|
||||
resource kvKmsByo 'Microsoft.KeyVault/vaults@2021-11-01-preview' existing = if(!empty(keyVaultKmsByoName)) {
|
||||
name: keyVaultKmsByoName
|
||||
scope: resourceGroup(keyVaultKmsByoRG)
|
||||
}
|
||||
|
||||
@description('Creates a new Key vault for a new KMS Key')
|
||||
module kvKms 'keyvault.bicep' = if(keyVaultKmsCreateAndPrereqs) {
|
||||
name: 'keyvaultKms-${resourceName}'
|
||||
params: {
|
||||
resourceName: 'kms${resourceName}'
|
||||
keyVaultPurgeProtection: keyVaultPurgeProtection
|
||||
keyVaultSoftDelete: keyVaultSoftDelete
|
||||
location: location
|
||||
privateLinks: privateLinks
|
||||
//aksUaiObjectId: aksUai.properties.principalId
|
||||
}
|
||||
}
|
||||
|
||||
module kvKmsCreatedRbac 'keyvaultrbac.bicep' = if(keyVaultKmsCreateAndPrereqs) {
|
||||
name: 'keyvaultKmsRbacs-${resourceName}'
|
||||
params: {
|
||||
keyVaultName: keyVaultKmsCreate ? kvKms.outputs.keyVaultName : ''
|
||||
//We can't create a kms kv and key and do privatelink. Private Link is a BYO scenario
|
||||
// rbacKvContributorSps : [
|
||||
// createAksUai && privateLinks ? aksUai.properties.principalId : ''
|
||||
// ]
|
||||
//This allows the Aks Cluster to access the key vault key
|
||||
rbacCryptoUserSps: [
|
||||
createAksUai ? aksUai.properties.principalId : ''
|
||||
]
|
||||
//This allows the Deploying user to create the key vault key
|
||||
rbacCryptoOfficerUsers: [
|
||||
!empty(keyVaultKmsOfficerRolePrincipalId) && !automatedDeployment ? keyVaultKmsOfficerRolePrincipalId : ''
|
||||
]
|
||||
//This allows the Deploying sp to create the key vault key
|
||||
rbacCryptoOfficerSps: [
|
||||
!empty(keyVaultKmsOfficerRolePrincipalId) && automatedDeployment ? keyVaultKmsOfficerRolePrincipalId : ''
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
module kvKmsByoRbac 'keyvaultrbac.bicep' = if(!empty(keyVaultKmsByoKeyId)) {
|
||||
name: 'keyvaultKmsByoRbacs-${resourceName}'
|
||||
scope: resourceGroup(keyVaultKmsByoRG)
|
||||
params: {
|
||||
keyVaultName: kvKmsByo.name
|
||||
//Contribuor allows AKS to create the private link
|
||||
rbacKvContributorSps : [
|
||||
createAksUai && privateLinks ? aksUai.properties.principalId : ''
|
||||
]
|
||||
//This allows the Aks Cluster to access the key vault key
|
||||
rbacCryptoUserSps: [
|
||||
createAksUai ? aksUai.properties.principalId : ''
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@description('It can take time for the RBAC to propagate, this delays the deployment to avoid this problem')
|
||||
module waitForKmsRbac 'br/public:deployment-scripts/wait:1.0.1' = if(keyVaultKmsCreateAndPrereqs && kmsRbacWaitSeconds>0) {
|
||||
name: 'keyvaultKmsRbac-waits-${resourceName}'
|
||||
params: {
|
||||
waitSeconds: kmsRbacWaitSeconds
|
||||
location: location
|
||||
}
|
||||
dependsOn: [
|
||||
kvKmsCreatedRbac
|
||||
]
|
||||
}
|
||||
|
||||
@description('Adding a key to the keyvault... We can only do this for public key vaults')
|
||||
module kvKmsKey 'keyvaultkey.bicep' = if(keyVaultKmsCreateAndPrereqs) {
|
||||
name: 'keyvaultKmsKeys-${resourceName}'
|
||||
params: {
|
||||
keyVaultName: keyVaultKmsCreateAndPrereqs ? kvKms.outputs.keyVaultName : ''
|
||||
}
|
||||
dependsOn: [waitForKmsRbac]
|
||||
}
|
||||
|
||||
var azureKeyVaultKms = {
|
||||
securityProfile : {
|
||||
azureKeyVaultKms : {
|
||||
enabled: keyVaultKmsCreateAndPrereqs || !empty(keyVaultKmsByoKeyId)
|
||||
keyId: keyVaultKmsCreateAndPrereqs ? kvKmsKey.outputs.keyVaultKmsKeyUri : !empty(keyVaultKmsByoKeyId) ? keyVaultKmsByoKeyId : ''
|
||||
keyVaultNetworkAccess: privateLinks ? 'private' : 'public'
|
||||
keyVaultResourceId: privateLinks && !empty(keyVaultKmsByoKeyId) ? kvKmsByo.id : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@description('The name of the Kms Key Vault')
|
||||
output keyVaultKmsName string = keyVaultKmsCreateAndPrereqs ? kvKms.outputs.keyVaultName : !empty(keyVaultKmsByoKeyId) ? keyVaultKmsByoName : ''
|
||||
|
||||
@description('Indicates if the user has supplied all the correct parameter to use a AKSC Created KMS')
|
||||
output kmsCreatePrerequisitesMet bool = keyVaultKmsCreateAndPrereqs
|
||||
|
||||
|
||||
/* ___ ______ .______
|
||||
/ \ / | | _ \
|
||||
/ ^ \ | ,----' | |_) |
|
||||
|
@ -973,7 +1093,6 @@ var agentPoolProfiles = JustUseSystemPool ? array(union(systemPoolBase, userPool
|
|||
|
||||
var akssku = AksPaidSkuForSLA ? 'Paid' : 'Free'
|
||||
|
||||
|
||||
var aks_addons = union({
|
||||
azurepolicy: {
|
||||
config: {
|
||||
|
@ -1110,7 +1229,8 @@ var aksProperties = union({
|
|||
}
|
||||
},
|
||||
aksOutboundTrafficType == 'managedNATGateway' ? managedNATGatewayProfile : {},
|
||||
defenderForContainers && createLaw ? azureDefenderSecurityProfile : {}
|
||||
defenderForContainers && createLaw ? azureDefenderSecurityProfile : {},
|
||||
keyVaultKmsCreateAndPrereqs || !empty(keyVaultKmsByoKeyId) ? azureKeyVaultKms : {}
|
||||
)
|
||||
|
||||
resource aks 'Microsoft.ContainerService/managedClusters@2022-05-02-preview' = {
|
||||
|
@ -1126,6 +1246,7 @@ resource aks 'Microsoft.ContainerService/managedClusters@2022-05-02-preview' = {
|
|||
}
|
||||
dependsOn: [
|
||||
privateDnsZoneRbac
|
||||
waitForKmsRbac
|
||||
]
|
||||
}
|
||||
output aksClusterName string = aks.name
|
||||
|
|
16
cspell.json
16
cspell.json
|
@ -29,6 +29,7 @@
|
|||
"azurerm",
|
||||
"bitnami",
|
||||
"Burstable",
|
||||
"byoprivate",
|
||||
"BYOVNET",
|
||||
"carvals",
|
||||
"Cleanup",
|
||||
|
@ -41,12 +42,13 @@
|
|||
"currenttab",
|
||||
"currt",
|
||||
"currv",
|
||||
"Daemonset",
|
||||
"dapr",
|
||||
"Dapr",
|
||||
"Daemonset",
|
||||
"demoapp",
|
||||
"denydefault",
|
||||
"deploycmd",
|
||||
"deploystr",
|
||||
"DNAT",
|
||||
"dnsname",
|
||||
"dnszones",
|
||||
|
@ -56,19 +58,18 @@
|
|||
"externaldns",
|
||||
"fluentui",
|
||||
"ghpages",
|
||||
"gitops",
|
||||
"githubrepo",
|
||||
"deploystr",
|
||||
"updatevals",
|
||||
"githubrepobranch",
|
||||
"gitops",
|
||||
"Grafana",
|
||||
"hashicorp",
|
||||
"ilbsub",
|
||||
"initializr",
|
||||
"Inconsolata",
|
||||
"initializr",
|
||||
"jsondecode",
|
||||
"jsonencode",
|
||||
"Jumpboxes",
|
||||
"keda",
|
||||
"keyvault",
|
||||
"khowling",
|
||||
"kube",
|
||||
|
@ -98,6 +99,7 @@
|
|||
"NSG's",
|
||||
"omsagent",
|
||||
"pagename",
|
||||
"petclinic",
|
||||
"pivotkey",
|
||||
"playwrighttests",
|
||||
"podid",
|
||||
|
@ -118,6 +120,7 @@
|
|||
"testid",
|
||||
"Tfcmd",
|
||||
"tfplan",
|
||||
"updatevals",
|
||||
"urlname",
|
||||
"userauth",
|
||||
"valres",
|
||||
|
@ -127,8 +130,7 @@
|
|||
"vnetprivateend",
|
||||
"Walkthrough",
|
||||
"Wautoscale",
|
||||
"Wsku",
|
||||
"keda"
|
||||
"Wsku"
|
||||
],
|
||||
"ignoreWords": [
|
||||
"sconfiguration",
|
||||
|
|
|
@ -23,7 +23,7 @@ export const VMs = [
|
|||
]
|
||||
|
||||
export default function ({ tabValues, updateFn, featureFlag, invalidArray }) {
|
||||
const { cluster } = tabValues
|
||||
const { net, addons, cluster, deploy } = tabValues
|
||||
const defenderFeatureFlag = featureFlag.includes('defender')
|
||||
|
||||
|
||||
|
@ -339,6 +339,42 @@ export default function ({ tabValues, updateFn, featureFlag, invalidArray }) {
|
|||
/>
|
||||
</Stack.Item>
|
||||
|
||||
<Separator className="notopmargin" />
|
||||
|
||||
<Stack.Item align="start">
|
||||
<Label required={true}>
|
||||
Key Management Service (KMS) etcd Encryption
|
||||
</Label>
|
||||
<MessageBar messageBarType={MessageBarType.info}>
|
||||
Using the CSI Secrets Add-On, with volume mounted secrets is the recommended approach for secrets management. <Link target='_' href='https://docs.microsoft.com/azure/aks/csi-secrets-store-driver'>docs</Link>
|
||||
</MessageBar>
|
||||
<MessageBar messageBarType={MessageBarType.info} styles={{ root: { display: (net.vnetprivateend ? "block" : "none") } }}>
|
||||
Using an existing Key Vault for KMS is the only supported scenario when using Private Link Networking
|
||||
</MessageBar>
|
||||
<MessageBar messageBarType={MessageBarType.warning} styles={{ root: { display: (cluster.keyVaultKms !== "none" ? "block" : "none") } }}>
|
||||
KMS requires the customer to be responsible for key management (to include rotation).
|
||||
<br />
|
||||
Mismanagement can cause the secrets to be unrecoverable in the cluster. <Link target='_' href='https://docs.microsoft.com/azure/aks/use-kms-etcd-encryption'>docs</Link>
|
||||
</MessageBar>
|
||||
<ChoiceGroup
|
||||
selectedKey={cluster.keyVaultKms}
|
||||
styles={{ root: { marginLeft: '50px' } }}
|
||||
options={[
|
||||
{ key: 'none', text: 'No encryption of etcd required' },
|
||||
{ key: 'public', text: 'Create a new Key Vault with least privileged access and generate the key', disabled: net.vnetprivateend },
|
||||
{ key: 'byoprivate', text: 'Use an existing Key Vault Key.' }
|
||||
]}
|
||||
onChange={(ev, { key }) => updateFn("keyVaultKms", key)}
|
||||
/>
|
||||
|
||||
<Stack.Item align="center" styles={{ root: { marginLeft:'100px', maxWidth: '700px', display: (cluster.keyVaultKms === "byoprivate" ? "block" : "none") } }} >
|
||||
<TextField label="Existing Key Identifier" onChange={(ev, val) => updateFn("keyVaultKmsByoKeyId", val)} value={cluster.keyVaultKmsByoKeyId} errorMessage={getError(invalidArray, 'keyVaultKmsByoKeyId')} />
|
||||
<TextField label="Key Vault Resource Group Name" onChange={(ev, val) => updateFn("keyVaultKmsByoRG", val)} value={cluster.keyVaultKmsByoRG} required errorMessage={getError(invalidArray, 'keyVaultKmsByoRG')} />
|
||||
<MessageBar messageBarType={MessageBarType.warning}>The deploying user must have RBAC permission (Owner) on the existing vault to create new RBAC permissions for the AKS cluster to access the key and (if configured) create the network private link</MessageBar>
|
||||
</Stack.Item>
|
||||
|
||||
</Stack.Item>
|
||||
|
||||
<Stack.Item align="center" styles={{ root: { maxWidth: '700px', display: (cluster.apisecurity === "private" ? "block" : "none") } }} >
|
||||
<Label style={{ marginBottom: "0px" }}>Private dns zone mode for private cluster.</Label>
|
||||
<Stack tokens={{ childrenGap: 15 }}>
|
||||
|
|
|
@ -88,6 +88,10 @@ export default function DeployTab({ defaults, updateFn, tabValues, invalidArray,
|
|||
...(net.vnet_opt === "byo" && {
|
||||
...(net.aksOutboundTrafficType !== defaults.net.aksOutboundTrafficType && {aksOutboundTrafficType: net.aksOutboundTrafficType})
|
||||
}),
|
||||
...(cluster.keyVaultKms !== defaults.cluster.keyVaultKms && {
|
||||
...(cluster.keyVaultKms === "public" && {keyVaultKmsCreate: true, keyVaultKmsOfficerRolePrincipalId: "$(az ad signed-in-user show --query id --out tsv)"}),
|
||||
...(cluster.keyVaultKms === "byoprivate" && cluster.keyVaultKmsByoKeyId !== '' && cluster.keyVaultKmsByoRG !== '' && {keyVaultKmsByoKeyId: cluster.keyVaultKmsByoKeyId, keyVaultKmsByoRG: cluster.keyVaultKmsByoRG}),
|
||||
}),
|
||||
...(addons.csisecret !== "none" && { keyVaultAksCSI: true }),
|
||||
...(addons.csisecret === 'akvNew' && { keyVaultCreate: true, ...(deploy.kvCertSecretRole && { keyVaultOfficerRolePrincipalId: "$(az ad signed-in-user show --query id --out tsv)"}) }),
|
||||
...(addons.csisecret !== "none" && addons.keyVaultAksCSIPollInterval !== defaults.addons.keyVaultAksCSIPollInterval && { keyVaultAksCSIPollInterval: addons.keyVaultAksCSIPollInterval }),
|
||||
|
|
|
@ -330,6 +330,8 @@ export default function PortalNav({ config }) {
|
|||
invalidFn('cluster', 'osDiskType', cluster.osDiskType === 'Ephemeral' && !VMs.find(i => i.key === cluster.vmSize).eph, 'The selected VM cache is not large enough to support Ephemeral. Select \'Managed\' or a VM with a larger cache')
|
||||
invalidFn('cluster', 'aad_tenant_id', cluster.enable_aad && cluster.use_alt_aad && cluster.aad_tenant_id.length !== 36, 'Enter Valid Directory ID')
|
||||
invalidFn('addons', 'registry', net.vnetprivateend && (addons.registry !== 'Premium' && addons.registry !== 'none'), 'Premium tier is required for Private Link, either select Premium, or disable Private Link')
|
||||
invalidFn('cluster', 'keyVaultKmsByoKeyId', cluster.keyVaultKms === "byoprivate" && !cluster.keyVaultKmsByoKeyId.match('https:\/\/[^]+.vault.azure.net/keys/[^ ]+/[^ ]+$'), 'Enter valid KeyVault Versioned Key ID (https://YOURVAULTNAME.vault.azure.net/keys/YOURKEYNAME/KEYVERSIONSTRING)')
|
||||
invalidFn('cluster', 'keyVaultKmsByoRG', cluster.keyVaultKms === "byoprivate" && !cluster.keyVaultKmsByoRG, 'Enter existing KeyVault Resource Group Name')
|
||||
invalidFn('addons', 'dnsZoneId', addons.dns && !addons.dnsZoneId.match('^/subscriptions/[^/ ]+/resourceGroups/[^/ ]+/providers/Microsoft.Network/(dnszones|privateDnsZones)/[^/ ]+$'), 'Enter valid Azure Public or Private DNS Zone resourceId')
|
||||
invalidFn('cluster', 'dnsApiPrivateZoneId', cluster.apisecurity === 'private' && cluster.privateClusterDnsMethod==='privateDnsZone' && !cluster.dnsApiPrivateZoneId.match('^/subscriptions/[^/ ]+/resourceGroups/[^/ ]+/providers/Microsoft.Network/privateDnsZones/[^/ ]+.azmk8s.io$'), 'Enter valid Azure Private DNS Zone resourceId')
|
||||
invalidFn('addons', 'certEmail', addons.certMan && !addons.certEmail.match('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$'), 'Enter valid email for certificate generation')
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
"deployItemKey": "deployArmCli"
|
||||
},
|
||||
"cluster": {
|
||||
"keyVaultKmsByoRG": "",
|
||||
"keyVaultKmsByoKeyId": "",
|
||||
"keyVaultKms": "none",
|
||||
"AksPaidSkuForSLA": false,
|
||||
"apisecurity": "none",
|
||||
"privateClusterDnsMethod": "system",
|
||||
|
|
Загрузка…
Ссылка в новой задаче