@@ -50,8 +50,69 @@ internal PowerShellManager(ILogger logger)
50
50
51
51
internal void AuthenticateToAzure ( )
52
52
{
53
- // Try to authenticate to Azure
54
- // TODO: The Azure Functions Host might supply these differently. This might change but works for the demo
53
+ // Check if Az.Profile is available
54
+ Collection < PSModuleInfo > azprofile = _pwsh . AddCommand ( "Get-Module" )
55
+ . AddParameter ( "ListAvailable" )
56
+ . AddParameter ( "Name" , "Az.Profile" )
57
+ . InvokeAndClearCommands < PSModuleInfo > ( ) ;
58
+
59
+ if ( azprofile . Count == 0 )
60
+ {
61
+ _logger . Log ( LogLevel . Trace , "Required module to automatically authenticate with Azure `Az.Profile` was not found in the PSModulePath." ) ;
62
+ return ;
63
+ }
64
+
65
+ // Try to authenticate to Azure using MSI
66
+ string msiSecret = Environment . GetEnvironmentVariable ( "MSI_SECRET" ) ;
67
+ string msiEndpoint = Environment . GetEnvironmentVariable ( "MSI_ENDPOINT" ) ;
68
+ string accountId = Environment . GetEnvironmentVariable ( "WEBSITE_SITE_NAME" ) ;
69
+
70
+ if ( ! string . IsNullOrEmpty ( msiSecret ) &&
71
+ ! string . IsNullOrEmpty ( msiEndpoint ) &&
72
+ ! string . IsNullOrEmpty ( accountId ) )
73
+ {
74
+ // NOTE: There is a limitation in Azure PowerShell that prevents us from using the parameter set:
75
+ // Connect-AzAccount -MSI or Connect-AzAccount -Identity
76
+ // see this GitHub issue https://github.com/Azure/azure-powershell/issues/7876
77
+ // As a workaround, we can all an API endpoint on the MSI_ENDPOINT to get an AccessToken and use that to authenticate
78
+ Collection < PSObject > response = _pwsh . AddCommand ( "Microsoft.PowerShell.Utility\\ Invoke-RestMethod" )
79
+ . AddParameter ( "Method" , "Get" )
80
+ . AddParameter ( "Headers" , new Hashtable { { "Secret" , msiSecret } } )
81
+ . AddParameter ( "Uri" , $ "{ msiEndpoint } ?resource=https://management.azure.com&api-version=2017-09-01")
82
+ . InvokeAndClearCommands < PSObject > ( ) ;
83
+
84
+ if ( _pwsh . HadErrors )
85
+ {
86
+ _logger . Log ( LogLevel . Warning , "Failed to Authenticate to Azure via MSI. Check the logs for the errors generated." ) ;
87
+ }
88
+ else
89
+ {
90
+ // We have successfully authenticated to Azure so we can return out.
91
+ using ( ExecutionTimer . Start ( _logger , "Authentication to Azure" ) )
92
+ {
93
+ _pwsh . AddCommand ( "Az.Profile\\ Connect-AzAccount" )
94
+ . AddParameter ( "AccessToken" , response [ 0 ] . Properties [ "access_token" ] . Value )
95
+ . AddParameter ( "AccountId" , accountId )
96
+ . InvokeAndClearCommands ( ) ;
97
+
98
+ if ( _pwsh . HadErrors )
99
+ {
100
+ _logger . Log ( LogLevel . Warning , "Failed to Authenticate to Azure. Check the logs for the errors generated." ) ;
101
+ }
102
+ else
103
+ {
104
+ // We've successfully authenticated to Azure so we can return
105
+ return ;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ else
111
+ {
112
+ _logger . Log ( LogLevel . Trace , "Skip authentication to Azure via MSI. Environment variables for authenticating to Azure are not present." ) ;
113
+ }
114
+
115
+ // Try to authenticate to Azure using Service Principal
55
116
string applicationId = Environment . GetEnvironmentVariable ( "SERVICE_PRINCIPAL_APP_ID" ) ;
56
117
string applicationSecret = Environment . GetEnvironmentVariable ( "SERVICE_PRINCIPAL_APP_PASSWORD" ) ;
57
118
string tenantId = Environment . GetEnvironmentVariable ( "SERVICE_PRINCIPAL_TENANT_ID" ) ;
@@ -60,7 +121,7 @@ internal void AuthenticateToAzure()
60
121
string . IsNullOrEmpty ( applicationSecret ) ||
61
122
string . IsNullOrEmpty ( tenantId ) )
62
123
{
63
- _logger . Log ( LogLevel . Warning , "Required environment variables to authenticate to Azure were not present" ) ;
124
+ _logger . Log ( LogLevel . Trace , "Skip authentication to Azure via Service Principal. Environment variables for authenticating to Azure are not present. " ) ;
64
125
return ;
65
126
}
66
127
@@ -71,13 +132,18 @@ internal void AuthenticateToAzure()
71
132
secureString . AppendChar ( item ) ;
72
133
}
73
134
74
- using ( ExecutionTimer . Start ( _logger , "Authentication to Azure completed. " ) )
135
+ using ( ExecutionTimer . Start ( _logger , "Authentication to Azure" ) )
75
136
{
76
137
_pwsh . AddCommand ( "Az.Profile\\ Connect-AzAccount" )
77
138
. AddParameter ( "Credential" , new PSCredential ( applicationId , secureString ) )
78
139
. AddParameter ( "ServicePrincipal" )
79
140
. AddParameter ( "TenantId" , tenantId )
80
141
. InvokeAndClearCommands ( ) ;
142
+
143
+ if ( _pwsh . HadErrors )
144
+ {
145
+ _logger . Log ( LogLevel . Warning , "Failed to Authenticate to Azure via Service Principal. Check the logs for the errors generated." ) ;
146
+ }
81
147
}
82
148
}
83
149
@@ -89,8 +155,6 @@ internal void InitializeRunspace()
89
155
90
156
// Set the PSModulePath
91
157
Environment . SetEnvironmentVariable ( "PSModulePath" , Path . Join ( AppDomain . CurrentDomain . BaseDirectory , "Modules" ) ) ;
92
-
93
- AuthenticateToAzure ( ) ;
94
158
}
95
159
96
160
/// <summary>
0 commit comments