Azure / Azure/bicep-types-az

Unable to perform managed runcommand deployed via bicep

Open
#2,102 5 comments 0 reactions 1 assignee Claimed by @shenglol View on GitHub
Needs: Triage :mag:
Dominant language
TypeScript
Stars
108
Forks
44
Avg merge
18h 53m
Merged PRs (30d)
29

Description

**Bicep version**
v0.25.23

**Describe the bug**
Deploying the runcommand resource against a VM using a domain joined run as account to perform activity on the domain fails. In this case it is simply a script calling the get-addomain command on a domain controller to retrieve domain info to pass to an azure command.

Bicep resource

```bicep
resource domainjoinstorage 'Microsoft.Compute/virtualMachines/runCommands@2023-09-01' = {
name: 'domainjoin${storageaccount}'
location: deploymentLocation
parent: taskvm
properties: {
source: {
scriptUri: 'https://${scriptsa}.blob.${environment().suffixes.storage}/config/Script-DomainJoinStorage.ps1'
scriptUriManagedIdentity: {
clientId: umi
}
}
parameters: stdparamters
errorBlobUri: 'https://${scriptsa}.blob.${environment().suffixes.storage}/config/error-${storageaccount}-${date}.txt'
errorBlobManagedIdentity: {
clientId: umi
}
outputBlobUri: 'https://${scriptsa}.blob.${environment().suffixes.storage}/config/output-${storageaccount}-${date}.txt'
outputBlobManagedIdentity: {
clientId: umi
}
runAsUser: '${domain}\\${domainUsername}'
runAsPassword:runaspassword
timeoutInSeconds: 300
}
dependsOn: [
installmanagementmodules
]
}
```

Powershell script being called

```PowerShell
param(
[string] $StorageAccountName,
[string] $StorageAccountRG,
[string] $ClientId,
[string] $SubscriptionId,
[string] $OUName
)
$ErrorActionPreference = 'stop'
whoami

$spn = "cifs/" + $StorageAccountName + "file.core.windows.net"
$domain = get-addomain
write-host "got $domain.dnsroot info"

if (test-path HKLM:\SOFTWARE\360) {

Write-host "Connecting to managed identity account"
try {
Connect-AzAccount -Identity -AccountId $ClientId -WarningAction:SilentlyContinue
Write-host "Setting Azure subscription to $SubscriptionId"
Select-AzSubscription -SubscriptionId $SubscriptionId
write-host "subscription set"
}
catch {
[System.Exception]
throw $_
}

#get storage account key
try {
New-AzStorageAccountKey -ResourceGroupName $StorageAccountRG -Name $StorageAccountName -KeyName kerb1
$key = ConvertTo-SecureString -AsPlainText ((Get-AzStorageAccountKey -ResourceGroupName $StorageAccountRG -Name $StorageAccountName -ListKerbKey | where-object{$_.Keyname -contains "kerb1"}).value) -force
}
catch {
[System.Exception]
throw $_
}

try {
$computer = New-ADComputer -name $StorageAccountName -samaccountname $StorageAccountName -path $OUName -KerberosEncryptionType "AES256" -accountpassword $key -ServicePrincipalNames $spn -passthru
}
catch {[System.Exception]
write-error "unable to create computer account"
throw $_
}

try {
write-host "configuring storage account"
set-azstorageaccount -ResourceGroupName $StorageAccountRG -Name $StorageAccountName `
-EnableActiveDirectoryDomainServicesForFile $true `
-ActiveDirectoryDomainName $domain.dnsroot `
-ActiveDirectoryNetBiosDomainName $domain.dnsroot `
-ActiveDirectoryForestName $domain.forest `
-ActiveDirectoryDomainGuid $domain.objectguid `
-ActiveDirectoryDomainsid $domain.domainsid `
-ActiveDirectoryAzureStorageSid $computer.sid `
-ActiveDirectorySamAccountName $StorageAccountName `
-ActiveDirectoryAccountType "computer"
}
catch {[System.Exception]
write-error "unable to set storage account"
write-error $_
}

#mount file share to set permissions
$DriveLetter = 'Y'
$FileShareLocation = '\\' + $StorageAccountName + "file.core.windows.net" + '\data'
$connectTestResult = Test-NetConnection -ComputerName "$StorageAccountName.file.core.windows.net" -Port 445
if ($connectTestResult.TcpTestSucceeded){
try {
Write-Host "mapping drive to set permissions"
$UserStorage = "/user:Azure\$StorageAccountName"
$StorageKey = (Get-AzStorageAccountKey -ResourceGroupName $StorageAccountRG -AccountName $StorageAccountName) | Where-Object { $_.KeyName -eq "key1" }
net use ${DriveLetter}: $FileShareLocation $UserStorage $StorageKey.Value
}
Catch {[System.Exception]
write-error "failed to connect to storage"
write error $_
}

#configure permissions
try {
write-host "assign permissions"
#$fcgroup = $domain.dnsroot + '\admins'
#$ragroup = $domain.dnsroot + '\read'
#icacls ${DriveLetter}: /grant $fcgroup
#icacls ${DriveLetter}: /grant $ragroup
net use ${DriveLetter} /delete
}
catch {[System.Exception]
write-error "failed to set permissions"
write error $_
}
}
}
```
Error message produced:

```
Attempting to perform the InitializeDefaultDrives operation on the 'ActiveDirectory' provider failed.

get-addomain : Server instance not found on the given port.

At C:\Packages\Plugins\Microsoft.CPlat.Core.RunCommandHandlerWindows\2.0.8\Downloads\Script_domainjoinsticihdjtest_0.ps
1:12 char:11
+ $domain = get-addomain
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (COMPANY:ADDomain) [Get-ADDomain], ArgumentException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Comm
ands.GetADDomain

```

**To Reproduce**
deploy the above resource to use the script against a domain controller. Running against a server with AD PowerShell installed produces the following error:

```
get-addomain : Unable to contact the server. This may be because this server does not exist, it is currently down, or

it does not have the Active Directory Web Services running.

At C:\Packages\Plugins\Microsoft.CPlat.Core.RunCommandHandlerWindows\2.0.8\Downloads\Script_domainjoinsticihdjtest_7.ps

1:11 char:11

+ $domain = get-addomain

+ ~~~~~~~~~~~~

+ CategoryInfo : ResourceUnavailable: (COMPANY:ADDomain) [Get-ADDomain], ADServerDownException

+ FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADDomain


```

**Additional context**
I suspect the issue here is with the managed run command execution not performing elevation however I cannot see anywhere else to log this.
Now I obviously don't want to have to run any domain commands against a domain controller in azure, a management server would be preferable but there seems to be a double hop employed when going via that route based off the error above. All the commands function perfectly when run locally. The mechanism employed here has some limitations which aren't well documented.
We wanted to use this method as it allows multiple commands to be run. custom script extensions require deployment and removal in order to use again. This is part of a hosted environment where multiple resources are deployed for customers to add some context.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.