rollsch
rollsch

Reputation: 2770

How to remotely update azure webapp firewall with local IP via powershell or C#

How can I remotely update my azure webapp firewall with my local PCs IP address for administration either via powershell or C#.

I have had a look over the documentation but I can only find out how to do it from the actual server itself, not remotely.

I can get visual studio to pop up and ask me if I want to add my IP address to the firewall randomly, but most the time it simply fails and does not ask me so I am looking for a solution other than manually logging into the azure portal whenever my IP address changes.

Looking for either an example or a link to documentation that shows which libraries to use.

Update: I tried Tom Suns answer however we are using a web app not an sql server so it does not work.

azure.WebApps.GetByResourceGroup("resourcegroup","webapp")

returns the web app but I cannot find anyway to programatically access the "Access Restrictions" found under networking for this web app.

I also can only access the main deployment slot for this web app. I need to set the firewall individually per deployment slot (as can be done via the azure web interface).

I have tried accessing the second deployment slot via the following names, all return null. This is assuming the web app is named 'webapp' and the deployment slot is named 'slo1'

webapp-slot1 webapp_slot1 webapp/slot1

I have also tried GetByID instead of GetByResourceGroup however I cannot find any examples of what he ID is and where it can be found. I've tried almost every single ID I can find on the azure web UI.

Finally Tom Sun's answer requires hard coded credentials being stored on a drive. This is far from optimal. I would prefer a popup UI that prompts the user for their username and password, this used to be possible with older versions of the API however everything I can find says it is no longer. I may have to resort to powershell.

Upvotes: 4

Views: 2323

Answers (3)

GaussZ
GaussZ

Reputation: 881

From C# you can access all Azure resources via Microsoft.Azure.Management.Fluent like this

// Create an authentication context to Azure and acquire a login token
var context = new AuthenticationContext("https://login.microsoftonline.com/tenantId");
var auth = await context.AcquireTokenAsync("https://management.core.windows.net/",
                    "yourClientId", new Uri("urn:ietf:wg:oauth:2.0:oob"),
                    new PlatformParameters(PromptBehavior.Always));
string token = auth.AccessToken;
var tokenCredentials = new TokenCredentials(token);
var azureCredentials = new AzureCredentials(tokenCredentials, tokenCredentials, 
                           AzureParts.Tenant, AzureEnvironment.AzureGlobalCloud);

// Build the client with the acquired token as a credential.
RestClient client = RestClient.Configure()
                .WithEnvironment(AzureEnvironment.AzureGlobalCloud)
                .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
                .WithCredentials(azureCredentials)
                .Build();

// Authenticate against azure with the correct subscription to access.
var azure = Azure.Authenticate(client, AzureParts.Tenant)
                .WithSubscription("subscriptionId");

// Search for the sql server and add a firewall rule.
var sqlServer = azure.SqlServers.GetByResourceGroup("ResourceGroup", "servername");
sqlServer.FirewallRules.Define("LetMeIn").WithIPAddress("yourIp").Create();

Note that acquiring the login token via AcquireTokenAsync will open a login window and thus can not be used in an automated fashion. You could provide a token-cache with an already stored token if you want to only login once.

A more complex example to retrieve the token without a token-cache (see the overloads for the AuthenticationContext constructor if you want to add a token cache):

var context = new AuthenticationContext("https://login.microsoftonline.com/<tenantId>", false);
AuthenticationResult authResult = null;

try
{
    authResult = await context.AcquireTokenSilentAsync("https://management.core.windows.net/", clientId);
}
catch (AdalSilentTokenAcquisitionException)
{
    authResult = await context.AcquireTokenAsync("https://management.core.windows.net/",
    clientId, new Uri("urn:ietf:wg:oauth:2.0:oob"),
    new PlatformParameters(PromptBehavior.Always));
}
string token = authResult.AccessToken;

Upvotes: 1

Tom Sun
Tom Sun

Reputation: 24529

We can do that with Microsoft.Azure.Management.Fluent and Microsoft.Azure.Management.ResourceManager.Fluent,more detail info about library, please refer to the packages.config. We also could get more demo code from the github. Before coding we need to registry an Azure AD Application and assign corresponding role for it, more details please refer to the document. Then we can get the clientId, key(secret key) and tenant from the Azure AD App. After that we could create the Auth file with following format

subscription=########-####-####-####-############
client=########-####-####-####-############
tenant=########-####-####-####-############
key=XXXXXXXXXXXXXXXX
managementURI=https\://management.core.windows.net/
baseURL=https\://management.azure.com/
authURL=https\://login.windows.net/
graphURL=https\://graph.windows.net/

Demo code:

 var credFile = @"File Path"; // example: c:\tom\auth.txt
            var resourceGroup = "resource group";
            var azureSQLServer = "Azure sql server name"; //just name of the Azure sql server such as tomdemo
            var firewallRull = "firewall rull name";//such as myFirewallRull
            var firewallRuleIPAddress = "x.x.x.x";//your Ip address
            var credentials = SdkContext.AzureCredentialsFactory.FromFile(credFile);
            var azure = Azure
                .Configure()
                .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
                .Authenticate(credentials)
                .WithDefaultSubscription();

            var sqlServer = azure.SqlServers.GetByResourceGroup(resourceGroup, azureSQLServer);
            var newFirewallRule = sqlServer.FirewallRules.Define(firewallRull)
                .WithIPAddress(firewallRuleIPAddress)
                .Create();

packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.AppService.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Batch.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Cdn.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Compute.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.ContainerInstance.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.ContainerRegistry.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.CosmosDB.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Dns.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Graph.RBAC.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.KeyVault.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Network.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Redis.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.ResourceManager.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Search.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.ServiceBus.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Sql.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.Storage.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Azure.Management.TrafficManager.Fluent" version="1.3.0" targetFramework="net461" />
  <package id="Microsoft.Data.Edm" version="5.8.2" targetFramework="net461" />
  <package id="Microsoft.Data.OData" version="5.8.2" targetFramework="net461" />
  <package id="Microsoft.Data.Services.Client" version="5.8.2" targetFramework="net461" />
  <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.28.3" targetFramework="net461" />
  <package id="Microsoft.Rest.ClientRuntime" version="2.3.9" targetFramework="net461" />
  <package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.10" targetFramework="net461" />
  <package id="Microsoft.Rest.ClientRuntime.Azure.Authentication" version="2.3.1" targetFramework="net461" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net461" />
  <package id="System.ComponentModel.EventBasedAsync" version="4.0.11" targetFramework="net461" />
  <package id="System.Dynamic.Runtime" version="4.0.0" targetFramework="net461" />
  <package id="System.Linq.Queryable" version="4.0.0" targetFramework="net461" />
  <package id="System.Net.Requests" version="4.0.11" targetFramework="net461" />
  <package id="System.Spatial" version="5.8.2" targetFramework="net461" />
  <package id="WindowsAzure.Storage" version="8.1.4" targetFramework="net461" />
</packages>

Upvotes: 5

Gaurav Mantri
Gaurav Mantri

Reputation: 136136

For PowerShell, you would need to use New-AzureRmSqlServerFirewallRule.

From this link:

New-AzureRmSqlServerFirewallRule -ResourceGroupName "myResourceGroup" -ServerName $servername -FirewallRuleName "AllowSome" -StartIpAddress "0.0.0.0" -EndIpAddress "0.0.0.0"

Upvotes: 1

Related Questions