Remove extra spacing

This commit is contained in:
Lorin Thwaits
2023-02-20 19:33:29 +00:00
parent 434b798c98
commit b062f2c734
1461 changed files with 13333 additions and 76271 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
# SQL Security
<!--placeholder for summary.-->
<!--placeholder for summary.-->
[Ledger Demos](ledger)
[Always Encrypted with secure enclaves Demos](always-encrypted-with-secure-enclaves)
[Azure Active Directory Authentication Demos](azure-active-directory-auth)
[Azure SQL Security Demo](https://github.com/Microsoft/azure-sql-security-sample)
[Azure SQL Security Demo](https://github.com/Microsoft/azure-sql-security-sample)
[SQL 2016 Security Demo](contoso-clinic)
@@ -130,7 +130,7 @@ Perform the below steps before each demo presentation.
- **Column Encryption Setting = Enabled** turns the Always Encrypted on in the client driver, allowing it to transparently encrypt query parameters and decrypt query results.
- **Attestation Protocol = AAS** specifies Microsoft Azure Attestation is used for attesting the secure enclave for the **ContosoHR** database.
- **Enclave Attestation Url** is an attest URI of the attestation provider.
- **Enclave Attestation Url** is an attest URI of the attestation provider.
![Connection string](./img/portal-web-app-connection-string.png)
@@ -205,7 +205,7 @@ Perform the below steps before you show the demo.
![Extended event results](./img/ssms-xevents-results.png)
1. Click on the link in the second column of the first row of the result set to see the extended event with the latest query from the application. This will open the extended event in the new tab.
1. Review the query statement. Note that the query contains the **WHERE** clause with rich computations on encrypted columns: pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column. The query also sorts records (the **ORDER BY** clause) by **SSN** or **Salary**. **Pro Tip:** to make it easier to view the query statement, you can put line brakes in it.
1. Review the query statement. Note that the query contains the **WHERE** clause with rich computations on encrypted columns: pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column. The query also sorts records (the **ORDER BY** clause) by **SSN** or **Salary**. **Pro Tip:** to make it easier to view the query statement, you can put line brakes in it.
![Extended event](./img/ssms-xevent.png)
@@ -308,13 +308,13 @@ Perform the below steps before you show the demo.
1. Switch to Security Administrator's instance of SSMS, select the **EncryptColumns.sql** tab and click **F5** to execute the query, encrypts the data in the **SSN** and **Salary** columns in place, using the secure enclave.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
![Encrypted results](./img/ssms-encrypted-results.png)
1. In the web browser, move the slider to reset the filter for salary and then re-enter a few digits of an SSN. Confirm the application still can filter employee records by salary and SSN.
1. Switch to DBA's instance of SSMS, select the **QueryXevents.sql** tab and click **F5** to re-run the query.
1. Switch to DBA's instance of SSMS, select the **QueryXevents.sql** tab and click **F5** to re-run the query.
1. Click on the link in the second column of the first row of the result set to see the extended event with the latest query from the application. This will open the extended event in the new tab.
1. Review the query statement. Note that the query statement the query sends to the database has not changed - it still contains pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column, as well as sorting (the **ORDER BY** clause) by **SSN** or **Salary**. **Pro Tip:** to make it easier to view the query statement, you can put line brakes in it.
@@ -1,9 +1,9 @@
version= 1.0;
authorizationrules
authorizationrules
{
[ type=="x-ms-sgx-is-debuggable", value==false ]
&& [ type=="x-ms-sgx-product-id", value==4639 ]
&& [ type=="x-ms-sgx-svn", value>= 2 ]
&& [ type=="x-ms-sgx-mrsigner", value=="e31c9e505f37a58de09335075fc8591254313eb20bb1a27e5443cc450b6e33e5"]
&& [ type=="x-ms-sgx-mrsigner", value=="e31c9e505f37a58de09335075fc8591254313eb20bb1a27e5443cc450b6e33e5"]
=> permit();
};
@@ -7,7 +7,7 @@ BEGIN
END
go
CREATE EVENT SESSION [Demo] ON DATABASE
CREATE EVENT SESSION [Demo] ON DATABASE
ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
ACTION(sqlserver.sql_text)
WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%SSN%')AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection'))
@@ -16,7 +16,7 @@ ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
--CREATE EVENT SESSION [Demo] ON DATABASE
--CREATE EVENT SESSION [Demo] ON DATABASE
--ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
-- WHERE ([sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'ContosoHR') AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection')))
--ADD TARGET package0.ring_buffer(SET max_memory=(4096))
@@ -11,7 +11,7 @@ CREATE TABLE [dbo].[Employees](
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[Salary] [money] NOT NULL,
CONSTRAINT [PK_dbo.Employees] PRIMARY KEY CLUSTERED
CONSTRAINT [PK_dbo.Employees] PRIMARY KEY CLUSTERED
(
[EmployeeID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
@@ -128,7 +128,7 @@ INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('658-41-8532', 'Twanna', 'Evans', 35364)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('943-41-6011', 'Carolyn', 'Farino', 76201)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('691-30-8623', 'Geri', 'Farrell', 39600)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('361-08-3217', 'François', 'Ferrier', 3704)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('361-08-3217', 'Franois', 'Ferrier', 3704)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('827-51-1487', 'Kathie', 'Flood', 78467)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('483-93-0057', 'John', 'Ford', 77552)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('738-37-1607', 'Garth', 'Fort', 34381)
@@ -232,7 +232,7 @@ INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('321-14-1319', 'Scott', 'MacDonald', 30158)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('340-75-5874', 'Kathy', 'Marcovecchio', 10228)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('043-85-0648', 'Melissa', 'Marple', 46100)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('253-33-7509', 'Frank', 'Mart¡nez', 46267)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('253-33-7509', 'Frank', 'Martnez', 46267)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('335-68-4629', 'Chris', 'Maxwell', 92921)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('535-30-6577', 'Sandra', 'Maynard', 60264)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('613-34-9127', 'Walter', 'Mays', 70620)
@@ -9,7 +9,7 @@ param projectName string
param userObjectId string
@description('The username of the user running the deployment.')
param userName string
param userName string
@description('The username of the Azure SQL database server administrator for SQL authentication.')
param sqlAdminUserName string
@@ -18,7 +18,7 @@ param sqlAdminUserName string
param sqlAdminPassword string
@description('The IP address the user will connect from to the logical server in Azure SQL Database.')
param clientIP string
param clientIP string
@description('The location (the Azure region) for all resources.')
param location string = resourceGroup().location
@@ -86,7 +86,7 @@ resource Database_Resource 'Microsoft.Sql/servers/databases@2022-05-01-preview'
tags: {}
sku: {
name: 'GP_DC_2'
tier: 'GeneralPurpose'
tier: 'GeneralPurpose'
}
properties: {}
}
@@ -106,7 +106,7 @@ resource attestationProviderName_resource 'Microsoft.Attestation/attestationProv
// Configure the web application //
///////////////////////////////////
// Create an App Service plan
// Create an App Service plan
resource WebAppServicePlan_Resource 'Microsoft.Web/serverfarms@2022-03-01' = {
name: '${projectName}plan'
location: location
@@ -124,9 +124,9 @@ resource WebApp_Resource 'Microsoft.Web/sites@2022-03-01' = {
type: 'SystemAssigned'
}
properties: {
serverFarmId: WebAppServicePlan_Resource.id
serverFarmId: WebAppServicePlan_Resource.id
}
//Set the database connection string for the application
resource WebAppConnectionString_Resource 'config' = {
name: 'connectionstrings'
@@ -136,7 +136,7 @@ resource WebApp_Resource 'Microsoft.Web/sites@2022-03-01' = {
type: 'SQLAzure'
}
}
}
}
//Define AppSetting to fetch the correct project from the GitHub Repository
resource AppSetting 'config' = {
name: 'appsettings'
@@ -157,7 +157,7 @@ resource sourceControl 'Microsoft.Web/sites/sourcecontrols@2022-03-01' = {
dependsOn: [
Server_Name_resource
]
}
}
//////////////////////////////////////
// Create and configure a key vault //
@@ -196,7 +196,7 @@ resource KeyVault_Resource 'Microsoft.KeyVault/vaults@2022-07-01' = {
}
}
// Assign key permissions to the web app
// Assign key permissions to the web app
resource KeyVaultWebAppAccessPolicy_Resource 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
name: any('${KeyVault_Resource.name}/add')
properties: {
@@ -1,5 +1,5 @@
Import-Module "Az" -MinimumVersion "9.3"
Import-Module "SqlServer" #-Version "22.0.49-preview"
Import-Module "SqlServer" #-Version "22.0.49-preview"
######################################################################
# Prompt the user to enter the values of deployment parameters
@@ -102,7 +102,7 @@ Invoke-Sqlcmd -ServerInstance "tcp:$serverName" -Database $databaseName -AccessT
# Get the column master key from Azure Key Vault
$keyVaultName = "${projectName}vault"
$keyName = "CMK"
$key = Get-AzKeyVaultKey -VaultName $keyVaultName -Name $keyName
$key = Get-AzKeyVaultKey -VaultName $keyVaultName -Name $keyName
# Connect to the database using the SqlServer PowerShell module
$connStr = "Data Source=tcp:$serverName;Initial Catalog=$databaseName;User ID=$sqlAdminUserName;Password=$sqlAdminPassword"
@@ -142,14 +142,14 @@ $policy=Get-Content -path $policyFile -Raw
Set-AzAttestationPolicy -Name $attestationProviderName -ResourceGroupName $resourceGroupName -Tee $teeType -Policy $policy -PolicyFormat $policyFormat
# Get the attestation URL
$attestationProvider = Get-AzAttestationProvider -Name $attestationProviderName -ResourceGroupName $resourceGroupName
$attestationProvider = Get-AzAttestationProvider -Name $attestationProviderName -ResourceGroupName $resourceGroupName
$attestationUrl = $attestationProvider.AttestUri
######################################################################
# Print parameters for the demo
######################################################################
$app = Get-AzWebApp -Name $appName -ResourceGroupName $resourceGroupName
$app = Get-AzWebApp -Name $appName -ResourceGroupName $resourceGroupName
Write-Host -ForegroundColor "green" "Resource group name: $resourceGroupName"
Write-Host -ForegroundColor "green" "Database server name: $serverName"
Write-Host -ForegroundColor "green" "Database name: $databaseName"
@@ -6,7 +6,7 @@ ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, AL
GO
ALTER TABLE [dbo].[Employees]
ALTER COLUMN [Salary] [Money]
ALTER COLUMN [Salary] [Money]
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL;
GO
@@ -6,7 +6,7 @@ GO
DECLARE @SSNPattern CHAR(11) = '%9838'
SELECT * FROM [dbo].[Employees] WHERE [SSN] LIKE @SSNPattern;
GO
GO
DECLARE @MinSalary MONEY = 40000
DECLARE @MaxSalary MONEY = 45000
@@ -2,31 +2,31 @@ DECLARE @ExtendedEventsSessionName sysname = N'Demo';
DECLARE @StartTime datetimeoffset;
DECLARE @EndTime datetimeoffset;
DECLARE @Offset int;
DROP TABLE IF EXISTS #xmlResults;
CREATE TABLE #xmlResults
(
xeTimeStamp datetimeoffset NOT NULL
, xeXML XML NOT NULL
);
SET @StartTime = DATEADD(HOUR, -4, GETDATE()); --modify this to suit your needs
SET @EndTime = GETDATE();
SET @Offset = DATEDIFF(MINUTE, GETDATE(), GETUTCDATE());
SET @StartTime = DATEADD(MINUTE, @Offset, @StartTime);
SET @EndTime = DATEADD(MINUTE, @Offset, @EndTime);
DECLARE @target_data xml;
SELECT @target_data = CONVERT(xml, target_data)
FROM sys.dm_xe_database_sessions AS s
JOIN sys.dm_xe_database_session_targets AS t
FROM sys.dm_xe_database_sessions AS s
JOIN sys.dm_xe_database_session_targets AS t
ON t.event_session_address = s.address
WHERE s.name = @ExtendedEventsSessionName
AND t.target_name = N'ring_buffer';
;WITH src AS
;WITH src AS
(
SELECT xeXML = xm.s.query('.')
FROM @target_data.nodes('/RingBufferTarget/event') AS xm(s)
@@ -188,7 +188,7 @@ Perform the below steps before you show the demo.
![Extended event results](./img/ssms-xevents-results.png)
1. Click on the link in the second column of the first row of the result set to see the extended event with the latest query from the application. This will open the extended event in the new tab.
1. Review the query statement. Note that the query contains the **WHERE** clause with rich computations on encrypted columns: pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column. The query also sorts records (the **ORDER BY** clause) by **SSN** or **Salary**. **Pro Tip:** to make it easier to view the query statement, you can put line brakes in it.
1. Review the query statement. Note that the query contains the **WHERE** clause with rich computations on encrypted columns: pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column. The query also sorts records (the **ORDER BY** clause) by **SSN** or **Salary**. **Pro Tip:** to make it easier to view the query statement, you can put line brakes in it.
![Extended event](./img/ssms-xevent.png)
@@ -291,13 +291,13 @@ Perform the below steps before you show the demo.
1. Switch to Security Administrator's instance of SSMS, select the **EncryptColumns.sql** tab and click **F5** to execute the query, encrypts the data in the **SSN** and **Salary** columns in place, using the secure enclave.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
![Encrypted results](./img/ssms-encrypted-results.png)
1. In the web browser, move the slider to reset the filter for salary and then re-enter a few digits of an SSN. Confirm the application still can filter employee records by salary and SSN.
1. Switch to DBA's instance of SSMS, select the **QueryXevents.sql** tab and click **F5** to re-run the query.
1. Switch to DBA's instance of SSMS, select the **QueryXevents.sql** tab and click **F5** to re-run the query.
1. Click on the link in the second column of the first row of the result set to see the extended event with the latest query from the application. This will open the extended event in the new tab.
1. Review the query statement. Note that the query statement the query sends to the database has not changed - it still contains pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column, as well as sorting (the **ORDER BY** clause) by **SSN** or **Salary**. **Pro Tip:** to make it easier to view the query statement, you can put line brakes in it.
@@ -7,7 +7,7 @@ BEGIN
END
go
CREATE EVENT SESSION [Demo] ON DATABASE
CREATE EVENT SESSION [Demo] ON DATABASE
ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
ACTION(sqlserver.sql_text)
WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%SSN%')AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection'))
@@ -16,7 +16,7 @@ ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
--CREATE EVENT SESSION [Demo] ON DATABASE
--CREATE EVENT SESSION [Demo] ON DATABASE
--ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
-- WHERE ([sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'ContosoHR') AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection')))
--ADD TARGET package0.ring_buffer(SET max_memory=(4096))
@@ -11,7 +11,7 @@ CREATE TABLE [dbo].[Employees](
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[Salary] [money] NOT NULL,
CONSTRAINT [PK_dbo.Employees] PRIMARY KEY CLUSTERED
CONSTRAINT [PK_dbo.Employees] PRIMARY KEY CLUSTERED
(
[EmployeeID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
@@ -128,7 +128,7 @@ INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('658-41-8532', 'Twanna', 'Evans', 35364)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('943-41-6011', 'Carolyn', 'Farino', 76201)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('691-30-8623', 'Geri', 'Farrell', 39600)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('361-08-3217', 'François', 'Ferrier', 3704)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('361-08-3217', 'Franois', 'Ferrier', 3704)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('827-51-1487', 'Kathie', 'Flood', 78467)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('483-93-0057', 'John', 'Ford', 77552)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('738-37-1607', 'Garth', 'Fort', 34381)
@@ -232,7 +232,7 @@ INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('321-14-1319', 'Scott', 'MacDonald', 30158)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('340-75-5874', 'Kathy', 'Marcovecchio', 10228)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('043-85-0648', 'Melissa', 'Marple', 46100)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('253-33-7509', 'Frank', 'Mart¡nez', 46267)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('253-33-7509', 'Frank', 'Martnez', 46267)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('335-68-4629', 'Chris', 'Maxwell', 92921)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('535-30-6577', 'Sandra', 'Maynard', 60264)
INSERT INTO [dbo].[Employees] ([SSN], [FirstName], [LastName], [Salary]) VALUES ('613-34-9127', 'Walter', 'Mays', 70620)
@@ -9,7 +9,7 @@ param projectName string
param userObjectId string
@description('The username of the user running the deployment.')
param userName string
param userName string
@description('The username of the Azure SQL database server administrator for SQL authentication.')
param sqlAdminUserName string
@@ -18,7 +18,7 @@ param sqlAdminUserName string
param sqlAdminPassword string
@description('The IP address the user will connect from to the logical server in Azure SQL Database.')
param clientIP string
param clientIP string
@description('The location (the Azure region) for all resources.')
param location string = resourceGroup().location
@@ -86,7 +86,7 @@ resource Database_Resource 'Microsoft.Sql/servers/databases@2022-05-01-preview'
tags: {}
sku: {
name: 'GP_Gen5_2'
tier: 'GeneralPurpose'
tier: 'GeneralPurpose'
}
properties: {
//preferredEnclaveType: 'VBS'
@@ -97,7 +97,7 @@ resource Database_Resource 'Microsoft.Sql/servers/databases@2022-05-01-preview'
// Configure the web application //
///////////////////////////////////
// Create an App Service plan
// Create an App Service plan
resource WebAppServicePlan_Resource 'Microsoft.Web/serverfarms@2022-03-01' = {
name: '${projectName}plan'
location: location
@@ -115,9 +115,9 @@ resource WebApp_Resource 'Microsoft.Web/sites@2022-03-01' = {
type: 'SystemAssigned'
}
properties: {
serverFarmId: WebAppServicePlan_Resource.id
serverFarmId: WebAppServicePlan_Resource.id
}
//Set the database connection string for the application
resource WebAppConnectionString_Resource 'config' = {
name: 'connectionstrings'
@@ -127,7 +127,7 @@ resource WebApp_Resource 'Microsoft.Web/sites@2022-03-01' = {
type: 'SQLAzure'
}
}
}
}
//Define AppSetting to fetch the correct project from the GitHub Repository
resource AppSetting 'config' = {
name: 'appsettings'
@@ -148,7 +148,7 @@ resource sourceControl 'Microsoft.Web/sites/sourcecontrols@2022-03-01' = {
dependsOn: [
Server_Name_resource
]
}
}
//////////////////////////////////////
// Create and configure a key vault //
@@ -187,7 +187,7 @@ resource KeyVault_Resource 'Microsoft.KeyVault/vaults@2022-07-01' = {
}
}
// Assign key permissions to the web app
// Assign key permissions to the web app
resource KeyVaultWebAppAccessPolicy_Resource 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
name: any('${KeyVault_Resource.name}/add')
properties: {
@@ -1,5 +1,5 @@
Import-Module "Az" -MinimumVersion "9.3"
Import-Module "SqlServer" -Version "22.0.49-preview"
Import-Module "SqlServer" -Version "22.0.49-preview"
######################################################################
# Prompt the user to enter the values of deployment parameters
@@ -102,7 +102,7 @@ Invoke-Sqlcmd -ServerInstance "tcp:$serverName" -Database $databaseName -AccessT
# Get the column master key from Azure Key Vault
$keyVaultName = "${projectName}vault"
$keyName = "CMK"
$key = Get-AzKeyVaultKey -VaultName $keyVaultName -Name $keyName
$key = Get-AzKeyVaultKey -VaultName $keyVaultName -Name $keyName
# Connect to the database using the SqlServer PowerShell module
$connStr = "Data Source=tcp:$serverName;Initial Catalog=$databaseName;User ID=$sqlAdminUserName;Password=$sqlAdminPassword"
@@ -133,7 +133,7 @@ Set-SqlColumnEncryption -ColumnEncryptionSettings $encryptedColumnSettings -Inpu
# Print parameters for the demo
######################################################################
$app = Get-AzWebApp -Name $appName -ResourceGroupName $resourceGroupName
$app = Get-AzWebApp -Name $appName -ResourceGroupName $resourceGroupName
Write-Host -ForegroundColor "green" "Resource group name: $resourceGroupName"
Write-Host -ForegroundColor "green" "Database server name: $serverName"
Write-Host -ForegroundColor "green" "Database name: $databaseName"
@@ -6,7 +6,7 @@ ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, AL
GO
ALTER TABLE [dbo].[Employees]
ALTER COLUMN [Salary] [Money]
ALTER COLUMN [Salary] [Money]
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL;
GO
@@ -6,7 +6,7 @@ GO
DECLARE @SSNPattern CHAR(11) = '%9838'
SELECT * FROM [dbo].[Employees] WHERE [SSN] LIKE @SSNPattern;
GO
GO
DECLARE @MinSalary MONEY = 40000
DECLARE @MaxSalary MONEY = 45000
@@ -2,31 +2,31 @@ DECLARE @ExtendedEventsSessionName sysname = N'Demo';
DECLARE @StartTime datetimeoffset;
DECLARE @EndTime datetimeoffset;
DECLARE @Offset int;
DROP TABLE IF EXISTS #xmlResults;
CREATE TABLE #xmlResults
(
xeTimeStamp datetimeoffset NOT NULL
, xeXML XML NOT NULL
);
SET @StartTime = DATEADD(HOUR, -4, GETDATE()); --modify this to suit your needs
SET @EndTime = GETDATE();
SET @Offset = DATEDIFF(MINUTE, GETDATE(), GETUTCDATE());
SET @StartTime = DATEADD(MINUTE, @Offset, @StartTime);
SET @EndTime = DATEADD(MINUTE, @Offset, @EndTime);
DECLARE @target_data xml;
SELECT @target_data = CONVERT(xml, target_data)
FROM sys.dm_xe_database_sessions AS s
JOIN sys.dm_xe_database_session_targets AS t
FROM sys.dm_xe_database_sessions AS s
JOIN sys.dm_xe_database_session_targets AS t
ON t.event_session_address = s.address
WHERE s.name = @ExtendedEventsSessionName
AND t.target_name = N'ring_buffer';
;WITH src AS
;WITH src AS
(
SELECT xeXML = xm.s.query('.')
FROM @target_data.nodes('/RingBufferTarget/event') AS xm(s)
@@ -37,7 +37,7 @@
@Html.DisplayFor(model => model.Employee.Salary)
</dd>
</dl>
<form method="post">
<input type="hidden" asp-for="Employee.EmployeeId" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
@@ -28,7 +28,7 @@ namespace ContosoHR
public void ConfigureServices(IServiceCollection services)
{
string s = Configuration.GetConnectionString("ContosoHRDatabase");
services.AddDbContext<ContosoHRContext>(options =>
services.AddDbContext<ContosoHRContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ContosoHRDatabase")));
services.AddControllers();
services.AddRazorPages();
@@ -72,7 +72,7 @@ namespace ContosoHR
// If the application uses a managed identity to talk to Azure SQL Database, use the managed identity for Azure Key Vault too.
tokenCredential = new ManagedIdentityCredential();
}
else {
else {
// Assume a managed identity is not available to the app. Instead, use a client id/secret to authenticate to Azure Key Vault.
// Fetch client id, secret, tenant id from the configuration.
// It is recommended you specify these parameters in secrets.json.
@@ -155,7 +155,7 @@ DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, bu
};
// IE9 throws an 'unknown error' if document.activeElement is used
// inside an iframe or frame.
// inside an iframe or frame.
var activeEl;
try {
@@ -157,7 +157,7 @@ DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, bu
};
// IE9 throws an 'unknown error' if document.activeElement is used
// inside an iframe or frame.
// inside an iframe or frame.
var activeEl;
try {
@@ -166,7 +166,7 @@ DataTable.ext.renderer.pageButton.material = function ( settings, host, idx, but
};
// IE9 throws an 'unknown error' if document.activeElement is used
// inside an iframe or frame.
// inside an iframe or frame.
var activeEl;
try {
@@ -166,7 +166,7 @@ DataTable.ext.renderer.pageButton.semanticUI = function ( settings, host, idx, b
};
// IE9 throws an 'unknown error' if document.activeElement is used
// inside an iframe or frame.
// inside an iframe or frame.
var activeEl;
try {
@@ -149,7 +149,7 @@ DataTable.ext.renderer.pageButton.uikit = function ( settings, host, idx, button
};
// IE9 throws an 'unknown error' if document.activeElement is used
// inside an iframe or frame.
// inside an iframe or frame.
var activeEl;
try {
@@ -11,7 +11,7 @@
// AMD. Register as an anonymous module.
define("jquery.validate.unobtrusive", ['jquery-validation'], factory);
} else if (typeof module === 'object' && module.exports) {
// CommonJS-like environments that support module.exports
// CommonJS-like environments that support module.exports
module.exports = factory(require('jquery-validation'));
} else {
// Browser global
@@ -142,12 +142,12 @@ Perform the below steps before you show the demo.
1. Click **OK** to close the statement window.
1. As a Security Administrator, provision a column master key for Always Encrypted.
1. In Object Explorer of the Security Administrator's instance of SSMS, expand the node of the **ContosoHR** database and navigate to **Security/ Always Encrypted Keys/Column Master Keys**.
1. In Object Explorer of the Security Administrator's instance of SSMS, expand the node of the **ContosoHR** database and navigate to **Security/ Always Encrypted Keys/Column Master Keys**.
1. Right-click on the **Column Master Keys** folder and select **New Column Master Key…**.
![NewCMK](img/new-cmk.png)
1. Enter a column master key name: **CMK1**.
1. Select **Windows Certificate Store - Current User**.
1. Make sure **Allow enclave computations** is selected.
1. Make sure **Allow enclave computations** is selected.
![NewCMK](img/new-cmk-dialog.png)
1. Click **Generate Certificate** to create a new certificate to be used as a column master key.
1. Click **OK**.
@@ -159,7 +159,7 @@ Perform the below steps before you show the demo.
1. Click **OK**.
1. As a Security Administrator, encrypt the **SSN** and **Salary** columns in place, using the secure enclave.
1. In Security Administrator's instance of SSMS, select the **EncryptColumns.sql** tab and click **F5** to execute the query.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
![Encrypted results](./img/ssms-encrypted-results.png)
@@ -168,7 +168,7 @@ Perform the below steps before you show the demo.
1. Inspect the queries the demo application sends to the database, after encrypting the columns.
1. In DBA's instance of SSMS, select the **Demo Live Data** window, which should contain a table with some events your demo application triggered.
1. Double click on the statement column in the last row of the table to see the last query the application sent to the database. Inspect the query statement. Note that the query statement the query sends to the database has not changed - it still contains pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column, as well as sorting (the **ORDER BY** clause) by **SSN** or **Salary**.
1. Double click on the statement column in the last row of the table to see the last query the application sent to the database. Inspect the query statement. Note that the query statement the query sends to the database has not changed - it still contains pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column, as well as sorting (the **ORDER BY** clause) by **SSN** or **Salary**.
1. Locate the value of query parameters: **@SSNSearchPattern**, **@MinSalary**, **@MaxSalary**. Note that the values of the parameters are now encrypted the client driver inside the web app transparently encrypts parameters corresponding to encrypted columns, before sending the query to the database. Not only does not the DBA have access to sensitive data in the database, but the DBA cannot see the plaintext values of query parameters used to process that data either.
![XEventSessionColumnsAfterEncryption](img/xevent-after-encryption.png)
@@ -185,6 +185,6 @@ The unique benefit of Always Encrypted with secure enclaves is that it allows yo
In Security Administrator's instance of SSMS:
1. Open and execute **tsql-scripts/DecryptColumns.sql**.
1. Open and execute **tsql-scripts/DropKeys.sql**.
1. Open and execute **tsql-scripts/DecryptColumns.sql**.
1. Open and execute **tsql-scripts/DropKeys.sql**.
1. Close both SSMS windows.
@@ -1,11 +1,11 @@
CREATE EVENT SESSION [Demo] ON SERVER
CREATE EVENT SESSION [Demo] ON SERVER
ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
ACTION(sqlserver.sql_text)
WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%SSN%') AND [sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'ContosoHR') AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection')))
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=2 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
ALTER EVENT SESSION [Demo]
ON SERVER
STATE = start;
ALTER EVENT SESSION [Demo]
ON SERVER
STATE = start;
GO
@@ -6,7 +6,7 @@ ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, AL
GO
ALTER TABLE [dbo].[Employees]
ALTER COLUMN [Salary] [Money]
ALTER COLUMN [Salary] [Money]
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL;
GO
@@ -6,7 +6,7 @@ GO
DECLARE @SSNPattern CHAR(11) = '%9838'
SELECT * FROM [dbo].[Employees] WHERE [SSN] LIKE @SSNPattern;
GO
GO
DECLARE @MinSalary MONEY = 40000
DECLARE @MaxSalary MONEY = 45000
@@ -42,7 +42,7 @@ This section describes the initial setup steps.
1. Start Visual Studio and open the **ContosoHR** solution file located in **../source**.
1. Using Solution Explorer, locate and open the **appsettings.json** file under the **ContosoHR** project.
1. Look for the line that contains the database connection string for the web application. The line should look like this:
```json
```json
"ContosoHRDatabase": "Server=tcp:<yourservername>.database.windows.net;Database=ContosoHR;Column Encryption Setting=Enabled; Attestation Protocol = AAS; Enclave Attestation Url=<yourattestationurl>; Authentication=Active Directory Managed Identity"
```
replace it with
@@ -141,12 +141,12 @@ Perform the below steps before you show the demo.
1. Click **OK** to close the statement window.
1. As a Security Administrator, provision a column master key for Always Encrypted.
1. In Object Explorer of the Security Administrator's instance of SSMS, expand the node of the **ContosoHR** database and navigate to **Security/ Always Encrypted Keys/Column Master Keys**.
1. In Object Explorer of the Security Administrator's instance of SSMS, expand the node of the **ContosoHR** database and navigate to **Security/ Always Encrypted Keys/Column Master Keys**.
1. Right-click on the **Column Master Keys** folder and select **New Column Master Key…**.
![NewCMK](img/new-cmk.png)
1. Enter a column master key name: **CMK1**.
1. Select **Windows Certificate Store - Current User**.
1. Make sure **Allow enclave computations** is selected.
1. Make sure **Allow enclave computations** is selected.
![NewCMK](img/new-cmk-dialog.png)
1. Click **Generate Certificate** to create a new certificate to be used as a column master key.
1. Click **OK**.
@@ -158,7 +158,7 @@ Perform the below steps before you show the demo.
1. Click **OK**.
1. As a Security Administrator, encrypt the **SSN** and **Salary** columns in place, using the secure enclave.
1. In Security Administrator's instance of SSMS, select the **EncryptColumns.sql** tab and click **F5** to execute the query.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
1. Switch back to DBA's instance of SSMS, select the **ListAllEmployees.sql** tab and click **F5** to execute the query again. Now the query should show the encrypted data in the **SSN** and **Salary** columns. As both columns are encrypted, the DBA cannot see the data in plaintext.
![Encrypted results](./img/ssms-encrypted-results.png)
@@ -167,7 +167,7 @@ Perform the below steps before you show the demo.
1. Inspect the queries the demo application sends to the database, after encrypting the columns.
1. In DBA's instance of SSMS, select the **Demo Live Data** window, which should contain a table with some events your demo application triggered.
1. Double click on the statement column in the last row of the table to see the last query the application sent to the database. Inspect the query statement. Note that the query statement the query sends to the database has not changed - it still contains pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column, as well as sorting (the **ORDER BY** clause) by **SSN** or **Salary**.
1. Double click on the statement column in the last row of the table to see the last query the application sent to the database. Inspect the query statement. Note that the query statement the query sends to the database has not changed - it still contains pattern matching using the **LIKE** predicate on the **SSN** column and the range comparison on the **Salary** column, as well as sorting (the **ORDER BY** clause) by **SSN** or **Salary**.
1. Locate the value of query parameters: **@SSNSearchPattern**, **@MinSalary**, **@MaxSalary**. Note that the values of the parameters are now encrypted the client driver inside the web app transparently encrypts parameters corresponding to encrypted columns, before sending the query to the database. Not only does not the DBA have access to sensitive data in the database, but the DBA cannot see the plaintext values of query parameters used to process that data either.
![XEventSessionColumnsAfterEncryption](img/xevent-after-encryption.png)
@@ -184,6 +184,6 @@ The unique benefit of Always Encrypted with secure enclaves is that it allows yo
In Security Administrator's instance of SSMS:
1. Open and execute **tsql-scripts/DecryptColumns.sql**.
1. Open and execute **tsql-scripts/DropKeys.sql**.
1. Open and execute **tsql-scripts/DecryptColumns.sql**.
1. Open and execute **tsql-scripts/DropKeys.sql**.
1. Close both SSMS windows.
@@ -1,11 +1,11 @@
CREATE EVENT SESSION [Demo] ON SERVER
CREATE EVENT SESSION [Demo] ON SERVER
ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
ACTION(sqlserver.sql_text)
WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%SSN%') AND [sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'ContosoHR') AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection')))
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=2 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
ALTER EVENT SESSION [Demo]
ON SERVER
STATE = start;
ALTER EVENT SESSION [Demo]
ON SERVER
STATE = start;
GO
@@ -6,7 +6,7 @@ ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, AL
GO
ALTER TABLE [dbo].[Employees]
ALTER COLUMN [Salary] [Money]
ALTER COLUMN [Salary] [Money]
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL;
GO
@@ -6,7 +6,7 @@ GO
DECLARE @SSNPattern CHAR(11) = '%9838'
SELECT * FROM [dbo].[Employees] WHERE [SSN] LIKE @SSNPattern;
GO
GO
DECLARE @MinSalary MONEY = 40000
DECLARE @MaxSalary MONEY = 45000
@@ -40,7 +40,7 @@ namespace ContosoClinic
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
@@ -81,7 +81,7 @@ namespace ContosoClinic
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
@@ -29,12 +29,12 @@ namespace ContosoClinic
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
@@ -9,8 +9,8 @@
padding-right: 15px;
}
/* Override the default bootstrap behavior where horizontal description lists
will truncate terms that are too long to fit in the left column
/* Override the default bootstrap behavior where horizontal description lists
will truncate terms that are too long to fit in the left column
*/
.dl-horizontal dt {
white-space: normal;
@@ -34,9 +34,9 @@ namespace ContosoClinic.Controllers
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
private set
{
_signInManager = value;
}
}
@@ -116,9 +116,9 @@ namespace ContosoClinic.Controllers
return View(model);
}
// The following code protects for brute force attacks against the two factor codes.
// If a user enters incorrect codes for a specified amount of time then the user account
// will be locked out for a specified amount of time.
// The following code protects for brute force attacks against the two factor codes.
// If a user enters incorrect codes for a specified amount of time then the user account
// will be locked out for a specified amount of time.
// You can configure the account lockout settings in IdentityConfig
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
switch (result)
@@ -156,7 +156,7 @@ namespace ContosoClinic.Controllers
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
@@ -32,9 +32,9 @@ namespace ContosoClinic.Controllers
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
private set
{
_signInManager = value;
}
}
@@ -21,8 +21,8 @@ namespace ContosoClinic.Controllers
select p;
if (!String.IsNullOrEmpty(searchString))
{
patients = patients.Where(s => s.FirstName.Contains(searchString)
|| s.LastName.Contains(searchString)
patients = patients.Where(s => s.FirstName.Contains(searchString)
|| s.LastName.Contains(searchString)
|| s.SSN.Contains(searchString));
}
if (maxAgeString != null)
@@ -56,7 +56,7 @@ namespace ContosoClinic.Controllers
}
// POST: Patients/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -88,7 +88,7 @@ namespace ContosoClinic.Controllers
}
// POST: Patients/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -44,7 +44,7 @@ namespace ContosoClinic.Controllers
}
// POST: Visits/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -78,7 +78,7 @@ namespace ContosoClinic.Controllers
}
// POST: Visits/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Initial : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Initial));
string IMigrationMetadata.Id
{
get { return "201602170540262_Initial"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Initial : DbMigration
{
public override void Up()
@@ -23,7 +23,7 @@ namespace ContosoClinic.Migrations
BirthDate = c.DateTime(nullable: false, storeType: "date"),
})
.PrimaryKey(t => t.PatientID);
CreateTable(
"dbo.AspNetRoles",
c => new
@@ -33,7 +33,7 @@ namespace ContosoClinic.Migrations
})
.PrimaryKey(t => t.Id)
.Index(t => t.Name, unique: true, name: "RoleNameIndex");
CreateTable(
"dbo.AspNetUserRoles",
c => new
@@ -46,7 +46,7 @@ namespace ContosoClinic.Migrations
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId)
.Index(t => t.RoleId);
CreateTable(
"dbo.AspNetUsers",
c => new
@@ -66,7 +66,7 @@ namespace ContosoClinic.Migrations
})
.PrimaryKey(t => t.Id)
.Index(t => t.UserName, unique: true, name: "UserNameIndex");
CreateTable(
"dbo.AspNetUserClaims",
c => new
@@ -79,7 +79,7 @@ namespace ContosoClinic.Migrations
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId);
CreateTable(
"dbo.AspNetUserLogins",
c => new
@@ -91,9 +91,9 @@ namespace ContosoClinic.Migrations
.PrimaryKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId })
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId);
}
public override void Down()
{
DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers");
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Visits : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Visits));
string IMigrationMetadata.Id
{
get { return "201602170605457_Visits"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Visits : DbMigration
{
public override void Up()
@@ -21,9 +21,9 @@ namespace ContosoClinic.Migrations
.PrimaryKey(t => t.VisitID)
.ForeignKey("dbo.Patients", t => t.PatientID, cascadeDelete: true)
.Index(t => t.PatientID);
}
public override void Down()
{
DropForeignKey("dbo.Visits", "PatientID", "dbo.Patients");
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Nullability : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Nullability));
string IMigrationMetadata.Id
{
get { return "201602170720063_Nullability"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Nullability : DbMigration
{
public override void Up()
@@ -16,7 +16,7 @@ namespace ContosoClinic.Migrations
AlterColumn("dbo.Visits", "Reason", c => c.String(nullable: false, maxLength: 4000));
AlterColumn("dbo.Visits", "Treatment", c => c.String(nullable: false, maxLength: 4000));
}
public override void Down()
{
AlterColumn("dbo.Visits", "Treatment", c => c.String(maxLength: 4000));
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Assignments : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Assignments));
string IMigrationMetadata.Id
{
get { return "201602170857179_Assignments"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Assignments : DbMigration
{
public override void Up()
@@ -19,9 +19,9 @@ namespace ContosoClinic.Migrations
.ForeignKey("dbo.Patients", t => t.Patient_PatientID, cascadeDelete: true)
.Index(t => t.ApplicationUser_Id)
.Index(t => t.Patient_PatientID);
}
public override void Down()
{
DropForeignKey("dbo.ApplicationUserPatients", "Patient_PatientID", "dbo.Patients");
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -151,7 +151,7 @@ namespace ContosoClinic.Migrations
new Patient { SSN = "658-41-8532", FirstName = "Twanna", LastName = "Evans", MiddleName = "R.", StreetAddress = "Lewis County Mall", City = "Chehalis", ZipCode = "98532", State = "WA", BirthDate = new System.DateTime(1968, 11, 4) },
new Patient { SSN = "943-41-6011", FirstName = "Carolyn", LastName = "Farino", MiddleName = "", StreetAddress = "3250 South Meridian", City = "Puyallup", ZipCode = "98371", State = "WA", BirthDate = new System.DateTime(1950, 2, 12) },
new Patient { SSN = "691-30-8623", FirstName = "Geri", LastName = "Farrell", MiddleName = "P.", StreetAddress = "49925 Crestview Drive N.E.", City = "Rio Rancho", ZipCode = "87124", State = "NM", BirthDate = new System.DateTime(1962, 8, 11) },
new Patient { SSN = "361-08-3217", FirstName = "François", LastName = "Ferrier", MiddleName = "", StreetAddress = "Eastridge Mall", City = "Casper", ZipCode = "82601", State = "WY", BirthDate = new System.DateTime(1957, 6, 14) },
new Patient { SSN = "361-08-3217", FirstName = "Franois", LastName = "Ferrier", MiddleName = "", StreetAddress = "Eastridge Mall", City = "Casper", ZipCode = "82601", State = "WY", BirthDate = new System.DateTime(1957, 6, 14) },
new Patient { SSN = "827-51-1487", FirstName = "Kathie", LastName = "Flood", MiddleName = "", StreetAddress = "705 SE Mall Parkway", City = "Everett", ZipCode = "98201", State = "WA", BirthDate = new System.DateTime(1978, 2, 8) },
new Patient { SSN = "483-93-0057", FirstName = "John", LastName = "Ford", MiddleName = "", StreetAddress = "23025 S.W. Military Rd.", City = "San Antonio", ZipCode = "78204", State = "TX", BirthDate = new System.DateTime(1987, 9, 16) },
new Patient { SSN = "738-37-1607", FirstName = "Garth", LastName = "Fort", MiddleName = "", StreetAddress = "3250 Baldwin Park Blvd", City = "Baldwin Park", ZipCode = "91706", State = "CA", BirthDate = new System.DateTime(1964, 11, 25) },
@@ -255,7 +255,7 @@ namespace ContosoClinic.Migrations
new Patient { SSN = "321-14-1319", FirstName = "Scott", LastName = "MacDonald", MiddleName = "", StreetAddress = "St. Louis Marketplace", City = "Saint Louis", ZipCode = "63103", State = "MS", BirthDate = new System.DateTime(1984, 11, 12) },
new Patient { SSN = "340-75-5874", FirstName = "Kathy", LastName = "Marcovecchio", MiddleName = "R.", StreetAddress = "9905 Three Rivers Drive", City = "Kelso", ZipCode = "98626", State = "WA", BirthDate = new System.DateTime(1994, 4, 3) },
new Patient { SSN = "043-85-0648", FirstName = "Melissa", LastName = "Marple", MiddleName = "R.", StreetAddress = "603 Gellert Blvd", City = "Daly City", ZipCode = "94015", State = "CA", BirthDate = new System.DateTime(1956, 9, 26) },
new Patient { SSN = "253-33-7509", FirstName = "Frank", LastName = "Mart¡nez", MiddleName = "", StreetAddress = "870 N. 54th Ave.", City = "Chandler", ZipCode = "85225", State = "AZ", BirthDate = new System.DateTime(2003, 9, 2) },
new Patient { SSN = "253-33-7509", FirstName = "Frank", LastName = "Martnez", MiddleName = "", StreetAddress = "870 N. 54th Ave.", City = "Chandler", ZipCode = "85225", State = "AZ", BirthDate = new System.DateTime(2003, 9, 2) },
new Patient { SSN = "335-68-4629", FirstName = "Chris", LastName = "Maxwell", MiddleName = "", StreetAddress = "3025 E Waterway Blvd", City = "Shelton", ZipCode = "98584", State = "WA", BirthDate = new System.DateTime(2013, 3, 16) },
new Patient { SSN = "535-30-6577", FirstName = "Sandra", LastName = "Maynard", MiddleName = "B.", StreetAddress = "9952 E. Lohman Ave.", City = "Las Cruces", ZipCode = "88001", State = "NM", BirthDate = new System.DateTime(1971, 6, 20) },
new Patient { SSN = "613-34-9127", FirstName = "Walter", LastName = "Mays", MiddleName = "J.", StreetAddress = "Po Box 252525", City = "Santa Ana", ZipCode = "92701", State = "CA", BirthDate = new System.DateTime(1974, 2, 5) },
@@ -318,8 +318,8 @@ namespace ContosoClinic.Migrations
new Visit { PatientID = 1, Date = new System.DateTime(2016, 1, 10), Reason = "Headache", Treatment = "A nap" },
new Visit { PatientID = 1, Date = new System.DateTime(2016, 1, 10), Reason = "Worse headache", Treatment = "A longer nap" }
);
// Create test userts
var manager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(
@@ -49,7 +49,7 @@ $.extend($.fn, {
}
validator = new $.validator( options, this[0] );
$.data(this[0], 'validator', validator);
$.data(this[0], 'validator', validator);
if ( validator.settings.onsubmit ) {
@@ -233,7 +233,7 @@ $.validator.format = function(source, params) {
/// </param>
/// <returns type="String" />
if ( arguments.length == 1 )
if ( arguments.length == 1 )
return function() {
var args = $.makeArray(arguments);
args.unshift(source);
@@ -395,7 +395,7 @@ $.extend($.validator, {
for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
this.check( elements[i] );
}
return this.valid();
return this.valid();
},
// http://docs.jquery.com/Plugins/Validation/Validator/element
@@ -997,7 +997,7 @@ $.extend($.validator, {
// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
addMethod: function(name, method, message) {
/// <summary>
/// Add a custom validation method. It must consist of a name (must be a legal javascript
/// Add a custom validation method. It must consist of a name (must be a legal javascript
/// identifier), a javascript based function and a default string message.
/// </summary>
/// <param name="name" type="String">
@@ -1008,8 +1008,8 @@ $.extend($.validator, {
/// The actual method implementation, returning true if an element is valid
/// </param>
/// <param name="message" type="String" optional="true">
/// (Optional) The default message to display for this method. Can be a function created by
/// jQuery.validator.format(value). When undefined, an already existing message is used
/// (Optional) The default message to display for this method. Can be a function created by
/// jQuery.validator.format(value). When undefined, an already existing message is used
/// (handy for localization), otherwise the field-specific messages have to be defined.
/// </param>
@@ -1051,7 +1051,7 @@ $.extend($.validator, {
previous.originalMessage = this.settings.messages[element.name].remote;
this.settings.messages[element.name].remote = previous.message;
param = typeof param == "string" && {url:param} || param;
param = typeof param == "string" && {url:param} || param;
if ( this.pending[element.name] ) {
return "pending";
@@ -1135,7 +1135,7 @@ $.extend($.validator, {
// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
},
// http://docs.jquery.com/Plugins/Validation/Methods/date
date: function(value, element) {
return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
@@ -1187,7 +1187,7 @@ $.extend($.validator, {
// http://docs.jquery.com/Plugins/Validation/Methods/accept
accept: function(value, element, param) {
param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
},
// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
@@ -1211,7 +1211,7 @@ $.format = $.validator.format;
// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
;(function($) {
var pendingRequests = {};
// Use a prefilter if available (1.5+)
@@ -1246,7 +1246,7 @@ $.format = $.validator.format;
// IE has native support, in other browsers, use event caputuring (neither bubbles)
// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
;(function($) {
// only implement if not provided by jQuery core (since 1.4)
// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
@@ -1,30 +1,30 @@
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
window.matchMedia = window.matchMedia || (function(doc, undefined){
var bool,
docElem = doc.documentElement,
refNode = docElem.firstElementChild || docElem.firstChild,
// fakeBody required for <FF4 when executed in <head>
fakeBody = doc.createElement('body'),
div = doc.createElement('div');
div.id = 'mq-test-1';
div.style.cssText = "position:absolute;top:-100em";
fakeBody.style.background = "none";
fakeBody.appendChild(div);
return function(q){
div.innerHTML = '&shy;<style media="'+q+'"> #mq-test-1 { width: 42px; }</style>';
docElem.insertBefore(fakeBody, refNode);
bool = div.offsetWidth == 42;
bool = div.offsetWidth == 42;
docElem.removeChild(fakeBody);
return { matches: bool, media: q };
};
})(document);
@@ -149,11 +149,11 @@ window.matchMedia = window.matchMedia || (function(doc, undefined){
for( ; j < eql; j++ ){
thisq = eachq[ j ];
mediastyles.push( {
mediastyles.push( {
media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
rules : rules.length - 1,
hasquery: thisq.indexOf("(") > -1,
minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
} );
}
@@ -199,7 +199,7 @@ window.matchMedia = window.matchMedia || (function(doc, undefined){
return ret;
},
//cached container for 1em value, populated the first time it's needed
//cached container for 1em value, populated the first time it's needed
eminpx,
//enable/disable styles
@@ -264,13 +264,13 @@ window.matchMedia = window.matchMedia || (function(doc, undefined){
//this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
head.insertBefore( ss, lastLink.nextSibling );
if ( ss.styleSheet ){
if ( ss.styleSheet ){
ss.styleSheet.cssText = css;
}
}
else {
ss.appendChild( doc.createTextNode( css ) );
}
//push to appendedEls to track for later removal
appendedEls.push( ss );
}
@@ -293,7 +293,7 @@ window.matchMedia = window.matchMedia || (function(doc, undefined){
}
req.send( null );
},
//define ajax obj
//define ajax obj
xmlHttp = (function() {
var xmlhttpmethod = false;
try {
@@ -30,13 +30,13 @@
</dd>
@*
Phone Numbers can used as a second factor of verification in a two-factor authentication system.
See <a href="http://go.microsoft.com/fwlink/?LinkId=403804">this article</a>
for details on setting up this ASP.NET application to support two-factor authentication using SMS.
Uncomment the following block after you have set up two-factor authentication
*@
@*
@*
<dt>Phone Number:</dt>
<dd>
@(Model.PhoneNumber ?? "None") [
@@ -7,10 +7,10 @@
<h2>Create</h2>
@using (Html.BeginForm())
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Patient</h4>
<hr />
@@ -10,7 +10,7 @@
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Patient</h4>
<hr />
@@ -7,10 +7,10 @@
<h2>Create</h2>
@using (Html.BeginForm())
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Visit</h4>
<hr />
@@ -10,7 +10,7 @@
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Visit</h4>
<hr />
@@ -5,7 +5,7 @@
-->
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="SqlColumnEncryptionEnclaveProviders" type="System.Data.SqlClient.SqlColumnEncryptionEnclaveProviderConfigurationSection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
@@ -1,10 +1,10 @@
CREATE EVENT SESSION [ClinicDemo] ON SERVER
CREATE EVENT SESSION [ClinicDemo] ON SERVER
ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1),collect_statement=(1)
WHERE ([sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'Clinic') AND [package0].[not_equal_unicode_string]([statement],N'exec sp_reset_connection')))
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=2 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
ALTER EVENT SESSION [ClinicDemo]
ON SERVER
STATE = start;
ALTER EVENT SESSION [ClinicDemo]
ON SERVER
STATE = start;
GO
@@ -5,7 +5,7 @@ DECLARE @SSNSuffix [CHAR](11) = '%38'
DECLARE @LastNamePettern [NVARCHAR](50) = 'A%'
DECLARE @MinBirthDate [DATETIME2](7) = '19900101'
DECLARE @MaxBirthDate [DATETIME2](7) = '20150101'
SELECT * FROM [dbo].[Patients]
SELECT * FROM [dbo].[Patients]
WHERE [SSN] LIKE @SSNSuffix
AND [LastName] LIKE @LastNamePettern
AND [BirthDate] >= @MinBirthDate AND [BirthDate] < @MaxBirthDate
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
</configuration>
@@ -49,7 +49,7 @@
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
@@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Integrated")]
@@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -25,11 +25,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
@@ -1,5 +1,5 @@
## Run this sample
Note: Run this project on a machine joined to a domain that is federated with Azure Active Directory. A contained database user representing your Azure AD principal, or one of the groups, you belong to, must exist in the database and must have the CONNECT permission.
Note: Run this project on a machine joined to a domain that is federated with Azure Active Directory. A contained database user representing your Azure AD principal, or one of the groups, you belong to, must exist in the database and must have the CONNECT permission.
1. Before building and running the Integrated project:
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
</configuration>
@@ -49,7 +49,7 @@
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
@@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Password")]
@@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -25,11 +25,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
@@ -12,7 +12,7 @@ string username = "bob@cqclinic.onmicrosoft.com"; // replace with your username
```
Note: A contained user database must exist and a contained database user representing the specified Azure AD user or one of the groups, the specified Azure AD user belongs to, must exist in the database and must have the CONNECT permission (except for AAD server admin or group)
Please note that
Please note that
builder["Authentication"] method is set to SqlAuthenticationMethod.ActiveDirectoryPassword.
![screenshot of visual studio showing builder fields to change] (/samples/features/security/azure-active-directory-auth/img/vs-authentication-method-password.png)
@@ -13,8 +13,8 @@
## About this sample
<!-- Delete the ones that don't apply -->
- **Applies to:** Azure SQL Database, Azure SQL Data Warehouse
- **Key features:** Azure Active Directory Authentication
- **Applies to:** Azure SQL Database, Azure SQL Data Warehouse
- **Key features:** Azure Active Directory Authentication
- **Programming Language:** C#
- **Authors:** Mirek Sztajno [mireks-msft]
@@ -33,24 +33,24 @@ To run this sample, you need the following prerequisites:
+ To install .Net Framework 4.6, see https://msdn.microsoft.com/library/5a4x27ek.aspx
2. Active Directory Authentication Library for SQL Server (ADALSQL.DLL)
+ ADALSQL.DLL enables applications to authenticate to Microsoft Azure SQL Database using Azure Active Directory. The ADALSQL.DLL is not installed with Visual Studio so download the DLL at http://www.microsoft.com/en-us/download/details.aspx?id=48742
+ ADALSQL.DLL is automatically downloaded with Visual Studio 2015 Update 2, SQL Server Management Studio, and the newest version of SQL Server Data tools
+ ADALSQL.DLL is automatically downloaded with Visual Studio 2015 Update 2, SQL Server Management Studio, and the newest version of SQL Server Data tools
1. Create Azure Active Directory (AD), or federate your domain with existing Azure AD
This allows either to use managed or federated accounts associated with a specific Azure AD
2. Create Azure AD administrator for Azure SQL DB using Azure portal, PowerShell command or Rest API
3. With help from T-SQL query interface (i.e. SSMS query editor), using Azure AD admin credentials for SQL DB & SQL DW, create an Azure AD user in a designated database. The database user represents your Azure AD principal (or one of the groups you belong to) and must exist in the database having CONNECT permission prior to executing a connection attempt
2. Create Azure AD administrator for Azure SQL DB using Azure portal, PowerShell command or Rest API
3. With help from T-SQL query interface (i.e. SSMS query editor), using Azure AD admin credentials for SQL DB & SQL DW, create an Azure AD user in a designated database. The database user represents your Azure AD principal (or one of the groups you belong to) and must exist in the database having CONNECT permission prior to executing a connection attempt
**Other Prerequisites**
**Other Prerequisites**
1. For Azure AD integrated authentication a computer joined to a domain that is federated with Azure Active Directory is required
2. An existing database created before a connection attempt is required. The database can be created using credentials for SQL administrator, or Azure AD SQL administrator
2. An existing database created before a connection attempt is required. The database can be created using credentials for SQL administrator, or Azure AD SQL administrator
<a name=run-this-sample></a>
## Run this sample
<!-- Place sample links here -->
<!-- Place sample links here -->
[Integrated Demo](integrated)
@@ -65,17 +65,17 @@ To run this sample, you need the following prerequisites:
This demo provides a simple tool for exploring Azure Active Directory authentication to Azure SQL DB or Azure SQL DW.
Azure Active Directory authentication with Azure SQL Database V12 supports the following authentication methods:
- User/password authentication
- Integrated authentication
- User/password authentication
- Integrated authentication
- Application token authentication
<a name=disclaimers></a>
## Disclaimers
The code included in this sample is only intended to provide a method to demonstrate sucessful authentication to Azure SQL Database or Azure SQL Data Warehouse via Azure Active Directory authentication methods.
The code included in this sample is only intended to provide a method to demonstrate sucessful authentication to Azure SQL Database or Azure SQL Data Warehouse via Azure Active Directory authentication methods.
<a name=related-links></a>
## Related Links
<!-- Links to more articles. Remember to delete "en-us" from the link path. -->
<!-- For more information, see these articles: -->
<!-- For more information, see these articles: -->
@@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Token")]
@@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -25,11 +25,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
@@ -8,17 +8,17 @@
## About this sample
The Token project contains a simple console application that connects to Azure SQL database using a self-signed certificate.
The Token project contains a simple console application that connects to Azure SQL database using a self-signed certificate.
**Software prerequisites:**
1. The `makecert.exe` utility, which is included in the Windows SDK
+ It is sometimes included in Visual Studio installations (depending on the selections made during installation). A search of your machine for `makecert.exe` would provide verification that the Windows SDK was installed.
1. The `makecert.exe` utility, which is included in the Windows SDK
+ It is sometimes included in Visual Studio installations (depending on the selections made during installation). A search of your machine for `makecert.exe` would provide verification that the Windows SDK was installed.
+ If the Windows SDK was not installed, you may [download it here](http://msdn.microsoft.com/en-US/windows/desktop/aa904949)
+ You can learn more about the `makecert.exe` [utility here](https://msdn.microsoft.com/library/windows/desktop/aa386968.aspx)
2. PowerShell with Azure Active Directory Module
+ To download the latest PowerShell version [see this page](https://azure.microsoft.com/en-us/documentation/articles/powershell-install-configure/#Install)
+ [Install the Azure AD PowerShell Module](https://msdn.microsoft.com/en-us/library/azure/jj151815.aspx), if it is not already installed in your client machine.
+ To download the latest PowerShell version [see this page](https://azure.microsoft.com/en-us/documentation/articles/powershell-install-configure/#Install)
+ [Install the Azure AD PowerShell Module](https://msdn.microsoft.com/en-us/library/azure/jj151815.aspx), if it is not already installed in your client machine.
<a name=run-this-sample></a>
## Run this sample
@@ -42,22 +42,22 @@ The Token project contains a simple console application that connects to Azure S
```
- [See this link](https://azure.microsoft.com/en-us/documentation/articles/sql-database-aad-authentication/) for more details on how to create an Azure Ad admin and a contained database user.
3. On the machine you are going to run the project on, generate and install a self-signed certificate.
- To complete this step, you will need to use `Makecert.exe`
3. On the machine you are going to run the project on, generate and install a self-signed certificate.
- To complete this step, you will need to use `Makecert.exe`
- Open a command prompt window
- Navigate to a folder where you want to generate a certificate file ( such as the folder where the demo files are) and change the following command for your environment
- Navigate to a folder where you want to generate a certificate file ( such as the folder where the demo files are) and change the following command for your environment
```
<Windows SDK Path>\makecert.exe -r -pe -n "CN=Cert_name" -ss My -len 2048 Cert_name.cer
```
for example, like so:
for example, like so:
```
c:/"Program Files (x86)/Windows Kits/8.1/bin/x64"/makecert -r -pe -n "CN=mytokentestCert" -ss My -len 2048 mytokentestCert.cer
```
4. Add the certificate as a key for the application you created in Azure AD.
- Click the Microsoft Azure Active Directory Module for Windows PowerShell shortcut on desktop to open a Windows PowerShell workspace that has the Azure AD cmdlets.
- Copy the following code snippet to a text editor.
- `connect-msolservice` will ask for you Azure AD credentials. Please be sure to use credentials that are part of Azure AD global admin to connect and to proceed with the scripts below.
```
4. Add the certificate as a key for the application you created in Azure AD.
- Click the Microsoft Azure Active Directory Module for Windows PowerShell shortcut on desktop to open a Windows PowerShell workspace that has the Azure AD cmdlets.
- Copy the following code snippet to a text editor.
- `connect-msolservice` will ask for you Azure AD credentials. Please be sure to use credentials that are part of Azure AD global admin to connect and to proceed with the scripts below.
```
connect-msolservice
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
@@ -66,19 +66,19 @@ The Token project contains a simple console application that connects to Azure S
$credValue = [System.Convert]::ToBase64String($binCert);
New-MsolServicePrincipalCredential -AppPrincipalId "<client id>" -Type asymmetric -Value $credValue -Usage verify
```
+ Replace <full path> with the path to your certificate and Cert_name with your Certificate name that you used in step 3 above.
+ Replace <client id> with the client ID you copied in step 1.
+ Copy and paste your snippet into the powershell window and run it.
+ Replace <full path> with the path to your certificate and Cert_name with your Certificate name that you used in step 3 above.
+ Replace <client id> with the client ID you copied in step 1.
+ Copy and paste your snippet into the powershell window and run it.
- The following command will verify that you added the certificate to your application's Active Directory Registration
``` Get-MsolServicePrincipalCredential ServicePrincipalName "URL"-ReturnKeyValues 0 ```
``` Get-MsolServicePrincipalCredential ServicePrincipalName "URL"-ReturnKeyValues 0 ```
5. Configure the certificate and your application account in the *app.config* file in the project.
5. Configure the certificate and your application account in the *app.config* file in the project.
+ In Visual Studio, open *app.config* in the Solution Explorer
![App.config file highlights](/samples/features/security/azure-active-directory-auth/img/app-config-key-value-example.png)
- Find the app key `ida:Tenant` and replace the value with your AAD tenant name (your AAD domain)
- Find the app key `ida:ClientID` and replace the value with the Client ID for the application registration from the Azure Portal (the value from step 1).
- Find the app key `ida:ClientID` and replace the value with the Client ID for the application registration from the Azure Portal (the value from step 1).
- Find the app key `ida:Cert_Name` and replace the value with the subject name (CN) of the self-signed certificate you created
- For example:
- For example:
```csharp
<add key="ida:Tenant" value="cqclinic.onmicrosoft.com" /> //this is the AAD domain
<add key="ida:ClientId" value="a4bbfe26-dbaa-4fec-8ef5-223d229f647d"/> //this is the Client ID
@@ -86,11 +86,11 @@ The Token project contains a simple console application that connects to Azure S
```
+ In Visual Studio, open *Program.cs* in the Solution Explorer
![Program.cs field highlights](/samples/features/security/azure-active-directory-auth/img/program-cs-builder-highlight.png)
- Make the following changes:
- Make the following changes:
```csharp
builder["Data Source"] = "aad-managed-demo.database.windows.net"; // replace with your server name
builder["Initial Catalog"] = "demo"; // replace with your database name
```
6. Run the demo. (Click *Run* or press *F5*)
+ A successful authorization should result in a message that states "Connected to the database" similar to the following:
+ A successful authorization should result in a message that states "Connected to the database" similar to the following:
![succesful auth](/samples/features/security/azure-active-directory-auth/img/token-press-any-key-to-stop.png)
@@ -63,7 +63,7 @@
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
@@ -3,5 +3,5 @@ src/packages/
src/ContosoClinic/obj
src/ContosoClinic/bin
src/ContosoClinicProject/ContosoClinic/Project_Readme.html
src/ContosoClinic/ContosoClinic.csproj.user
src/ContosoClinic/ContosoClinic.csproj.user
!src/ContosoClinic.sln
@@ -1,22 +1,22 @@
# Contoso Clinic Demo Application
# Contoso Clinic Demo Application
Sample application with database that showcases security features of SQL Server 2016.
Sample application with database that showcases security features of SQL Server 2016.
## About this sample
- **Applies to:** SQL Server 2016
- **Programming Language:** .NET C#, T-SQL
- **Authors:** Jakub Szymaszek [jaszymas-MSFT]
This project has adopted the [Microsoft Open Source Code of Conduct](http://microsoft.github.io/codeofconduct). For more information see the [Code of Conduct FAQ](http://microsoft.github.io/codeofconduct/faq.md) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
This project has adopted the [Microsoft Open Source Code of Conduct](http://microsoft.github.io/codeofconduct). For more information see the [Code of Conduct FAQ](http://microsoft.github.io/codeofconduct/faq.md) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Contents
1. [Prerequisites](#prerequisites)
2. [Setup](#setup)
1. [Prerequisites](#prerequisites)
2. [Setup](#setup)
* Set up the Demo Database
* Modify the Sample Application
4. [SQL 2016 Security Features in this demo](#sql-2016-security-features-in-this-demo)
* Always Encrypted
* Row Level Security
4. [SQL 2016 Security Features in this demo](#sql-2016-security-features-in-this-demo)
* Always Encrypted
* Row Level Security
* Dynamic Data Masking
5. [Application Notes](#application-notes)
@@ -24,8 +24,8 @@ This project has adopted the [Microsoft Open Source Code of Conduct](http://micr
## Prerequisites
1. Visual Studio 2015 (or newer)
2. [SQL Server 2016](https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2016)
3. [SQL Server Management Studio](https://msdn.microsoft.com/en-us/library/mt238290.aspx)
2. [SQL Server 2016](https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2016)
3. [SQL Server Management Studio](https://msdn.microsoft.com/en-us/library/mt238290.aspx)
## Setup
### Set up the Demo Database
@@ -34,21 +34,21 @@ This project has adopted the [Microsoft Open Source Code of Conduct](http://micr
+ In Object Explorer right-click on the server instance and select Properties. In the Security tab set Server authentication to SQL Server and Windows Authentication. Close the Properties window.
+ In Object Explorer right-click on the server instance and select Restart.
3. Import the *Clinic* database
+ In SSMS, right-click on *Databases* in Object Explorer and select *Import Data-tier Application...*.
+ Locate your copy of the bacpac file, located in the */setup* folder.
+ In SSMS, right-click on *Databases* in Object Explorer and select *Import Data-tier Application...*.
+ Locate your copy of the bacpac file, located in the */setup* folder.
![Import Data-tier Application Wizard](img/import-bacpac.png)
+ Complete the steps of the wizard.
+ Complete the steps of the wizard.
4. While connected to your database (master) via SSMS, execute [setup/Create-Application-Login.sql](setup/Create-Application-Login.sql) link.
+ Before running the script, create a password for the `ContosoClinicApplicaation` user.
+ This script creates a login and user, assigns `datareader` and `datawriter` permissions, and gives several Always Encrypted specific permissions to the `ContosoClinicApplication` user
+ Before running the script, create a password for the `ContosoClinicApplicaation` user.
+ This script creates a login and user, assigns `datareader` and `datawriter` permissions, and gives several Always Encrypted specific permissions to the `ContosoClinicApplication` user
### Modify and Set up the Sample Application Project
1. Start Visual Studio and open the Contoso Application solution file- located in /src.
2. Modify the connection string in the demo web app.
+ Using Solution Explorer, locate and open the web.config file under the ContosoClinic project.
1. Start Visual Studio and open the Contoso Application solution file- located in /src.
2. Modify the connection string in the demo web app.
+ Using Solution Explorer, locate and open the web.config file under the ContosoClinic project.
+ Look for the line that looks like this:
```csharp
```csharp
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=youserver;Initial Catalog=Clinic;
User ID=ContosoClinicApplication;Password=yourpassword" providerName="System.Data.SqlClient" />
@@ -57,37 +57,37 @@ This project has adopted the [Microsoft Open Source Code of Conduct](http://micr
-->
</connectionStrings>
```
+ Update the value of the *Data Source* key word in the database connection string to denote your server
+ Update the value of the *Data Source* key word in the database connection string to denote your server
+ Make sure the *password* for your application users is correct (matches the password that you configured earlier)
+ Make sure the *Initial Catalog* value is set to *Clinic*
+ Save the file
3. Make sure the .NET Framework 4.6.1 or higher is configured as the target .NET Framework for your project.
3. Make sure the .NET Framework 4.6.1 or higher is configured as the target .NET Framework for your project.
+ Right click on your project in Solution Explorer and select *Properties*
+ Verify the value of the Target framework property is correct (change it, if necessary)
+ Verify the value of the Target framework property is correct (change it, if necessary)
![Contoso Clinic Application Properties .Net Framework Version Setting](img/dot-net-framework-4-6.png)
4. Test the Demo Setup
+ Run the ContosoClinic application from Visual Studio (by hitting *F5* OR select *Debug* > *Start Debugging*). This will compile the solution and open the application in your default web browser.
+ Click on the *Patients* tab. You should see a list of patients.
+ Run the ContosoClinic application from Visual Studio (by hitting *F5* OR select *Debug* > *Start Debugging*). This will compile the solution and open the application in your default web browser.
+ Click on the *Patients* tab. You should see a list of patients.
![List of Patients on web app patients tab](img/list-of-patients.png)
+ Click *Edit* for one of the patients, change patient's SSN and click *Save*. The updated SSN should show up in the list of patients.
+ You are now ready to demo the security features described below.
+ Click *Edit* for one of the patients, change patient's SSN and click *Save*. The updated SSN should show up in the list of patients.
+ You are now ready to demo the security features described below.
## SQL 2016 Security Features in this Demo
### Always Encrypted
### Always Encrypted
#### Enable Always Encrypted
+ Connect to your database using SSMS:
+ Connect to your database using SSMS:
- For more information on using SSMS to connect to a Database, [click here](https://azure.microsoft.com/en-us/documentation/articles/sql-database-connect-query-ssms/)
+ Encrypt Sensitive Data Columns using the Column Encryption Wizard
+ Encrypt Sensitive Data Columns using the Column Encryption Wizard
- Right click on the **Patients** table in the **Clinic** database and select **Encrypt Columns...**
![Right Click patients table encrypt columns dropdown](img/right-click-patients-table-encrypt-columns.png)
![Right Click patients table encrypt columns dropdown](img/right-click-patients-table-encrypt-columns.png)
- The Column Encryption wizard will open. Click **Next**.
![Always Encrypted Wizard introduction page](img/always-encrypted-wizard-introduction-page.png)
- Select the **SSN** and **BirthDate** columns.
* Select **Deterministic Encryption** for **SSN** as the application needs to be able to search patients by SSN; Deterministic Encryption preserves that functionality for our app without leaving data exposed.
* Select **Randomized Encryption** for **BirthDate**
- Select the **SSN** and **BirthDate** columns.
* Select **Deterministic Encryption** for **SSN** as the application needs to be able to search patients by SSN; Deterministic Encryption preserves that functionality for our app without leaving data exposed.
* Select **Randomized Encryption** for **BirthDate**
![Always Encrypted Column Selection Page](img/column-selection-ssn-birthdate.png)
- Leave **CEK_Auto1 (New)** as the Key for both columns. Click **Next**.
- On the **Master Key Configuration** page, the Master Key Source should default to to **Windows Certificate Store**, with the **Master Key Source** defaulted to **Current User**. (This will store the key on your local machine.)
@@ -98,62 +98,62 @@ This project has adopted the [Microsoft Open Source Code of Conduct](http://micr
![Always Encrypted Summary Page](img/always-encrypted-summary.png)
- Monitor the progress of the wizard; once finished, click **Close**.
![Always Encrypted Results Success](img/always-encrypted-results.png)
+ View the data in SSMS (in SSMS use: `SELECT SSN, BirthDate FROM dbo.Patients` or `SELECT * FROM dbo.Patients` )
- Note that the data is now encrypted on the server for both the **SSN** and **BirthDate** columns.
+ View the data in SSMS (in SSMS use: `SELECT SSN, BirthDate FROM dbo.Patients` or `SELECT * FROM dbo.Patients` )
- Note that the data is now encrypted on the server for both the **SSN** and **BirthDate** columns.
+ Navigate to or refresh the /patients page
- Notice that the application now throws an exception.
- Notice that the application now throws an exception.
- This was expected as the application driver does not know how to handle the encrypted data.
- We designed this web app to have a type mismatch, but more flexible webpage design would expose the encrypted value.
+ Configure the web app to use Always Encrypted
- Stop the web app (close the window/ or click *Stop Debugging*)
- Using the Solution Explorer of Visual Studio, locate and open the web.config file under the ContosoClinic project.
- We designed this web app to have a type mismatch, but more flexible webpage design would expose the encrypted value.
+ Configure the web app to use Always Encrypted
- Stop the web app (close the window/ or click *Stop Debugging*)
- Using the Solution Explorer of Visual Studio, locate and open the web.config file under the ContosoClinic project.
- Look for the connection string, and add `Column Encryption Setting=Enabled` to the end of the connection string so that it reads like this:
```csharp
```csharp
<add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=Clinic;User
ID=ContosoClinicApplication;Password={Some Strong Password};Column Encryption Setting=Enabled"
providerName="System.Data.SqlClient" />
```
- Run the ContosoClinic application from Visual Studio (by hitting *F5* OR select *Debug* > *Start Debugging*)
- Click on the *Patients* tab. You should see a list of patients again.
- Click on the *Patients* tab. You should see a list of patients again.
#### How did that work?
#### How did that work?
##### Connection String
Our connection string for our application now contains `Column Encryption Setting=Enabled` which instructs the driver to automatically encrypt parameters targeting encrypted columns and decrypt any results retrieved from encrypted columns, without code changes. Don't forget this for your app if you intend to use Always Encrypted functonality. For more information this feature, [see our blog](https://blogs.msdn.microsoft.com/sqlsecurity/2016/07/11/always-encrypted-in-azure-sql-database-is-generally-available/).
Our connection string for our application now contains `Column Encryption Setting=Enabled` which instructs the driver to automatically encrypt parameters targeting encrypted columns and decrypt any results retrieved from encrypted columns, without code changes. Don't forget this for your app if you intend to use Always Encrypted functonality. For more information this feature, [see our blog](https://blogs.msdn.microsoft.com/sqlsecurity/2016/07/11/always-encrypted-in-azure-sql-database-is-generally-available/).
### Row Level Security (RLS)
### Row Level Security (RLS)
#### Login to the application
#### Login to the application
Sign in using (Rachel@contoso.com/Password!1) or (alice@contoso.com/Password!1)
#### Enable Row Level Security (RLS)
+ Connect to your database using SSMS:
#### Enable Row Level Security (RLS)
+ Connect to your database using SSMS:
[Instructions](https://azure.microsoft.com/en-us/documentation/articles/sql-database-connect-query-ssms/)
+ Open Enable-RLS.sql ( [Find it here](tsql-scripts/Enable-RLS.sql))
+ Execute the commands
+ Execute the commands
+ Observe the changes to the results returned on the /visits or /patients page
#### How did that work?
#### How did that work?
##### The application leverages an Entity Framework feature called **interceptors**
Specifically, we used a `DbConnectionInterceptor`. The `Opened()` function is called whenever Entity Framework opens a connection and we set SESSION_CONTEXT with the current application `UserId` there.
##### The application leverages an Entity Framework feature called **interceptors**
Specifically, we used a `DbConnectionInterceptor`. The `Opened()` function is called whenever Entity Framework opens a connection and we set SESSION_CONTEXT with the current application `UserId` there.
##### Predicate functions
The predicate functions we created in Enable-RLS.sql identify users by the `UserId` which was set by our interceptor whenever a connection is established from the application. The two types of predicates we created were **Filter** and **Block**.
+ **Filter** predicates silently filter `SELECT`, `UPDATE`, and `DELETE` operations to exclude rows that do not satisfy the predicate.
+ **Block** predicates explicitly block (throw errors) on `INSERT`, `UPDATE`, and `DELETE` operations that do not satisfy the predicate.
The predicate functions we created in Enable-RLS.sql identify users by the `UserId` which was set by our interceptor whenever a connection is established from the application. The two types of predicates we created were **Filter** and **Block**.
+ **Filter** predicates silently filter `SELECT`, `UPDATE`, and `DELETE` operations to exclude rows that do not satisfy the predicate.
+ **Block** predicates explicitly block (throw errors) on `INSERT`, `UPDATE`, and `DELETE` operations that do not satisfy the predicate.
### Dynamic Data Masking
#### Enable Dynamic Data Masking
+ Navigate to the /patients page
+ Connect to your deployed database using SSMS: [Instructions](https://azure.microsoft.com/en-us/documentation/articles/sql-database-connect-query-ssms/)
+ Open Enable-DDM.sql ([Find it here](tsql-scripts/Enable-DDM.sql))
+ Open Enable-DDM.sql ([Find it here](tsql-scripts/Enable-DDM.sql))
+ Execute the commands
+ Observe the changes in results returned on the /visits page
#### How did that work?
Dynamic data masking limits sensitive data exposure by masking the data according to policies defined on the database level while the data in the database remains unchanged; this is based on the database user's permissions. Those with the `UNMASK` permission will
have the ability to see the data without masks. In our case, the application's database login did not have the `UNMASK` permission and saw the data as masked. For your administrator login, the data was visible, as the user had the `UNMASK` permission. For more information on Dynamic Data Masking, [see the documentation](https://msdn.microsoft.com/en-us/library/mt130841.aspx).
#### How did that work?
Dynamic data masking limits sensitive data exposure by masking the data according to policies defined on the database level while the data in the database remains unchanged; this is based on the database user's permissions. Those with the `UNMASK` permission will
have the ability to see the data without masks. In our case, the application's database login did not have the `UNMASK` permission and saw the data as masked. For your administrator login, the data was visible, as the user had the `UNMASK` permission. For more information on Dynamic Data Masking, [see the documentation](https://msdn.microsoft.com/en-us/library/mt130841.aspx).
## Application Notes
The code included in this sample is only intended to provide a simple demo platform for users to enable and gain experience with SQL Server 2016 security features; the demo web app is not intended to hold sensitive data and should not be used as a reference for applications that use or store sensitive data. Please take adequate steps to securely develop your application and store your data.
The code included in this sample is only intended to provide a simple demo platform for users to enable and gain experience with SQL Server 2016 security features; the demo web app is not intended to hold sensitive data and should not be used as a reference for applications that use or store sensitive data. Please take adequate steps to securely develop your application and store your data.
@@ -4,9 +4,9 @@ go
CREATE LOGIN [ContosoClinicApplication] WITH PASSWORD = <enter a strong password here>
CREATE USER [ContosoClinicApplication] FOR LOGIN [ContosoClinicApplication]
EXEC sp_addrolemember N'db_datareader', N'ContosoClinicApplication'
EXEC sp_addrolemember N'db_datawriter', N'ContosoClinicApplication'
GRANT VIEW ANY COLUMN MASTER KEY DEFINITION TO [ContosoClinicApplication]
GRANT VIEW ANY COLUMN ENCRYPTION KEY DEFINITION TO [ContosoClinicApplication]
EXEC sp_addrolemember N'db_datareader', N'ContosoClinicApplication'
EXEC sp_addrolemember N'db_datawriter', N'ContosoClinicApplication'
GRANT VIEW ANY COLUMN MASTER KEY DEFINITION TO [ContosoClinicApplication]
GRANT VIEW ANY COLUMN ENCRYPTION KEY DEFINITION TO [ContosoClinicApplication]
@@ -40,7 +40,7 @@ namespace ContosoClinic
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
@@ -81,7 +81,7 @@ namespace ContosoClinic
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
@@ -29,12 +29,12 @@ namespace ContosoClinic
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
@@ -9,8 +9,8 @@
padding-right: 15px;
}
/* Override the default bootstrap behavior where horizontal description lists
will truncate terms that are too long to fit in the left column
/* Override the default bootstrap behavior where horizontal description lists
will truncate terms that are too long to fit in the left column
*/
.dl-horizontal dt {
white-space: normal;
@@ -34,9 +34,9 @@ namespace ContosoClinic.Controllers
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
private set
{
_signInManager = value;
}
}
@@ -116,9 +116,9 @@ namespace ContosoClinic.Controllers
return View(model);
}
// The following code protects for brute force attacks against the two factor codes.
// If a user enters incorrect codes for a specified amount of time then the user account
// will be locked out for a specified amount of time.
// The following code protects for brute force attacks against the two factor codes.
// If a user enters incorrect codes for a specified amount of time then the user account
// will be locked out for a specified amount of time.
// You can configure the account lockout settings in IdentityConfig
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
switch (result)
@@ -156,7 +156,7 @@ namespace ContosoClinic.Controllers
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
@@ -32,9 +32,9 @@ namespace ContosoClinic.Controllers
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
private set
{
_signInManager = value;
}
}
@@ -42,7 +42,7 @@ namespace ContosoClinic.Controllers
}
// POST: Patients/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -74,7 +74,7 @@ namespace ContosoClinic.Controllers
}
// POST: Patients/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -44,7 +44,7 @@ namespace ContosoClinic.Controllers
}
// POST: Visits/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -78,7 +78,7 @@ namespace ContosoClinic.Controllers
}
// POST: Visits/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Initial : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Initial));
string IMigrationMetadata.Id
{
get { return "201602170540262_Initial"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Initial : DbMigration
{
public override void Up()
@@ -23,7 +23,7 @@ namespace ContosoClinic.Migrations
BirthDate = c.DateTime(nullable: false, storeType: "date"),
})
.PrimaryKey(t => t.PatientID);
CreateTable(
"dbo.AspNetRoles",
c => new
@@ -33,7 +33,7 @@ namespace ContosoClinic.Migrations
})
.PrimaryKey(t => t.Id)
.Index(t => t.Name, unique: true, name: "RoleNameIndex");
CreateTable(
"dbo.AspNetUserRoles",
c => new
@@ -46,7 +46,7 @@ namespace ContosoClinic.Migrations
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId)
.Index(t => t.RoleId);
CreateTable(
"dbo.AspNetUsers",
c => new
@@ -66,7 +66,7 @@ namespace ContosoClinic.Migrations
})
.PrimaryKey(t => t.Id)
.Index(t => t.UserName, unique: true, name: "UserNameIndex");
CreateTable(
"dbo.AspNetUserClaims",
c => new
@@ -79,7 +79,7 @@ namespace ContosoClinic.Migrations
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId);
CreateTable(
"dbo.AspNetUserLogins",
c => new
@@ -91,9 +91,9 @@ namespace ContosoClinic.Migrations
.PrimaryKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId })
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId);
}
public override void Down()
{
DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers");
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Visits : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Visits));
string IMigrationMetadata.Id
{
get { return "201602170605457_Visits"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Visits : DbMigration
{
public override void Up()
@@ -21,9 +21,9 @@ namespace ContosoClinic.Migrations
.PrimaryKey(t => t.VisitID)
.ForeignKey("dbo.Patients", t => t.PatientID, cascadeDelete: true)
.Index(t => t.PatientID);
}
public override void Down()
{
DropForeignKey("dbo.Visits", "PatientID", "dbo.Patients");
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Nullability : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Nullability));
string IMigrationMetadata.Id
{
get { return "201602170720063_Nullability"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Nullability : DbMigration
{
public override void Up()
@@ -16,7 +16,7 @@ namespace ContosoClinic.Migrations
AlterColumn("dbo.Visits", "Reason", c => c.String(nullable: false, maxLength: 4000));
AlterColumn("dbo.Visits", "Treatment", c => c.String(nullable: false, maxLength: 4000));
}
public override void Down()
{
AlterColumn("dbo.Visits", "Treatment", c => c.String(maxLength: 4000));
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -5,22 +5,22 @@ namespace ContosoClinic.Migrations
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
public sealed partial class Assignments : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(Assignments));
string IMigrationMetadata.Id
{
get { return "201602170857179_Assignments"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
@@ -2,7 +2,7 @@ namespace ContosoClinic.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Assignments : DbMigration
{
public override void Up()
@@ -19,9 +19,9 @@ namespace ContosoClinic.Migrations
.ForeignKey("dbo.Patients", t => t.Patient_PatientID, cascadeDelete: true)
.Index(t => t.ApplicationUser_Id)
.Index(t => t.Patient_PatientID);
}
public override void Down()
{
DropForeignKey("dbo.ApplicationUserPatients", "Patient_PatientID", "dbo.Patients");
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -151,7 +151,7 @@ namespace ContosoClinic.Migrations
new Patient { SSN = "658-41-8532", FirstName = "Twanna", LastName = "Evans", MiddleName = "R.", StreetAddress = "Lewis County Mall", City = "Chehalis", ZipCode = "98532", State = "WA", BirthDate = new System.DateTime(1968, 11, 4) },
new Patient { SSN = "943-41-6011", FirstName = "Carolyn", LastName = "Farino", MiddleName = "", StreetAddress = "3250 South Meridian", City = "Puyallup", ZipCode = "98371", State = "WA", BirthDate = new System.DateTime(1950, 2, 12) },
new Patient { SSN = "691-30-8623", FirstName = "Geri", LastName = "Farrell", MiddleName = "P.", StreetAddress = "49925 Crestview Drive N.E.", City = "Rio Rancho", ZipCode = "87124", State = "NM", BirthDate = new System.DateTime(1962, 8, 11) },
new Patient { SSN = "361-08-3217", FirstName = "François", LastName = "Ferrier", MiddleName = "", StreetAddress = "Eastridge Mall", City = "Casper", ZipCode = "82601", State = "WY", BirthDate = new System.DateTime(1957, 6, 14) },
new Patient { SSN = "361-08-3217", FirstName = "Franois", LastName = "Ferrier", MiddleName = "", StreetAddress = "Eastridge Mall", City = "Casper", ZipCode = "82601", State = "WY", BirthDate = new System.DateTime(1957, 6, 14) },
new Patient { SSN = "827-51-1487", FirstName = "Kathie", LastName = "Flood", MiddleName = "", StreetAddress = "705 SE Mall Parkway", City = "Everett", ZipCode = "98201", State = "WA", BirthDate = new System.DateTime(1978, 2, 8) },
new Patient { SSN = "483-93-0057", FirstName = "John", LastName = "Ford", MiddleName = "", StreetAddress = "23025 S.W. Military Rd.", City = "San Antonio", ZipCode = "78204", State = "TX", BirthDate = new System.DateTime(1987, 9, 16) },
new Patient { SSN = "738-37-1607", FirstName = "Garth", LastName = "Fort", MiddleName = "", StreetAddress = "3250 Baldwin Park Blvd", City = "Baldwin Park", ZipCode = "91706", State = "CA", BirthDate = new System.DateTime(1964, 11, 25) },
@@ -255,7 +255,7 @@ namespace ContosoClinic.Migrations
new Patient { SSN = "321-14-1319", FirstName = "Scott", LastName = "MacDonald", MiddleName = "", StreetAddress = "St. Louis Marketplace", City = "Saint Louis", ZipCode = "63103", State = "MS", BirthDate = new System.DateTime(1984, 11, 12) },
new Patient { SSN = "340-75-5874", FirstName = "Kathy", LastName = "Marcovecchio", MiddleName = "R.", StreetAddress = "9905 Three Rivers Drive", City = "Kelso", ZipCode = "98626", State = "WA", BirthDate = new System.DateTime(1994, 4, 3) },
new Patient { SSN = "043-85-0648", FirstName = "Melissa", LastName = "Marple", MiddleName = "R.", StreetAddress = "603 Gellert Blvd", City = "Daly City", ZipCode = "94015", State = "CA", BirthDate = new System.DateTime(1956, 9, 26) },
new Patient { SSN = "253-33-7509", FirstName = "Frank", LastName = "Mart¡nez", MiddleName = "", StreetAddress = "870 N. 54th Ave.", City = "Chandler", ZipCode = "85225", State = "AZ", BirthDate = new System.DateTime(2003, 9, 2) },
new Patient { SSN = "253-33-7509", FirstName = "Frank", LastName = "Martnez", MiddleName = "", StreetAddress = "870 N. 54th Ave.", City = "Chandler", ZipCode = "85225", State = "AZ", BirthDate = new System.DateTime(2003, 9, 2) },
new Patient { SSN = "335-68-4629", FirstName = "Chris", LastName = "Maxwell", MiddleName = "", StreetAddress = "3025 E Waterway Blvd", City = "Shelton", ZipCode = "98584", State = "WA", BirthDate = new System.DateTime(2013, 3, 16) },
new Patient { SSN = "535-30-6577", FirstName = "Sandra", LastName = "Maynard", MiddleName = "B.", StreetAddress = "9952 E. Lohman Ave.", City = "Las Cruces", ZipCode = "88001", State = "NM", BirthDate = new System.DateTime(1971, 6, 20) },
new Patient { SSN = "613-34-9127", FirstName = "Walter", LastName = "Mays", MiddleName = "J.", StreetAddress = "Po Box 252525", City = "Santa Ana", ZipCode = "92701", State = "CA", BirthDate = new System.DateTime(1974, 2, 5) },
@@ -318,8 +318,8 @@ namespace ContosoClinic.Migrations
new Visit { PatientID = 1, Date = new System.DateTime(2016, 1, 10), Reason = "Headache", Treatment = "A nap" },
new Visit { PatientID = 1, Date = new System.DateTime(2016, 1, 10), Reason = "Worse headache", Treatment = "A longer nap" }
);
// Create test userts
var manager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(

Some files were not shown because too many files have changed in this diff Show More