Using Always Encrypted with Entity Framework and Azure Key Vault - sql-server

I've encrypted some columns in an Azure SQL Database, using Always Encrypted and a column master key stored in an Azure Key Vault, but I'm having trouble accessing them from my application using Entity Framework.
There's a recent MSDN article and an older blog post that explain how to set up a SqlConnection to use Always Encrypted with an Azure Key Vault, so I'm guessing that a normal DbContext could be created using the constructor that accepts a DbConnection.
The problem is that I'm using an IdentityDbContext, which doesn't have that constructor - the only constructor that takes a DbConnection also takes a DbCompiledModel, which is beyond my pay-grade at the moment.
Can anyone explain how to set up an IdentityDbContext to use the Key Vault?

It seems that EF team have a test that uses encryption.
var connectionStringBuilder = new SqlConnectionStringBuilder(SqlServerTestStore.CreateConnectionString("adventureworks"))
{
Encrypt = encryptionEnabled
};
var options = new DbContextOptionsBuilder();
options.UseSqlServer(connectionStringBuilder.ConnectionString);
using (var context = new AdventureWorksContext(options.Options))
{
context.Database.OpenConnection();
Assert.Equal(ConnectionState.Open, context.Database.GetDbConnection().State);
}
TODO: test IdentityDbContext Constructor exposes same constructor as AdventureWorksContext.

Related

How would I configure Effort Testing Tool to mock Entity Framework's DbContext withOut the actual SQL Server Database up and running?

Our team's application development involves using Effort Testing Tool to mock our Entity Framework's DbContext. However, it seems that Effort Testing Tool needs to be see the actual SQL Server Database that the application uses in order to mock our Entity Framework's DbContext which seems to going against proper Unit Testing principles.
The reason being that in order to unit test our application code by mocking anything related to Database connectivity ( for example Entity Framework's DbContext), we should Never need a Database to be up and running.
How would I configure Effort Testing Tool to mock Entity Framework's DbContext withOut the actual SQL Server Database up and running?
*
Update:
#gert-arnold We are using Entity Framework Model First approach to implement the back-end model and database.
The following excerpt is from the test code:
connection = Effort.EntityConnectionFactory.CreateTransient("name=NorthwindModel");
jsAudtMppngPrvdr = new BlahBlahAuditMappingProvider();
fctry = new BlahBlahDataContext(jsAudtMppngPrvdr, connection, false);
qryCtxt = new BlahBlahDataContext(connection, false);
audtCtxt = new BlahBlahAuditContext(connection, false);
mockedReptryCtxt = new BlahBlahDataContext(connection, false);
_repository = fctry.CreateRepository<Account>(mockedReptryCtxt, null);
_repositoryAccountRoleMaps = fctry.CreateRepository<AccountRoleMap>(null, _repository);
The "name=NorthwindModel" pertains to our edmx file which contains information about our Database tables
and their corresponding relationships.
If I remove the "name=NorthwindModel" by making the connection like the following line of code, I get an error stating that it expects an argument:
connection = Effort.EntityConnectionFactory.CreateTransient(); // throws error
Could you please explain how the aforementioned code should be rewritten?
You only need that connection string because Effort needs to know where the EDMX file is.
The EDMX file contains all information required for creating an inmemory store with an identical schema you have in your database. You have to specify a connection string only because I thought it would be convenient if the user didn't have to mess with EDMX paths.
If you check the implementation of the CreateTransient method you will see that it merely uses the connection string to get the metadata part of it.
public static EntityConnection CreateTransient(string entityConnectionString, IDataLoader dataLoader)
{
var metadata = GetEffortCompatibleMetadataWorkspace(ref entityConnectionString);
var connection = DbConnectionFactory.CreateTransient(dataLoader);
return CreateEntityConnection(metadata, connection);
}
private static MetadataWorkspace GetEffortCompatibleMetadataWorkspace(ref string entityConnectionString)
{
entityConnectionString = GetFullEntityConnectionString(entityConnectionString);
var connectionStringBuilder = new EntityConnectionStringBuilder(entityConnectionString);
return MetadataWorkspaceStore.GetMetadataWorkspace(
connectionStringBuilder.Metadata,
metadata => MetadataWorkspaceHelper.Rewrite(
metadata,
EffortProviderConfiguration.ProviderInvariantName,
EffortProviderManifestTokens.Version1));
}

Batch create extranet users in Composite C1

I am in the process of building a website that in near future shall replace an existing web-site. The existing web-site contains aprox. 300 users which I need to "import" to the extranet-module (which I have bought) in composite.
Is there a way to batch create users to the extranet module?
Yes, you can import your existing user database. You can either do this by writing a script and have that execute on your web site or by directly manipulating the underlying SQL table / XML file (depending on what you use to store Composite C1 data). You can also build a provider that links your existing user database with Composite C1 Extranet.
Importing users programmatically: For a script approach please see methods like AddNewUser described on http://docs.composite.net/Packages/Community/Extranet/CompositeCommunityExtranetDeveloperGuide/Using-Extranet-Facade-Methods
You would write this script as web service, aspx page or similar which executes on the Composite C1 website.
If you are running the Extranet in a default setup expect the providerName to be "Default".
Manipulating the physical data store directly: This depends on what data store you are running on. I suggest you add the groups you want and a test user to help you recognize data when you look at the underlying XML files / SQL tables.
If you are running on XML (default) you should focus on the files named Composite.Community.Extranet.DefaultProvider.DataTypes.DefaultProvider*.xml located in the folder ~/App_Data/Composite/DataStores. There are 3 sush files, one for groups, one for users and one for the relation between users and groups.
If you are running on SQL Server you should focus on the 3 tables named Composite.Community.Extranet.DefaultProvider.DataTypes.DefaultProvider*
In both cases you would need to add new entries to the User table/xml file and matching group relations to the GroupUser table/xml file. When you add a user you provide a unique ID and this ID you reuse to register the user in GroupUser.
When you have made your changes you can force Composite C1 to reload by using the Tools | Restart Server command in the C1 Console. If you make a backup of files/tables before you make changes you can easily revert by restoring the backup (in case you need to start over).
Writing a user/group provider: If your user data is in an external store and you would like to keep it there you could also make a bridge between this existing user store and the Composite C1 Extranet by creating a custom provider. If this is relevant see http://docs.composite.net/Packages/Community/Extranet/CompositeCommunityExtranetDeveloperGuide/Writing-Custom-Extranet-Providers
Thank you. It now works. I imported the users programmatically. I opened the composite solution in visual studio and added a aspx page. Here is the code behind.
using System;
using System.Collections.Generic;
using System.IO;
using Composite.Community.Extranet;
using Composite.Community.Extranet.Data;
public partial class ImportUsers : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string path = Server.MapPath("UsersToImport.csv");
StreamReader _streamReader = new StreamReader(path);
IList<Guid> userIds = new List<Guid>();
string line;
while ((line = _streamReader.ReadLine()) != null)
{
string[] fields = line.Split(',');
IExtranetUser extranetUser = new ExtranetUser();
extranetUser.Name = fields[0];
extranetUser.UserName = fields[1];
extranetUser.Email = fields[2];
extranetUser.IsApproved = true;
IExtranetUser addedUser = ExtranetFacade.AddNewUser("Default", extranetUser);
userIds.Add(addedUser.Id);
ExtranetFacade.SetUsersForGroup("Default", new Guid("bc728100-e28e-4135-a14c-bead6e0b9b00"), userIds);
Response.Write(string.Format("User: {0} added at {1}", addedUser.UserName, addedUser.CreationDate));
}
}
}

Insert data into external MSSQL database through Yii Framework

I'm using Yii Framework to create my project. I need to export some data from MySQL (my project) to an external Microsoft SQL server which is on the same network.
Basically, the user needs to click on a button (which will do the export-insert) in my view and the results should be displayed - Success (if the query has been successful) or Failure (if something went wrong).
The results part is quite easy as I'll be using 'setFlash' to display the appropriate message but I want to know how to insert data into an external database through Yii.
Do you have any idea how this can be done?
Well, I agree with #SuVeRa on the first part of defining two db instances in the config.php but i don't think the sql Commands part is necessary (Plus i hate writing sql :D )
Instead you can do:
class SomeModel extends CActiveRecord
{
...
// Override the getDbConnection() function to use the ms sql db connection
public function getDbConnection()
{
return Yii::app()->ms_sql_db_connection; // The name of the connection in config.php
}
public function transfer()
{
// Here you can do all the transferring logic using normal Yii Active Record functions
}
}
Check out the docs on getDbConnection().

Runtime dynamic SQL Server database access by different connection strings

I've searched the stackoverflow for a long time and didn't find a solution fit my situation, so I asked here.
I have a single asp.net website, and need the web app to access different SQL Server database by the subdomain name.
According to the url request subdomian to determine the access the different database.
prj1.test.com prj1--->use the prj1_DB
prj2.test.com prj2 use the prj2_DB
I couldn't find a better practice to solve the issue.
My intuition solution:
when the url request coming, get the url subdomain, get the subdomain's db connection string stored in the main db, passing the connection string to the DAL to get the data.
Index.aspx.cs
DataTable dt = ProjectObject.GetProjectIndexNotice(new object[] { 0, CurrentProject.DbConnectionString });
ProjectObject.cs
public static DataTable GetProjectIndexNotice(object[] param)
{
ProjectDLC obj = new ProjectDLC();
return obj.GetProjectIndexNotice(param);
}
ProjectDAL.cs
public DataTable GetProjectIndexNotice(object[] param)
{
return base.GetDataTableFromDatabase(param, "NEMP_GetProjectIndexNotice");
}
DALBase.cs
DataBase db = new Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase(CurrentProject.DbConnectionString);
I want to find a better way to solve this problem.
The solution I using above is:
get the dbConnectionString from main DB,
passing it over the Index.page ->BusinessObject Layer -->DAL Layer
It's so bad that passing the DB connection string from UI page to the DAL layer.
Any ideas?
Update 1:
What I really want is: don't pass the db connection string from UI to DAL layer.
I want to find a solution that don't do pass the db connstr from UI to DAL linearly.
Is there some pattern in asp.net to share some variable for UI layer and DAL Layer?
Update 2:
if I stored the project db info in a xml file or in the main db, it looks like this
it's a key-value part for the project. here is the question, I get the values all in the main DB or a xml file. How I get the key when I need to access the DB in DAL layer?
in the DAL layer, how to get the correct key for the currnet url request?
it's back to the above, pass the key from UI to DAL. that's I want to avoid.
the real problem is, I can get the key from url request in the UI layer, and I can get the value for that key in the DAL layer. but there is a gap between the two layers, How to conquer this gap?
If you can compute your connection string from a base connection string, then you could do something like this:
store the base connection string in your web.config
<connectionStrings>
<add name="BaseConnString"
connectionString="server=MyServer;database=master;Integrated Security=SSPI;" />
</connectionStrings>
load the base connection string into a SqlConnectionStringBuilder in your code:
string baseConnStr = WebConfigurationManager.ConnectionString["BaseConnString"].ConnectionString;
SqlConnectionStringBuilder scsBuilder =
new SqlConnectionStringBuilder(baseConnStr);
now, just define the database you want to connect to, e.g. based on something in your URL
scsBuilder.InitialCatalog = "ProjectDatabase" + ........ ;
use the resulting complete connection string for your SqlConnection:
using(SqlConnection _con = new SqlConnection(scsBuilder.ConnectionString))
{
// do something
}
Check out the MSDN docs on SqlConnectionStringBuilder.
With this approach, you'd store a single "base" connection string in your web.config and this wouldn't be changing, and using SqlConnectionStringBuilder, you can safely and efficiently define and "compute" your real, "dynamic" connection strings at runtime.
How about adding add the connection strings in web.config as:
Subdomain_connectionString
Now read the subdomain from Request:
Reading connection string from web.config in your DL:
ConfigurationManager.ConnectionStrings[Subdomain_connectionString].ConnectionString
Update:
You can also use xml files to store connection string values:
<ROOT>
<Project_1>
<IPAddress></IPAddress>
<DBName></DBName>
...
</Project_1>
<Project_2>
....
</ROOT>
Anytime a new project is added/removed this xml file would be updated. Use XPath expressions to parse the xml file.
#Passing Connection string from UI to DAL: Just try to add the System.web namespace to DAL layer. This would give access to Request object in DAL. Now you can get the subdomain and build the connectionstring in DAL itself. Not sure whether this is a right approach, but might work in your case.

Fluent NHibernate ExportSchema without connection string

I want to generate a database script without having an actual database connection string declared.
To do this for now i use NHibernate ExportSchema bases on a NHibernate configuration generated with Fluent NHibernate this way (during my ISessionFactory creation method):
FluentConfiguration configuration = Fluently.Configure();
//Mapping conf ...
configuration.Database(fluentDatabaseProvider);
this.nhibernateConfiguration = configuration.BuildConfiguration();
returnSF = configuration.BuildSessionFactory();
//Later
new SchemaExport(this.nhibernateConfiguration)
.SetOutputFile(filePath)
.Execute(false, false, false);
fluentDatabaseProvider is a FluentNHibernate IPersistenceConfigurer which is needed to get proper sql dialect for database creation.
When factory is created with an existing database, everything works fine.
But what i want to do is to create an NHibernate Configuration object on a selected database engine without a real database behind the scene... And i don't manage to do this.
If anybody has some idea.
This is what I used. My mistake was calling BuildSessionFactory which tries to connect to the database:
var config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008)
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<SessionManager>());
new SchemaExport(config.BuildConfiguration())
.SetOutputFile(filedestination)
.Create(false, false);
Try using:
.Create(false, false);
inplace of
.Execute(false, false, false);
Do not add the connectionstring property to the IPersistenceConfigurer (fluentDatabaseProvider).

Resources