jacknova
jacknova

Reputation: 1

Invoking PowerShell script from within dotnet with authentication using Connect-AzAccount service principal

Using dotnet7 background worker, calling PowerShell

 using PowerShell ps = PowerShell.Create();
 ps.AddScript("auth.ps1"); 
 var pipelineObjects = await ps.InvokeAsync();

Minimal PowerShell code here with Az.Accounts verison 2.2.3

Import-Module Az.Accounts
Clear-AzContext -Force 

$tenantID = " " 
$subscriptionID = " "

 $azureAplicationId = " ";
 $azurePassword = ConvertTo-SecureString "" -AsPlainText -Force; 
 $credentials = New-Object System.Management.Automation.PSCredential($azureAplicationId, $azurePassword);  

try 
{ 
     Connect-AzAccount -Credential $credentials -TenantId $tenantID -ServicePrincipal -ErrorAction Stop
}
catch 
{   
    Write-Error  $Exception ; 
}

And the exception

PSMessageDetails      :
Exception             : System.EntryPointNotFoundException: Entry point was not found.
                           at System.Threading.Tasks.Sources.IValueTaskSource`1.GetStatus(Int16 token)
                           at Microsoft.Azure.PowerShell.Authenticators.MsalAccessToken.GetAccessTokenAsync(String callerClassName, String parametersLog, TokenCredential tokenCredential, TokenRequestContext requestContext, CancellationToken cancellationToken, String tenantId, String userId, String homeAccountId)
                           at Microsoft.Azure.Commands.Common.Authentication.Factories.AuthenticationFactory.Authenticate(IAzureAccount account, IAzureEnvironment environment, String tenant, SecureString password, String promptBehavior, Action`1 promptAction, IAzureTokenCache tokenCache, String resourceId)
                           at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.AcquireAccessToken(IAzureAccount account, IAzureEnvironment environment, String tenantId, SecureString password, String promptBehavior, Action`1 promptAction, String resourceId)
                           at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.Login(IAzureAccount account, IAzureEnvironment environment, String tenantIdOrName, String subscriptionId, String subscriptionName, SecureString password, Boolean skipValidation, Action`1 promptAction, String name, Boolean shouldPopulateContextList, Int32 maxContextPopulation, String authScope)
                           at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass127_2.<ExecuteCmdlet>b__5()
                           at System.Threading.Tasks.Task`1.InnerInvoke()
                           at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
                        --- End of stack trace from previous location ---
                           at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
                           at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
                        --- End of stack trace from previous location ---
                           at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass127_0.<ExecuteCmdlet>b__1(AzureRmProfile localProfile, RMProfileClient profileClient, String name)
                           at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass136_0.<SetContextWithOverwritePrompt>b__0(AzureRmProfile prof, RMProfileClient client)
                           at Microsoft.Azure.Commands.Profile.Common.AzureContextModificationCmdlet.ModifyContext(Action`2 contextAction)
                           at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.SetContextWithOverwritePrompt(Action`3 setContextAction)
                           at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.ExecuteCmdlet()
                           at Microsoft.WindowsAzure.Commands.Utilities.Common.CmdletExtensions.<>c__3`1.<ExecuteSynchronouslyOrAsJob>b__3_0(T c)
                           at Microsoft.WindowsAzure.Commands.Utilities.Common.CmdletExtensions.ExecuteSynchronouslyOrAsJob[T](T cmdlet, Action`1 executor)
                           at Microsoft.WindowsAzure.Commands.Utilities.Common.CmdletExtensions.ExecuteSynchronouslyOrAsJob[T](T cmdlet)
                           at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord()
TargetObject          :
CategoryInfo          : CloseError: (:) [Connect-AzAccount], EntryPointNotFoundException
FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 15
PipelineIterationInfo : {}

MyCommand             : Connect-AzAccount
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 15
OffsetInLine          : 6
HistoryId             : 1
ScriptName            :
Line                  :      Connect-AzAccount -Credential $credentials -TenantId $tenantID -ServicePrincipal -ErrorAction Stop

PositionMessage       : At line:15 char:6
                        +      Connect-AzAccount -Credential $credentials -TenantId $tenantID - .
                        +      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot          :
PSCommandPath         :
InvocationName        : Connect-AzAccount
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition :

Need to execute the PowerShell script so I can execute authenticated PowerShell commands in the same PowerShell script. Its a dotnet worker listening to service bus which then executes PowerShell . Eventually will be containerized

Upvotes: 0

Views: 346

Answers (1)

RohitVarun
RohitVarun

Reputation: 68

I created one console app :-

enter image description here

Copy the SubscriptionID from Azure Portal.

Assigned my service principal contributor role at Subscription level for it to perform tasks at Subscription level and read, write subscription.

In my subscription > Access Control (IAM) - > Role assignments > contributor access given to SP.

enter image description here

You can provide contributor access to your SP by clicking on Add Role Assignment in Access control (IAM) page > Select role Contributor > select member > your SP > Select > review + Create.

enter image description here

Get SP Tenant ID and application Id from here :-

enter image description here

Add these parameters in Powershell commands.

Created a simple console app in VisualStudio.

enter image description here

Installed Microsoft.Powershell.SDK NuGet package 7.21.1 Version.

enter image description here

Disable Enable Just My Code in the Debugging> General Settings in VS studio.

enter image description here

Simple program to run Powershell from .net console app in Program.cs:

using System.Diagnostics;
using System.Management.Automation.Runspaces;
using System.Management.Automation;
using System.Xml.Linq;
using System;

var initialState = InitialSessionState.CreateDefault2();
initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;

using  var ps = PowerShell.Create(initialState);

var results = ps.AddScript("\r\nInstall-Module Az.Accounts\r\nInstall-Module Az.esources\r\nImport-Module Az.Accounts\r\nImport-Module Az.Resources\r\n\r\nClear-AzContext -Force \r\n\r\n$tenantID = \"83331f4e-7f45-4ce4-99ed-af9038592395\" \r\n$subscriptionID = \"0151c365-f598-44d6-b4fd-e2b6e97cb2a7\"\r\n\r\n $azureAplicationId = \"c0c952e9-5254-45b5-b838-6d26a31435cb\";\r\n $azurePassword = ConvertTo-SecureString \"Mom8Q~AX1xc9OlrUislxBJvTvbfUKuWtpO9gadfE\" -AsPlainText -Force; \r\n $credentials = New-Object System.Management.Automation.PSCredential($azureAplicationId, $azurePassword); \r\n\r\ntry \r\n{ \r\n Connect-AzAccount -Credential $credentials -TenantId $tenantID -ServicePrincipal -ErrorAction Stop\r\n New-AzResourceGroup -Name RG05 -Location \"South Central US\"\r\n}\r\ncatch \r\n{ \r\n Write-Error $Exception ; \r\n}\r\n").Invoke();

With the above code I am able to connect to my Azure account successfully with service principal, I have also added one command to create a Resource group with the Service principal, And the Resource group was created on Azure Portal after the build was successful.

Added these lines of code in PowerShell to Install the PowerShell Module first before you Import them.


Install-Module  Az.Accounts
Install-Module  Az.Resources
Import-Module  Az.Accounts
Import-Module  Az.Resources

Added one command to create a new resource group in Azure Portal to verify if service principal is authenticating and creating resources in azure.

enter image description here

enter image description here

The PowerShell command ran successfully locally and Resource group RG03 was created on Azure Portal.

enter image description here

Now, I ran the same command via .NET console app, the build was successful in authenticating to Azure and created an RG.

Upvotes: 1

Related Questions