I am a developer and trying to disassociate NSG from subnets using rest API but could not find any good answer please tell me community for Azure Rest API so that I can ask my question there.
If you want to disassociate NSG from subnets, please refer to the following steps
Create a service principal and assign contributor role to the sp
az login
# it will create a service principal and assign a contributor rolen to the sp
az ad sp create-for-rbac -n "MyApp" --sdk-auth
code
var msRestNodeAuth = require("#azure/ms-rest-nodeauth");
var { NetworkManagementClient } = require("#azure/arm-network");
const clientId = "sp clientId";
const secret = "sp clientSecret";
const domain = "hanxia.onmicrosoft.com";
const subscriptionId = "e5b0fcfa-e****e5fe29f4c68";
async function main() {
try {
const creds = await msRestNodeAuth.loginWithServicePrincipalSecret(
clientId,
secret,
domain,
);
const client = new NetworkManagementClient(creds, subscriptionId);
const resourceGroupName = "testvnet";
const virtualNetworkName = "test";
const subnetName = "default";
//get the subnet
const subnetrespose = await client.subnets.get(
resourceGroupName,
virtualNetworkName,
subnetName,
);
const subnet = subnetrespose._response.parsedBody;
console.log(subnet);
console.log("----------update-----------");
subnet.networkSecurityGroup = null;
const res = await client.subnets.createOrUpdate(
resourceGroupName,
virtualNetworkName,
subnetName,
subnet,
);
console.log(res._response.parsedBody);
} catch (error) {
console.log(error);
}
}
main();
Related
I was trying to use a user-assigned managed identity with the DefaultAzureCredential, but am getting the 403 permissions mismatch error. I'm following the code example found in MS docs and it still fails. However, replacing the DefaultAzureCredential with the explicit ManagedIdentityCredential works just fine.
This is my code:
const { BlobServiceClient } = require('#azure/storage-blob');
const { DefaultAzureCredential } = require('#azure/identity');
const {url, clientId} = require('./config');
const cred = new DefaultAzureCredential({managedIdentityClientId: clientId});
const containerClient = new BlobServiceClient(url, cred).getContainerClient('container-name');
(async () => {
const exists = await containerClient.exists();
console.log({exists});
})();
This looks like it should work, but it does not. Any thoughts?
versions:
"#azure/identity": "^1.1.0",
"#azure/storage-blob": "^12.12.0",
node v16.18.1
I tried in my environment and got below results:
I tried to reproduce same code in my environment, and it successfully executed with container exist or not.
Code:
const { BlobServiceClient } = require('#azure/storage-blob');
const { DefaultAzureCredential } = require('#azure/identity');
const url="https://venkat123.blob.core.windows.net";
const clientId="<client-id>";
const cred = new DefaultAzureCredential({managedIdentityClientId: clientId});
const Client = new BlobServiceClient(url, cred);
const containerClient=Client.getContainerClient("test");
(async () => {
const exists = await containerClient.exists();
console.log({exists});
})();
Console:
403, This request is not authorized to perform this operation using this permission.
If you are accessing storage account with identity, you need a role like Storage-blob-contributor or storage-blob-owner.
Go to portal -> your storage account -> Access Control (IAM) ->Add -> Add role assignments -> storage-blob-contributor or storage-blob-owner->Add your user managed identity id.
Also, I tried with user-assigned managed identity with the DefaultAzureCredential it worked perfectly.
Code:
const { BlobServiceClient } = require('#azure/storage-blob');
const { DefaultAzureCredential } = require('#azure/identity');
const url="https://venkat123.blob.core.windows.net";
const cred = new DefaultAzureCredential();
const Client = new BlobServiceClient(url, cred);
const containerClient=Client.getContainerClient("test");
(async () => {
const exists = await containerClient.exists();
console.log({exists});
})();
Console:
Trying to upload a file to azure blob storage using #azure/storage-blob sdk in nodejs:
module.exports.createBlob = (blobName, containerName, blobContent) => {
return new Promise(async (resolve, reject) => {
try {
const sharedKeyCredential = await this.createSharedAccessToken(blobName, 'c')
const blobServiceClient = new BlobServiceClient(
`https://${process.env.AZURE_BLOB_ACCOUNT}.blob.core.windows.net`,
sharedKeyCredential
)
const containerClient = blobServiceClient.getContainerClient(containerName)
const blockBlobClient = containerClient.getBlockBlobClient(blobName)
const blob = await blockBlobClient.upload(blobContent, blobContent.length) // implement later
resolve(blob)
} catch (err) {
console.log(err)
reject(err)
}
})
}
module.exports.createSharedAccessToken = (blobName, permission) => {
return new Promise(async (resolve, reject) => {
const sharedKeyCredential = new StorageSharedKeyCredential(process.env.AZURE_BLOB_ACCOUNT, process.env.AZURE_BLOB_KEY)
const containerName = process.env.AZURE_CONTAINER_NAME
const startsOn = new Date()
expiresOn.setMinutes(expiresOn.getMinutes() + parseInt(autoLogoutDuration.KeyValue))
const blobSAS = generateBlobSASQueryParameters({
containerName, // Required
blobName, // Required
permissions: BlobSASPermissions.parse(permission), // Required
startsOn: startsOn, // Required
},
sharedKeyCredential // StorageSharedKeyCredential - `new StorageSharedKeyCredential(account, accountKey)`
).toString()
resolve(decodeURI(blobSAS))
})
}
It keeps throwing a "NoAuthenticationInformation" error. The same creds work for downloading an existing blob but uploading is not working no matter what I try. Any help would be appreciated.
Followed by this MS DOC , I tried to reproduce your issue ,but able to upload files into my azure blob container using Node.js without any authentication error.
As you are using shared key credential we need to have all those permissions in our portal as shown below:
Also i am using #azure/storage-blob sdk in nodejs in my package.json .
Also added #azure/storage-blob sdk in my testupload.js file
And added the below code into my testupload.js file as i have already created container i just commented the above screenshot code .
const account="testa";
const sharedKeyCredential = new StorageSharedKeyCredential("yourstorageaccountname", "your storage key connection string");
const blobServiceClient1 = new BlobServiceClient(
// When using AnonymousCredential, following url should include a valid SAS or support public access
`https://${account}.blob.core.windows.net`,
sharedKeyCredential
);
const blobnewname="example2.txt"
blobContent="hi hello";
const containerClient1 = blobServiceClient.getContainerClient("test")
const blockBlobClient1= containerClient.getBlockBlobClient(blobnewname)
const blob = blockBlobClient1.upload(blobContent, blobContent.length)
Then i can able to test and upload my files to Azure blob container
Here are screenshot for reference:
For more information please refer this MS DOC : Azure Storage samples using v12 JavaScript client libraries
UPDATE:-
As suggested by #Setanjan Roy
Alternate way:-
To get rid of this we can use new BlobServiceClient( https://${process.env.AZURE_BLOB_ACCOUNT}.blob.core.windows.net${sharedKeyCredential} )
I am now trying to use Service Principal to access azure blob storage in nodes, instead of using connection string.
What I did (and succeeded) is using connection string as follows:
// connect via connection string
const AZURE_STORAGE_CONNECTION_STRING = process.env.AZURE_STORAGE_CONNECTION_STRING;
const blobServiceClient = BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING);
Now I want to use Service Principal instead of connection string, but I can't seem to make it work. I can see some examples using some token credentials, e.g.
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net`,
defaultAzureCredential
);
Is it possible to use service principal credentials this way, or are there other ways to do this?
Try this :
const { BlobServiceClient } = require("#azure/storage-blob");
const { ClientSecretCredential } = require("#azure/identity");
const account = '<your accounr name>'
//Using Service Principal
const appID = ""
const appSec = ""
const tenantID = ""
const clientCred = new ClientSecretCredential(tenantID,appID,appSec)
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net`,
clientCred
);
//try to list all containers in stroage account to check if success
blobServiceClient.listContainers().byPage().next().then(result =>{
result.value.containerItems.forEach(element => {
console.log(element.name);
});
})
Result:
Note:
Before you run this demo, pls make sure that you have granted the required permissions to your Service Principal, details see this official doc.
I can't use /regenerateKey [1] to regenerate keys for a Storage Account with the Azure Management API.
I'm using the following code in JavaScript (the resource has the subscription removed)
const { ClientSecretCredential } = require('#azure/identity');
const { SecretClient } = require('#azure/keyvault-secrets');
const MSRestAzure = require('ms-rest-azure');
const keyVaultName = process.env.KEY_VAULT_NAME;
const KVUri = `https://${keyVaultName}.vault.azure.net`;
const credential = new ClientSecretCredential(
process.env.AZURE_TENANT_ID,
process.env.AZURE_CLIENT_ID,
process.env.AZURE_CLIENT_SECRET,
);
const vault = new SecretClient(KVUri, credential);
function getCreds() {
return new Promise((res, rej) => {
MSRestAzure.loginWithServicePrincipalSecret(
process.env.AZURE_CLIENT_ID,
process.env.AZURE_CLIENT_SECRET,
process.env.AZURE_TENANT_ID,
(err, creds) => {
if (err) {
rej(err);
return;
}
res(creds);
},
);
});
}
const getResourceUrl = (resource, action) => `https://management.azure.com${resource}/${action}?api-version=2019-04-01`;
const resource = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Storage/storageAccounts/MyStore
const creds = await getCreds();
const client = new MSRestAzure.AzureServiceClient(creds);
const regenUrl = getResourceUrl(resource, 'regenerateKey');
await client.sendRequest({ method: 'POST', url: regenUrl }).then(console.log);
I'm getting an UnexpectedException response -
{
"error": {
"code": "UnexpectedException",
"message": "The server was unable to complete your request."
}
}
The Client ID/Secret belongs to an app registration that has access to the storage account, as well as Contributor and Storage Account Key Operator over that subscription.
I'm lead to think that I've not formed the request properly.
I am able to reproduce the error if I don't specify the request body.
Please provide the request body in the following format:
{
keyName: "key1 or key2 (basically which key you want to regenerate)"
}
I would like to create a dashboard with graphs about costs of my azure resources (as detailed as possible). Meaning, a list of monthly invoices is not enough (but I would already be very happy if I a could achieve that!!)
Anyway, the first thing I noticed is that if you find an example the endpoint urls look like this
https://management.azure.com/subscriptions/${subscriptionId}/resourcegroups?api-version=2016-09-01
Check the end of the url 2016-09-01, doesn't look very up2date. This medium post was the best article I could find, but it also uses these urls.
Furthermore, I was not able to follow the steps described, first it uses postman to retrieve an access_token (not very useful for me because I need it automated) and second, somewhere in the middle an access_token is retrieved but never used.
So, I found a npm packages like [azure-arm-billing][2] from which I was able to write the following program (mostly copy-paste):
const msRestAzure = require('ms-rest-azure');
const BillingManagement = require('azure-arm-billing')
const clientId = process.env['CLIENT_ID'];
const secret = process.env['APPLICATION_SECRET'];
const domain = process.env['DOMAIN'];
const subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
// Retrieve access_token
const app = new msRestAzure.ApplicationTokenCredentials(clientId, domain, secret);
app.getToken((err, token) => {
console.log(token.accessToken);
});
// =======
msRestAzure
.interactiveLogin( { domain }) // The argument here is nowhere documented
.then(credentials => {
console.log(credentials);
let client = new BillingManagement(credentials, subscriptionId);
return client.invoices.list();
})
.then(invoices => {
console.log('List of invoices:');
console.dir(invoices, { depth: null, colors: true });
});
Running this shows a nice access_token and invoices
...
List of invoices:
[
{
id: '/subscriptions/../providers/Microsoft.Billing/invoices/....',
name: '...',
type: 'Microsoft.Billing/invoices',
invoicePeriodStartDate: 2019-08-25T00:00:00.000Z,
invoicePeriodEndDate: 2019-09-24T00:00:00.000Z,
billingPeriodIds: [
'/subscriptions/.../pr..s/Micro..ing/bill..ods/201910-1'
]
},
{
id: '/subscriptions/9ea...3d/providers/Microsoft.Billing/invoices/201909-...',
name: '....',
type: 'Microsoft.Billing/invoices',
invoicePeriodStartDate: 2019-07-25T00:00:00.000Z,
invoicePeriodEndDate: 2019-08-24T00:00:00.000Z,
billingPeriodIds: [
'/subscriptions/..../providers/Microsoft.Billing/billingPeriods/201909-1...'
]
}
]
Although I have my invoices, there are no numbers. And I would like to retrieve costs for every resources.
So the documentation seems to be outdated up to not existing for what I want (as it seems). My question is if someone was able to retrieve information like this? I would really like to know how!!
UPDATE
It seems to be a permission issue. So, below I share some screenshots showing what I have right now. Maybe from these it is clear what I miss or have setup incorrectly. So first, here is my latest nodejs app:
const msRestAzure = require("ms-rest-azure");
const ConsumptionManagementClient = require("azure-arm-consumption");
const clientId = '76d79....'; // App registration ID
const secret = '****...'; // App registration secret
const domain = 'dc36...'; // tenantId
const subscriptionId = '9ea2d...'; // subscription ID
const AzureServiceClient = msRestAzure.AzureServiceClient;
//an example to list resource groups in a subscription
msRestAzure.loginWithServicePrincipalSecret(clientId, secret, domain).then((creds) => {
const client = new ConsumptionManagementClient(creds, subscriptionId);
const expand = '';
const filter = '';
const skiptoken = '';
const top = 1000;
const apply = '';
return client.usageDetails.list(expand, filter, skiptoken, top, apply).then(result => {
console.log('The result is:', result);
});
}).catch((err) => {
console.log('An error occurred:');
console.dir(err, { depth: null, colors: true });
});
Which outputs a statusCode 401
Error: Unauthorized. Request ID: e6b127...
...
So, I have in AD an App registration
Its API permissions are
Finally, I have just one subscription
With the following IAM settings
Any suspicious?
If you're looking for resource costs, I would suggest that you take a look at Consumption API - List Usage Details. That will give you the consumption for all the resources.
You will need to install azure-arm-consumption package.
Here's the sample code:
const msRestAzure = require("ms-rest-azure");
const ConsumptionManagementClient = require("azure-arm-consumption");
msRestAzure.interactiveLogin().then((creds) => {
const subscriptionId = "<your subscription id>";
const client = new ConsumptionManagementClient(creds, subscriptionId);
const expand = "";
const filter = "";
const skiptoken = "";
const top = 1000;
const apply = "";
return client.usageDetails.list(expand, filter, skiptoken, top, apply).then((result) => {
console.log("The result is:");
console.log(result);
});
}).catch((err) => {
console.log('An error occurred:');
console.dir(err, {depth: null, colors: true});
});
This is taken from here: https://github.com/Azure/azure-sdk-for-node/tree/master/lib/services/consumptionManagement.