Unable to create PNS credentials in notification hub using PowerShell - azure

I am using the following JSON input file to create a new notification hub in PowerShell:
"Name": "my-tester",
"Location": "West US",
"Tags": {
"tag1": "tag"
},
"Properties": {
"ApnsCredential": {
"Properties": {
"KeyId": "xxx",
"Token": "xxx",
"AppName": "xxx",
"AppId": "xxx",
"Endpoint":"https://api.push.apple.com:443/3/device"
}
},
"GcmCredential": {
"Properties": {
"GoogleApiKey": "yyyy"
}
}
}
}
The PowerShell command is:
$newHub = New-AzureRmNotificationHub -Namespace $nameSpace -ResourceGroup $resourceGroup -InputFile ".\$newHubName-HubProps.json"
The command does create the hub ...but the PNS credentials are empty (I also verified from the portal). So when I inspect the
newly created hub using this PowerShell, I get nothing. Here is the PowerShell command:
$newHubPnsCreds = Get-AzureRmNotificationHubPNSCredentials -Namespace $nameSpace -ResourceGroup $resourceGroup -NotificationHub $newHubName
# This returns nothing:
$newHubPnsCreds.GcmCredential
Any help is appreciated.
Regards

Related

Get properties for an object returned by Get-AzResource on Azure

I am trying get the properties of an Azure Disk Resource. When I run the command in my subscription
$R=Get-AzResource -Name <ResourceName>
It provides a list of properties given here I am specifically interested getting the Properties PSobject. However running the following command:
$R.Properties -eq $null
does returns true. When I look at this resource from Azure Portal (Same user principal as in Powershell command) in Json format I am given a selection of schemas to choose from and lots of properties are provided. Below is a sample:
"properties": {
"osType": "Linux",
"hyperVGeneration": "V2",
"supportsHibernation": true,
"supportedCapabilities": {
"acceleratedNetwork": true,
"architecture": "x64"
},
"creationData": {
"createOption": "FromImage",
"imageReference": {
"id": "xxx"
}
},
"diskSizeGB": 30,
"diskIOPSReadWrite": 500,
"diskMBpsReadWrite": 60,
"encryption": {
"type": "EncryptionAtRestWithPlatformKey"
},
"networkAccessPolicy": "AllowAll",
"publicNetworkAccess": "Enabled",
"timeCreated": "2023-01-09T13:38:24.500223+00:00",
"provisioningState": "Succeeded",
"diskState": "Attached",
"diskSizeBytes": 32213303296,
"uniqueId": "xxx"
What is the proper command to get this information using PowerShell?
You should set the ExpandProperties switch
https://learn.microsoft.com/en-us/powershell/module/az.resources/get-azresource?view=azps-9.3.0#-expandproperties
$resourceWithProperties = Get-AzResource -Name <ResourceName> -ExpandProperties
You can the access the properties with
$resourceWithProperties.Properties
You can get all properties using -ExapandProperties command and Alternative way of getting all properties is by using below commands:
Connect-AzAccount
$disk = Get-AzResource -ResourceId "/subscriptions/<subscriptionId>/resourceGroups/<Rg name>/providers/Microsoft.Compute/disks/<Diskname>"
$disk.Properties | Format-List *
Output:

Using the New-AzPrivateLinkServiceConnection Command-let to Create a Manual Private Link Service Connection

I am trying to create a private link to a Microsoft partner service in Azure using Powershell.
When I configure the endpoint through the Azure console, the segment of the template for the endpoint looks as follows:
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-11-01",
"name": "[parameters('privateEndpoints_foo_pl_silverfish_name')]",
"location": "eastus2",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworks_foo_pl_vnet_name'), 'foo_pl_subnet')]"
],
"tags": {
"owner": "foo"
},
"properties": {
"privateLinkServiceConnections": [],
"manualPrivateLinkServiceConnections": [
{
"name": "[parameters('privateEndpoints_foo_pl_silverfish_name')]",
"properties": {
"privateLinkServiceId": "xyz-prod.67395a8a-a9d4-4c85-bd01-109a99e7eca2.eastus2.azure.privatelinkservice",
"groupIds": [],
"privateLinkServiceConnectionState": {
"status": "Approved"
}
}
}
],
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworks_foo_pl_vnet_name'), 'foo_pl_subnet')]"
},
"customDnsConfigs": []
}
}
You can see the privateLinkServiceConnections array is empty. I've got content under the manualPrivateLinkServiceConnections array, which doesn't conform to the options in the New-AzPrivateLinkServiceConnection commandlet.
This is with me creating the private endpoint through the console:
Can I create a manual private link service connection with the New-AzPrivateLinkServiceConnection and New-AzPrivateEndpoint commandlets?
## Create the private link service configuration
$plink = New-AzPrivateLinkServiceConnection `
-Name 'foo_pl_silverfish_config' `
-PrivateLinkServiceId 'xyz-prod.67395a8a-a9d4-4c85-bd01-109a99e7eca2.eastus2.azure.privatelinkservice'
$privateEndpoint = New-AzPrivateEndpoint `
-ResourceGroupName 'foo_private_link' `
-Name 'foo_pl_db' `
-Location 'eastus2' `
-Subnet $sub `
-PrivateLinkServiceConnection $plink
I get the following error when running the above:
New-AzPrivateEndpoint: Operation returned an invalid status code 'BadRequest'
StatusCode: 400
ReasonPhrase: Bad Request
ErrorCode: LinkedInvalidPropertyId
ErrorMessage: Property id 'xyz-prod.67395a8a-a9d4-4c85-bd01-109a99e7eca2.eastus2.azure.privatelinkservice' at path 'properties.privateLinkServiceConnections[0].properties.privateLinkServiceId' is invalid. Expect fully qualified resource Id that start with '/subscriptions/{subscriptionId}' or '/providers/{resourceProviderNamespace}/'.
ErrorMessage: Property id
'xyz-prod.67395a8a-a9d4-4c85-bd01-109a99e7eca2.eastus2.azure.privatelinkservice'
at path
'properties.privateLinkServiceConnections[0].properties.privateLinkServiceId'
is invalid. Expect fully qualified resource Id that start with
'/subscriptions/{subscriptionId}' or
'/providers/{resourceProviderNamespace}/'.
You need to pass the resourceId for the property PrivateLinkServiceId to the New-AzPrivateLinkServiceConnection cmdlet.
Can I create a manual private link service connection with the
New-AzPrivateLinkServiceConnection and New-AzPrivateEndpoint
commandlets?
Yes, you can create manualPrivateLinkServiceConnections using -ByManualRequest in the New-AzPrivateLinkServiceConnection powershell cmdlet.
Here is the reference documentation for more information about the supported properties for the above cmdlet.
I have tested this in my local environment by creating a private endpoint to storage table in one of the storage accounts in my subscription.
Here is the cmdlet that I have used:
$virtualNetwork = Get-AzVirtualNetwork -ResourceName '<VirtualNetworkName>' -ResourceGroupName '<resourceGroupName>'
$subnet = $virtualNetwork | Select-Object -ExpandProperty subnets | Where-Object Name -eq '<SubnetName>'
$plsConnection= New-AzPrivateLinkServiceConnection -Name '<PLSConnectionsName>' -PrivateLinkServiceId '<ResourceID to which resource you want to create endpoint connection>' -RequestMessage 'Please Approve my request' -GroupId 'queue'
New-AzPrivateEndpoint -Name '<PrivateEndpointName>' -ResourceGroupName '<ResourceGroupName>' -Location 'eastus' -PrivateLinkServiceConnection $plsConnection -Subnet $subnet -ByManualRequest
Here is the sample output for your reference:
Updated Answer:
If you want to create the private endpoint using the private link service alias(foo..<azure_region>.azure.privatelinkservice) you can use the below powershell script.
$virtualNetwork = Get-AzVirtualNetwork -ResourceName '<VirtualNetworkName>' -ResourceGroupName '<resourceGroupName>'
$subnet = $virtualNetwork | Select-Object -ExpandProperty subnets | Where-Object Name -eq '<SubnetName>'
$privatelinkAlias= Get-AzPrivateLinkService -Name '<privateServiceLinkName>' -ResourceGroupName '<resourceGroupName>'
$plsConnection= New-AzPrivateLinkServiceConnection -Name '<PLSConnectionsName>' -PrivateLinkServiceId $privatelinkAlias.Alias -RequestMessage 'Please Approve my request'
New-AzPrivateEndpoint -Name '<PrivateEndpointName>' -ResourceGroupName '<ResourceGroupName>' -Location 'eastus' -PrivateLinkServiceConnection $plsConnection -Subnet $subnet -ByManualRequest
Here is the sample output screenshot:
The only way I was able to build the private endpoint was using an ARM template that I deployed via Powershell script.
The ARM template looks like the following:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The location for resources created as part of the deployment."
}
},
"virtualNetworkName": {
"type": "string",
"metadata": {
"description": "The name of the virtual network hosting the private endpoint for the Astra private link."
}
},
"privatelinkEndpointSubnetName": {
"type": "string",
"metadata": {
"description": "The name of the subnet hosting the private endpoint."
}
},
"privatelinkEndpointSubnetCIDR": {
"type": "string",
"metadata": {
"description": "The CIDR range associated with the subnet hosting the private endpoint."
}
},
"privateEndpointName": {
"type": "string",
"metadata": {
"description": "The name of the private endpoint associated with the database's private link."
}
},
"AstraDBServiceName": {
"type": "string",
"metadata": {
"description": "The 'Service Name' for the subject Astra DB database."
}
}
},
"variables": {
"PrivatelinkEndpointSubnetNameRef": "[concat(parameters('virtualNetworkName'), '/', parameters('privatelinkEndpointSubnetName'))]",
"PrivatelinkEndpointSubnetIdRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('privatelinkEndpointSubnetName'))]"
},
"resources": [{
"apiVersion": "2018-04-01",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[variables('PrivatelinkEndpointSubnetNameRef')]",
"location": "[parameters('location')]",
"properties": {
"addressPrefix": "[concat(parameters('privatelinkEndpointSubnetCIDR'))]",
"privateLinkServiceNetworkPolicies": "Disabled",
"privateEndpointNetworkPolicies": "Disabled"
}
},
{
"dependsOn": [
"[variables('PrivatelinkEndpointSubnetIdRef')]"
],
"apiVersion": "2019-02-01",
"type": "Microsoft.Network/privateEndpoints",
"name": "[parameters('privateEndpointName')]",
"location": "[parameters('location')]",
"properties": {
"manualPrivateLinkServiceConnections": [{
"name": "{plsConnection}",
"properties": {
"privateLinkServiceId": "[parameters('AstraDBServiceName')]",
"requestMessage": "Please approve my connection, thanks."
}
}],
"subnet": {
"id": "[variables('PrivatelinkEndpointSubnetIdRef')]"
}
}
}
]
}
Here is the code I would use to build the template...
$arm_template_parameters = #{
'AstraDBServiceName' = 'abc.593caf89-071c-4be7-f5ce9d3f9bc6
.eastus.azure.privatelinkservice'
'privateEndpointName' = 'myEndpoint'
'virtualNetworkName' = 'myVNET'
'privatelinkEndpointSubnetName' = 'mySubnet'
'privatelinkEndpointSubnetCIDR' = '10.0.2.0/24'
}
New-AzResourceGroupDeployment `
-Name 'myDeployment' `
-ResourceGroupName 'myResourceGroup' `
-TemplateFile '.\template.json' `
-TemplateParameterObject $arm_template_parameters `
-verbose
The problem for me is I ONLY have a resource id or alias. I can build from an ARM template or the Azure console. All the examples building the PE using Powershell require me to know the details about the service's load balancer, which I don't.

Getting httpResponseMessage when trying to add Certificate to function app

I am deploying a function app via ARM template. I have added the following snippet to add the certificate from the Azure Key vault and the added a host name binding.
{
"type": "Microsoft.Web/certificates",
"apiVersion": "2019-08-01",
"name": "[parameters('certificateName')]",
"location": "North Europe",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
],
"properties": {
"keyVaultId": "[resourceId(parameters('keyvaultRG'), 'Microsoft.KeyVault/vaults', parameters('keyvaultName'))]",
"keyVaultSecretName": "[parameters('existingKeyVaultSecretName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverFarms', parameters('hostingPlanName'))]"
}
},
{
"type": "Microsoft.Web/sites/hostnameBindings",
"name": "[concat(parameters('functionAppName'), '/', parameters('customDomainName'))]",
"apiVersion": "2019-08-01",
"location": "North Europe",
"dependsOn": [
"[resourceId('Microsoft.Web/certificates', parameters('certificateName'))]"
],
"properties": {
"sslState": "SniEnabled",
"thumbprint": "[reference(resourceId('Microsoft.Web/certificates', parameters('certificateName'))).Thumbprint]"
}
}
But when I don deploy the ARM template I get the following error at Microsoft.Web/certificates
"message": "The parameter httpResponseMessage has an invalid value."
Please check if the below steps help to fix the issue:
error at Microsoft.Web/certificates "message": "The parameter {0} has an invalid value."
Follow the below steps to fix this issue:
Enable the Microsoft.Web resource provider to direct access the Azure Key Vault using the Azure PowerShell.
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId AZURE_SUBSCRIPTION_ID
Set-AzureRmKeyVaultAccessPolicy -VaultName KEY_VAULT_NAME -ServicePrincipalName <ServicePrincipalId> -PermissionsToSecrets get
Check the Access Policies of Azure Key Vault: Azure Key Vault > Access Policies > Add New (Microsft.Web) Your-Function-App
Azure PowerShell Commands for inserting the certificate to the KeyVault:
$pfxFilePath = "PFX_CERTIFICATE_FILE_PATH" # Change this path
$pwd = "PFX_CERTIFICATE_PASSWORD" # Change this password
$flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$collection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$collection.Import($pfxFilePath, $pwd, $flag)
$pkcs12ContentType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12
$clearBytes = $collection.Export($pkcs12ContentType)
$fileContentEncoded = [System.Convert]::ToBase64String($clearBytes)
$secret = ConvertTo-SecureString -String $fileContentEncoded -AsPlainText –Force
$secretContentType = 'application/x-pkcs12'
Set-AzureKeyVaultSecret -VaultName KEY_VAULT_NAME -Name KEY_VAULT_SECRET_NAME -SecretValue $Secret -ContentType $secretContentType # Change Name of Azure KV & Secret
Next step is using the KeyVaultSecretName for directly accessing the KeyVault in order to get the value.
WebSite.parameters:
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentParameters.json",
"contentVersion": "1.0.0.0",
"parameters": {
"functionAppName": {
"value": "yourfunctionappname"
},
"customHostname": {
"value": "yourcustomdomianname"
},
"existingKeyVaultId": {
"value": "/subscriptions/subscriptionsID/resourceGroups/resourceGroupsName/providers/Microsoft.KeyVault/vaults/vaultsName"
},
"existingKeyVaultSecretName": {
"value": "The key vaults SecretName"
}
}
}

Can't create SendGrid resource with Azure CLI template - "Invalid subscription identifier provided"

I'm not able to create a SendGrid resource in Azure using a JSON template - I get a ResourcePurchaseValidationFailed error. I am able to create other Azure resources e.g. storage.
To reproduce:
az login
az group create --name MyResourceGroup --location "uksouth"
az group deployment create `
--name MyDeployment `
--resource-group MyResourceGroup `
--template-file template.json `
template.json:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2015-01-01",
"name": "mysendgrid",
"type": "Sendgrid.Email/accounts",
"location": "uksouth",
"plan": {
"name": "free",
"publisher": "Sendgrid",
"product": "sendgrid_azure",
"promotionCode": ""
},
"properties": {
"password": "mypassword",
"acceptMarketingEmails": false,
"email": "me#myemail.com",
"firstName": "John",
"lastName": "Smith",
"company":"My Company",
"website": "",
}
}
]
}
Error:
"error": {
"code": "ResourcePurchaseValidationFailed",
"message": "User failed validation to purchase resources. Error message: '{\"error\":{\"code\":\"InvalidSubscriptionId\",\"message\":\"Invalid subscription identifier provided.\"}}'"
}
I don't know how to provide any other subscription ID.
Maybe, your account has more than one subscription and by default, you logging into a subscription that doesn't have access to the SendGrid?
You can display all your subscriptions using the command:
az account list
And then set the correct one:
az account set --subscription <name or id>
It seems that it was some problem at sendgrid end. Since this is not a docs-related issue, please contact our Support team directly and they can help you out. You can access support contact options by logging into https://support.sendgrid.com.
You could try to point out subscription ID by add subscription parameters.
az group deployment create `
--name MyDeployment `
--resource-group MyResourceGroup `
--template-file template.json `
--subscription subId

How to get nested properties using Azure CLI

I had been using the line below to grab the value of the internalIpAddress property from an ILB App Service Environment in Azure:
az resource show `
--ids "/subscriptions/$subscription_id/resourceGroups/$ilbase_rg_name/providers/Microsoft.Web/hostingEnvironments/$ilbase_name/capacities/virtualip" `
--query "internalIpAddress"
The format of the virtualip resource was:
{
"internalIpAddress": "10.30.0.139",
"outboundIpAddresses": [
"13.72.76.135"
],
"serviceIpAddress": "13.72.76.135",
"vipMappings": []
}
Seems like in the past day or so, the format of the virtualip resource has now changed to this:
{
"additionalProperties": {
"internalIpAddress": "10.30.0.139",
"outboundIpAddresses": [
"13.72.76.135"
],
"serviceIpAddress": "13.72.76.135",
"vipMappings": []
},
"id": null,
"identity": null,
"kind": null,
"location": null,
"managedBy": null,
"name": null,
"plan": null,
"properties": null,
"sku": null,
"tags": null,
"type": null
}
And now my command no longer works...it returns nothing. I can modify my command to get the entire additionalProperties object but I then don't know how to parse thru it to get just the value of the internalIpAddress property.
Another interesting note on this is, if you go to the Azure Resource Explorer and navigate to the virtualip resource, it still shows it in the same old format. If you try the PowerShell code the Azure Resource Explorer gives you to query the resource, it returns nothing.
Here is the PowerShell the Azure Resource Explorer said to use:
Get-AzureRmResource -ResourceGroupName MyRG -ResourceType Microsoft.Web/hostingEnvironments/capacities -ResourceName "myilbase/virtualip" -ApiVersion 2018-02-01
Looking for some help on how to parse the nested internalIpAddress property from the additionalProperties object
just traverse the object like you normally would:
--query "additionalProperties.internalIpAddress"

Resources