From 0ba1330b8cd12f8118c17e63009c62a74af23913 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Wed, 8 Feb 2023 23:20:39 -0500 Subject: [PATCH 01/12] add sshPublicKey Module --- .../ms.compute.sshpublickeys.yml | 50 ++++ .../workflows/ms.compute.sshpublickeys.yml | 165 ++++++++++++ .../.bicep/nested_roleAssignments.bicep | 89 ++++++ .../.test/.scripts/New-SshPubKey.ps1 | 9 + .../.test/common/dependencies.bicep | 61 +++++ .../.test/common/deploy.test.bicep | 56 ++++ .../sshPublicKeys/.test/min/deploy.test.bicep | 41 +++ .../sshPublicKeys/deploy.bicep | 80 ++++++ .../Microsoft.Compute/sshPublicKeys/readme.md | 253 ++++++++++++++++++ .../sshPublicKeys/version.json | 4 + 10 files changed, 808 insertions(+) create mode 100644 .azuredevops/modulePipelines/ms.compute.sshpublickeys.yml create mode 100644 .github/workflows/ms.compute.sshpublickeys.yml create mode 100644 modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep create mode 100644 modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 create mode 100644 modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep create mode 100644 modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep create mode 100644 modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep create mode 100644 modules/Microsoft.Compute/sshPublicKeys/deploy.bicep create mode 100644 modules/Microsoft.Compute/sshPublicKeys/readme.md create mode 100644 modules/Microsoft.Compute/sshPublicKeys/version.json diff --git a/.azuredevops/modulePipelines/ms.compute.sshpublickeys.yml b/.azuredevops/modulePipelines/ms.compute.sshpublickeys.yml new file mode 100644 index 0000000000..b45dc54455 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.sshpublickeys.yml @@ -0,0 +1,50 @@ +name: 'Compute - SshPublicKeys' + +parameters: + - name: staticValidation + displayName: Execute static validation + type: boolean + default: true + - name: deploymentValidation + displayName: Execute deployment validation + type: boolean + default: true + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +pr: none + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.sshpublickeys.yml' + - '/.azuredevops/pipelineTemplates/*.yml' + - '/modules/Microsoft.Compute/sshPublicKeys/*' + - '/utilities/pipelines/*' + exclude: + - '/utilities/pipelines/deploymentRemoval/*' + - '/**/*.md' + +variables: + - template: '../../settings.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/modules/Microsoft.Compute/sshPublicKeys' + +stages: + - template: /.azuredevops/pipelineTemplates/stages.module.yml + parameters: + staticValidation: '${{ parameters.staticValidation }}' + deploymentValidation: '${{ parameters.deploymentValidation }}' + removeDeployment: '${{ parameters.removeDeployment }}' + prerelease: '${{ parameters.prerelease }}' diff --git a/.github/workflows/ms.compute.sshpublickeys.yml b/.github/workflows/ms.compute.sshpublickeys.yml new file mode 100644 index 0000000000..8ef45a5dd8 --- /dev/null +++ b/.github/workflows/ms.compute.sshpublickeys.yml @@ -0,0 +1,165 @@ +name: 'Compute: SshPublicKeys' + +on: + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: 'Execute static validation' + required: false + default: true + deploymentValidation: + type: boolean + description: 'Execute deployment validation' + required: false + default: true + removeDeployment: + type: boolean + description: 'Remove deployed module' + required: false + default: true + prerelease: + type: boolean + description: 'Publish prerelease module' + required: false + default: false + push: + branches: + - main + paths: + - '.github/actions/templates/**' + - '.github/workflows/ms.compute.sshpublickeys.yml' + - 'modules/Microsoft.Compute/sshPublicKeys/**' + - 'utilities/pipelines/**' + - '!utilities/pipelines/deploymentRemoval/**' + - '!*/**/readme.md' + +env: + variablesPath: 'settings.yml' + modulePath: 'modules/Microsoft.Compute/sshPublicKeys' + workflowPath: '.github/workflows/ms.compute.sshPublicKeys.yml' + AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} + ARM_SUBSCRIPTION_ID: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + ARM_MGMTGROUP_ID: '${{ secrets.ARM_MGMTGROUP_ID }}' + ARM_TENANT_ID: '${{ secrets.ARM_TENANT_ID }}' + TOKEN_NAMEPREFIX: '${{ secrets.TOKEN_NAMEPREFIX }}' + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + name: 'Initialize pipeline' + steps: + - name: 'Checkout' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: 'Set input parameters to output variables' + id: get-workflow-param + uses: ./.github/actions/templates/getWorkflowInput + with: + workflowPath: '${{ env.workflowPath}}' + - name: 'Get parameter file paths' + id: get-module-test-file-paths + uses: ./.github/actions/templates/getModuleTestFiles + with: + modulePath: '${{ env.modulePath }}' + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + + ######################### + # Static validation # + ######################### + job_module_static_validation: + runs-on: ubuntu-20.04 + name: 'Static validation' + if: (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).staticValidation == 'true' + needs: + - job_initialize_pipeline + steps: + - name: 'Checkout' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Run tests' + uses: ./.github/actions/templates/validateModulePester + with: + modulePath: '${{ env.modulePath }}' + moduleTestFilePath: '${{ env.moduleTestFilePath }}' + + ############################# + # Deployment validation # + ############################# + job_module_deploy_validation: + runs-on: ubuntu-20.04 + name: 'Deploying' + if: | + !cancelled() && + (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).deploymentValidation == 'true' && + needs.job_module_static_validation.result != 'failure' + needs: + - job_initialize_pipeline + - job_module_static_validation + strategy: + fail-fast: false + matrix: + moduleTestFilePaths: ${{ fromJson(needs.job_initialize_pipeline.outputs.moduleTestFilePaths) }} + steps: + - name: 'Checkout' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' + uses: ./.github/actions/templates/validateModuleDeployment + with: + templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' + location: '${{ env.location }}' + subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' + removeDeployment: '${{ (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).removeDeployment }}' + + ################## + # Publishing # + ################## + job_publish_module: + name: 'Publishing' + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.prerelease == 'true' + runs-on: ubuntu-20.04 + needs: + - job_module_deploy_validation + steps: + - name: 'Checkout' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Publishing' + uses: ./.github/actions/templates/publishModule + with: + templateFilePath: '${{ env.modulePath }}/deploy.bicep' + templateSpecsRGName: '${{ env.templateSpecsRGName }}' + templateSpecsRGLocation: '${{ env.templateSpecsRGLocation }}' + templateSpecsDescription: '${{ env.templateSpecsDescription }}' + templateSpecsDoPublish: '${{ env.templateSpecsDoPublish }}' + bicepRegistryName: '${{ env.bicepRegistryName }}' + bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' + bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' + bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' + publishLatest: '${{ env.publishLatest }}' diff --git a/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep new file mode 100644 index 0000000000..a2e5c142d4 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep @@ -0,0 +1,89 @@ +@sys.description('Required. The IDs of the principals to assign the role to.') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to.') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. The description of the role assignment.') +param description string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') +param condition string = '' + +@sys.description('Optional. Version of the condition.') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. Id of the delegated managed identity resource.') +param delegatedManagedIdentityResourceId string = '' + +var builtInRoleNames = { + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Azure Center for SAP solutions reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '05352d14-a920-4328-a0de-4cbe7430e26b') + 'Azure Center for SAP solutions service role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aabbc5dd-1af0-458b-a942-81af88f9c138') + 'Azure Kubernetes Service Policy Add-on Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18ed5180-3e48-46fd-8541-4ea054d57064') + 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') + 'Desktop Virtualization Power On Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33') + 'Desktop Virtualization Power On Off Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e') + 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + 'VM Scanner Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd') + 'Windows Admin Center Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a6333a3e-0164-44c3-b281-7a577aff287f') +} + +resource disk 'Microsoft.Compute/disks@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { + name: guid(disk.id, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? any(principalType) : null + condition: !empty(condition) ? condition : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + } + scope: disk +}] diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 b/modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 new file mode 100644 index 0000000000..43ca6ff500 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 @@ -0,0 +1,9 @@ +param( + [string]$resourceGroupName, + [string]$keyName +) +$publicKey = (New-AzSshKey -ResourceGroupName $resourceGroupName -Name $keyName -WarningAction SilentlyContinue).publicKey +Remove-AzSshKey -ResourceGroupName $resourceGroupName -Name $keyName +Write-Output $publicKey +$DeploymentScriptOutputs = @{} +$DeploymentScriptOutputs['pubKey'] = $publicKey diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep new file mode 100644 index 0000000000..6e6861f769 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep @@ -0,0 +1,61 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Optional. Name of the Deployment Script that creates the SSH Public Key.') +param generateSshPubKeyScriptName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. Name of the temporary SSH Public Key to create for test.') +param tempKeyName string + +@description('Optional. Do not provide a value. Used to force the deployment script to rerun on every redeployment.') +param utcValue string = utcNow() + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +// required for the deployment script to create a new temporary ssh public key object +resource msi_ContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'ManagedIdentityContributor', '<>') + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource createPubKeyScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: generateSshPubKeyScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-resourceGroupName ${resourceGroup().name} -keyName ${tempKeyName}' + scriptContent: loadTextContent('../.scripts/New-SshPubKey.ps1') + cleanupPreference: 'OnExpiration' + forceUpdateTag: utcValue + } + dependsOn: [ + msi_ContributorRoleAssignment + ] +} + +@description('The public key to be added to the SSH Public Key resource.') +output publicKey string = createPubKeyScript.properties.outputs.pubKey + +@description('The Resource ID of the managed Identity') +output managedIdentityId string = managedIdentity.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep new file mode 100644 index 0000000000..3eff132ab9 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep @@ -0,0 +1,56 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.compute.sshPublicKeys-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'sshcom' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Do not provide a value. Used to ensure a unique temporary key is generated by the deployment script.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + generateSshPubKeyScriptName: 'dep-<>-ds-${serviceShort}-generateSshPubKey' + tempKeyName: '${uniqueString(resourceGroup.name, baseTime)}-temp' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '<>-sshkey-${serviceShort}001' + publicKey: nestedDependencies.outputs.publicKey + } +} diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep new file mode 100644 index 0000000000..cfad481108 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep @@ -0,0 +1,41 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.compute.sshPublicKeys-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'sshmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '<>-${serviceShort}001' + } +} diff --git a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep new file mode 100644 index 0000000000..5a02ebb163 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep @@ -0,0 +1,80 @@ +@description('Required. The name of the SSH public Key that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@description('Optional. SSH public key used to authenticate to a virtual machine through SSH. If this property is not initially provided when the resource is created, the publicKey property will be populated when generateKeyPair is called. If the public key is provided upon resource creation, the provided public key needs to be at least 2048-bit and in ssh-rsa format.') +param publicKey string = '' + +@allowed([ + '' + 'CanNotDelete' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource sshPublicKey 'Microsoft.Compute/sshPublicKeys@2022-08-01' = { + name: name + location: location + tags: tags + properties: { + publicKey: !empty(publicKey) ? publicKey : null + } +} + +resource sshPublicKey_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock)) { + name: '${sshPublicKey.name}-${lock}-lock' + properties: { + level: any(lock) + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: sshPublicKey +} + +module sshPublicKey_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-sshPublicKey-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + condition: contains(roleAssignment, 'condition') ? roleAssignment.condition : '' + delegatedManagedIdentityResourceId: contains(roleAssignment, 'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : '' + resourceId: sshPublicKey.id + } +}] + +@description('The resource group the disk was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the disk.') +output resourceId string = sshPublicKey.id + +@description('The name of the disk.') +output name string = sshPublicKey.name + +@description('The location the resource was deployed into.') +output location string = sshPublicKey.location diff --git a/modules/Microsoft.Compute/sshPublicKeys/readme.md b/modules/Microsoft.Compute/sshPublicKeys/readme.md new file mode 100644 index 0000000000..c2bb8a69c1 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/readme.md @@ -0,0 +1,253 @@ +# Compute Disks `[Microsoft.Compute/sshPublicKeys]` + +This template deploys a disk + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Deployment examples](#Deployment-examples) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Compute/sshPublicKeys` | [2022-08-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-08-01/sshPublicKeys) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SSH public Key that is being created. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via a Globally Unique Identifier (GUID). | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `''` | `['', CanNotDelete, ReadOnly]` | Specify the type of lock. | +| `publicKey` | string | `''` | | SSH public key used to authenticate to a virtual machine through SSH. If this property is not initially provided when the resource is created, the publicKey property will be populated when generateKeyPair is called. If the public key is provided upon resource creation, the provided public key needs to be at least 2048-bit and in ssh-rsa format. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | +| `tags` | object | `{object}` | | Tags of the availability set resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +
+ +Parameter JSON format + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +
+ +
+ +Bicep format + +```bicep +roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + description: 'Reader Role Assignment' + principalIds: [ + '12345678-1234-1234-1234-123456789012' // object 1 + '78945612-1234-1234-1234-123456789012' // object 2 + ] + } + { + roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + principalIds: [ + '12345678-1234-1234-1234-123456789012' // object 1 + ] + principalType: 'ServicePrincipal' + } +] +``` + +
+

+ +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +

+ +Parameter JSON format + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +
+ +
+ +Bicep format + +```bicep +tags: { + Environment: 'Non-Prod' + Contact: 'test.user@testcompany.com' + PurchaseOrder: '1234' + CostCenter: '7890' + ServiceName: 'DeploymentValidation' + Role: 'DeploymentValidation' +} +``` + +
+

+ +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the disk. | +| `resourceGroupName` | string | The resource group the disk was deployed into. | +| `resourceId` | string | The resource ID of the disk. | + +## Cross-referenced modules + +_None_ + +## Deployment examples + +The following module usage examples are retrieved from the content of the files hosted in the module's `.test` folder. + >**Note**: The name of each example is based on the name of the file from which it is taken. + + >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +

Example 1: Common

+ +
+ +via Bicep module + +```bicep +module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { + name: '${uniqueString(deployment().name, location)}-test-sshcom' + params: { + // Required parameters + name: '<>-sshkey-sshcom001' + // Non-required parameters + enableDefaultTelemetry: '' + publicKey: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "<>-sshkey-sshcom001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + }, + "publicKey": { + "value": "" + } + } +} +``` + +
+

+ +

Example 2: Min

+ +
+ +via Bicep module + +```bicep +module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { + name: '${uniqueString(deployment().name, location)}-test-sshmin' + params: { + // Required parameters + name: '<>-sshmin001' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "<>-sshmin001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

diff --git a/modules/Microsoft.Compute/sshPublicKeys/version.json b/modules/Microsoft.Compute/sshPublicKeys/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/modules/Microsoft.Compute/sshPublicKeys/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} From 4abb8373a47240fb6cb4c2bb1b8676148df62646 Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:07:06 -0500 Subject: [PATCH 02/12] Update modules/Microsoft.Compute/sshPublicKeys/readme.md Co-authored-by: Alexander Sehr --- modules/Microsoft.Compute/sshPublicKeys/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/readme.md b/modules/Microsoft.Compute/sshPublicKeys/readme.md index c2bb8a69c1..2e1330d65b 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/readme.md +++ b/modules/Microsoft.Compute/sshPublicKeys/readme.md @@ -1,4 +1,4 @@ -# Compute Disks `[Microsoft.Compute/sshPublicKeys]` +# Public SSH Keys `[Microsoft.Compute/sshPublicKeys]` This template deploys a disk From 19be048f1754d777ef100ee8a4479a5155e1c4c7 Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:07:20 -0500 Subject: [PATCH 03/12] Update modules/Microsoft.Compute/sshPublicKeys/deploy.bicep Co-authored-by: Alexander Sehr --- modules/Microsoft.Compute/sshPublicKeys/deploy.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep index 5a02ebb163..470862797c 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep @@ -73,7 +73,7 @@ output resourceGroupName string = resourceGroup().name @description('The resource ID of the disk.') output resourceId string = sshPublicKey.id -@description('The name of the disk.') +@description('The name of the Public SSH Key.') output name string = sshPublicKey.name @description('The location the resource was deployed into.') From db10ae379f0c388bb7f2438aaea83bb3d107d062 Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:09:13 -0500 Subject: [PATCH 04/12] Update modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep Co-authored-by: Alexander Sehr --- .../sshPublicKeys/.test/common/dependencies.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep index 6e6861f769..1a38b2fbb7 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep @@ -54,7 +54,7 @@ resource createPubKeyScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = @description('The public key to be added to the SSH Public Key resource.') output publicKey string = createPubKeyScript.properties.outputs.pubKey -@description('The Resource ID of the managed Identity') +@description('The resource ID of the managed Identity') output managedIdentityId string = managedIdentity.id @description('The principal ID of the created Managed Identity.') From ff1bcd58c68896c5219ce4b8e5e6fb92c2ca5d4a Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:09:35 -0500 Subject: [PATCH 05/12] Update modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep Co-authored-by: Alexander Sehr --- .../sshPublicKeys/.test/common/deploy.test.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep index 3eff132ab9..3fc2852dd3 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep @@ -12,7 +12,7 @@ param resourceGroupName string = 'ms.compute.sshPublicKeys-${serviceShort}-rg' param location string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'sshcom' +param serviceShort string = 'cspkcom' @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') param enableDefaultTelemetry bool = true From 723a59c1a713b4bd2aa4058c6aa52a1b3b167621 Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:11:00 -0500 Subject: [PATCH 06/12] Update modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep Co-authored-by: Alexander Sehr --- .../Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep index cfad481108..5f5403280f 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/min/deploy.test.bicep @@ -12,7 +12,7 @@ param resourceGroupName string = 'ms.compute.sshPublicKeys-${serviceShort}-rg' param location string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'sshmin' +param serviceShort string = 'cspkmin' @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') param enableDefaultTelemetry bool = true From 6c2db7a463758ad15e5187eaec47e95a87af3129 Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:15:22 -0500 Subject: [PATCH 07/12] Update modules/Microsoft.Compute/sshPublicKeys/readme.md Co-authored-by: Alexander Sehr --- modules/Microsoft.Compute/sshPublicKeys/readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/readme.md b/modules/Microsoft.Compute/sshPublicKeys/readme.md index 2e1330d65b..420e3bb560 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/readme.md +++ b/modules/Microsoft.Compute/sshPublicKeys/readme.md @@ -1,6 +1,7 @@ # Public SSH Keys `[Microsoft.Compute/sshPublicKeys]` -This template deploys a disk +This template deploys a Public SSH Key resource. +> Note: The resource does not auto-generate the key for you. ## Navigation From 651721f21c0ebd2fc1396e55ef6f6f145f6ea307 Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:15:36 -0500 Subject: [PATCH 08/12] Update modules/Microsoft.Compute/sshPublicKeys/deploy.bicep Co-authored-by: Alexander Sehr --- modules/Microsoft.Compute/sshPublicKeys/deploy.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep index 470862797c..3b05586434 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep @@ -70,7 +70,7 @@ module sshPublicKey_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for @description('The resource group the disk was deployed into.') output resourceGroupName string = resourceGroup().name -@description('The resource ID of the disk.') +@description('The resource ID of the Public SSH Key.') output resourceId string = sshPublicKey.id @description('The name of the Public SSH Key.') From 5d56cfe2fc0ac69362807712babd231908192e4a Mon Sep 17 00:00:00 2001 From: Shawn Meyer <49066369+shawntmeyer@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:15:51 -0500 Subject: [PATCH 09/12] Update modules/Microsoft.Compute/sshPublicKeys/deploy.bicep Co-authored-by: Alexander Sehr --- modules/Microsoft.Compute/sshPublicKeys/deploy.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep index 3b05586434..8c90d6e241 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/deploy.bicep @@ -67,7 +67,7 @@ module sshPublicKey_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for } }] -@description('The resource group the disk was deployed into.') +@description('The name of the Resource Group the Public SSH Key was created in.') output resourceGroupName string = resourceGroup().name @description('The resource ID of the Public SSH Key.') From c61517c32db11940680c68b3090ee6da3bf16fc7 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 18 Apr 2023 12:45:38 -0400 Subject: [PATCH 10/12] resolved comments --- modules/.shared/.scripts/New-SSHKey.ps1 | 40 +++++++++++++++++++ .../.test/.scripts/New-SshPubKey.ps1 | 9 ----- .../.test/common/dependencies.bicep | 6 +-- .../.test/common/deploy.test.bicep | 6 +-- 4 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 modules/.shared/.scripts/New-SSHKey.ps1 delete mode 100644 modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 diff --git a/modules/.shared/.scripts/New-SSHKey.ps1 b/modules/.shared/.scripts/New-SSHKey.ps1 new file mode 100644 index 0000000000..3e5c532388 --- /dev/null +++ b/modules/.shared/.scripts/New-SSHKey.ps1 @@ -0,0 +1,40 @@ +<# +.SYNOPSIS +Generate a new Public SSH Key or fetch it from an existing Public SSH Key resource. + +.DESCRIPTION +Generate a new Public SSH Key or fetch it from an existing Public SSH Key resource. + +.PARAMETER SSHKeyName +Mandatory. The name of the Public SSH Key Resource as it would be deployed in Azure + +.PARAMETER ResourceGroupName +Mandatory. The resource group name of the Public SSH Key Resource as it would be deployed in Azure + +.EXAMPLE +./New-SSHKey.ps1 -SSHKeyName 'myKeyResource' -ResourceGroupName 'ssh-rg' + +Generate a new Public SSH Key or fetch it from an existing Public SSH Key resource 'myKeyResource' in Resource Group 'ssh-rg' +#> +param( + [Parameter(Mandatory = $true)] + [string] $SSHKeyName, + + [Parameter(Mandatory = $true)] + [string] $ResourceGroupName +) + +if (-not ($sshKey = Get-AzSshKey -ResourceGroupName $ResourceGroupName | Where-Object { $_.Name -eq $SSHKeyName })) { + Write-Verbose "No SSH key [$SSHKeyName] found in Resource Group [$ResourceGroupName]. Generating new." -Verbose + $null = ssh-keygen -f generated -N (Get-Random -Maximum 99999) + $publicKey = Get-Content 'generated.pub' -Raw + # $privateKey = cat generated | Out-String +} else { + Write-Verbose "SSH key [$SSHKeyName] found in Resource Group [$ResourceGroupName]. Returning." -Verbose + $publicKey = $sshKey.publicKey +} +# Write into Deployment Script output stream +$DeploymentScriptOutputs = @{ + # Requires conversion as the script otherwise returns an object instead of the plain public key string + publicKey = $publicKey | Out-String +} diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 b/modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 deleted file mode 100644 index 43ca6ff500..0000000000 --- a/modules/Microsoft.Compute/sshPublicKeys/.test/.scripts/New-SshPubKey.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -param( - [string]$resourceGroupName, - [string]$keyName -) -$publicKey = (New-AzSshKey -ResourceGroupName $resourceGroupName -Name $keyName -WarningAction SilentlyContinue).publicKey -Remove-AzSshKey -ResourceGroupName $resourceGroupName -Name $keyName -Write-Output $publicKey -$DeploymentScriptOutputs = @{} -$DeploymentScriptOutputs['pubKey'] = $publicKey diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep index 1a38b2fbb7..27b6f54c35 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/common/dependencies.bicep @@ -8,7 +8,7 @@ param generateSshPubKeyScriptName string param managedIdentityName string @description('Required. Name of the temporary SSH Public Key to create for test.') -param tempKeyName string +param sshKeyName string @description('Optional. Do not provide a value. Used to force the deployment script to rerun on every redeployment.') param utcValue string = utcNow() @@ -41,8 +41,8 @@ resource createPubKeyScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = properties: { azPowerShellVersion: '8.0' retentionInterval: 'P1D' - arguments: '-resourceGroupName ${resourceGroup().name} -keyName ${tempKeyName}' - scriptContent: loadTextContent('../.scripts/New-SshPubKey.ps1') + arguments: '-ResourceGroupName ${resourceGroup().name} -SSHKeyName ${sshKeyName}' + scriptContent: loadTextContent('../../../../.shared/.scripts/New-SSHKey.ps1') cleanupPreference: 'OnExpiration' forceUpdateTag: utcValue } diff --git a/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep b/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep index 3fc2852dd3..1bd8893349 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.test/common/deploy.test.bicep @@ -12,14 +12,12 @@ param resourceGroupName string = 'ms.compute.sshPublicKeys-${serviceShort}-rg' param location string = deployment().location @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +@maxLength(7) param serviceShort string = 'cspkcom' @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') param enableDefaultTelemetry bool = true -@description('Optional. Do not provide a value. Used to ensure a unique temporary key is generated by the deployment script.') -param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') - // ============ // // Dependencies // // ============ // @@ -36,7 +34,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { generateSshPubKeyScriptName: 'dep-<>-ds-${serviceShort}-generateSshPubKey' - tempKeyName: '${uniqueString(resourceGroup.name, baseTime)}-temp' + sshKeyName: 'dep-<>-ssh-${serviceShort}' managedIdentityName: 'dep-<>-msi-${serviceShort}' } } From 70e4fb95a8c714f06dcac532ec5975a3ceba4580 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 18 Apr 2023 12:59:20 -0400 Subject: [PATCH 11/12] updated readme and nested role assignments --- .../.bicep/nested_roleAssignments.bicep | 7 ++++--- .../Microsoft.Compute/sshPublicKeys/readme.md | 18 +++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep index a2e5c142d4..99339261b4 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep @@ -36,6 +36,7 @@ param delegatedManagedIdentityResourceId string = '' var builtInRoleNames = { 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Azure Center for SAP solutions administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b0c7e81-271f-4c71-90bf-e30bdfdbc2f7') 'Azure Center for SAP solutions reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '05352d14-a920-4328-a0de-4cbe7430e26b') 'Azure Center for SAP solutions service role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aabbc5dd-1af0-458b-a942-81af88f9c138') 'Azure Kubernetes Service Policy Add-on Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18ed5180-3e48-46fd-8541-4ea054d57064') @@ -70,12 +71,12 @@ var builtInRoleNames = { 'Windows Admin Center Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a6333a3e-0164-44c3-b281-7a577aff287f') } -resource disk 'Microsoft.Compute/disks@2021-08-01' existing = { +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-11-01' existing = { name: last(split(resourceId, '/')) } resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { - name: guid(disk.id, principalId, roleDefinitionIdOrName) + name: guid(resourceId, principalId, roleDefinitionIdOrName) properties: { description: description roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName @@ -85,5 +86,5 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null } - scope: disk + scope: sshKey }] diff --git a/modules/Microsoft.Compute/sshPublicKeys/readme.md b/modules/Microsoft.Compute/sshPublicKeys/readme.md index 420e3bb560..eb33edd4ea 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/readme.md +++ b/modules/Microsoft.Compute/sshPublicKeys/readme.md @@ -144,9 +144,9 @@ tags: { | Output Name | Type | Description | | :-- | :-- | :-- | | `location` | string | The location the resource was deployed into. | -| `name` | string | The name of the disk. | -| `resourceGroupName` | string | The resource group the disk was deployed into. | -| `resourceId` | string | The resource ID of the disk. | +| `name` | string | The name of the Public SSH Key. | +| `resourceGroupName` | string | The name of the Resource Group the Public SSH Key was created in. | +| `resourceId` | string | The resource ID of the Public SSH Key. | ## Cross-referenced modules @@ -167,10 +167,10 @@ The following module usage examples are retrieved from the content of the files ```bicep module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { - name: '${uniqueString(deployment().name, location)}-test-sshcom' + name: '${uniqueString(deployment().name, location)}-test-cspkcom' params: { // Required parameters - name: '<>-sshkey-sshcom001' + name: '<>-sshkey-cspkcom001' // Non-required parameters enableDefaultTelemetry: '' publicKey: '' @@ -192,7 +192,7 @@ module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { "parameters": { // Required parameters "name": { - "value": "<>-sshkey-sshcom001" + "value": "<>-sshkey-cspkcom001" }, // Non-required parameters "enableDefaultTelemetry": { @@ -216,10 +216,10 @@ module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { ```bicep module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { - name: '${uniqueString(deployment().name, location)}-test-sshmin' + name: '${uniqueString(deployment().name, location)}-test-cspkmin' params: { // Required parameters - name: '<>-sshmin001' + name: '<>-cspkmin001' // Non-required parameters enableDefaultTelemetry: '' } @@ -240,7 +240,7 @@ module sshPublicKeys './Microsoft.Compute/sshPublicKeys/deploy.bicep' = { "parameters": { // Required parameters "name": { - "value": "<>-sshmin001" + "value": "<>-cspkmin001" }, // Non-required parameters "enableDefaultTelemetry": { From d61d19553f2e4209471d21e69cf164590915a607 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 18 Apr 2023 13:01:04 -0400 Subject: [PATCH 12/12] added ! --- .../sshPublicKeys/.bicep/nested_roleAssignments.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep index 99339261b4..b7f80f662b 100644 --- a/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep +++ b/modules/Microsoft.Compute/sshPublicKeys/.bicep/nested_roleAssignments.bicep @@ -72,7 +72,7 @@ var builtInRoleNames = { } resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-11-01' existing = { - name: last(split(resourceId, '/')) + name: last(split(resourceId, '/'))! } resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: {