What permissions does Azure Mobile Services use to access an Azure SQL Database with the mssql object? - azure

I have set up an Azure Mobile Service (AMS) that's associated with an Azure SQL database, as usual. However, when I try to use a custom api to query another table (NOT a mobile services table) with the custom API mssql object, I get a permissions error:
Error: [Microsoft][SQL Server Native Client 10.0][SQL Server]Login failed for user 'zwxABOesblahblahHYzLogin'.
Some things to note:
I had to drop delete the database and then re-create it with the same name after the mobile service was created.
Mobile service name is 'abc', and the table I'm trying to access is owned by an 'abc' schema, not dbo. The other table was created from SQL Server Management studio via a standard T-SQL script.
The AMS api script is very basic:
exports.get = function(request, response) {
var mssql = request.service.mssql;
var sql = "select * from abc.TestTable";
mssql.query(sql, {
success : function(results) {
console.log("Results from SQL Query to TestTable:\n"+results);
response.send(statusCodes.OK, results);
},
error: function(err) {
console.log("Error in SQL Query to TestTable:\n"+err);
response.send(statusCodes.Error,err.message);
}
});
};
So to my question(s)... what credentials are used by AMS to access the SQL database? How can I change permissions so that the script above just works (as implied by all the docs I've seen!). Or am I stuck with having to pass a connection string as suggested by this question.
Thanks!

When you create a Mobile Service it generates the SQL Database backend, or connects to an existing SQL database. When it does this is creates a SQL Login user with a random name. In your case the user was 'zwxABOesblahblahHYzLogin'. When you dropped and recreated your database you lost this user having access to the database (which I think you already knew).
To determine the permissions that were assigned to the created user I created a new Mobile Service and I then used SQL Management Studio to script the entire database (I modified the scripting options to ensure the permissions would be included in the script). I then trimmed it down to just what pertained to the user and the schema. If you already recreated your schema you can skip that part.
CREATE USER [zwxABOesblahblahHYzLogin] FOR LOGIN [zwxABOesblahblahHYzLogin] WITH DEFAULT_SCHEMA=[abc]
GO
GRANT CONNECT TO [zwxABOesblahblahHYzLogin] AS [dbo]
GRANT CREATE TABLE TO [zwxABOesblahblahHYzLogin] AS [dbo]
CREATE SCHEMA [abc]
GRANT CONTROL ON SCHEMA::[abc] TO [zwxABOesblahblahHYzLogin] AS [dbo]
From this it looks like the AMS user is granted a login in the database, Connect permissions, create table permissions and then granted control of the schema as DBO.
I test this by dropping a mobile service then recreating it which I think would put us in the same scenario.

Related

Connect to Azure SQL Database using Managed Identity

I am trying to configure connecting to azure sql using managed identity. However before, I need to connect to sql azure from visual studio using AD identity.
I have followed steps here.
https://learn.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cef%2Cdotnet#3-modify-your-project
I have this code in console app.
SqlConnectionStringBuilder builder = new
Microsoft.Data.SqlClient.SqlConnectionStringBuilder();
builder.DataSource = "sqlserveraddress";
builder.InitialCatalog = "dbaddress";
string connstring = builder.ConnectionString;
await using var conn = new Microsoft.Data.SqlClient.SqlConnection(connstring)
{
AccessToken = await GetAzureSqlAccessToken()
} ;
await conn.OpenAsync();
As required, I have added my visual studio App service authentication identity user in sql azure db.
CREATE USER "user#domain.com" FROM EXTERNAL
PROVIDER;
ALTER ROLE db_datareader ADD MEMBER
"user#domain.com";
ALTER ROLE db_datawriter ADD MEMBER
"user#domain.com";
ALTER ROLE db_ddladmin ADD MEMBER
"user#domain.com";
GO
Now if i try running my console application, I get following error.
If i try to decode the access token it shows the user I have added to sql azure. user#domain.com.
What Am I Missing here??
You need to set the created Managed Identity as admin in SQL Server.
Follow this: Azure SQL Server -> Settings -> Azure Active Directory
Now click on Set Admin option and search for the Managed Identity to which you want to give access.
Click on Save.

Login failed for user '<token-identified principal>' but works in Data Studio

I am trying to use my AD account to connect to the Azure SQL using Java 8, JDBC Driver, and my accessToken.
When I use Data Studio using my AD Account, I can connect successfully to the Azure SQL DB.
But when I use my Java Program then it gives me this error:
Request processing failed; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user ''
My code abstract:
SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName("NAME.database.windows.net");
ds.setDatabaseName("db-name");
ds.setAccessToken(accessToken);
ds.setEncrypt(true);
ds.setTrustServerCertificate(true);
try (Connection connection = ds.getConnection();
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
if (rs.next()) {
System.out.println("dbResults => You have successfully logged on as: " + rs.getString(1));
res = rs.getString(1);
}
}
After discussion in comments, we found out that we needed to change the scope used when getting the access token.
"User.Read.All" was specified, which is the short form "https://graph.microsoft.com/User.Read.All".
This means a Microsoft Graph API access token is returned, which won't work with Azure SQL DB.
Changing the scope to "https://database.windows.net/.default" resolved the issue.
This gets an access token for Azure SQL DB with the static permissions that the app registration has on Azure SQL DB.
Documentation: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent

BigQuery Node.js API Permission Bug

I am building a Node.js server to run queries against BigQuery. For security reasons, I want this server to be read only. For example, if I write a query with DROP, INSERT, ALTER, etc. statement my query should get rejected. However, something like SELECT * FROM DATASET.TABLE LIMIT 10 should be allowed.
To solve this problem, I decided to use a service account with "jobUser" level access. According to BQ documentation, that should allow me to run queries, but I shouldn't be able to "modify/delete tables".
So I created such a service account using the Google Cloud Console UI and I pass that file to the BigQuery Client Library (for Node.js) as the keyFilename parameter in the code below.
// Get service account key for .env file
require( 'dotenv' ).config()
const BigQuery = require( '#google-cloud/bigquery' );
// Query goes here
const query = `
SELECT *
FROM \`dataset.table0\`
LIMIT 10
`
// Creates a client
const bigquery = new BigQuery({
projectId: process.env.BQ_PROJECT,
keyFilename: process.env.BQ_SERVICE_ACCOUNT
});
// Use standard sql
const query_options = {
query : query,
useLegacySql : false,
useQueryCache : false
}
// Run query and log results
bigquery
.query( query_options )
.then( console.log )
.catch( console.log )
I then ran the above code against my test dataset/table in BigQuery. However, running this code results in the following error message (fyi: exemplary-city-194015 is my projectID for my test account)
{ ApiError: Access Denied: Project exemplary-city-194015: The user test-bq-jobuser#exemplary-city-194015.iam.gserviceaccount.com does not have bigquery.jobs.create permission in project exemplary-city-194015.
What is strange is that my service account (test-bq-jobuser#exemplary-city-194015.iam.gserviceaccount.com) has the 'Job User' role and the Job User role does contain the bigquery.jobs.create permission. So that error message doesn't make sense.
In fact, I tested out all possible access control levels (dataViewer, dataEditor, ... , admin) and I get error messages for every role except the "admin" role. So either my service account isn't correctly configured or #google-cloud/bigquery has some bug. I don't want to use a service account with 'admin' level access because that allows me to run DROP TABLE-esque queries.
Solution:
I created a service account and assigned it a custom role with bigquery.jobs.create and bigquery.tables.getData permissions. And that seemed to work. I can run basic SELECT queries but DROP TABLE and other write operations fail, which is what I want.
As the error message shows, your service account doesn't have permissions to create BigQuery Job
You need to grant it roles/bigquery.user or roles/bigquery.jobUser access, see BigQuery Access Control Roles, as you see in this reference dataViewer and dataEditor don't have Create jobs/queries, but admin does, but you don't need that
To do the required roles, you can follow the instructions in Granting Access to a Service Account for a Resource
From command line using gcloud, run
gcloud projects add-iam-policy-binding $BQ_PROJECT \
--member serviceAccount:$SERVICE_ACOUNT_EMAIL \
--role roles/bigquery.user
Where BQ_PROJECT is your project-id and SERVICE_ACOUNT_EMAIL is your service-account email/id
Or from Google Cloud Platform console search or add your service-account email/id and give it the required ACLs
I solved my own problem. To make queries you need both bigquery.jobs.create and bigquery.tables.getData permissions. The JobUser role has the former but not the latter. I created a custom role (and assigned my service account to that custom role) that has both permissions and now it works. I did this using the Google Cloud Console UI ( IAM -> Roles -> +Add ) then ( IAM -> IAM -> <set service account to custom role> )

How to replace the App_Data\aspnetdb.mdf when migrating to MS Azure?

Having a ASP.NET webforms application, I use aspnetdb database created in the SQL server.
When migrating to Azure, is there any way to replace the aspnetdb database by something else so that it would not eat one database from the Azure SQL Database component? Or is the specific database supported somehow as the part of the App Services (Azure component)?
What is the typical replacement of the form of the aspnetdb datababase when working with Azure App Services?
Update: In the original application, I am using two databases in MS SQL Standard Ed. -- typically like company_users (this is the name for the aspnetdb) and company_app for the application tables. I usually create the company_users via a small external application that creates the database, the roles, and also the initial users -- see the shortened code below.
So, it probably would be more straightforward to migrate the two databases to Azure SQL Database, and to use it the same way. On the other hand, one have to pay for the Azure SQL based on the number of databases. While it is fine for the company_app, the company_users is rather small and probably worth to be replaced by something cheaper. This is the motivation for replacing the one for authentication/authorization part of the framework (aspnetdb alias company_users) by something else that would not eat one SQL database.
The shortened source code of my InitUsers.exe:
// ... get the configuration information to be used for...
SqlServices.Install(SQLServerName,
SQLServerUser, SQLServerPassword,
ASPNETdbName, SqlFeatures.All);
// ... and the roles in the loop...
SqlRoleProvider roleProvider = AModule.GetRoleProvider();
string[] roles = { "admin", "poweruser", /* ... */ };
foreach (var role in roles) {
if (!roleProvider.RoleExists(role))
roleProvider.CreateRole(role);
}
// ... and the initial users...
List<string[]> userList = new List<string[]> {
// 0 1 2 3 4 5 6
// login, email, roles, first, last tit., phone
new[] { "nemo", "nemo#ocean.org", "admin", "Nihil", "Nemo", "cpt.", "123 456 789"}
};
foreach (var info in userList) {
string login = info[0];
string password = ...;
string email = info[1];
string[] rolenames = info[2].Split();
string first = info[3];
string last = info[4];
string title = info[5];
string phone = info[6];
AModule.MakeUser(login, password, email, rolenames,
first, last, title, phone,
true); // isApproved
}
How to replace the App_Data\aspnetdb.mdf when migrating to MS Azure?
Based on my understanding, you are using SQL Server LocalDB. Azure Web Apps do not install the SQL Server Express. I assume that you could migrate your LocalDB database to SQL Server or SQL Azure. Here is a similar issue, you could refer to it. In order to migrate your database to Azure SQL Database or SQL Server, you could follow the approaches below:
Use SQL Server Management Studio (SSMS), right click your database, then choose "Tasks > Export Data", configure the Data Source and Destination. More details, you could refer to here.
Use the SSIS Import and Export Wizard from Visual Studio, more details you could refer to here.
Moreover, for creating Azure SQL database, you could follow here. Additionally, if you are using Entity Framework Model First or Entity Framework Code First, you could change your connection string and regenerate your database easily.

Azure - Data only for the owner

I use an Azure Mobile Serivce to save data from my app useres in my Windows 8 Store App. I want to publish the app in the app store but for this I have to be sure every user can only get his own data. If 10 people upload data to my Azure service they should only be able to get their own data. How can I do this?
You should check the Use scripts to authorize users in Mobile Services tutorial it will show you how to partition the data per user
Basically you have to write custom scripts server side (directly in the Azure Portal in the Mobile Service script section) for the Insert operation like this
function insert(item, user, request) {
item.userId = user.userId;
request.execute();
}
And the Read operation like this
function read(query, user, request) {
query.where({ userId: user.userId });
request.execute();
}
But first you will have to add authorization to your app as shown in the Get started with authentication in Mobile Services tutorial

Resources