How can I connect my azure function with my azure sql - azure

I developed a cron trigger azure fuction who needs to search for soe data in my database.
Localy i can connect whit sql server, so i change the connection string in loca.settings.json to connect in azure sql and published the function, but the function cant connect with database.
I need to do something more than configure the local.settings.json?

The local.settings.json is only used for local testing. It's not even exported to azure.
You need to create a connection string in your application settings.
In Azure Functions - click Platform features and then Configuration.
Set the connection string
A function app hosts the execution of your functions in Azure. As a best security practice, store connection strings and other secrets in your function app settings. Using application settings prevents accidental disclosure of the connection string with your code. You can access app settings for your function app right from Visual Studio.
You must have previously published your app to Azure. If you haven't already done so, Publish your function app to Azure.
In Solution Explorer, right-click the function app project and choose Publish > Manage application settings.... Select Add setting, in New app setting name, type sqldb_connection, and select OK.
Application settings for the function app.
In the new sqldb_connection setting, paste the connection string you copied in the previous section into the Local field and replace {your_username} and {your_password} placeholders with real values. Select Insert value from local to copy the updated value into the Remote field, and then select OK.
Add SQL connection string setting.
The connection strings are stored encrypted in Azure (Remote). To prevent leaking secrets, the local.settings.json project file (Local) should be excluded from source control, such as by using a .gitignore file.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-scenario-database-table-cleanup

If you are using entity framework core to make a connection, Other Way of connection to SQL is by using dependency injection from .netcore library.
You can keep the connection string in Azure Key-vault or the config file from there you can read the same using azure function startup class. which need below code setup in your function app.
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof( TEST.Startup))]
namespace TEST
{
internal class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
Contract.Requires(builder != null);
builder.Services.AddHttpClient();
var configBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddAzureKeyVault($"https://XYZkv.vault.azure.net/");
var configuration = configBuilder.Build();
var conn = configuration["connectionString"];
builder.Services.AddDbContext<yourDBContext>(
options => options.UseSqlServer(configuration["connectionString"]));
}
}
}
after that where ever you are injecting this dbcontext, with context object you can do all CRUD operations by following microsoft's entity framework core library documentation.

Having just dealt with this beast (using a custom handler with Linux), I believe the simple way is to upgrade your App to premium-plan, allowing you to access the "Networking" page from "App Service plans". This should allow you to put both sql-server and app in the same virtual network, which probably makes it easier. (but what do I know?)
Instead, if you don't have the extra cash laying around, you can try what I did, and set up a private endpoint, and use the proxy connection setting for your database:
Create a virtual network
I used Address space: 10.1.0.0/16 (default I think)
Add subnet 10.1.0.0/24 with any name (adding a subnet is required)
Go to "Private link center" and create a private endpoint.
any name, resource-group you fancy
use resource type "Microsoft.Sql/Server" and you should be able to select your sql-server (which I assume you have created already) and also set target sub-resource to "sqlServer" (the only option)
In the next step your virtual network and submask should be auto-selected
set Private DNS integration to yes (or suffer later).
Update your firewall by going to Sql Databases, select your database and click "Set Server Firewall" from the overview tab.
Set Connection Policy to proxy. (You either do this, or upgrade to premium!)
Add existing virtual network (rule with any name)
Whitelist IPs
There probably is some other way, but the azure-cli makes it easy to get all possible IP's your app might use: az functionapp show --resource-group <group_name> --name <app_name> --query possibleOutboundIpAddresses
https://learn.microsoft.com/en-us/azure/app-service/overview-inbound-outbound-ips
whitelist them all! (copy paste exercise)
Find your FQDN from Private link center > Private Endpoints > DNS Configuration. It's probably something like yourdb.privatelink.database.windows.net
Update your app to use this url. You just update your sql server connection string and replace the domain, for example as ADO string: Server=tcp:yourdb.privatelink.database.windows.net,1433;Initial Catalog=somedbname;Persist Security Info=False;User ID=someuser;Password=abc123;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;
Also note that I at some point during all of this I switched to TrustServerCertificate=True and now I can't bother to figure out if it does a difference or not. So I left it as an exercise to the reader to find out.
So what we have done here...?
We have forced your function app to go outside the "azure-sphere" by connecting to the private endpoint. I think that if you bounce between azure-services directly, then you'll need some sort of authentication (like logging in to your DB using AD), and in my case, using custom handler and linux base for my app, I think that means you need some trust negotiation (kerberos perhaps?). I couldn't figure that out, so I came up with this instead.

Related

How do I allow ContinuousIntegration.exe to use a connection string in Azure Key Vault

I've got a Kentico Xperience (v13) instance in Azure and I want to run ContinuousIntegration.exe to populate my database up there with content from my CI xml files. The catch is that we're injecting the CMSConnectionString setting into the web app from Azure Key Vault (AKV) and the CI.exe isn't seeing it. Instead I get this error message:
CMS.DataEngine.ApplicationInitException: Cannot access the database specified by the 'CMSConnectionString' connection string. Please install the database externally and set a correct connection string.
Or maybe this error message:
Failed to execute the command.
Here's the relevant section from our web.config (that works for the website!):
<connectionStrings>
<!--Should be provided by Azure Key Vault-->
</connectionStrings>
How do I ensure that the executable gets access to the secrets in AKV?
It is possible to let ContinuousIntegration.exe know about a secure connection string with a small custom module that sets the connection string at startup. Here is the basic code of the module:
[assembly: AssemblyDiscoverable]
[assembly: RegisterModule(typeof(AzureConnectionStringModule))]
public class AzureConnectionStringModule : Module
{
public AzureConnectionStringModule()
: base(nameof(AzureConnectionStringModule))
{
}
protected override void OnPreInit()
{
base.OnPreInit();
var azureConnectionString = Environment.GetEnvironmentVariable("SQLAZURECONNSTR_CMSConnectionString");
if (string.IsNullOrWhiteSpace(azureConnectionString))
{
azureConnectionString = Environment.GetEnvironmentVariable("CMSConnectionString");
}
if (!string.IsNullOrWhiteSpace(azureConnectionString))
{
SettingsHelper.ConnectionStrings.SetConnectionString("CMSConnectionString", azureConnectionString);
}
}
}
From a fresh installation of Kentico Xperience 13, here are steps to configure this:
Follow the steps here to add Key Vault support to the admin app locally: https://learn.microsoft.com/en-us/azure/key-vault/general/vs-key-vault-add-connected-service.
Add the module above to the solution in a class library. Make sure the main project references the class library so that it is included during building.
Ensure that the ~\web.config does not have a connection string, or an app setting, named CMSConnectionString.
Deploy the app to an App Service.
In Azure, create an App Service configuration setting with name CMSConnectionString and value #Microsoft.KeyVault(VaultName=your-keyvault;SecretName=CMSConnectionString).
In the Key Vault, create a secret with name CMSConnectionString and value a connection string to an Azure SQL database. You may also need to follow https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references to create an access policy for my App Service.
At this point, the Kentico Xperience 13 admin should load with access to the database.
In the App Service portal, under Development Tools select Console.
In the console, run cd bin and then ContinuousIntegration.exe -r. This should produce a message about the repository not being configured, or output on the restore action.

Storing connection strings in Azure App Service Settings

I have an ASP .Net Core 2.2 Web API which connects to a MySQL Database.
It is hosted on Azure App Service.
Currently I am storing the connection strings in the appsettings.json file:
"ConnectionStrings": {
"MyDataContext": "Server=server1.mysql.database.azure.com;user id=username;Pwd=password;persistsecurityinfo=True;database=db1;"
}
And I read the connection strings in Startup.cs (in the ConfigureServices method) like this:
services.AddDbContext<MyContext>(options => options.UseMySql(Configuration.GetConnectionString("MyDataContext")));
I read that I can store these connection strings in the Azure App Service Settings instead, as it offers some advantages. I've been trying to do this, but am struggling to get it to work.
My first question is, when adding the connection string to Azure App Service Settings (under the Connection Strings section), what do I put in for Name in the Name/Value pairs? Do I just put "MyDataContext" or do I put in "ConnectionStrings:MyDataContext"? (I'm trying to keep the same structure as I have in the appsettings.json file).
My second question is, can I still read the connections string in my Startup.ConfigureServices method the same way I am doing now? From what I understand, Azure App Service will automatically inject the connection string store in Settings into the Configuration object in the API? I'm not sure if I'm missing something, but it's not working...
Yes and yes.
Yes, you can name the connection string as almost anything you want, though I've discovered recently that certain characters aren't allowed, but Azure doesn't tell you this, it will just strip them out and not tell you, so to be safe I'd only use alphanumeric characters, you can use CamelCasing if you need to. You don't need to prefix with anything like ConnectionStrings: as this is done automatically by Azure, and the syntax has changed in the most recent version anyway.
And yes, if you haven't specified your own ConfigurationBuilder, your web app should call CreateDefaultBuilder which will add environment variables at runtime. The code you've written will stay the same and you can delete the connection string from your appsettings.json file, if you keep it in there it will get overridden anyway.
It is a good idea to remove connection strings from the appsettings.json file if you are able to store them in Azure instead for security reasons, so that you are not storing either database server address nor connection credentials in your source code. One step up from this is using Managed Identity in conjunction with Active Directory, where you specify an AD username in the connection string but no password, then assign that user (or the user's group) as the server admin.
It looks like there's a slight delay (a couple of seconds at least) when changing the Settings of an Azure App Service - I was too quick...

how to override local connection string with azure connection string

I am using appsettings.json in .Net core project for connection string. My connection string is :
"ConnectionStrings": {
"OT_DB_Connection": "Data Source=108.***.**.**;Initial Catalog=O*******s;User ID=O*******s;Password=O*********$"
},
In startup.cs i am accessing connection string with key like this
options.UseSqlServer(Configuration.GetConnectionString("OT_DB_Connection"));
I deployed this code on azure and i have sql database on azure.
After deployment how my website will use the connection string of azure ?
How to override the local connection string with azure connection string at run time.
You should read the following article:
Multiple Environment Configuration Files in ASP.NET Core
You can have multiple appSettings e.g. 1 for you local environment and 1 for Azure etc. When you publish your app to Azure, you can add an application setting called ASPNETCORE_ENVIRONMENT and add a value that maps to your environment for your app to pick up the correct configuration. If you have an appSettings.Azure.json file you can set ASPNETCORE_ENVIRONMENT to Azure and it will use that configuration file.
If you do not want to take this approach, you can also override the connection string directly in Azure as show in the picture below. This is accessible under your app service -> Application Settings -> Connection Strings. You will want to override OT_DB_Connection.

How can I view the final appSettings values on an Azure App Service web app?

I have an ASP.NET MVC app deployed to Microsoft Azure App Service and am having some trouble with the appSettings and connectionStrings values.
I have some values set in the web.config and some values overriding them in the Application Settings tab of the App Service. I want to quickly and easily view the final values to check that the settings are being picked up correctly.
How can I do this?
Note: I've tried using az webapp config appsettings list but this only seems to bring back what is configured in the Application Settings of the App Service and not the merged results of combining with web.config.
No Azure API will return values that include settings that come from your web.config file.
The only way to get this is to ask the config system within your own runtime. e.g. Use code along these lines:
foreach (string name in ConfigurationManager.AppSettings)
{
string val = ConfigurationManager.AppSettings[name];
...
}
foreach (ConnectionStringSettings settings in ConfigurationManager.ConnectionStrings)
{
string connStr = settings.ConnectionString;
string provider = settings.ProviderName;
...
}
This will give you the effective values that are applied to your app.
You may also use the following blades in Azure Portal (under Development Tools section):
Console
In order to see the file, you may use type command, e.g.:
type web.config
Advanced Tools
This points to the Kudu service.
You may see files deployed when navigating to Debug Console > Choose either CMD or PowerShell. Then navigate to your config directory (e.g. site/wwwroot) and choose to either download or edit file.
App Service Editor
App Service Editor is a relatively new tool in Azure toolset. Default view is a list of files, so you can browse all hosted files, including configuration ones.
You can view all of your runtime appSettings, connection strings and environment variables (and more..) using azure KUDU SCM. if your application address is "https://app_name.azurewebsites.net" you can access it in the address "https://app_name.scm.azurewebsites.net" or from azure portal
With kudo REST API, you can get the settings, delete or post them in this address https://app_name.scm.azurewebsites.net/api/settings
kudo wiki

deploying Azure webrole to the cloud, but dont understand dataconnection string (for queues)

I have written and successfully deployed a test app to the azure cloud, but I am lost now that I have added a queue to the application.
Currently I using a configuration string:
Setting name="DataConnectionString" value="UseDevelopmentStorage=true"
then create/open the queue with the following code:
var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
var queueClient = storageAccount.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("messagequeue");
queue.CreateIfNotExist();
This works fine in local mode, however,
I do not undertsand how to change the DataConnectionString to use the cloud!
I have tried:
Setting name="DataConnectionString" value="DefaultEndpointsProtocol=http;AccountName=*XXXXX*;AccountKey=*YYYYY*"
but this does not work - it wont run locally.
Help is certainly appreciated!
Thanks
You'll need to make sure you've created a hosted azure storage service via the Windows Azure portal. When creating the storage service, you provide the account name and the system will assign two keys. Use these two values in your connection string settings. You can either manually edit the string in the service configuration, or my preferred approach is to set it via the role's property settings. Simply right click on the role in the cloud service project in visual studio, then select properties. You'll be able to access the role's settings via one of the tabs. Use the provided dialog box to modify the connection string by inputing the account name and connection string for your storage service.

Resources