Reputation: 169
I'm hoping to manage some Azure resources using a scheduled C# Azure Function.
Currently in a command line application I've made, I've been using libraries 'Microsoft.IdentityModel.Clients.ActiveDirectory' for token authorization and 'Microsoft.Azure.Management.Compute' for client calls for resource management like so.
//... var credential generated my AD authentication and extending Microsoft.Rest.ServiceClientCredentials
using (var client = new ComputeManagementClient(credential)) {
client.SubscriptionId = "[SOME_SUBSCRIPTION_ID]";
client.VirtualMachines.BeginPowerOff("[RESOURCE_GROUP]", "[VM_NAME]");
}
Can my management client interact with Azure resources without providing a User Credential or Key-Secret like credential establishment?
My previous experience is related to AWS and admittedly it has confused my view of Azure Resource Management.
Older posts I've looked at are: Start and Stop Azure Virtual Machine
and
Is it possible to stop/start an Azure ARM Virtual from an Azure Function?
-EDIT 1-
I was hoping for something similar to run-time credentials in AWS resource clients for Lambda based on an assigned role with a variety of permissions. I will have a look at certificates though.
Upvotes: 2
Views: 6899
Reputation: 2474
There are a few resources online on using C# to make REST API calls to start and stop a VM. Here's a link to such a document:
https://msftstack.wordpress.com/2016/01/03/how-to-call-the-azure-resource-manager-rest-api-from-c/
You could use the above as a reference to create C# Functions to start/stop your VM.
However, using C# to make these REST calls requires pre-packaging the HTTP request and post processing the HTTP response. If your use-case just calls for a start/stop VM, an easier approach would be use PowerShell in Azure Functions to call the Start-AzureRmVM
and Stop-AzureRmVM
cmdlets.
The following are steps on how to create HTTP-triggered PowerShell Functions to start and stop a VM:
Setup a service principal to obtain the username, password and tenant id. This initial setup may be considered tedious by some users, but since it's a one-time task, I feel that it is worth it to leverage running Azure PowerShell in Functions. There are many docs online, but here are some links to documents on how to setup your service principal:
i. http://blog.davidebbo.com/2014/12/azure-service-principal.html (I used this one)
Log into the Functions portal to access your Function app.
Click on Function app settings->Configure app settings and add the key-value pairs for the settings SP_USERNAME
, SP_PASSWORD
, and TENANTID
(You may use other desired key names).
Create an HTTP-triggered PowerShell Function named, e.g. StartVm with the following content in its run.ps1
file.
$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Start VM Start-AzureRmVM -ResourceGroupName $requestBody.resourcegroup -Name $requestBody.vmname | Out-String
Click on the Save button.
Next, click on the Logs button to open the log viewer.
Click on the Test button to open the simple HTTP client. In the request body, provide the vmname and resourcegroup values for the VM, e.g.
{ "vmname": "testvm", "resourcegroup": "testresourcegroup" }
Start-AzureRmVM
cmdlet to run to completion. When it does, you should see similar entries in the log viewer.2016-11-30T07:11:26.479 Function started (Id=1e38ae2c-3cca-4e2f-a85d-f62c0d565c34) 2016-11-30T07:11:28.276 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:11:28.276 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:11:59.312 RequestId IsSuccessStatusCode StatusCode ReasonPhrase --------- ------------------- ---------- ------------ True OK OK 2016-11-30T07:11:59.327 Function completed (Success, Id=1e38ae2c-3cca-4e2f-a85d-f62c0d565c34)
run.ps1
file. If the execution succeeds, the log output should be similar to the log entries for the StartVm Function.$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Stop VM Stop-AzureRmVM -ResourceGroupName $requestBody.resourcegroup -Name $requestBody.vmname -Force | Out-String
run.ps1
file to verify that the VM has indeed been stopped.$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Get VM Get-AzureRmVM -ResourceGroupName $requestBody.resourcegroup -Name $requestBody.vmname -Status | Out-String
The log entries for the GetVM Function on a stopped VM will would be similar to the following:
2016-11-30T07:53:59.956 Function started (Id=1841757f-bbb8-45cb-8777-80edb4e75ced) 2016-11-30T07:54:02.040 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:54:02.040 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:54:02.977 ResourceGroupName : testresourcegroup Name : testvm BootDiagnostics : ConsoleScreenshotBlobUri : https://teststorage.blob.core.windows.net/boot diagnostics-vmtest-[someguid]/testvm.[someguid].screenshot.bmp Disks[0] : Name : windowsvmosdisk Statuses[0] : Code : ProvisioningState/succeeded Level : Info DisplayStatus : Provisioning succeeded Time : 11/30/2016 7:15:15 AM Extensions[0] : Name : BGInfo VMAgent : VmAgentVersion : Unknown Statuses[0] : Code : ProvisioningState/Unavailable Level : Warning DisplayStatus : Not Ready Message : VM Agent is unresponsive. Time : 11/30/2016 7:54:02 AM Statuses[0] : Code : ProvisioningState/succeeded Level : Info DisplayStatus : Provisioning succeeded Time : 11/30/2016 7:15:15 AM Statuses[1] : Code : PowerState/deallocated Level : Info DisplayStatus : VM deallocated 2016-11-30T07:54:02.977 Function completed (Success, Id=1841757f-bbb8-45cb-8777-80edb4e75ced)
Note: FYI, while you may write a Function to create a VM by calling the New-AzureRmVM
cmdlet, it will not run to completion in Azure Functions. VM creation in Azure Function's infrastructure seem to take ~9 mins to complete but a Function's execution is terminated at 5 minutes. You may write another script to poll the results separately. This limitation will be lifted when we start supporting custom configuration for maximum execution time in one of our upcoming releases.
--Update-- I just realized you were trying to create scheduled Functions. In that case, you can use Timer-triggered PowerShell Functions and hard-code the vmname and resourcegroup.
Upvotes: 9
Reputation: 72171
Well, I don't really understand how do you expect to authenticate without authenticating, I guess your only option would be certificates?
https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-daemon-certificate-credential/
Upvotes: 0