Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add the creation of Microsoft.KeyVault/vaults/secrets in Sql Server Module - avm/res/sql/server #2859

Merged
merged 8 commits into from
Oct 12, 2024
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
169 changes: 161 additions & 8 deletions avm/res/sql/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This module deploys an Azure SQL Server.
| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) |
| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) |
| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) |
| `Microsoft.KeyVault/vaults/secrets` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2023-07-01/vaults/secrets) |
| `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) |
| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) |
| `Microsoft.Sql/servers` | [2023-08-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Sql/servers) |
Expand All @@ -45,10 +46,11 @@ The following section provides usage examples for the module, which were used to
- [With an administrator](#example-1-with-an-administrator)
- [With audit settings](#example-2-with-audit-settings)
- [Using only defaults](#example-3-using-only-defaults)
- [Using large parameter set](#example-4-using-large-parameter-set)
- [With a secondary database](#example-5-with-a-secondary-database)
- [With vulnerability assessment](#example-6-with-vulnerability-assessment)
- [WAF-aligned](#example-7-waf-aligned)
- [Deploying with a key vault reference to save secrets](#example-4-deploying-with-a-key-vault-reference-to-save-secrets)
- [Using large parameter set](#example-5-using-large-parameter-set)
- [With a secondary database](#example-6-with-a-secondary-database)
- [With vulnerability assessment](#example-7-with-vulnerability-assessment)
- [WAF-aligned](#example-8-waf-aligned)

### Example 1: _With an administrator_

Expand Down Expand Up @@ -310,7 +312,115 @@ param location = '<location>'
</details>
<p>

### Example 4: _Using large parameter set_
### Example 4: _Deploying with a key vault reference to save secrets_

This instance deploys the module saving all its secrets in a key vault.


<details>

<summary>via Bicep module</summary>

```bicep
module server 'br/public:avm/res/sql/server:<version>' = {
name: 'serverDeployment'
params: {
// Required parameters
name: 'sqlkvs001'
// Non-required parameters
administratorLogin: 'adminUserName'
administratorLoginPassword: '<administratorLoginPassword>'
databases: [
{
name: 'myDatabase'
}
]
location: '<location>'
secretsExportConfiguration: {
keyVaultResourceId: '<keyVaultResourceId>'
sqlAdminPasswordSecretName: 'adminLoginPasswordKey'
sqlAzureConnectionStringSercretName: 'sqlConnectionStringKey'
}
}
}
```

</details>
<p>

<details>

<summary>via JSON parameters file</summary>

```json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// Required parameters
"name": {
"value": "sqlkvs001"
},
// Non-required parameters
"administratorLogin": {
"value": "adminUserName"
},
"administratorLoginPassword": {
"value": "<administratorLoginPassword>"
},
"databases": {
"value": [
{
"name": "myDatabase"
}
]
},
"location": {
"value": "<location>"
},
"secretsExportConfiguration": {
"value": {
"keyVaultResourceId": "<keyVaultResourceId>",
"sqlAdminPasswordSecretName": "adminLoginPasswordKey",
"sqlAzureConnectionStringSercretName": "sqlConnectionStringKey"
}
}
}
}
```

</details>
<p>

<details>

<summary>via Bicep parameters file</summary>

```bicep-params
using 'br/public:avm/res/sql/server:<version>'

// Required parameters
param name = 'sqlkvs001'
// Non-required parameters
param administratorLogin = 'adminUserName'
param administratorLoginPassword = '<administratorLoginPassword>'
param databases = [
{
name: 'myDatabase'
}
]
param location = '<location>'
param secretsExportConfiguration = {
keyVaultResourceId: '<keyVaultResourceId>'
sqlAdminPasswordSecretName: 'adminLoginPasswordKey'
sqlAzureConnectionStringSercretName: 'sqlConnectionStringKey'
}
```

</details>
<p>

### Example 5: _Using large parameter set_

This instance deploys the module with most of its features enabled.

Expand Down Expand Up @@ -833,7 +943,7 @@ param vulnerabilityAssessmentsObj = {
</details>
<p>

### Example 5: _With a secondary database_
### Example 6: _With a secondary database_

This instance deploys the module with a secondary database.

Expand Down Expand Up @@ -956,7 +1066,7 @@ param tags = {
</details>
<p>

### Example 6: _With vulnerability assessment_
### Example 7: _With vulnerability assessment_

This instance deploys the module with a vulnerability assessment.

Expand Down Expand Up @@ -1133,7 +1243,7 @@ param vulnerabilityAssessmentsObj = {
</details>
<p>

### Example 7: _WAF-aligned_
### Example 8: _WAF-aligned_

This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.

Expand Down Expand Up @@ -1579,6 +1689,7 @@ param vulnerabilityAssessmentsObj = {
| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and neither firewall rules nor virtual network rules are set. |
| [`restrictOutboundNetworkAccess`](#parameter-restrictoutboundnetworkaccess) | string | Whether or not to restrict outbound network access for this server. |
| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. |
| [`secretsExportConfiguration`](#parameter-secretsexportconfiguration) | object | Key vault reference and secret settings for the module's secrets export. |
| [`securityAlertPolicies`](#parameter-securityalertpolicies) | array | The security alert policies to create in the server. |
| [`tags`](#parameter-tags) | object | Tags of the resource. |
| [`virtualNetworkRules`](#parameter-virtualnetworkrules) | array | The virtual network rules to create in the server. |
Expand Down Expand Up @@ -2411,6 +2522,47 @@ The principal type of the assigned principal ID.
]
```

### Parameter: `secretsExportConfiguration`

Key vault reference and secret settings for the module's secrets export.

- Required: No
- Type: object

**Required parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`keyVaultResourceId`](#parameter-secretsexportconfigurationkeyvaultresourceid) | string | The resource ID of the key vault where to store the secrets of this module. |

**Optional parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`sqlAdminPasswordSecretName`](#parameter-secretsexportconfigurationsqladminpasswordsecretname) | string | The sqlAdminPassword secret name to create. |
| [`sqlAzureConnectionStringSercretName`](#parameter-secretsexportconfigurationsqlazureconnectionstringsercretname) | string | The sqlAzureConnectionString secret name to create. |

### Parameter: `secretsExportConfiguration.keyVaultResourceId`

The resource ID of the key vault where to store the secrets of this module.

- Required: Yes
- Type: string

### Parameter: `secretsExportConfiguration.sqlAdminPasswordSecretName`

The sqlAdminPassword secret name to create.

- Required: No
- Type: string

### Parameter: `secretsExportConfiguration.sqlAzureConnectionStringSercretName`

The sqlAzureConnectionString secret name to create.

- Required: No
- Type: string

### Parameter: `securityAlertPolicies`

The security alert policies to create in the server.
Expand Down Expand Up @@ -2446,6 +2598,7 @@ The vulnerability assessment configuration.

| Output | Type | Description |
| :-- | :-- | :-- |
| `exportedSecrets` | | A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret's name. |
| `location` | string | The location the resource was deployed into. |
| `name` | string | The name of the deployed SQL server. |
| `privateEndpoints` | array | The private endpoints of the SQL server. |
Expand Down
55 changes: 55 additions & 0 deletions avm/res/sql/server/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ param vulnerabilityAssessmentsObj object = {}
@description('Optional. The audit settings configuration.')
param auditSettings auditSettingsType?

@description('Optional. Key vault reference and secret settings for the module\'s secrets export.')
param secretsExportConfiguration secretsExportConfigurationType?

var builtInRoleNames = {
Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
Expand Down Expand Up @@ -491,6 +494,36 @@ module server_audit_settings 'audit-settings/main.bicep' = if (!empty(auditSetti
}
}

module secretsExport 'modules/keyVaultExport.bicep' = if (secretsExportConfiguration != null) {
name: '${uniqueString(deployment().name, location)}-secrets-kv'
scope: resourceGroup(
split((secretsExportConfiguration.?keyVaultResourceId ?? '//'), '/')[2],
split((secretsExportConfiguration.?keyVaultResourceId ?? '////'), '/')[4]
)
params: {
keyVaultName: last(split(secretsExportConfiguration.?keyVaultResourceId ?? '//', '/'))
secretsToSet: union(
[],
contains(secretsExportConfiguration!, 'sqlAdminPasswordSecretName')
? [
{
name: secretsExportConfiguration!.sqlAdminPasswordSecretName
value: administratorLoginPassword
}
]
: [],
contains(secretsExportConfiguration!, 'sqlAzureConnectionStringSercretName')
? [
{
name: secretsExportConfiguration!.sqlAzureConnectionStringSercretName
value: 'Server=${server.properties.fullyQualifiedDomainName}; Database=${!empty(databases) ? databases[0].name : ''}; User=${administratorLogin}; Password=${administratorLoginPassword}'
}
]
: []
)
}
}

@description('The name of the deployed SQL server.')
output name string = server.name

Expand All @@ -506,6 +539,11 @@ output systemAssignedMIPrincipalId string = server.?identity.?principalId ?? ''
@description('The location the resource was deployed into.')
output location string = server.location

@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.')
output exportedSecrets secretsOutputType = (secretsExportConfiguration != null)
? toObject(secretsExport.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret)
: {}

@description('The private endpoints of the SQL server.')
output privateEndpoints array = [
for (pe, i) in (!empty(privateEndpoints) ? array(privateEndpoints) : []): {
Expand Down Expand Up @@ -681,3 +719,20 @@ type auditSettingsType = {
@description('Optional. Specifies the identifier key of the auditing storage account.')
storageAccountResourceId: string?
}

type secretsExportConfigurationType = {
@description('Required. The resource ID of the key vault where to store the secrets of this module.')
keyVaultResourceId: string

@description('Optional. The sqlAdminPassword secret name to create.')
sqlAdminPasswordSecretName: string?

@description('Optional. The sqlAzureConnectionString secret name to create.')
sqlAzureConnectionStringSercretName: string?
}?

import { secretSetType } from 'modules/keyVaultExport.bicep'
type secretsOutputType = {
@description('An exported secret\'s references.')
*: secretSetType
}
Loading