I am new person to Azure development. Is it possible to add custom domain names to web apps using .Net REST API?
yes, you can do that.
1) Install the NuGet Web Sites Management Package into your project.
2) Get Azure Publish Settings file (for example, by using Powershell Get-AzurePublishSettingsFile). You will need that later (the value of the management certificate field inside of that file).
2) Instantiate WebSiteManagementClient. That should help with the understanding of the code.
3) Next, the code is below. I just tested and it works. First, it lists the webspaces, then the websites inside of each of webspace, and you should copy and paste the website webspace into the
public const string base64EncodedCertificate = "ManagementCertificateValueFromPublishSettingsFile";
public const string subscriptionId = "AzureSubscriptionId";
static SubscriptionCloudCredentials getCredentials()
{
return new CertificateCloudCredentials(subscriptionId, new X509Certificate2(Convert.FromBase64String(base64EncodedCertificate)));
}
static void Main(string[] args)
{
WebSiteManagementClient client = new WebSiteManagementClient(getCredentials());
WebSpacesListResponse n = client.WebSpaces.List();
n.Select(p =>
{
Console.WriteLine("webspace {0}", p.Name);
WebSpacesListWebSitesResponse websitesInWebspace = client.WebSpaces.ListWebSites(p.Name,
new WebSiteListParameters()
{
});
websitesInWebspace.Select(o =>
{
Console.Write(o.Name);
return o;
}).ToArray();
return p;
}).ToArray();
Console.ReadLine();
var configuration = client.WebSites.Get("WebSpaceName", "WebSiteName", new WebSiteGetParameters());
configuration.WebSite.HostNames.Add("new domain");
var resp = client.WebSites.Update("WebSpaceName", "WebSiteName", new WebSiteUpdateParameters() { HostNames = configuration.WebSite.HostNames });
Console.WriteLine(resp.StatusCode);
Console.ReadLine();
}
https://learn.microsoft.com/en-us/azure/app-service/scripts/app-service-powershell-configure-custom-domain
Most easily done with PowerShell.
$fqdn="<Replace with your custom domain name>"
$webappname="mywebapp$(Get-Random)"
$location="West Europe"
# Create a resource group.
New-AzureRmResourceGroup -Name $webappname -Location $location
# Create an App Service plan in Free tier.
New-AzureRmAppServicePlan -Name $webappname -Location $location `
-ResourceGroupName $webappname -Tier Free
# Create a web app.
New-AzureRmWebApp -Name $webappname -Location $location -AppServicePlan $webappname `
-ResourceGroupName $webappname
Write-Host "Configure a CNAME record that maps $fqdn to $webappname.azurewebsites.net"
Read-Host "Press [Enter] key when ready ..."
# Before continuing, go to your DNS configuration UI for your custom domain and follow the
# instructions at https://aka.ms/appservicecustomdns to configure a CNAME record for the
# hostname "www" and point it your web app's default domain name.
# Upgrade App Service plan to Shared tier (minimum required by custom domains)
Set-AzureRmAppServicePlan -Name $webappname -ResourceGroupName $webappname `
-Tier Shared
# Add a custom domain name to the web app.
Set-AzureRmWebApp -Name $webappname -ResourceGroupName $webappname `
-HostNames #($fqdn,"$webappname.azurewebsites.net")
Related
I have a .net Azure function project which includes multiple functions such as EventGridTrigger function, BlobTrigger function etc. Few trigger functions in the project needs to be enabled only for specific regions. Is it possible to enable/disable trigger functions based on regions through app settings ?
[FunctionName("CosmosDBFunction")] //enable only in US-west
public static void Run([CosmosDBTrigger()])
{}
[FunctionName("EventGridFunction")] //enable only in US-east
public static void Run([EventGridTrigger]EventGridEvent eventGridEvent)
{}
Edit:
I'm trying to disable in "isolated" Azure functions via appsettings.json within the project. The "[Disable]" and AzureWebJobs.$FunctionName.Disabled properties are not working from appsettings.json, though it is working if mentioned in azure portal.
You can use the Disable attribute, which dynamically disables specific Functions based on app settings.
For example:
[Disable("FUNCTION_DISABLED")]
[FunctionName(nameof(EventGridFunction))]
public static void Run(...
Each regional deployment will then set the FUNCTION_DISABLED setting to true if the Function should be disabled.
One way to disable/Enable Azure functions based on regions by using PowerShell command. I could able to achieve this by using Update-AzFunctionAppSetting command wherein all the functions of the mentioned location will be Disabled - MSFT Docs.
Subscription Level
$GetFunction=Get-AzFunctionApp -SubscriptionId <SUBSCRIPTION_ID>
$ResourceGroup=($GetFunction).ResourceGroupName
$Name = ($GetFunction).Name
For($I=0;$I -lt $ResourceGroup.count;$I++) {
$FunctionDetails=Get-AzResource -ApiVersion "2022-03-01" -Name $Name[$I] -ResourceGroupName $ResourceGroup[$I] -ResourceType "Microsoft.Web/sites/functions"
if($GetFunction[$I].Location -eq "<YOUR_REQUIRED_LOCATION>"){
For($J=0;$J -lt $FunctionDetails.count;$J++){
$Function=$FunctionDetails[$J].ResourceName
$FunctionName=$Function.Substring(($Function.IndexOf("/")+1),($Function.length-($Function.IndexOf("/")+1)))
Update-AzFunctionAppSetting -Name $Name[$I] -ResourceGroupName $ResourceGroup[$I] -AppSetting #{"AzureWebJobs.$FunctionName.Disabled" = "true"}
}
}
}
FunctionApp Level
$FunctionDetails=Get-AzResource -ApiVersion "2022-03-01" -Name <FUNCTIONAPP_NAME> -ResourceGroupName <RESOURCE_GROUP> -ResourceType "Microsoft.Web/sites/functions"
$Function=$FunctionDetails.ResourceName | Where-Object {$FunctionDetails.Location -eq "<YOUR_REQUIRED_LOCATION>"}
For($I=0;$I -lt $Function.count;$I++) {
$FunctionExtract=$Function[$I]
$FunctionName=$FunctionExtract.Substring(($FunctionExtract.IndexOf("/")+1),($FunctionExtract.length-($FunctionExtract.IndexOf("/")+1)))
Update-AzFunctionAppSetting -Name <FUNCTIONAPP_NAME> -ResourceGroupName <RESOURCE_GROUP> -AppSetting #{"AzureWebJobs.$FunctionName[$I].Disabled" = "true"}
}
SAMPLE RESULTS:
Note: Replace -AppSetting #{"AzureWebJobs.$FunctionName.Disabled" = "false"} to true to enable it again.
I am working on writing some Powershell that I am going to use in Azure DevOPS pipelines. This is to create an AppServiceplan. I have included the code below. I have used this same basic template to deploy a few other things and I have not run into this problem before.
This piece of the code $appSP = Get-AzAppServicePlan -Name $appServicePlanName -ResourceGroupName $rgname does not return a value, which is expected because this is the first time running it, yet its triggering this piece of code Write-verbose "AppService Plan '$appServicePlanName' already exists."
So it seems that even though the Get-AzAppServicePlan appears to be blank, maybe its returning some sort of object that I cant see?
Any ideas?
function Assert-AppServicePlan {
<#
.SYNOPSIS
This function will ensure that specified AppServicePlan exists.
.DESCRIPTION
Function will check if specified Azure AppServicePlan exists, and if not - it will be created.
Will return AppServicePLan object or, in case of error, $null.
.PARAMETER appServicePlanName
App Service Plan to be checked or created.
.PARAMETER rgName
Resource Group.
.PARAMETER SKU
SKU for App Service Plan. Default is P2V2.
.EXAMPLE
Assert-AppServicePlan -appServicePlansName "BARF" -rgName "MyResourceGroup" -SKU "F1" -verbose
#>
param(
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$appServicePlanName,
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$rgName,
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$SKU
);
$appSP = Get-AzAppServicePlan -Name $appServicePlanName -ResourceGroupName $rgname
if ($notPresent)
{
Write-Verbose "App Service Plan '$appServicePlanName' doesn't exist. Creating it."
try
{
$appSP = New-AzResourceGroupDeployment -ResourceGroupName `
$rgname -TemplateFile .\templates\appserviceplan.json `
-TemplateParameterFile .\templates\appserviceplan.parameters.json `
-ErrorAction Stop
}
catch
{
Write-verbose "Error while creating App Service Plan."
Write-Error $_
}
}
else
{
Write-verbose "AppService Plan '$appServicePlanName' already exists."
}
return $appSP
}
The Get-AzAppServicePlan cmdlet returns the App Service Plan object if found in the specified resource group, else nothing. So, it would be sufficient to check on this result in your if condition.
Another case where the result might mislead returning null is when you query under an incorrect PS context or a different Subscription (locally). However, since you intend to run this as part of Azure DevOps pipelines, the Service connection used by the task would ensure it.
Just another suggestion, you can use ErrorVariable
Get-AzAppServicePlan -Name $appServicePlanName -ResourceGroupName $rgname -ErrorAction Silentlycontinue -ErrorVariable notPresent
if ($notPresent)
{
#create something
}
else {
#exits
}
I am using powershell to handle various CI/CD functions.
=============================================
Here is what I have done so far.
Build NodeJS App
Package NodeJS App in Container
Publish Container to Private Azure Container Registry
=============================================
Here is what I am trying to figure out.
Create App Service Plan on the Fly
Create Web App (Container) on the Fly
Pull in Container from ACR into App Service
Here is my code. It doesn't seem to be working.
$azureContainerCredential = Get-AzContainerRegistryCredential -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP -Name $env:AZURE_CONTAINER_REGISTRY_NAME
$azureSecuredPassword = ConvertTo-SecureString $azureContainerCredential.Password -AsPlainText -Force
$azureContainerRegistry = Get-AzContainerRegistry -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP
$azureAppServicePlan = Get-AzAppServicePlan -ResourceGroupName "amlihelloworld" -Name "amlihelloworld-app-service-plan"
if($null -eq $azureAppServicePlan)
{
"==============================================================================="
Write-Output "CREATING HELLO WORLD WEB APPLICATION"
$azureAppServicePlan = New-AzAppServicePlan -Name "amlihelloworld-app-service-plan" -Location "Central
US" -ResourceGroupName "amlihelloworld" -Tier Standard
$azureApp = New-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld2" -AppServicePlan
$azureAppServicePlan.Name -ContainerImageName "amlihelloworld:20200422.7" -ContainerRegistryPassword
$azureSecuredPassword -ContainerRegistryUrl $azureContainerRegistry.LoginServer -
ContainerRegistryUser $azureContainerCredential.Username
$azureAppSlot = New-AzWebAppSlot -Name $azureApp.Name -ResourceGroupName "amlihelloworld" -Slot
"development"
}
$azureApp1 = Get-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld"
=============================================
Here is whats happening
When I switch the slots to my app for production.
It doesn't seem to be showing my app at all.
How can I tell if it uploaded my app or not?
Actually, I don't think there is a logic problem in the code, but a problem for the commands itself.
First, if you want to cut the PowerShell command into multiple lines, you need to add the character ` append each line except the last one. And you'd better use the same web app name if you want to get it. So you'd like to make a little change in your code:
$azureContainerCredential = Get-AzContainerRegistryCredential -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP -Name $env:AZURE_CONTAINER_REGISTRY_NAME
$azureSecuredPassword = ConvertTo-SecureString $azureContainerCredential.Password -AsPlainText -Force
$azureContainerRegistry = Get-AzContainerRegistry -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP
$azureAppServicePlan = Get-AzAppServicePlan -ResourceGroupName "amlihelloworld" -Name "amlihelloworld-app-service-plan"
if($null -eq $azureAppServicePlan)
{
"==============================================================================="
Write-Output "CREATING HELLO WORLD WEB APPLICATION"
$azureAppServicePlan = New-AzAppServicePlan -Name "amlihelloworld-app-service-plan" -Location "Central
US" -ResourceGroupName "amlihelloworld" -Tier Standard
$azureApp = New-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld2" `
-AppServicePlan $azureAppServicePlan.Name `
-ContainerImageName "amlihelloworld:20200422.7" `
-ContainerRegistryPassword $azureSecuredPassword `
-ContainerRegistryUrl $azureContainerRegistry.LoginServer `
-ContainerRegistryUser $azureContainerCredential.Username
$azureAppSlot = New-AzWebAppSlot -Name $azureApp.Name -ResourceGroupName "amlihelloworld" -Slot
"development"
}
$azureApp1 = Get-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld2"
You also need to check carefully if your environment variables exist as normal.
Apparently it's a bug on Microsoft side and it's not possible to publish containers through powershell scripts.
Please read here:
https://github.com/Azure/azure-powershell/issues/10645
I'm trying to do an IP changeover and I'm looking to get the Virtual IP of all our app service instances.
So far I've put together the following powershell script:
$apps = Get-AzureRmWebApp
Foreach($app in $apps)
{
Write-Output "$($app.Name)|$($app.OutboundIpAddresses)"
($app | Get-AzureDeployment -Slot Production).VirtualIPs[0].Address
break;
}
But I'm stuck at the Get-AzureDeployment step - I think there should be a RM version of this, but I can't find it.
Related GitHub issue - this indicates it does exist: https://github.com/Azure/azure-powershell/issues/1648
I'm trying to get to the Virtual Ip Address as per the below screenshot:
If you want to get the VIRTUAL IP ADDRESS, you could use the command below.
$slot = Get-AzureRmWebAppSlot -ResourceGroupName "<ResourceGroupName>" -Name "<yourwebappname>" -Slot "<yourslotname>"
($slot.OutboundIpAddresses -split ",")[0]
Your complete command should be:
$apps = Get-AzureRmWebApp
Foreach($app in $apps)
{
Write-Output "$($app.Name)|$($app.OutboundIpAddresses)"
$slot = Get-AzureRmWebAppSlot -ResourceGroupName $app.ResourceGroup -Name $app.Name -Slot "<yourslotname>"
($slot.OutboundIpAddresses -split ",")[0]
break;
}
I have an issue setting up an ES cluster on Azure. I'd like my cluster to be behind an application gateway and also use shield authentication.
The problem is that the azure application gateway needs to send a health ping to the cluster and get back a 200 response, otherwise it returns a 502 "bad gateway". If I create an anonymous use then I can get the cluster to return a 200 but I'd rather not enable an anonymous user and use basic authentication instead.
Is there some endpoint on the cluster that will return a 200 even if the user is not authenticated and anonymous users are turned off?
Thanks!
There is no such endpoint in Elasticsearch. There is status.allowAnonymous in Kibana for the stats api endpoint, but nothing similar in Elasticsearch.
You'd have to define your own user that has access to a specific healthcheck url and use that or anonymous access enabled.
The healthchecks story can have variations: you check the health of a specific node (/_cluster/health?local=true), or the health of the cluster. You can also get a 200 if you send a _search request (with preference=_local) to a specific node even if that cluster doesn't have an elected master node, for example, because by default a _search operation is permitted on a node even in such situation.
In addition to #Andrei's answer, I'd recommend taking a look at Elastic's Azure ARM template which can deploy a cluster with Application Gateway configured for load balancing and SSL offload to the cluster.
This also works with X-Pack Security by setting up anonymous access for the Application Gateway ping health check that is assigned a role with access only to
cluster:
- cluster:monitor/main
It would be great if the ping check supported supplying credentials in the future, in which case anonymous access would not be required, locking things down further.
To deploy a cluster with Application Gateway using Azure PowerShell
function PromptCustom($title, $optionValues, $optionDescriptions)
{
Write-Host $title
Write-Host
$a = #()
for($i = 0; $i -lt $optionValues.Length; $i++){
Write-Host "$($i+1))" $optionDescriptions[$i]
}
Write-Host
while($true)
{
Write-Host "Choose an option: "
$option = Read-Host
$option = $option -as [int]
if($option -ge 1 -and $option -le $optionValues.Length)
{
return $optionValues[$option-1]
}
}
}
function Prompt-Subscription() {
# Choose subscription. If there's only one we will choose automatically
$subs = Get-AzureRmSubscription
$subscriptionId = ""
if($subs.Length -eq 0) {
Write-Error "No subscriptions bound to this account."
return
}
if($subs.Length -eq 1) {
$subscriptionId = $subs[0].SubscriptionId
}
else {
$subscriptionChoices = #()
$subscriptionValues = #()
foreach($subscription in $subs) {
$subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))";
$subscriptionValues += ($subscription.SubscriptionId);
}
$subscriptionId = PromptCustom "Choose a subscription" $subscriptionValues $subscriptionChoices
}
return $subscriptionId
}
$subscriptionId = "{YOUR SUBSCRIPTION ID}"
try {
Select-AzureRmSubscription -SubscriptionId $subscriptionId -ErrorAction Stop
}
catch {
Write-Host "Please Login"
Login-AzureRmAccount
$subscriptionId = Prompt-Subscription
Select-AzureRmSubscription -SubscriptionId $subscriptionId
}
# Specify the template version to use. This can be a branch name, commit hash, tag, etc.
# NOTE: different template versions may require different parameters to be passed, so be sure to check
# the parameters/password.parameters.json file in the respective tag branch
$templateVersion = "master"
$templateSrc = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src"
$elasticTemplate = "$templateSrc/mainTemplate.json"
$location = "Australia Southeast"
$resourceGroup = "app-gateway-cluster"
$name = $resourceGroup
$cert = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes("{PATH TO cert.pfx}"))
$clusterParameters = #{
"artifactsBaseUrl"= $templateSrc
"esVersion" = "5.1.2"
"esClusterName" = $name
# Deploy to same location as Resource Group location
"location" = "ResourceGroup"
# Install X-Pack plugins.
# Will install trial license
"xpackPlugins" = "Yes"
# Use Application Gateway
"loadBalancerType" = "gateway"
"vmDataDiskCount" = 2
"dataNodesAreMasterEligible" = "Yes"
"adminUsername" = "russ"
"authenticationType" = "password"
"adminPassword" = "{Super Secret Password}"
"securityAdminPassword" = "{Super Secret Admin User Password}"
"securityReadPassword" = "{Super Secret Read User Password}"
"securityKibanaPassword" = "{Super Secret Kibana User Password}"
"appGatewayCertBlob" = $cert
"appGatewayCertPassword" = "{Password for cert.pfx (if it has one)}"
}
Write-Host "[$(Get-Date -format 'u')] Deploying cluster"
New-AzureRmResourceGroup -Name $resourceGroup -Location $location
New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $resourceGroup -TemplateUri $elasticTemplate -TemplateParameterObject $clusterParameters
Write-Host "[$(Get-Date -format 'u')] Deployed cluster"
Take a look at the other parameters available for the template which can be used to control other elements such as size and number of disks to attach to each data node, setting up Azure Cloud plugin for snapshot/restore, etc.