Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions cli/azd/pkg/azapi/stack_deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,7 @@ func (d *StackDeployments) DeployToSubscription(
clonedTags := maps.Clone(tags)
clonedTags[azure.TagKeyAzdDeploymentTemplateHashName] = &templateHash

stackParams := map[string]*armdeploymentstacks.DeploymentParameter{}
for k, v := range parameters {
stackParams[k] = &armdeploymentstacks.DeploymentParameter{
Value: v.Value,
}
}
stackParams := convertToStackParams(parameters)

deploymentStackOptions, err := parseDeploymentStackOptions(options)
if err != nil {
Expand Down Expand Up @@ -321,12 +316,7 @@ func (d *StackDeployments) DeployToResourceGroup(
clonedTags := maps.Clone(tags)
clonedTags[azure.TagKeyAzdDeploymentTemplateHashName] = &templateHash

stackParams := map[string]*armdeploymentstacks.DeploymentParameter{}
for k, v := range parameters {
stackParams[k] = &armdeploymentstacks.DeploymentParameter{
Value: v.Value,
}
}
stackParams := convertToStackParams(parameters)

deploymentStackOptions, err := parseDeploymentStackOptions(options)
if err != nil {
Expand Down Expand Up @@ -754,3 +744,26 @@ func convertFromStacksProvisioningState(

return DeploymentProvisioningState("")
}

// convertToStackParams converts the given ARM parameters to deployment stack parameters
func convertToStackParams(parameters azure.ArmParameters) map[string]*armdeploymentstacks.DeploymentParameter {
stackParams := map[string]*armdeploymentstacks.DeploymentParameter{}
for k, v := range parameters {
if v.KeyVaultReference != nil {
stackParams[k] = &armdeploymentstacks.DeploymentParameter{
Reference: &armdeploymentstacks.KeyVaultParameterReference{
KeyVault: &armdeploymentstacks.KeyVaultReference{
ID: &v.KeyVaultReference.KeyVault.ID,
},
SecretName: &v.KeyVaultReference.SecretName,
SecretVersion: &v.KeyVaultReference.SecretVersion,
},
}
} else {
stackParams[k] = &armdeploymentstacks.DeploymentParameter{
Value: v.Value,
}
}
}
return stackParams
}
21 changes: 17 additions & 4 deletions cli/azd/pkg/azure/arm_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package azure

// ArmParameters is a map of arm template parameters to their configured values.
type ArmParameters map[string]ArmParameterValue
type ArmParameters map[string]ArmParameter

// ArmParametersFile is the model type for a `.parameters.json` file. It fits the schema outlined here:
// https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json
Expand All @@ -14,7 +14,20 @@ type ArmParameterFile struct {
Parameters ArmParameters `json:"parameters"`
}

// ArmParameterValue wraps the configured value for the parameter.
type ArmParameterValue struct {
Value any `json:"value"`
// ArmParameter wraps the configured value or KV reference for the parameter.
type ArmParameter struct {
Value any `json:"value"`
KeyVaultReference *KeyVaultParameterReference `json:"reference"`
}

// KeyVaultParameterReference is the model type for a Key Vault parameter reference.
type KeyVaultParameterReference struct {
KeyVault KeyVaultReference `json:"keyVault"`
SecretName string `json:"secretName"`
SecretVersion string `json:"secretVersion"`
}

// KeyVaultReference represents the Key Vault resource ID.
type KeyVaultReference struct {
ID string `json:"id"`
Comment thread
JeffreyCA marked this conversation as resolved.
}
25 changes: 16 additions & 9 deletions cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1483,7 +1483,7 @@ func (p *BicepProvider) createOutputParameters(

// loadParameters reads the parameters file template for environment/module specified by Options,
// doing environment and command substitutions, and returns the values.
func (p *BicepProvider) loadParameters(ctx context.Context) (map[string]azure.ArmParameterValue, error) {
func (p *BicepProvider) loadParameters(ctx context.Context) (map[string]azure.ArmParameter, error) {
parametersFilename := fmt.Sprintf("%s.parameters.json", p.options.Module)
parametersRoot := p.options.Path

Expand Down Expand Up @@ -1761,7 +1761,7 @@ func (p *BicepProvider) modulePath() string {
// whether new inputs were written, and an error if any occurred during the generation of input values.
func inputsParameter(
existingInputs map[string]map[string]any, autoGenParameters map[string]map[string]azure.AutoGenInput) (
inputsParameter azure.ArmParameterValue, inputsUpdated bool, err error) {
inputsParameter azure.ArmParameter, inputsUpdated bool, err error) {
wroteNewInput := false

for inputResource, inputResourceInfo := range autoGenParameters {
Expand Down Expand Up @@ -1793,7 +1793,7 @@ func inputsParameter(
existingInputs[inputResource] = existingRecordsForResource
}

return azure.ArmParameterValue{
return azure.ArmParameter{
Value: existingInputs,
}, wroteNewInput, nil
}
Expand Down Expand Up @@ -1830,8 +1830,15 @@ func (p *BicepProvider) ensureParameters(
// If a value is explicitly configured via a parameters file, use it.
// unless the parameter value inference is nil/empty
if v, has := parameters[key]; has {
paramValue := armParameterFileValue(parameterType, v.Value, param.DefaultValue)
// Directly pass through Key Vault references without prompting.
if v.KeyVaultReference != nil {
configuredParameters[key] = azure.ArmParameter{
KeyVaultReference: v.KeyVaultReference,
}
continue
}

paramValue := armParameterFileValue(parameterType, v.Value, param.DefaultValue)
if paramValue != nil {
needForDeployParameter := hasMetadata &&
azdMetadata.Type != nil &&
Expand All @@ -1844,7 +1851,7 @@ func (p *BicepProvider) ensureParameters(
paramValue = defValue
}
}
configuredParameters[key] = azure.ArmParameterValue{
configuredParameters[key] = azure.ArmParameter{
Value: paramValue,
}
if needForDeployParameter {
Expand All @@ -1871,7 +1878,7 @@ func (p *BicepProvider) ensureParameters(

if v, has := p.env.Config.Get(configKey); has {
if isValueAssignableToParameterType(parameterType, v) {
configuredParameters[key] = azure.ArmParameterValue{
configuredParameters[key] = azure.ArmParameter{
Value: v,
}
continue
Expand All @@ -1892,7 +1899,7 @@ func (p *BicepProvider) ensureParameters(
if err != nil {
return nil, err
}
configuredParameters[key] = azure.ArmParameterValue{
configuredParameters[key] = azure.ArmParameter{
Value: genValue,
}
mustSetParamAsConfig(key, genValue, p.env.Config, param.Secure())
Expand Down Expand Up @@ -1930,7 +1937,7 @@ func (p *BicepProvider) ensureParameters(
value := values[prompt.key]
mustSetParamAsConfig(key, value, p.env.Config, prompt.param.Secure())
configModified = true
configuredParameters[key] = azure.ArmParameterValue{
configuredParameters[key] = azure.ArmParameter{
Value: value,
}
}
Expand All @@ -1946,7 +1953,7 @@ func (p *BicepProvider) ensureParameters(

mustSetParamAsConfig(key, value, p.env.Config, prompt.param.Secure())
configModified = true
configuredParameters[key] = azure.ArmParameterValue{
configuredParameters[key] = azure.ArmParameter{
Value: value,
}
}
Expand Down
19 changes: 19 additions & 0 deletions cli/azd/pkg/infra/provisioning/bicep/bicep_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,24 @@ func TestBicepPlan(t *testing.T) {
)
}

func TestBicepPlanKeyVaultRef(t *testing.T) {
mockContext := mocks.NewMockContext(context.Background())
prepareBicepMocks(mockContext)
infraProvider := createBicepProvider(t, mockContext)

deploymentPlan, err := infraProvider.plan(*mockContext.Context)

require.Nil(t, err)

require.IsType(t, &deploymentDetails{}, deploymentPlan)
configuredParameters := deploymentPlan.CompiledBicep.Parameters

require.NotEmpty(t, configuredParameters["kvSecret"])
Comment thread
JeffreyCA marked this conversation as resolved.
require.NotNil(t, configuredParameters["kvSecret"].KeyVaultReference)
require.Nil(t, configuredParameters["kvSecret"].Value)
require.Equal(t, "secretName", configuredParameters["kvSecret"].KeyVaultReference.SecretName)
}

const paramsArmJson = `{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
Expand Down Expand Up @@ -399,6 +417,7 @@ func prepareBicepMocks(
Parameters: azure.ArmTemplateParameterDefinitions{
"environmentName": {Type: "string"},
"location": {Type: "string"},
"kvSecret": {Type: "securestring"},
},
Outputs: azure.ArmTemplateOutputs{
"WEBSITE_URL": {Type: "string"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ param intTagValue int
@description('Test parameter for bool-typed values.')
param boolTagValue bool

@secure()
@description('Test secure parameter.')
param kvSecret string

var tags = {
'azd-env-name': environmentName
DeleteAfter: deleteAfterTime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ param environmentName = readEnvironmentVariable('AZURE_ENV_NAME')
param location = readEnvironmentVariable('AZURE_LOCATION')
param intTagValue = int(readEnvironmentVariable('INT_TAG_VALUE', '678'))
param boolTagValue = bool(readEnvironmentVariable('BOOL_TAG_VALUE', 'false'))
param kvSecret = getSecret('SUBSCRIPTION_ID', 'RESOURCE_GROUP', 'VAULT', 'secretName')
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ param location string
@description('A time to mark on created resource groups, so they can be cleaned up via an automated process.')
param deleteAfterTime string = dateTimeAdd(utcNow('o'), 'PT1H')

@secure()
param kvSecret string

var tags = { 'azd-env-name': environmentName, DeleteAfter: deleteAfterTime }

resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
},
"location": {
"value": "${AZURE_LOCATION}"
},
"kvSecret": {
"reference": {
"keyVault": {
"id": "/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/VAULT"
},
"secretName": "secretName"
}
}
}
}