I have an Azure subscription and an image I created.
I wrote some typescript code to a monitoring webpage that will allow users from the organization to spawn more instances of this image (first stage).
I’m using the default active directory, and have created a new user "admin" that has both "Application Administrator" and "Cloud Application Administrator" (does it really need both?).
I’m having an issue with the authentication.
The error I’m getting is:
Error creating VM: RestError: The client '<clientID>' with object id '<clientID>' does not have authorization to perform action 'Microsoft.Compute/virtualMachines/write' over scope '/subscriptions/<subscriptionID>/resourceGroups/Azure-test_group/providers/Microsoft.Compute/virtualMachines/myVM' or the scope is invalid. If access was recently granted, please refresh your credentials.
{
"name": "RestError",
"code": "AuthorizationFailed",
"statusCode": 403,
"request": {
"url": "https://management.azure.com/subscriptions/<SubscriptionID>/resourceGroups/Azure-test_group/providers/Microsoft.Compute/virtualMachines/myVM?api-version=2023-03-01",
"headers": {
"content-type": "application/json",
"accept": "application/json",
"accept-encoding": "gzip,deflate",
"user-agent": "azsdk-js-arm-compute/21.1.0 core-rest-pipeline/1.12.0 Node/v16.17.0 OS/(arm64-Darwin-21.6.0)",
"x-ms-client-request-id": "<id>",
"authorization": "REDACTED",
"content-length": "324"
},
"method": "PUT",
"timeout": 0,
"disableKeepAlive": false,
"streamResponseStatusCodes": {},
"withCredentials": false,
"requestId": "<Id>",
"allowInsecureConnection": false,
"enableBrowserStreams": false
},
"details": {
"error": {
"code": "AuthorizationFailed",
"message": "The client '<clientID>' with object id '<clientID>' does not have authorization to perform action 'Microsoft.Compute/virtualMachines/write' over scope '/subscriptions/<SubscriptionID>/resourceGroups/Azure-test_group/providers/Microsoft.Compute/virtualMachines/myVM' or the scope is invalid. If access was recently granted, please refresh your credentials."
}
},
"message": "The client '<clientID>' with object id '<clientID>' does not have authorization to perform action 'Microsoft.Compute/virtualMachines/write' over scope '/subscriptions/<SubscriptionID>/resourceGroups/Azure-test_group/providers/Microsoft.Compute/virtualMachines/myVM' or the scope is invalid. If access was recently granted, please refresh your credentials."
}
my code files look as follows:
1.
// pages/api/azure-test/index.tsx
import { useState } from 'react';
interface AzureVm {
InstanceId: string;
PublicIpAddress: string | null;
}
const TestPage = () => {
const [isLoading, setIsLoading] = useState(false);
const [vms, setVms] = useState<AzureVm[]>([]);
// Function to handle creating a new Azure VM
const handleCreateInstance = async () => {
setIsLoading(true);
try {
const response = await fetch('/api/azure-create-instance', { method: 'POST' });
if (response.ok) {
console.log('VM created successfully!');
// fetchVms(); // Refresh the vm list after creation
} else {
console.error('Failed to create vm.');
}
} catch (error) {
console.error('An error occurred:', error);
} finally {
setIsLoading(false);
}
};
return (
<div>
<h1>Test Page</h1>
<button onClick={handleCreateInstance} disabled={isLoading}>
{isLoading ? 'Creating VM...' : 'Create VM'}
</button>
<table>
<thead>
<tr>
<th>VM ID</th>
<th>Public IP Address</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{vms.map((vm) => (
<tr key={vm.InstanceId}>
<td>{vm.InstanceId}</td>
<td>{vm.PublicIpAddress || 'N/A'}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default TestPage;
// pages/api/azure-create-instances.ts
import { ComputeManagementClient, VirtualMachine } from '@azure/arm-compute';
import { DefaultAzureCredential } from '@azure/identity';
const subscriptionId = process.env.AZURE_SUBSCRIPTION_ID!;
// console.log('subscriptionId: ', subscriptionId);
const resourceGroupName = 'Azure-test_group'; // Replace with your resource group name
const vmName = 'myVM'; // Replace with your desired VM name
const location = 'westeurope'; // Replace with your desired location
const vmSize = 'Standard_DS1_v2'; // Replace with your desired VM size
const createVM = async () => {
try {
// Authenticate using DefaultAzureCredential
const creds = new DefaultAzureCredential();
// console.log(creds);
const computeClient = new ComputeManagementClient(creds, subscriptionId);
// Define VM parameters
const vmParams: VirtualMachine = {
location,
hardwareProfile: {
vmSize,
},
storageProfile: {
imageReference: {
publisher: 'Canonical',
offer: 'UbuntuServer',
sku: '18.04-LTS',
version: 'latest',
},
},
osProfile: {
computerName: vmName,
adminUsername: 'myAdmin', // Replace with your desired admin username
adminPassword: 'myPassword123!', // Replace with your desired admin password
},
networkProfile: {
// Network configuration
},
// Other VM configurations
};
// Create VM
const result = await computeClient.virtualMachines.beginCreateOrUpdate(resourceGroupName, vmName, vmParams);
console.log('VM created:', result);
} catch (err) {
console.error('Error creating VM:', err);
}
};
createVM();
my .env file has the following Ids: AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID
But I think the authentication still fails.
I am not sure if it is something I should change in the Azure portal, or in the code.
Important to note, so far I only gave the secret ID (AZURE_CLIENT_SECRET) but still did not use anywhere the secret "value".
any help / guidance would be appreciated.
2
Answers
[
Above is a screen shot of adding the role assignment, below is me checking that the roles exist.
I assigned the user "Application Administrator" and "Cloud Application Administrator" role and when I tried to create the VM, I got the same error:
The error usually occurs if the user doesn’t have sufficient permissions to perform the action.
Note that: To create VM the user must have
Virtual Machine Contributor
role assigned in the subscription level.The "Application Administrator**" and "Cloud Application Administrator" doesn’t include
Microsoft.Compute/virtualMachines/write
permission which is needed to create VM.The
Virtual Machine Contributor
role have the permission:To resolve the error, assign
Virtual Machine Contributor
role to the user like below:After assigning the role, you will be able to create the VMs.
Reference:
Azure built-in roles – Azure RBAC