Skip to content

Commit 86d24b5

Browse files
authored
Merge pull request #287793 from MutemwaRMasheke/mc-user-assigned-identity
Mc user assigned identity
2 parents 9c098fc + cada2d0 commit 86d24b5

File tree

7 files changed

+204
-45
lines changed

7 files changed

+204
-45
lines changed

articles/governance/machine-configuration/how-to/create-policy-definition.md

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ description: Learn how to create a machine configuration policy.
44
ms.date: 02/01/2024
55
ms.topic: how-to
66
---
7+
78
# How to create custom machine configuration policy definitions
89

910
Before you begin, it's a good idea to read the overview page for [machine configuration][01], and
@@ -105,18 +106,36 @@ Parameters of the `New-GuestConfigurationPolicy` cmdlet:
105106
- **Description**: Policy description.
106107
- **Parameter**: Policy parameters provided in a hash table.
107108
- **PolicyVersion**: Policy version.
108-
- **Path**: Destination path where policy definitions are created.
109+
- **Path**: Destination path where policy definitions are created. Don't specify this parameter as
110+
the path to a local copy of the package.
109111
- **Platform**: Target platform (Windows/Linux) for machine configuration policy and content
110112
package.
111-
- **Mode**: (case sensitive: `ApplyAndMonitor`, `ApplyAndAutoCorrect`, `Audit`) choose if the policy should audit
112-
or deploy the configuration. The default is `Audit`.
113-
- **Tag** adds one or more tag filters to the policy definition
114-
- **Category** sets the category metadata field in the policy definition
113+
- **Mode**: (case sensitive: `ApplyAndMonitor`, `ApplyAndAutoCorrect`, `Audit`) choose if the
114+
policy should audit or deploy the configuration. The default is `Audit`.
115+
- **Tag**: Adds one or more tag filters to the policy definition.
116+
- **Category**: Sets the category metadata field in the policy definition.
117+
- **LocalContentPath**: The path to the local copy of the `.zip` Machine Configuration package
118+
file. This parameter is required if you're using a User Assigned Managed Identity to provide
119+
access to an Azure Storge blob.
120+
- **ManagedIdentityResourceId**: The `resourceId` of the User Assigned Managed Identity that has
121+
read access to the Azure Storage blob containing the `.zip` Machine Configuration package file.
122+
This parameter is required if you're using a User Assigned Managed Identity to provide access to
123+
an Azure Storge blob.
124+
- **ExcludeArcMachines**: Specifies that the Policy definition should exclude Arc machines. This
125+
parameter is required if you are using a User Assigned Managed Identity to provide access to an
126+
Azure Storge blob.
127+
128+
> [!IMPORTANT]
129+
> Unlike Azure VMs, Arc-connected machines currently do not support User Assigned Managed
130+
> Identities. As a result, the `-ExcludeArcMachines` flag is required to ensure the exclusion of
131+
> those machines from the policy definition. For the Azure VM to download the assigned package and
132+
> apply the policy, the Guest Configuration Agent must be version `1.29.82.0` or higher for Windows
133+
> and version `1.26.76.0` or higher for Linux.
115134
116135
For more information about the **Mode** parameter, see the page
117136
[How to configure remediation options for machine configuration][02].
118137

119-
Create a policy definition that audits using a custom configuration package, in a specified path:
138+
Create a policy definition that **audits** using a custom configuration package, in a specified path:
120139

121140
```powershell
122141
$PolicyConfig = @{
@@ -132,8 +151,7 @@ $PolicyConfig = @{
132151
New-GuestConfigurationPolicy @PolicyConfig
133152
```
134153

135-
Create a policy definition that deploys a configuration using a custom configuration package, in a
136-
specified path:
154+
Create a policy definition that **enforces** a custom configuration package, in a specified path:
137155

138156
```powershell
139157
$PolicyConfig2 = @{
@@ -150,6 +168,30 @@ $PolicyConfig2 = @{
150168
New-GuestConfigurationPolicy @PolicyConfig2
151169
```
152170

171+
Create a policy definition that **enforces** a custom configuration package using a User-Assigned
172+
Managed Identity:
173+
174+
```powershell
175+
$PolicyConfig3 = @{
176+
PolicyId = '_My GUID_'
177+
ContentUri = $contentUri
178+
DisplayName = 'My deployment policy'
179+
Description = 'My deployment policy'
180+
Path = './policies/deployIfNotExists.json'
181+
Platform = 'Windows'
182+
PolicyVersion = 1.0.0
183+
Mode = 'ApplyAndAutoCorrect'
184+
ContentLocalPath = "C:\Local\Path\To\Package" # Required parameter for managed identity
185+
ManagedIdentityResourceId = "YourManagedIdentityResourceId" # Required parameter for managed identity
186+
}
187+
188+
New-GuestConfigurationPolicy @PolicyConfig3 -ExcludeArcMachines
189+
```
190+
191+
> [!NOTE]
192+
> You can retrieve the resorceId of a nmanaged identity using the `Get-AzUserAssignedIdentity`
193+
> PowerShell cmdlet.
194+
153195
The cmdlet output returns an object containing the definition display name and path of the policy
154196
files. Definition JSON files that create audit policy definitions have the name
155197
`auditIfNotExists.json` and files that create policy definitions to apply configurations have the

articles/governance/machine-configuration/how-to/develop-custom-package/4-publish-package.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ $contentUri = New-AzStorageBlobSASToken @tokenParams
110110
## Next step
111111

112112
> [!div class="nextstepaction"]
113-
> [Sign a custom machine configuration package](./5-sign-package.md)
113+
> [Provide secure access to a custom machine configuration package](./5-access-package.md)
114+
114115

115116
<!-- Reference link definitions -->
116117
[01]: ../../overview.md
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
title: How to access custom machine configuration package artifacts
3+
description: Learn how to provide access to a machine configuration package file in Azure blob storage .
4+
ms.date: 08/28/2024
5+
ms.topic: how-to
6+
ms.custom: devx-track-azurepowershell
7+
---
8+
9+
# How to provide secure access to custom machine configuration packages
10+
11+
This page provides a guide on how to provide access to Machine Configuration packages stored in
12+
Azure storage by using the resource ID of a user-assigned managed identity or a Shared Access
13+
Signature (SAS) token.
14+
15+
## Prerequisites
16+
17+
- Azure subscription
18+
- Azure Storage account with the Machine Configuration package
19+
20+
## Steps to provide access to the package
21+
22+
The following steps prepare your resources for more secure operations. TThe code snippets for the
23+
steps include values in angle brackets, like `<storage-account-container-name>`, which you must
24+
replace with a valid value when following the steps. If you just copy and paste the code, the
25+
commands may raise errors due to invalid values.
26+
27+
### Using a User Assigned Identity
28+
29+
> [!IMPORTANT]
30+
> Please note that, unlike Azure VMs, Arc-connected machines currently do not support User-Assigned
31+
> Managed Identities.
32+
33+
You can grant private access to a machine configuration package in an Azure Storage blob by
34+
assigning a [User-Assigned Identity][01] to a scope of Azure VMs. For this to work, you need to
35+
grant the managed identity read access to the Azure storage blob. This involves assigning the
36+
"Storage Blob Data Reader" role to the identity at the scope of the blob container. This setup
37+
ensures that your Azure VMs can securely read from the specified blob container using the
38+
user-assigned managed identity. To learn how you can assign a User Assigned Identity at scale, see
39+
[Use Azure Policy to assign managed identities][02].
40+
41+
### Using a SAS Token
42+
43+
Optionally, you can add a shared access signature (SAS) token in the URL to ensure secure access to
44+
the package. The below example generates a blob SAS token with read access and returns the full
45+
blob URI with the shared access signature token. In this example, the token has a time limit of
46+
three years.
47+
48+
```powershell
49+
$startTime = Get-Date
50+
$endTime = $startTime.AddYears(3)
51+
52+
$tokenParams = @{
53+
StartTime = $startTime
54+
ExpiryTime = $endTime
55+
Container = '<storage-account-container-name>'
56+
Blob = '<configuration-blob-name>'
57+
Permission = 'r'
58+
Context = '<storage-account-context>'
59+
FullUri = $true
60+
}
61+
62+
$contentUri = New-AzStorageBlobSASToken @tokenParams
63+
```
64+
65+
## Summary
66+
67+
By using the resource ID of a user-assigned managed identity or SAS token, you can securely provide
68+
access to Machine Configuration packages stored in Azure storage. The additional parameters ensure
69+
that the package is retrieved using the managed identity and that Azure Arc machines aren't
70+
included in the policy scope.
71+
72+
## Next Steps
73+
- After creating the policy definition, you can assign it to the appropriate scope, like management
74+
group, subscription, or resource group, within your Azure environment.
75+
- Remember to monitor the policy compliance status and make any necessary adjustments to your
76+
Machine Configuration package or policy assignment to meet your organizational requirements.
77+
78+
> [!div class="nextstepaction"]
79+
> [Sign a custom machine configuration package](./6-sign-package.md)
80+
81+
<!-- Reference link definitions -->
82+
[01]: /entra/identity/managed-identities-azure-resources/managed-identity-best-practice-recommendations#using-user-assigned-identities-to-reduce-administration
83+
[02]: /entra/identity/managed-identities-azure-resources/how-to-assign-managed-identity-via-azure-policy

articles/governance/machine-configuration/how-to/develop-custom-package/5-sign-package.md renamed to articles/governance/machine-configuration/how-to/develop-custom-package/6-sign-package.md

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ ms.custom: linux-related-content
88

99
# How to sign machine configuration packages
1010

11-
Machine configuration custom policies use SHA256 hash to validate the policy package hasn't
11+
Machine configuration custom policies use a SHA256 hash to validate that the policy package hasn't
1212
changed. Optionally, customers may also use a certificate to sign packages and force the machine
1313
configuration extension to only allow signed content.
1414

15-
To enable this scenario, there are two steps you need to complete. Run the cmdlet to sign the
16-
content package, and append a tag to the machines that should require code to be signed.
15+
To enable this scenario, there are two steps you need to complete:
16+
17+
1. Run the cmdlet to sign the content package.
18+
1. Append a tag to the machines that should require code to be signed.
1719

1820
## Signature validation using a code signing certificate
1921

@@ -24,7 +26,7 @@ testing purposes to follow along with the example.
2426

2527
## Windows signature validation
2628

27-
```azurepowershell-interactive
29+
```powershell
2830
# How to create a self sign cert and use it to sign Machine Configuration
2931
# custom policy package
3032
@@ -34,26 +36,35 @@ $codeSigningParams = @{
3436
DnsName = 'GCEncryptionCertificate'
3537
HashAlgorithm = 'SHA256'
3638
}
37-
$mycert = New-SelfSignedCertificate @codeSigningParams
39+
$certificate = New-SelfSignedCertificate @codeSigningParams
3840
3941
# Export the certificates
40-
$mypwd = ConvertTo-SecureString -String "Password1234" -Force -AsPlainText
41-
$mycert | Export-PfxCertificate -FilePath C:\demo\GCPrivateKey.pfx -Password $mypwd
42-
$mycert | Export-Certificate -FilePath "C:\demo\GCPublicKey.cer" -Force
42+
$privateKey = @{
43+
Cert = $certificate
44+
Password = Read-Host "Enter password for private key" -AsSecureString
45+
FilePath = '<full-path-to-export-private-key-pfx-file>'
46+
}
47+
$publicKey = @{
48+
Cert = $certificate
49+
FilePath = '<full-path-to-export-public-key-cer-file>'
50+
Force = $true
51+
}
52+
Export-PfxCertificate @privateKey
53+
Export-Certificate @publicKey
4354
4455
# Import the certificate
4556
$importParams = @{
46-
FilePath = 'C:\demo\GCPrivateKey.pfx'
47-
Password = $mypwd
57+
FilePath = $privateKey.FilePath
58+
Password = $privateKey.Password
4859
CertStoreLocation = 'Cert:\LocalMachine\My'
4960
}
5061
Import-PfxCertificate @importParams
5162
5263
# Sign the policy package
53-
$certToSignThePackage = Get-ChildItem -Path cert:\LocalMachine\My |
54-
Where-Object { $_.Subject-eq "CN=GCEncryptionCertificate" }
64+
$certToSignThePackage = Get-ChildItem -Path Cert:\LocalMachine\My |
65+
Where-Object { $_.Subject -eq "CN=GCEncryptionCertificate" }
5566
$protectParams = @{
56-
Path = 'C:\demo\AuditWindowsService.zip'
67+
Path = '<path-to-package-to-sign>'
5768
Certificate = $certToSignThePackage
5869
Verbose = $true
5970
}
@@ -62,51 +73,64 @@ Protect-GuestConfigurationPackage @protectParams
6273

6374
## Linux signature validation
6475

65-
```azurepowershell-interactive
76+
```powershell
6677
# generate gpg key
6778
gpg --gen-key
6879
80+
$emailAddress = '<email-id-used-to-generate-gpg-key>'
81+
$publicGpgKeyPath = '<full-path-to-export-public-key-gpg-file>'
82+
$privateGpgKeyPath = '<full-path-to-export-private-key-gpg-file>'
83+
6984
# export public key
70-
gpg --output public.gpg --export <email-id-used-to-generate-gpg-key>
85+
gpg --output $publicGpgKeyPath --export $emailAddress
7186
7287
# export private key
73-
gpg --output private.gpg --export-secret-key <email-id-used-to-generate-gpg-key>
88+
gpg --output $privateGpgKeyPath --export-secret-key $emailAddress
7489
7590
# Sign linux policy package
7691
Import-Module GuestConfiguration
7792
$protectParams = @{
78-
Path = './not_installed_application_linux.zip'
79-
PrivateGpgKeyPath = './private.gpg'
80-
PublicGpgKeyPath = './public.gpg'
93+
Path = '<path-to-package-to-sign>'
94+
PrivateGpgKeyPath = $privateGpgKeyPath
95+
PublicGpgKeyPath = $publicGpgKeyPath
8196
Verbose = $true
8297
}
8398
Protect-GuestConfigurationPackage
8499
```
85100

86101
Parameters of the `Protect-GuestConfigurationPackage` cmdlet:
87102

88-
- **Path**: Full path of the machine configuration package.
103+
- **Path**: Full path to the machine configuration package.
89104
- **Certificate**: Code signing certificate to sign the package. This parameter is only supported
90105
when signing content for Windows.
106+
- **PrivateGpgKeyPath**: Full path to the private key `.gpg` file. This parameter is only supported
107+
when signing content for Linux.
108+
- **PublicGpgKeyPath**: Full path to the public key `.gpg` file. This parameter is only supported
109+
when signing content for Linux.
110+
91111

92112
## Certificate requirements
93113

94-
The machine configuration agent expects the certificate public key to be present in "Trusted Publishers" on Windows machines and in the path `/usr/local/share/ca-certificates/gc`
95-
on Linux machines. For the node to verify signed content, install the certificate public key on the
96-
machine before applying the custom policy. This process can be done using any technique inside the
97-
VM or by using Azure Policy. An example template is available
98-
[to deploy a machine with a certificate][01]. The Key Vault access policy must allow the Compute
99-
resource provider to access certificates during deployments. For detailed steps, see
114+
The machine configuration agent expects the certificate public key to be present in "Trusted
115+
Publishers" on Windows machines and in the path `/usr/local/share/ca-certificates/gc` on Linux
116+
machines. For the node to verify signed content, install the certificate public key on the machine
117+
before applying the custom policy.
118+
119+
You can install the certificate public key using normal tools inside the VM or by using Azure
120+
Policy. An [example template using Azure Policy][01] shows how you can deploy a machine with a
121+
certificate. The Key Vault access policy must allow the Compute resource provider to access
122+
certificates during deployments. For detailed steps, see
100123
[Set up Key Vault for virtual machines in Azure Resource Manager][02].
101124

102125
Following is an example to export the public key from a signing certificate, to import to the
103126
machine.
104127

105128
```azurepowershell-interactive
106-
$Cert = Get-ChildItem -Path cert:\LocalMachine\My |
107-
Where-Object { $_.Subject-eq "CN=mycert3" } |
129+
$Cert = Get-ChildItem -Path Cert:\LocalMachine\My |
130+
Where-Object { $_.Subject-eq 'CN=<CN-of-your-signing-certificate>' } |
108131
Select-Object -First 1
109-
$Cert | Export-Certificate -FilePath "$env:temp\DscPublicKey.cer" -Force
132+
133+
$Cert | Export-Certificate -FilePath '<path-to-export-public-key-cer-file>' -Force
110134
```
111135

112136
## Tag requirements

articles/governance/machine-configuration/how-to/develop-custom-package/overview.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ non-Azure machine.
3333
1. [Create a custom machine configuration package artifact][04]
3434
1. [Test the package artifact][05]
3535
1. [Publish the package artifact][06]
36-
1. [Sign the package artifact][07]
36+
1. [Provide access to a package][07]
37+
1. [Sign the package artifact][08]
3738

3839
<!-- Link reference definitions -->
3940
[01]: ../../overview.md
@@ -42,4 +43,5 @@ non-Azure machine.
4243
[04]: ./2-create-package.md
4344
[05]: ./3-test-package.md
4445
[06]: ./4-publish-package.md
45-
[07]: ./5-sign-package.md
46+
[07]: ./5-access-package.md
47+
[08]: ./6-sign-package.md

articles/governance/machine-configuration/toc.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,15 @@ items:
4141
href: ./how-to/develop-custom-package/3-test-package.md
4242
- name: 4. Publish a custom package
4343
href: ./how-to/develop-custom-package/4-publish-package.md
44-
- name: 5. Sign a custom package
45-
href: ./how-to/develop-custom-package/5-sign-package.md
44+
- name: 5. Access a custom package
45+
href: ./how-to/develop-custom-package/5-access-package.md
46+
- name: 6. Sign a custom package
47+
href: ./how-to/develop-custom-package/6-sign-package.md
4648
# Planned, not written
4749
# - name: Update a custom configuration
4850
# href: ./how-to/update-configuration.md
51+
- name: Create a custom policy definition
52+
href: ./how-to/create-policy-definition.md
4953
- name: Assign a configuration
5054
items:
5155
- name: Overview
@@ -56,8 +60,6 @@ items:
5660
href: ./how-to/assign-configuration/bicep.md
5761
- name: Using Terraform
5862
href: ./how-to/assign-configuration/terraform.md
59-
- name: Create a custom policy definition
60-
href: ./how-to/create-policy-definition.md
6163

6264
- name: Concepts
6365
items:

0 commit comments

Comments
 (0)