we're using Azure AD to authenticate user and service principals for access to our Azure Sql database. This works fine in my Azure Functions project when running locally via func start
or when deployed to Azure, using MSI.
Since we're not using the code first approach, there have been some changes in the structure of some tables. I need to scaffold the DbContext again.
Unlike the first time, in which I just provided the server admin connection string to (including credentials) the scaffold command, I now must authenticate via Azure Ad (MFA-enabled) even for this management task. This is where it does not work.
dotnet ef dbcontext scaffold "Data Source=tcp:server.database.windows.net,1433;Initial Catalog=DatabaseName" Microsoft.EntityFrameworkCore.SqlServer --schema schemaName -o someFolder
This generates the following output:
Build started...
Build succeeded.
To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
...
Login failed for user ''
Okay there was no User Id
argument in the above connection string, so I guess it does not implcitly take my user principal name automatically. Doing some reading on the topic, I found out that the scaffold command generates its own OnConfiguring
method in the DbContext.cs, and as it appears it just takes the connecting string I provided in the above command. So I guess this error is expected, because in that very method I am providing my accessToken to the SqlConnection object instance.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
SqlConnection connection = new SqlConnection();
connection.ConnectionString = _config.GetConnectionString("Name");
connection.AccessToken = _tokenSvc.GetToken().Result;
optionsBuilder.UseSqlServer(connection);
}
public class AzureSqlAuthTokenService : IDbAuthTokenService
{
public async Task<string> GetToken()
{
var tokenProvider = new AzureServiceTokenProvider();
var token = await tokenProvider.GetAccessTokenAsync("https://database.windows.net/");
return token;
}
}
Funny that just a few days ago, I read that a new preview release of EF Core 5 was released, which brings a new --no-onconfiguring flag to the scaffold command.
I then installed that preview release as a local dotnet tool and tried it again
dotnet ef dbcontext scaffold "Data Source=tcp:server.database.windows.net,1433;Initial Catalog=DatabaseName" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring --schema schemaName -o someFolder
But this fails again, with the same error
Build started...
Build succeeded.
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
...
As a last resort I tried explicitly providing my username (note the addition of User ID=my.name@company.com@server
)
dotnet ef dbcontext scaffold "Data Source=tcp:server.database.windows.net,1433;Initial Catalog=DatabaseName;User ID=my.name@company.com@server" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring --schema schemaName -o someFolder
This fails with
Build started...
Build succeeded.
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user 'my.name@company.com'.
...
And lastly, since my user principal is not directly added as a database user, but only as member of an authorised Azure Active Directory Security group
I tried this (note User ID=Group-Name
, the group has admin privileges):
dotnet ef dbcontext scaffold "Data Source=tcp:server.database.windows.net,1433;Initial Catalog=DatabaseName;User ID=Group-Name" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring --schema schemaName -o someFolder
Build started...
Build succeeded.
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user 'Group-Name'.
...
So now I am thinking that it is just impossible to use an Azure AD secured identity with the scaffold command. Is this also what you are seeing? Do you have a workaround?
I want to emphasise again, that the accessToken works fine both locally and remotely when just executing the program itself. Only EF Core makes itself impossible to use without the clear text server admin credentials...
User contributions licensed under CC BY-SA 3.0