aks-engine/pkg/engine/systemroleassignments.go

180 строки
8.6 KiB
Go

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
package engine
import (
"fmt"
"strings"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources"
"github.com/Azure/aks-engine/pkg/api"
"github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
"github.com/Azure/go-autorest/autorest/to"
)
func createVMASRoleAssignment() SystemRoleAssignmentARM {
systemRoleAssignment := SystemRoleAssignmentARM{
ARMResource: ARMResource{
APIVersion: "[variables('apiVersionAuthorizationSystem')]",
DependsOn: []string{
"[concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]",
},
Copy: map[string]string{
"count": "[sub(variables('masterCount'), variables('masterOffset'))]",
"name": "vmLoopNode",
},
},
}
systemRoleAssignment.Name = to.StringPtr("[guid(concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')), 'vmidentity'))]")
systemRoleAssignment.Type = to.StringPtr("Microsoft.Authorization/roleAssignments")
systemRoleAssignment.RoleAssignmentPropertiesWithScope = &authorization.RoleAssignmentPropertiesWithScope{
RoleDefinitionID: to.StringPtr("[variables('contributorRoleDefinitionId')]"),
PrincipalID: to.StringPtr("[reference(concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset'))), '2017-03-30', 'Full').identity.principalId]"),
PrincipalType: authorization.ServicePrincipal,
}
return systemRoleAssignment
}
func createAgentVMASSysRoleAssignment(profile *api.AgentPoolProfile) SystemRoleAssignmentARM {
systemRoleAssignment := SystemRoleAssignmentARM{
ARMResource: ARMResource{
APIVersion: "[variables('apiVersionAuthorizationSystem')]",
DependsOn: []string{
fmt.Sprintf("[concat('Microsoft.Compute/virtualMachines/', variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')))]", profile.Name),
},
Copy: map[string]string{
"count": fmt.Sprintf("[sub(variables('%[1]sCount'), variables('%[1]sOffset'))]", profile.Name),
"name": "vmLoopNode",
},
},
}
systemRoleAssignment.Name = to.StringPtr(fmt.Sprintf("[guid(concat('Microsoft.Compute/virtualMachines/', variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')), 'vmidentity'))]", profile.Name))
systemRoleAssignment.Type = to.StringPtr("Microsoft.Authorization/roleAssignments")
systemRoleAssignment.RoleAssignmentPropertiesWithScope = &authorization.RoleAssignmentPropertiesWithScope{
RoleDefinitionID: to.StringPtr("[variables('readerRoleDefinitionId')]"),
PrincipalID: to.StringPtr(fmt.Sprintf("[reference(concat('Microsoft.Compute/virtualMachines/', variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset'))), '2017-03-30', 'Full').identity.principalId]", profile.Name)),
PrincipalType: authorization.ServicePrincipal,
}
return systemRoleAssignment
}
func createAgentVMSSSysRoleAssignment(profile *api.AgentPoolProfile) SystemRoleAssignmentARM {
systemRoleAssignment := SystemRoleAssignmentARM{
ARMResource: ARMResource{
APIVersion: "[variables('apiVersionAuthorizationSystem')]",
DependsOn: []string{
fmt.Sprintf("[concat('Microsoft.Compute/virtualMachineScaleSets/', variables('%[1]sVMNamePrefix'))]", profile.Name),
},
},
}
systemRoleAssignment.RoleAssignmentPropertiesWithScope = &authorization.RoleAssignmentPropertiesWithScope{}
systemRoleAssignment.Name = to.StringPtr(fmt.Sprintf("[guid(concat('Microsoft.Compute/virtualMachineScaleSets/', variables('%[1]sVMNamePrefix'), 'vmidentity'))]", profile.Name))
systemRoleAssignment.Type = to.StringPtr("Microsoft.Authorization/roleAssignments")
systemRoleAssignment.RoleAssignmentPropertiesWithScope = &authorization.RoleAssignmentPropertiesWithScope{
RoleDefinitionID: to.StringPtr("[variables('readerRoleDefinitionId')]"),
PrincipalID: to.StringPtr(fmt.Sprintf("[reference(concat('Microsoft.Compute/virtualMachineScaleSets/', variables('%[1]sVMNamePrefix')), '2017-03-30', 'Full').identity.principalId]", profile.Name)),
PrincipalType: authorization.ServicePrincipal,
}
return systemRoleAssignment
}
func createKubernetesMasterRoleAssignmentForAgentPools(masterProfile *api.MasterProfile, agentPoolProfiles []*api.AgentPoolProfile) []DeploymentWithResourceGroupARM {
var dependenciesToMasterVms = make([]string, masterProfile.Count)
for masterIdx := 0; masterIdx < masterProfile.Count; masterIdx++ {
dependenciesToMasterVms[masterIdx] = fmt.Sprintf("[concat(variables('masterVMNamePrefix'), %d)]", masterIdx)
}
roleAssignmentsForAllAgentPools := []DeploymentWithResourceGroupARM{}
// The following is based on:
// * https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/role-based-access-control/role-assignments-template.md#create-a-role-assignment-at-a-resource-scope
// * https://github.com/Azure/azure-quickstart-templates/blob/master/201-rbac-builtinrole-multipleVMs/azuredeploy.json#L79
// We're gonna keep track of distinct VNETs in use across all our node pools;
// we only want to define master VM --> VNET role assignments once per VNET.
// If our cluster configuration includes more than one pool sharing a common VNET,
// we define the master VM --> VNET role assignments (one per master VM) just once for those pools
var vnetInCluster = struct{}{}
vnets := make(map[string]struct{})
for _, agentPool := range agentPoolProfiles {
var roleAssignments = make([]interface{}, masterProfile.Count)
subnetElements := strings.Split(agentPool.VnetSubnetID, "/")
// We expect a very specific string format for the VnetSubnetID property;
// if it can't be split into at least 9 "/"-delimited elements,
// then we should assume that our role assignment composition below will be malformed,
// and so we simply skip assigning a role assigment for this pool.
// This should never happen, but this defensive posture ensures no code panic execution path
// // when we statically grab the first 9 elements (`subnetElements[:9]` below)
if len(subnetElements) < 9 {
continue
}
vnetResourceURI := strings.Join(subnetElements[:9], "/")
if _, ok := vnets[vnetResourceURI]; ok {
continue
}
vnets[vnetResourceURI] = vnetInCluster
for masterIdx := 0; masterIdx < masterProfile.Count; masterIdx++ {
masterVMReference := fmt.Sprintf("reference(resourceId(resourceGroup().name, 'Microsoft.Compute/virtualMachines', concat(variables('masterVMNamePrefix'), %d)), '2017-03-30', 'Full').identity.principalId", masterIdx)
assignment := SystemRoleAssignmentARM{
ARMResource: ARMResource{
APIVersion: "[variables('apiVersionAuthorizationSystem')]",
// TODO: Use `copy` in ARM template instead of Go loops:
/*
Copy: map[string]string{
"count": "[variables('masterCount')]",
"name": "vmLoopNode",
},
*/
},
// Reference to the VNET of the worker VMs:
RoleAssignment: authorization.RoleAssignment{
Name: to.StringPtr(fmt.Sprintf("[concat(variables('%sVnet'), '/Microsoft.Authorization/', guid(uniqueString(%s)))]", agentPool.Name, masterVMReference)),
Type: to.StringPtr("Microsoft.Network/virtualNetworks/providers/roleAssignments"),
RoleAssignmentPropertiesWithScope: &authorization.RoleAssignmentPropertiesWithScope{
// Built-in role `network contributor`:
RoleDefinitionID: to.StringPtr("[variables('networkContributorRoleDefinitionId')]"),
// The MSI of the master VM:
PrincipalID: to.StringPtr(fmt.Sprintf("[%s]", masterVMReference)),
},
},
}
roleAssignments[masterIdx] = assignment
}
roleAssignmentsForAgentPoolSubDeployment := DeploymentWithResourceGroupARM{
DeploymentARMResource: DeploymentARMResource{
APIVersion: "2017-05-10",
DependsOn: dependenciesToMasterVms,
},
ResourceGroup: to.StringPtr(fmt.Sprintf("[variables('%sSubnetResourceGroup')]", agentPool.Name)),
DeploymentExtended: resources.DeploymentExtended{
Name: to.StringPtr(fmt.Sprintf("[concat('masterMsiRoleAssignment-', variables('%sVMNamePrefix'))]", agentPool.Name)),
Type: to.StringPtr("Microsoft.Resources/deployments"),
Properties: &resources.DeploymentPropertiesExtended{
Mode: "Incremental",
Template: map[string]interface{}{
"resources": roleAssignments,
"contentVersion": "1.0.0.0",
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
},
},
},
}
roleAssignmentsForAllAgentPools = append(roleAssignmentsForAllAgentPools, roleAssignmentsForAgentPoolSubDeployment)
}
return roleAssignmentsForAllAgentPools
}