├── .gitignore
├── .nuget
├── NuGet.Config
├── NuGet.exe
└── NuGet.targets
├── Devbridge.AzurePowerTools.sln
├── Devbridge.BackupDatabaseAzureStorage
├── App.config
├── Devbridge.BackupDatabaseAzureStorage.csproj
├── ExportFacade.cs
├── ImportExportHelper.cs
├── NLog.config
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Service References
│ └── DACWebService
│ │ ├── Devbridge.BackupDatabaseAzureStorage.DACWebService.StatusInfo.datasource
│ │ ├── Microsoft.SqlServer.Management.Dac.ServiceTypes.xsd
│ │ ├── Microsoft.SqlServer.Management.Dac.Services.wsdl
│ │ ├── Reference.cs
│ │ ├── Reference.svcmap
│ │ ├── configuration.svcinfo
│ │ ├── configuration91.svcinfo
│ │ ├── service.wsdl
│ │ ├── service.xsd
│ │ └── service1.xsd
└── packages.config
├── Devbridge.BackupDatabaseServer
├── App.config
├── Devbridge.BackupDatabaseServer.csproj
├── ExportFacade.cs
├── NLog.config
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Service References
│ └── DACWebService
│ │ ├── Devbridge.BackupDatabaseServer.DACWebService.StatusInfo.datasource
│ │ ├── Microsoft.SqlServer.Management.Dac.ServiceTypes.xsd
│ │ ├── Microsoft.SqlServer.Management.Dac.Services.wsdl
│ │ ├── Reference.cs
│ │ ├── Reference.svcmap
│ │ ├── configuration.svcinfo
│ │ ├── configuration91.svcinfo
│ │ ├── service.wsdl
│ │ ├── service.xsd
│ │ └── service1.xsd
├── packages.config
└── readme.txt
├── Devbridge.BasicAuthentication.Test
├── Config
│ └── basicAuthentication.config
├── Controllers
│ └── HomeController.cs
├── Devbridge.BasicAuthentication.Test.csproj
├── Global.asax
├── Global.asax.cs
├── Properties
│ └── AssemblyInfo.cs
├── Views
│ ├── Home
│ │ └── Index.cshtml
│ ├── Shared
│ │ ├── Error.cshtml
│ │ └── _Layout.cshtml
│ ├── Web.config
│ └── _ViewStart.cshtml
├── Web.Debug.config
├── Web.Release.config
├── Web.config
└── packages.config
├── Devbridge.BasicAuthentication
├── BasicAuthenticationModule.cs
├── Config
│ └── basicAuthentication.config
├── Configuration
│ ├── BasicAuthenticationConfigurationSection.cs
│ ├── CredentialElement.cs
│ ├── CredentialElementCollection.cs
│ ├── ExcludeElement.cs
│ └── ExcludeElementCollection.cs
├── Devbridge.BasicAuthentication.csproj
├── Devbridge.BasicAuthentication.nuspec
├── Properties
│ └── AssemblyInfo.cs
├── web.config.install.xdt
└── web.config.uninstall.xdt
├── PowerShell
└── PublishCloudService.ps1
├── README.md
├── SharedAssemblyInfo.cs
├── license.txt
└── packages
└── repositories.config
/.gitignore:
--------------------------------------------------------------------------------
1 | obj
2 | bin
3 | deploy
4 | deploy/*
5 | _ReSharper.*
6 | *.resharper
7 | *.suo
8 | *.cache
9 | ~$*
10 | *.user
11 |
12 | #Nuget
13 | packages/**
14 | !packages/repositories.config
15 | !packages.config
16 |
--------------------------------------------------------------------------------
/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devbridge/AzurePowerTools/eaf2e7d9189a09e2bb04c1da6407a9d70edd936e/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config"))
32 |
33 |
34 |
35 |
36 | $(SolutionDir).nuget
37 | packages.config
38 |
39 |
40 |
41 |
42 | $(NuGetToolsPath)\nuget.exe
43 | @(PackageSource)
44 |
45 | "$(NuGetExePath)"
46 | mono --runtime=v4.0.30319 $(NuGetExePath)
47 |
48 | $(TargetDir.Trim('\\'))
49 |
50 | -RequireConsent
51 |
52 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "
53 | $(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols
54 |
55 |
56 |
57 | RestorePackages;
58 | $(BuildDependsOn);
59 |
60 |
61 |
62 |
63 | $(BuildDependsOn);
64 | BuildPackage;
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
87 |
88 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/Devbridge.AzurePowerTools.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{743822B6-591F-46ED-88C6-BC4B236DEFE5}"
7 | ProjectSection(SolutionItems) = preProject
8 | SharedAssemblyInfo.cs = SharedAssemblyInfo.cs
9 | EndProjectSection
10 | EndProject
11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerShell", "PowerShell", "{B7FDCCA1-5E95-4F04-8515-FD9BB2DEDA98}"
12 | ProjectSection(SolutionItems) = preProject
13 | PowerShell\PublishCloudService.ps1 = PowerShell\PublishCloudService.ps1
14 | EndProjectSection
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{9D330DCB-F771-4959-A7C5-053D4FBC313B}"
17 | ProjectSection(SolutionItems) = preProject
18 | .nuget\NuGet.Config = .nuget\NuGet.Config
19 | .nuget\NuGet.exe = .nuget\NuGet.exe
20 | .nuget\NuGet.targets = .nuget\NuGet.targets
21 | EndProjectSection
22 | EndProject
23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devbridge.BasicAuthentication", "Devbridge.BasicAuthentication\Devbridge.BasicAuthentication.csproj", "{8B8D3FF3-9E4B-48D9-8BEF-52AB2651638A}"
24 | EndProject
25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devbridge.BasicAuthentication.Test", "Devbridge.BasicAuthentication.Test\Devbridge.BasicAuthentication.Test.csproj", "{11EBC198-765A-4017-9091-CCD5D934015A}"
26 | EndProject
27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devbridge.BackupDatabaseServer", "Devbridge.BackupDatabaseServer\Devbridge.BackupDatabaseServer.csproj", "{E27C9B4E-C2D9-41AD-AF13-2E02A82560FD}"
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devbridge.BackupDatabaseAzureStorage", "Devbridge.BackupDatabaseAzureStorage\Devbridge.BackupDatabaseAzureStorage.csproj", "{B3C134F6-E768-4C55-B11F-717214AC500D}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Release|Any CPU = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {8B8D3FF3-9E4B-48D9-8BEF-52AB2651638A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {8B8D3FF3-9E4B-48D9-8BEF-52AB2651638A}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {8B8D3FF3-9E4B-48D9-8BEF-52AB2651638A}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {8B8D3FF3-9E4B-48D9-8BEF-52AB2651638A}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {11EBC198-765A-4017-9091-CCD5D934015A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {11EBC198-765A-4017-9091-CCD5D934015A}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {11EBC198-765A-4017-9091-CCD5D934015A}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {11EBC198-765A-4017-9091-CCD5D934015A}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {E27C9B4E-C2D9-41AD-AF13-2E02A82560FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {E27C9B4E-C2D9-41AD-AF13-2E02A82560FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {E27C9B4E-C2D9-41AD-AF13-2E02A82560FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {E27C9B4E-C2D9-41AD-AF13-2E02A82560FD}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {B3C134F6-E768-4C55-B11F-717214AC500D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {B3C134F6-E768-4C55-B11F-717214AC500D}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {B3C134F6-E768-4C55-B11F-717214AC500D}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {B3C134F6-E768-4C55-B11F-717214AC500D}.Release|Any CPU.Build.0 = Release|Any CPU
53 | EndGlobalSection
54 | GlobalSection(SolutionProperties) = preSolution
55 | HideSolutionNode = FALSE
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | https://ch1prod-dacsvc.azure.com/DACWebService.svc
38 |
39 |
40 | Webtype
41 |
42 |
43 | https://{2}.blob.core.windows.net/{3}/{0}/{0}-{1:yyyy-MM-dd-hh-mm-ss-fff}.bacpac
44 |
45 |
46 | webtype
47 |
48 |
49 | databasebackups
50 |
51 |
52 | 3
53 |
54 |
55 | [StorageAccessKey]
56 |
57 |
58 | [Password]
59 |
60 |
61 |
62 |
64 | WebtypeLogs
65 | Webtype
66 |
67 |
68 |
69 |
70 | asadasdv.database.windows.net
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Devbridge.BackupDatabaseAzureStorage.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B3C134F6-E768-4C55-B11F-717214AC500D}
8 | Exe
9 | Properties
10 | Devbridge.BackupDatabaseAzureStorage
11 | Devbridge.BackupDatabaseAzureStorage
12 | v4.5
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 | ..\packages\Common.Logging.2.1.2\lib\net40\Common.Logging.dll
39 |
40 |
41 | ..\packages\Common.Logging.NLog.2.0.0\lib\2.0\Common.Logging.NLog.dll
42 |
43 |
44 | False
45 | ..\packages\Microsoft.Data.Edm.5.0.2\lib\net40\Microsoft.Data.Edm.dll
46 |
47 |
48 | False
49 | ..\packages\Microsoft.Data.OData.5.0.2\lib\net40\Microsoft.Data.OData.dll
50 |
51 |
52 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll
53 |
54 |
55 | ..\packages\WindowsAzure.Storage.2.0.3.0\lib\net40\Microsoft.WindowsAzure.Storage.dll
56 |
57 |
58 | ..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | False
67 | ..\packages\System.Spatial.5.0.2\lib\net40\System.Spatial.dll
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | True
83 | True
84 | Settings.settings
85 |
86 |
87 | True
88 | True
89 | Reference.svcmap
90 |
91 |
92 |
93 |
94 |
95 | PreserveNewest
96 |
97 |
98 |
99 | SettingsSingleFileGenerator
100 | Settings.Designer.cs
101 |
102 |
103 | Reference.svcmap
104 |
105 |
106 |
107 | Designer
108 |
109 |
110 |
111 | Designer
112 |
113 |
114 | Designer
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | WCF Proxy Generator
132 | Reference.cs
133 |
134 |
135 |
136 |
137 |
144 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/ExportFacade.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Common.Logging;
5 | using Devbridge.BackupDatabaseAzureStorage.Properties;
6 | using Microsoft.WindowsAzure.Storage;
7 | using Microsoft.WindowsAzure.Storage.Auth;
8 | using Microsoft.WindowsAzure.Storage.Blob;
9 |
10 | namespace Devbridge.BackupDatabaseAzureStorage
11 | {
12 | public class ExportFacade
13 | {
14 | private readonly ILog logger = LogManager.GetCurrentClassLogger();
15 |
16 | public void Export(string databaseName)
17 | {
18 | var ieHelper = new ImportExportHelper();
19 |
20 | //Set Inputs to the REST Requests in the helper class
21 | ieHelper.EndPointUri = Settings.Default.DACWebServiceUrl;
22 | ieHelper.ServerName = Settings.Default.DatabaseServerName;
23 | ieHelper.StorageKey = Settings.Default.StorageAccessKey;
24 | ieHelper.DatabaseName = databaseName;
25 | ieHelper.UserName = Settings.Default.DatabaseUserName;
26 | ieHelper.Password = Settings.Default.DatabaseUserPassword;
27 | }
28 |
29 | public void ExportDatabases(IList allDatabases)
30 | {
31 | foreach (var dbName in allDatabases)
32 | {
33 | logger.InfoFormat("Export of database '{0}' started", dbName);
34 | try
35 | {
36 | Export(dbName);
37 | logger.InfoFormat("Export of database '{0}' finished succesfully", dbName);
38 | }
39 | catch (Exception ex)
40 | {
41 | logger.ErrorFormat("Error occured while exporting database '{0}'", ex, dbName);
42 | }
43 | }
44 | }
45 |
46 | public void CleanupOlderBackups()
47 | {
48 | logger.Info("CleanupOlderBackups started");
49 | var storageAccount = new CloudStorageAccount(
50 | new StorageCredentials(Settings.Default.StorageName, Settings.Default.StorageAccessKey),
51 | true);
52 | var blobClient = storageAccount.CreateCloudBlobClient();
53 | var container = blobClient.GetContainerReference(Settings.Default.BackupsContainer);
54 | var filesToKeep = Settings.Default.BackupFilesToKeep;
55 | try
56 | {
57 | var databaseDirs = container.ListBlobs();
58 | foreach (var item in databaseDirs)
59 | {
60 | if (item.GetType() == typeof(CloudBlobDirectory))
61 | {
62 | var directory = (CloudBlobDirectory)item;
63 | var databaseBackups = directory.ListBlobs();
64 |
65 | var filesToDelete = databaseBackups.Where(b => b is CloudBlockBlob).Cast()
66 | .OrderByDescending(fi => fi.Properties.LastModified).Skip(filesToKeep);
67 |
68 | foreach (var fileToDelete in filesToDelete)
69 | {
70 | try
71 | {
72 | logger.InfoFormat("Deleting: {0}", fileToDelete.Name);
73 | fileToDelete.Delete();
74 | }
75 | catch (Exception ex)
76 | {
77 | logger.ErrorFormat("Error occured while deleting file '{0}'", ex, fileToDelete.Uri);
78 | }
79 | }
80 | }
81 | }
82 |
83 | //var backupDir = Settings.Default.BackupsDir;
84 | //var filesToKeep = Settings.Default.BackupFilesToKeep;
85 |
86 | //var dbSubfolders = Directory.GetDirectories(backupDir);
87 | //foreach (var dbDir in dbSubfolders)
88 | //{
89 | // var di = new DirectoryInfo(dbDir);
90 | // var backupFileInfos = di.GetFileSystemInfos("*." + BackupFileExtension);
91 | // if (backupFileInfos.Length > filesToKeep)
92 | // {
93 | // var filesToDelete = backupFileInfos.OrderByDescending(fi => fi.CreationTime).Skip(filesToKeep);
94 | // foreach (var fileToDelete in filesToDelete)
95 | // {
96 | // try
97 | // {
98 | // File.Delete(fileToDelete.FullName);
99 | // }
100 | // catch (Exception ex)
101 | // {
102 | // logger.ErrorFormat("Error occured while deleting file '{0}'", ex, fileToDelete.FullName);
103 | // }
104 | // }
105 | // }
106 | //}
107 |
108 | logger.Info("CleanupOlderBackups finished");
109 | }
110 | catch (Exception ex)
111 | {
112 | logger.Error("Error occured in CleanupOlderBackups", ex);
113 | throw;
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/ImportExportHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Runtime.Serialization;
7 | using System.Threading;
8 | using System.Web;
9 | using System.Xml;
10 | using Common.Logging;
11 | using Devbridge.BackupDatabaseAzureStorage.DACWebService;
12 |
13 | namespace Devbridge.BackupDatabaseAzureStorage
14 | {
15 | public class ImportExportHelper
16 | {
17 | private readonly ILog logger = LogManager.GetCurrentClassLogger();
18 |
19 | public string EndPointUri { get; set; }
20 | public string StorageKey { get; set; }
21 | public string BlobUri { get; set; }
22 | public string ServerName { get; set; }
23 | public string DatabaseName { get; set; }
24 | public string UserName { get; set; }
25 | public string Password { get; set; }
26 |
27 | public ImportExportHelper()
28 | {
29 | EndPointUri = "";
30 | ServerName = "";
31 | StorageKey = "";
32 | DatabaseName = "";
33 | UserName = "";
34 | Password = "";
35 | }
36 |
37 | public string DoExport(string blobUri)
38 | {
39 | logger.Info(String.Format("Starting Export Operation - {0}\n\r", DateTime.Now));
40 | string requestGuid = null;
41 | bool exportComplete = false;
42 | string exportedBlobPath = null;
43 |
44 | //Setup Web Request for Export Operation
45 | WebRequest webRequest = WebRequest.Create(this.EndPointUri + @"/Export");
46 | webRequest.Method = WebRequestMethods.Http.Post;
47 | webRequest.ContentType = @"application/xml";
48 |
49 | //Create Web Request Inputs - Blob Storage Credentials and Server Connection Info
50 | ExportInput exportInputs = new ExportInput
51 | {
52 | BlobCredentials = new BlobStorageAccessKeyCredentials
53 | {
54 | StorageAccessKey = this.StorageKey,
55 | Uri = String.Format(blobUri, this.DatabaseName, DateTime.UtcNow.Ticks.ToString())
56 | },
57 | ConnectionInfo = new ConnectionInfo
58 | {
59 | ServerName = this.ServerName,
60 | DatabaseName = this.DatabaseName,
61 | UserName = this.UserName,
62 | Password = this.Password
63 | }
64 | };
65 |
66 | //Perform Web Request
67 | logger.Info("Making Web Request For Export Operation...");
68 | Stream webRequestStream = webRequest.GetRequestStream();
69 | DataContractSerializer dataContractSerializer = new DataContractSerializer(exportInputs.GetType());
70 | dataContractSerializer.WriteObject(webRequestStream, exportInputs);
71 | webRequestStream.Close();
72 |
73 | //Get Response and Extract Request Identifier
74 | logger.Info("Reading Response and extracting Export Request Identifier...");
75 | WebResponse webResponse = null;
76 | XmlReader xmlStreamReader = null;
77 |
78 | try
79 | {
80 | //Initialize the WebResponse to the response from the WebRequest
81 | webResponse = webRequest.GetResponse();
82 |
83 | xmlStreamReader = XmlReader.Create(webResponse.GetResponseStream());
84 | xmlStreamReader.ReadToFollowing("guid");
85 | requestGuid = xmlStreamReader.ReadElementContentAsString();
86 | logger.Info(String.Format("Your Export Request Guid is: {0}", requestGuid));
87 |
88 | //Get Export Operation Status
89 | while (!exportComplete)
90 | {
91 | logger.Info("Checking export status...");
92 | List statusInfoList = CheckRequestStatus(requestGuid);
93 | StatusInfo statusInfo = statusInfoList.FirstOrDefault();
94 | logger.Info(statusInfo.Status);
95 |
96 | if (statusInfo.Status == "Failed")
97 | {
98 | logger.Info(String.Format("Database export failed: {0}", statusInfo.ErrorMessage));
99 | exportComplete = true;
100 | }
101 |
102 | if (statusInfo.Status == "Completed")
103 | {
104 | exportedBlobPath = statusInfo.BlobUri;
105 | logger.Info(String.Format("Export Complete - Database exported to: {0}\n\r", exportedBlobPath));
106 | exportComplete = true;
107 | }
108 |
109 | if (!exportComplete)
110 | {
111 | Thread.Sleep(3000);
112 | }
113 | }
114 |
115 | return exportedBlobPath;
116 | }
117 | catch (WebException responseException)
118 | {
119 | logger.ErrorFormat("Request Falied:{0}", responseException,responseException.Message);
120 | if (responseException.Response != null)
121 | {
122 | logger.ErrorFormat("Status Code: {0}", ((HttpWebResponse)responseException.Response).StatusCode);
123 | logger.ErrorFormat("Status Description: {0}\n\r", ((HttpWebResponse)responseException.Response).StatusDescription);
124 | }
125 | return null;
126 | }
127 | }
128 |
129 | public bool DoImport(string blobUri)
130 | {
131 | logger.Info(String.Format("Starting Import Operation - {0}\n\r", DateTime.Now));
132 | string requestGuid = null;
133 | bool importComplete = false;
134 |
135 | //Setup Web Request for Import Operation
136 | WebRequest webRequest = WebRequest.Create(this.EndPointUri + @"/Import");
137 | webRequest.Method = WebRequestMethods.Http.Post;
138 | webRequest.ContentType = @"application/xml";
139 |
140 | //Create Web Request Inputs - Database Size & Edition, Blob Store Credentials and Server Connection Info
141 | ImportInput importInputs = new ImportInput
142 | {
143 | AzureEdition = "Web",
144 | DatabaseSizeInGB = 1,
145 | BlobCredentials = new BlobStorageAccessKeyCredentials
146 | {
147 | StorageAccessKey = this.StorageKey,
148 | Uri = String.Format(blobUri, this.DatabaseName, DateTime.UtcNow.Ticks.ToString())
149 | },
150 | ConnectionInfo = new ConnectionInfo
151 | {
152 | ServerName = this.ServerName,
153 | DatabaseName = this.DatabaseName,
154 | UserName = this.UserName,
155 | Password = this.Password
156 | }
157 | };
158 |
159 | //Perform Web Request
160 | logger.Info("Making Web Request for Import Operation...");
161 | Stream webRequestStream = webRequest.GetRequestStream();
162 | DataContractSerializer dataContractSerializer = new DataContractSerializer(importInputs.GetType());
163 | dataContractSerializer.WriteObject(webRequestStream, importInputs);
164 | webRequestStream.Close();
165 |
166 | //Get Response and Extract Request Identifier
167 | logger.Info("Serializing response and extracting guid...");
168 | WebResponse webResponse = null;
169 | XmlReader xmlStreamReader = null;
170 |
171 | try
172 | {
173 | //Initialize the WebResponse to the response from the WebRequest
174 | webResponse = webRequest.GetResponse();
175 |
176 | xmlStreamReader = XmlReader.Create(webResponse.GetResponseStream());
177 | xmlStreamReader.ReadToFollowing("guid");
178 | requestGuid = xmlStreamReader.ReadElementContentAsString();
179 | logger.Info(String.Format("Request Guid: {0}", requestGuid));
180 |
181 | //Get Status of Import Operation
182 | while (!importComplete)
183 | {
184 | logger.Info("Checking status of Import...");
185 | List statusInfoList = CheckRequestStatus(requestGuid);
186 | StatusInfo statusInfo = statusInfoList.FirstOrDefault();
187 | logger.Info(statusInfo.Status);
188 |
189 | if (statusInfo.Status == "Failed")
190 | {
191 | logger.Info(String.Format("Database import failed: {0}", statusInfo.ErrorMessage));
192 | importComplete = true;
193 | }
194 |
195 | if (statusInfo.Status == "Completed")
196 | {
197 | logger.Info(String.Format("Import Complete - Database imported to: {0}\n\r", statusInfo.DatabaseName));
198 | importComplete = true;
199 | }
200 | }
201 |
202 | return importComplete;
203 | }
204 | catch (WebException responseException)
205 | {
206 | logger.ErrorFormat("Request Falied: {0}",responseException, responseException.Message);
207 | {
208 | logger.ErrorFormat("Status Code: {0}", ((HttpWebResponse)responseException.Response).StatusCode);
209 | logger.ErrorFormat("Status Description: {0}\n\r", ((HttpWebResponse)responseException.Response).StatusDescription);
210 | }
211 |
212 | return importComplete;
213 | }
214 | }
215 |
216 | public List CheckRequestStatus(string requestGuid)
217 | {
218 | WebRequest webRequest = WebRequest.Create(this.EndPointUri + string.Format("/Status?servername={0}&username={1}&password={2}&reqId={3}",
219 | HttpUtility.UrlEncode(this.ServerName),
220 | HttpUtility.UrlEncode(this.UserName),
221 | HttpUtility.UrlEncode(this.Password),
222 | HttpUtility.UrlEncode(requestGuid)));
223 |
224 | webRequest.Method = WebRequestMethods.Http.Get;
225 | webRequest.ContentType = @"application/xml";
226 | WebResponse webResponse = webRequest.GetResponse();
227 | XmlReader xmlStreamReader = XmlReader.Create(webResponse.GetResponseStream());
228 | DataContractSerializer dataContractSerializer = new DataContractSerializer(typeof(List));
229 |
230 | return (List)dataContractSerializer.ReadObject(xmlStreamReader, true);
231 | }
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/NLog.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Devbridge.BackupDatabaseAzureStorage.Properties;
3 |
4 | namespace Devbridge.BackupDatabaseAzureStorage
5 | {
6 | class Program
7 | {
8 | static void Main(string[] args)
9 | {
10 | var exportFacade = new ExportFacade();
11 | exportFacade.ExportDatabases(Settings.Default.BackupedDatabases.Cast().ToList());
12 | exportFacade.CleanupOlderBackups();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Devbridge.BackupDatabaseAzureStorage")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Devbridge.BackupDatabaseAzureStorage")]
13 | [assembly: AssemblyCopyright("Copyright © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("8aa70feb-fcb9-408e-bd0b-ccc22a926c12")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18034
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Devbridge.BackupDatabaseAzureStorage.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("https://ch1prod-dacsvc.azure.com/DACWebService.svc")]
29 | public string DACWebServiceUrl {
30 | get {
31 | return ((string)(this["DACWebServiceUrl"]));
32 | }
33 | }
34 |
35 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
36 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
37 | [global::System.Configuration.DefaultSettingValueAttribute("Webtype")]
38 | public string DatabaseUserName {
39 | get {
40 | return ((string)(this["DatabaseUserName"]));
41 | }
42 | }
43 |
44 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
45 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
46 | [global::System.Configuration.DefaultSettingValueAttribute("https://{2}.blob.core.windows.net/{3}/{0}/{0}-{1:yyyy-MM-dd-hh-mm-ss-fff}.bacpac")]
47 | public string ExportFileNameFormat {
48 | get {
49 | return ((string)(this["ExportFileNameFormat"]));
50 | }
51 | }
52 |
53 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
54 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
55 | [global::System.Configuration.DefaultSettingValueAttribute("webtype")]
56 | public string StorageName {
57 | get {
58 | return ((string)(this["StorageName"]));
59 | }
60 | }
61 |
62 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
64 | [global::System.Configuration.DefaultSettingValueAttribute("databasebackups")]
65 | public string BackupsContainer {
66 | get {
67 | return ((string)(this["BackupsContainer"]));
68 | }
69 | }
70 |
71 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
72 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
73 | [global::System.Configuration.DefaultSettingValueAttribute("3")]
74 | public int BackupFilesToKeep {
75 | get {
76 | return ((int)(this["BackupFilesToKeep"]));
77 | }
78 | }
79 |
80 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
81 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
82 | [global::System.Configuration.DefaultSettingValueAttribute("[StorageAccessKey]")]
83 | public string StorageAccessKey {
84 | get {
85 | return ((string)(this["StorageAccessKey"]));
86 | }
87 | }
88 |
89 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
90 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
91 | [global::System.Configuration.DefaultSettingValueAttribute("[Password]")]
92 | public string DatabaseUserPassword {
93 | get {
94 | return ((string)(this["DatabaseUserPassword"]));
95 | }
96 | }
97 |
98 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
100 | [global::System.Configuration.DefaultSettingValueAttribute("\r\n\r\n WebtypeLogs\r\n Webtype\r\n")]
103 | public global::System.Collections.Specialized.StringCollection BackupedDatabases {
104 | get {
105 | return ((global::System.Collections.Specialized.StringCollection)(this["BackupedDatabases"]));
106 | }
107 | }
108 |
109 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
110 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
111 | [global::System.Configuration.DefaultSettingValueAttribute("asadasdv.database.windows.net")]
112 | public string DatabaseServerName {
113 | get {
114 | return ((string)(this["DatabaseServerName"]));
115 | }
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | https://ch1prod-dacsvc.azure.com/DACWebService.svc
7 |
8 |
9 | Webtype
10 |
11 |
12 | https://{2}.blob.core.windows.net/{3}/{0}/{0}-{1:yyyy-MM-dd-hh-mm-ss-fff}.bacpac
13 |
14 |
15 | webtype
16 |
17 |
18 | databasebackups
19 |
20 |
21 | 3
22 |
23 |
24 | [StorageAccessKey]
25 |
26 |
27 | [Password]
28 |
29 |
30 | <?xml version="1.0" encoding="utf-16"?>
31 | <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
32 | <string>WebtypeLogs</string>
33 | <string>Webtype</string>
34 | </ArrayOfString>
35 |
36 |
37 | asadasdv.database.windows.net
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/Devbridge.BackupDatabaseAzureStorage.DACWebService.StatusInfo.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | Devbridge.BackupDatabaseAzureStorage.DACWebService.StatusInfo, Service References.DACWebService.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/Microsoft.SqlServer.Management.Dac.ServiceTypes.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/Microsoft.SqlServer.Management.Dac.Services.wsdl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/Reference.svcmap:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | true
6 | true
7 |
8 | false
9 | false
10 | false
11 |
12 |
13 | true
14 | Auto
15 | true
16 | true
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/configuration.svcinfo:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/configuration91.svcinfo:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/service.wsdl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/service.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/Service References/DACWebService/service1.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseAzureStorage/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | DatabaseBackups
29 |
30 |
31 | 14
32 |
33 |
34 | {0}_{1:yyyy-MM-dd_hh-mm-ss-fff}
35 |
36 |
37 |
38 |
39 | TestBackup
40 |
41 |
42 |
43 |
44 | Webtype
45 |
46 |
47 | tcp:sdasadasfg.database.windows.net
48 |
49 |
50 | [Password]
51 |
52 |
53 | DefaultEndpointsProtocol=https;AccountName=webtype;AccountKey=[ACCOUNTKEY]
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Devbridge.BackupDatabaseServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {E27C9B4E-C2D9-41AD-AF13-2E02A82560FD}
8 | Exe
9 | Properties
10 | Devbridge.BackupDatabaseServer
11 | Devbridge.BackupDatabaseServer
12 | v4.0
13 | 512
14 |
15 | ..\
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 | ..\packages\Common.Logging.2.1.2\lib\net40\Common.Logging.dll
40 |
41 |
42 | ..\packages\Common.Logging.NLog.2.0.0\lib\2.0\Common.Logging.NLog.dll
43 |
44 |
45 | False
46 | ..\packages\Microsoft.Data.Edm.5.0.2\lib\net40\Microsoft.Data.Edm.dll
47 |
48 |
49 | False
50 | ..\packages\Microsoft.Data.OData.5.0.2\lib\net40\Microsoft.Data.OData.dll
51 |
52 |
53 | ..\packages\Microsoft.SqlServer.Dac.1.0.1\lib\Microsoft.Data.Tools.Schema.Sql.dll
54 | True
55 |
56 |
57 | ..\packages\Microsoft.SqlServer.Dac.1.0.1\lib\Microsoft.Data.Tools.Utilities.dll
58 | True
59 |
60 |
61 | ..\packages\Microsoft.SqlServer.Dac.1.0.1\lib\Microsoft.SqlServer.Dac.dll
62 | True
63 |
64 |
65 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll
66 |
67 |
68 | ..\packages\WindowsAzure.Storage.2.0.3.0\lib\net40\Microsoft.WindowsAzure.Storage.dll
69 |
70 |
71 | ..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | False
80 | ..\packages\System.Spatial.5.0.2\lib\net40\System.Spatial.dll
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | True
94 | True
95 | Settings.settings
96 |
97 |
98 | True
99 | True
100 | Reference.svcmap
101 |
102 |
103 |
104 |
105 | Designer
106 |
107 |
108 | PreserveNewest
109 |
110 |
111 |
112 | SettingsSingleFileGenerator
113 | Settings.Designer.cs
114 |
115 |
116 | Reference.svcmap
117 |
118 |
119 |
120 | Designer
121 |
122 |
123 |
124 | Designer
125 |
126 |
127 | Designer
128 |
129 |
130 |
131 |
132 |
133 | WCF Proxy Generator
134 | Reference.cs
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
154 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/ExportFacade.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using Common.Logging;
10 | using Devbridge.BackupDatabaseServer.Properties;
11 | using Microsoft.SqlServer.Dac;
12 |
13 | namespace Devbridge.BackupDatabaseServer
14 | {
15 | public class ExportFacade
16 | {
17 | private SqlConnection connection;
18 | private string connectionString;
19 | private readonly ILog logger = LogManager.GetCurrentClassLogger();
20 | private const string BackupFileExtension = "bacpac";
21 |
22 | public ExportFacade(string connectionString)
23 | {
24 | this.connectionString = connectionString;
25 | this.connection = new SqlConnection(connectionString);
26 | }
27 |
28 | public void Export(string databaseName, string targetFilename)
29 | {
30 | DacServices dacServices = new DacServices(connectionString);
31 |
32 | dacServices.ExportBacpac(targetFilename, databaseName);
33 | }
34 |
35 | public void ExportAllDatabases()
36 | {
37 | logger.Info("ExportAllDatabases started");
38 | try
39 | {
40 | IList allDatabases = null;
41 | OpenConnection();
42 | try
43 | {
44 | allDatabases = GetServerDatabases();
45 | }
46 | finally
47 | {
48 | CloseConnection();
49 | }
50 |
51 | allDatabases = allDatabases.Where(db => db == "TestBackup").ToList();
52 |
53 | ExportDatabases(allDatabases);
54 |
55 | logger.Info("ExportAllDatabases finished");
56 | }
57 | catch (Exception ex)
58 | {
59 | logger.Error("Error occured in ExportAllDatabases", ex);
60 | throw ex;
61 | }
62 | }
63 |
64 | public void ExportDatabases(IList allDatabases)
65 | {
66 | foreach (var dbName in allDatabases)
67 | {
68 | string backupDir = Path.Combine(Settings.Default.BackupsDir, dbName);
69 | if (!Directory.Exists(backupDir))
70 | {
71 | Directory.CreateDirectory(backupDir);
72 | }
73 |
74 | string fileName = Path.Combine(backupDir, string.Format(Settings.Default.FileNameFormat, dbName, DateTime.Now) + "." + BackupFileExtension);
75 |
76 | logger.InfoFormat("Export of database '{0}' started", dbName);
77 | try
78 | {
79 | Export(dbName, fileName);
80 | logger.InfoFormat("Export of database '{0}' finished succesfully", dbName);
81 | }
82 | catch (Exception ex)
83 | {
84 | logger.ErrorFormat("Error occured while exporting database '{0}'", ex, dbName);
85 | }
86 | }
87 | }
88 |
89 | public void CleanupOlderBackups()
90 | {
91 | logger.Info("CleanupOlderBackups started");
92 | try
93 | {
94 | var backupDir = Settings.Default.BackupsDir;
95 | var filesToKeep = Settings.Default.BackupFilesToKeep;
96 |
97 | var dbSubfolders = Directory.GetDirectories(backupDir);
98 | foreach (var dbDir in dbSubfolders)
99 | {
100 | var di = new DirectoryInfo(dbDir);
101 | var backupFileInfos = di.GetFileSystemInfos("*." + BackupFileExtension);
102 | if (backupFileInfos.Length > filesToKeep)
103 | {
104 | var filesToDelete = backupFileInfos.OrderByDescending(fi => fi.CreationTime).Skip(filesToKeep);
105 | foreach (var fileToDelete in filesToDelete)
106 | {
107 | try
108 | {
109 | File.Delete(fileToDelete.FullName);
110 | }
111 | catch (Exception ex)
112 | {
113 | logger.ErrorFormat("Error occured while deleting file '{0}'", ex, fileToDelete.FullName);
114 | }
115 | }
116 | }
117 | }
118 |
119 | logger.Info("CleanupOlderBackups finished");
120 | }
121 | catch (Exception ex)
122 | {
123 | logger.Error("Error occured in CleanupOlderBackups", ex);
124 | throw ex;
125 | }
126 | }
127 |
128 | private void OpenConnection()
129 | {
130 | this.connection.Open();
131 | }
132 |
133 | private void CloseConnection()
134 | {
135 | this.connection.Close();
136 | }
137 |
138 | private IList GetServerDatabases()
139 | {
140 | SqlDataAdapter adapter = new SqlDataAdapter("select name from sys.databases where state_desc='ONLINE' and name<>'master'", connection);
141 |
142 | DataTable dt = new DataTable();
143 | adapter.Fill(dt);
144 |
145 | return dt.AsEnumerable().Select(row => row[0] as string).ToList();
146 | }
147 |
148 | private void BackupDatabase(string sourceDatabaseName, string targetDatabaseName)
149 | {
150 | SqlCommand backupCommand = new SqlCommand("CREATE DATABASE @targetDB AS COPY OF @sourceDB", connection);
151 | backupCommand.Parameters.AddWithValue("@sourceDB", sourceDatabaseName);
152 | backupCommand.Parameters.AddWithValue("@targetDB", targetDatabaseName);
153 | backupCommand.ExecuteNonQuery();
154 | }
155 |
156 |
157 | //public bool CheckIfBackupDatabaseFinishedSuccessfully(string databaseName)
158 | //{
159 | // SqlCommand backupCommand = new SqlCommand("SELECT state_desc FROM sys.databases WHERE name = @db", connection);
160 | // backupCommand.Parameters.AddWithValue("@db", databaseName);
161 | // backupCommand.ExecuteNonQuery();
162 | //}
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/NLog.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Devbridge.BackupDatabaseServer.Properties;
7 |
8 | namespace Devbridge.BackupDatabaseServer
9 | {
10 | class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 | var exportFacade = new ExportFacade(Settings.Default.ConnectionString);
15 | if (Settings.Default.BackupedDatabases != null && Settings.Default.BackupedDatabases.Count > 0)
16 | {
17 | exportFacade.ExportDatabases(Settings.Default.BackupedDatabases.Cast().ToList());
18 | }
19 | else
20 | {
21 | exportFacade.ExportAllDatabases();
22 | }
23 |
24 | exportFacade.CleanupOlderBackups();
25 |
26 |
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Devbridge.BackupDatabaseServer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Devbridge.BackupDatabaseServer")]
13 | [assembly: AssemblyCopyright("Copyright © 2012")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7885c6bb-e66f-456f-b6b6-e4507d101cb9")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18034
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Devbridge.BackupDatabaseServer.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("DatabaseBackups")]
29 | public string BackupsDir {
30 | get {
31 | return ((string)(this["BackupsDir"]));
32 | }
33 | }
34 |
35 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
36 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
37 | [global::System.Configuration.DefaultSettingValueAttribute("14")]
38 | public int BackupFilesToKeep {
39 | get {
40 | return ((int)(this["BackupFilesToKeep"]));
41 | }
42 | }
43 |
44 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
45 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
46 | [global::System.Configuration.DefaultSettingValueAttribute("{0}_{1:yyyy-MM-dd_hh-mm-ss-fff}")]
47 | public string FileNameFormat {
48 | get {
49 | return ((string)(this["FileNameFormat"]));
50 | }
51 | }
52 |
53 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
54 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
55 | [global::System.Configuration.DefaultSettingValueAttribute("\r\n\r\n TestBackup\r\n")]
58 | public global::System.Collections.Specialized.StringCollection BackupedDatabases {
59 | get {
60 | return ((global::System.Collections.Specialized.StringCollection)(this["BackupedDatabases"]));
61 | }
62 | }
63 |
64 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
65 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
66 | [global::System.Configuration.DefaultSettingValueAttribute("Webtype")]
67 | public string BlobDBUserName {
68 | get {
69 | return ((string)(this["BlobDBUserName"]));
70 | }
71 | }
72 |
73 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
74 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
75 | [global::System.Configuration.DefaultSettingValueAttribute("tcp:sdasadasfg.database.windows.net")]
76 | public string BlobDBServerName {
77 | get {
78 | return ((string)(this["BlobDBServerName"]));
79 | }
80 | }
81 |
82 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
83 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
84 | [global::System.Configuration.DefaultSettingValueAttribute("[Password]")]
85 | public string BlogDBUserPsw {
86 | get {
87 | return ((string)(this["BlogDBUserPsw"]));
88 | }
89 | }
90 |
91 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
92 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
93 | [global::System.Configuration.DefaultSettingValueAttribute("DefaultEndpointsProtocol=https;AccountName=webtype;AccountKey=[ACCOUNTKEY]")]
94 | public string BlobConnectionString {
95 | get {
96 | return ((string)(this["BlobConnectionString"]));
97 | }
98 | }
99 |
100 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
101 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
102 | [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
103 | [global::System.Configuration.DefaultSettingValueAttribute("Data Source=tcp:asdasdasd.database.windows.net,1433;Integrated Security=False;Use" +
104 | "r ID=[UserId];Password=[Password];Connect Timeout=15;Encrypt=False;TrustServerCe" +
105 | "rtificate=False")]
106 | public string ConnectionString {
107 | get {
108 | return ((string)(this["ConnectionString"]));
109 | }
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | DatabaseBackups
7 |
8 |
9 | 14
10 |
11 |
12 | {0}_{1:yyyy-MM-dd_hh-mm-ss-fff}
13 |
14 |
15 | <?xml version="1.0" encoding="utf-16"?>
16 | <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
17 | <string>TestBackup</string>
18 | </ArrayOfString>
19 |
20 |
21 | Webtype
22 |
23 |
24 | tcp:sdasadasfg.database.windows.net
25 |
26 |
27 | [Password]
28 |
29 |
30 | DefaultEndpointsProtocol=https;AccountName=webtype;AccountKey=[ACCOUNTKEY]
31 |
32 |
33 | <?xml version="1.0" encoding="utf-16"?>
34 | <SerializableConnectionString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
35 | <ConnectionString>Data Source=tcp:asdasdasd.database.windows.net,1433;Integrated Security=False;User ID=[UserId];Password=[Password];Connect Timeout=15;Encrypt=False;TrustServerCertificate=False</ConnectionString>
36 | </SerializableConnectionString>
37 | Data Source=tcp:asdasdasd.database.windows.net,1433;Integrated Security=False;User ID=[UserId];Password=[Password];Connect Timeout=15;Encrypt=False;TrustServerCertificate=False
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/Devbridge.BackupDatabaseServer.DACWebService.StatusInfo.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | Devbridge.BackupDatabaseServer.DACWebService.StatusInfo, Service References.DACWebService.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/Microsoft.SqlServer.Management.Dac.ServiceTypes.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/Microsoft.SqlServer.Management.Dac.Services.wsdl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/Reference.svcmap:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | true
6 |
7 | false
8 | false
9 | false
10 |
11 |
12 |
13 |
14 | true
15 | Auto
16 | true
17 | true
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/configuration.svcinfo:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/configuration91.svcinfo:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/service.wsdl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/service.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/Service References/DACWebService/service1.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Devbridge.BackupDatabaseServer/readme.txt:
--------------------------------------------------------------------------------
1 | This project exports all database in sql azure server to some folder (produces bacpac) files. It relies on DACFramework (http://www.microsoft.com/en-us/download/details.aspx?id=35756) which must be installed in order to use this tool.
2 | We need to improve backup process by first making database copies then exporting them - because exports are not transactionally consistent.
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Config/basicAuthentication.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using System.Web.Mvc;
2 |
3 | namespace Devbridge.BasicAuthentication.Test.Controllers
4 | {
5 | public class HomeController : Controller
6 | {
7 | public ActionResult Index()
8 | {
9 | return View();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Devbridge.BasicAuthentication.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 |
8 |
9 | 2.0
10 | {11EBC198-765A-4017-9091-CCD5D934015A}
11 | {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
12 | Library
13 | Properties
14 | Devbridge.BasicAuthentication.Test
15 | Devbridge.BasicAuthentication.Test
16 | v4.0
17 | false
18 | false
19 |
20 |
21 |
22 |
23 |
24 | ..\
25 | true
26 | true
27 | 4.0
28 |
29 |
30 | true
31 | full
32 | false
33 | bin\
34 | DEBUG;TRACE
35 | prompt
36 | 4
37 |
38 |
39 | pdbonly
40 | true
41 | bin\
42 | TRACE
43 | prompt
44 | 4
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | True
67 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
68 |
69 |
70 | True
71 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.Helpers.dll
72 |
73 |
74 | True
75 | ..\packages\Microsoft.AspNet.Mvc.3.0.20105.1\lib\net40\System.Web.Mvc.dll
76 |
77 |
78 | True
79 | ..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll
80 |
81 |
82 | True
83 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.dll
84 |
85 |
86 | True
87 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Deployment.dll
88 |
89 |
90 | True
91 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll
92 |
93 |
94 |
95 |
96 |
97 | Properties\SharedAssemblyInfo.cs
98 |
99 |
100 |
101 | Global.asax
102 |
103 |
104 |
105 |
106 |
107 |
108 | Designer
109 |
110 |
111 | Web.config
112 |
113 |
114 | Web.config
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | {8b8d3ff3-9e4b-48d9-8bef-52ab2651638a}
136 | Devbridge.BasicAuthentication
137 |
138 |
139 |
140 | 10.0
141 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | True
154 |
155 |
156 |
157 |
158 |
159 |
165 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Devbridge.BasicAuthentication.Test.MvcApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Linq;
5 | using System.Web;
6 | using System.Web.Mvc;
7 | using System.Web.Routing;
8 |
9 | namespace Devbridge.BasicAuthentication.Test
10 | {
11 | // Note: For instructions on enabling IIS6 or IIS7 classic mode,
12 | // visit http://go.microsoft.com/?LinkId=9394801
13 |
14 | public class MvcApplication : System.Web.HttpApplication
15 | {
16 | public static void RegisterGlobalFilters(GlobalFilterCollection filters)
17 | {
18 | filters.Add(new HandleErrorAttribute());
19 | }
20 |
21 | public static void RegisterRoutes(RouteCollection routes)
22 | {
23 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
24 |
25 | routes.MapRoute(
26 | "Default", // Route name
27 | "{controller}/{action}/{id}", // URL with parameters
28 | new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
29 | );
30 |
31 | }
32 |
33 | protected void Application_Start()
34 | {
35 | AreaRegistration.RegisterAllAreas();
36 |
37 | RegisterGlobalFilters(GlobalFilters.Filters);
38 | RegisterRoutes(RouteTable.Routes);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("DevBridge.BasicAuthentication.Test")]
8 | [assembly: AssemblyDescription("")]
9 |
10 | // Setting ComVisible to false makes the types in this assembly not visible
11 | // to COM components. If you need to access a type in this assembly from
12 | // COM, set the ComVisible attribute to true on that type.
13 | [assembly: ComVisible(false)]
14 |
15 | // The following GUID is for the ID of the typelib if this project is exposed to COM
16 | [assembly: Guid("33d49b02-a8e0-48c3-ab0b-cde0f7b08326")]
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewBag.Title = "Test page";
3 | }
4 |
5 | This is a test page.
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Views/Shared/Error.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = null;
3 | }
4 |
5 |
6 |
7 |
8 | Error
9 |
10 |
11 |
12 | Sorry, an error occurred while processing your request.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @ViewBag.Title
5 |
6 |
7 |
8 | @RenderBody()
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Views/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "~/Views/Shared/_Layout.cshtml";
3 | }
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication.Test/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/BasicAuthenticationModule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 | using System.Web;
9 |
10 | namespace Devbridge.BasicAuthentication
11 | {
12 | ///
13 | /// This module performs basic authentication.
14 | /// For details on basic authentication see RFC 2617.
15 | /// Based on the work by Mike Volodarsky (www.iis.net/learn/develop/runtime-extensibility/developing-a-module-using-net)
16 | ///
17 | /// The basic operational flow is:
18 | ///
19 | /// On AuthenticateRequest:
20 | /// extract the basic authentication credentials
21 | /// verify the credentials
22 | /// if succesfull, create and send authentication cookie
23 | ///
24 | /// On SendResponseHeaders:
25 | /// if there is no authentication cookie in request, clear response, add unauthorized status code (401) and
26 | /// add the basic authentication challenge to trigger basic authentication.
27 | ///
28 | public class BasicAuthenticationModule : IHttpModule
29 | {
30 | ///
31 | /// HTTP1.1 Authorization header
32 | ///
33 | public const string HttpAuthorizationHeader = "Authorization";
34 |
35 | ///
36 | /// HTTP1.1 Basic Challenge Scheme Name
37 | ///
38 | public const string HttpBasicSchemeName = "Basic"; //
39 |
40 | ///
41 | /// HTTP1.1 Credential username and password separator
42 | ///
43 | public const char HttpCredentialSeparator = ':';
44 |
45 | ///
46 | /// HTTP1.1 Not authorized response status code
47 | ///
48 | public const int HttpNotAuthorizedStatusCode = 401;
49 |
50 | ///
51 | /// HTTP1.1 Basic Challenge Scheme Name
52 | ///
53 | public const string HttpWwwAuthenticateHeader = "WWW-Authenticate";
54 |
55 | ///
56 | /// The name of cookie that is sent to client
57 | ///
58 | public const string AuthenticationCookieName = "BasicAuthentication";
59 |
60 | ///
61 | /// HTTP.1.1 Basic Challenge Realm
62 | ///
63 | public const string Realm = "demo";
64 |
65 | ///
66 | /// The App Setting that can enable/disable the entire functionality
67 | ///
68 | public const string EnabledAppSetting = "BasicAuthEnabled";
69 |
70 | ///
71 | /// The credentials that are allowed to access the site.
72 | ///
73 | private IDictionary activeUsers;
74 |
75 | ///
76 | /// Exclude configuration - request URL is matched to dictionary key and request method is matched to the value of the same key-value pair.
77 | ///
78 | private IDictionary excludes;
79 |
80 | ///
81 | /// Indicates whether redirects are allowed without authentication.
82 | ///
83 | private bool allowRedirects;
84 |
85 | ///
86 | /// Indicates whether local requests are allowed without authentication.
87 | ///
88 | private bool allowLocal;
89 |
90 | ///
91 | /// Regular expression that matches any given string.
92 | ///
93 | private readonly static Regex AllowAnyRegex = new Regex(".*", RegexOptions.Compiled);
94 |
95 | ///
96 | /// Boolean that allows an app setting to enable/disable basic auth
97 | ///
98 | private bool isEnabled = true;
99 |
100 | ///
101 | /// Dictionary that caches whether basic authentication challenge should be sent. Key is request URL + request method, value indicates whether
102 | /// challenge should be sent.
103 | ///
104 | private static IDictionary shouldChallengeCache = new Dictionary();
105 |
106 | public void AuthenticateUser(object source, EventArgs e)
107 | {
108 | var httpApp = (HttpApplication)source;
109 | var context = httpApp.Context;
110 |
111 | string authorizationHeader = context.Request.Headers[HttpAuthorizationHeader];
112 |
113 | // Extract the basic authentication credentials from the request
114 | string userName = null;
115 | string password = null;
116 | if (!ExtractBasicCredentials(authorizationHeader, ref userName, ref password))
117 | {
118 | httpApp.CompleteRequest();
119 | return;
120 | }
121 |
122 | // Validate the user credentials
123 | if (!ValidateCredentials(userName, password))
124 | {
125 | httpApp.CompleteRequest();
126 | return;
127 | }
128 |
129 | // Add Header with same name as Cookie
130 | if (context.Request.Headers.AllKeys.FirstOrDefault(x => x.Equals(AuthenticationCookieName)) == null)
131 | {
132 | context.Request.Headers.Add(AuthenticationCookieName, userName);
133 | }
134 |
135 | // check whether cookie is set and send it to client if needed
136 | var authCookie = context.Request.Cookies.Get(AuthenticationCookieName);
137 | if (authCookie == null)
138 | {
139 | authCookie = new HttpCookie(AuthenticationCookieName, "1") { Expires = DateTime.Now.AddHours(1) };
140 | context.Response.Cookies.Add(authCookie);
141 | }
142 | }
143 |
144 | public void IssueAuthenticationChallenge(object source, EventArgs e)
145 | {
146 | var context = ((HttpApplication)source).Context;
147 |
148 | if (allowLocal && context.Request.IsLocal)
149 | {
150 | return;
151 | }
152 |
153 | if (allowRedirects && IsRedirect(context.Response.StatusCode))
154 | {
155 | return;
156 | }
157 |
158 | if (ShouldChallenge(context))
159 | {
160 | // if authentication cookie is not set issue a basic challenge
161 | var authCookie = context.Request.Cookies.Get(AuthenticationCookieName);
162 | if (authCookie == null)
163 | {
164 | //make sure that user is not authencated yet
165 | if (!context.Response.Cookies.AllKeys.Contains(AuthenticationCookieName))
166 | {
167 | context.Response.Clear();
168 | context.Response.StatusCode = HttpNotAuthorizedStatusCode;
169 | context.Response.AddHeader(HttpWwwAuthenticateHeader, "Basic realm =\"" + Realm + "\"");
170 | }
171 | }
172 | }
173 | }
174 |
175 | ///
176 | /// Returns true if authentication challenge should be sent to client based on configured exclude rules
177 | ///
178 | private bool ShouldChallenge(HttpContext context)
179 | {
180 | // allow app setting take precedence
181 | if (!isEnabled)
182 | {
183 | return false;
184 | }
185 |
186 | // first check cache
187 | var key = string.Concat(context.Request.Path, context.Request.HttpMethod);
188 | if (shouldChallengeCache.ContainsKey(key))
189 | {
190 | return shouldChallengeCache[key];
191 | }
192 |
193 | // if value is not found in cache check exclude rules
194 | foreach (var urlVerbRegex in excludes)
195 | {
196 | if ((urlVerbRegex.Key.IsMatch(context.Request.Path) || urlVerbRegex.Key.IsMatch(context.Request.Url.Host)) && urlVerbRegex.Value.IsMatch(context.Request.HttpMethod))
197 | {
198 | shouldChallengeCache[key] = false;
199 |
200 | return false;
201 | }
202 | }
203 |
204 | shouldChallengeCache[key] = true;
205 | return true;
206 | }
207 |
208 | private static bool IsRedirect(int httpStatusCode)
209 | {
210 | return httpStatusCode == (int)HttpStatusCode.MovedPermanently ||
211 | httpStatusCode == (int)HttpStatusCode.Redirect ||
212 | httpStatusCode == (int)HttpStatusCode.TemporaryRedirect;
213 | }
214 |
215 | protected virtual bool ValidateCredentials(string userName, string password)
216 | {
217 | var lowerCaseUserName = userName.ToLower();
218 |
219 | if (activeUsers.ContainsKey(lowerCaseUserName) && activeUsers[lowerCaseUserName] == password)
220 | {
221 | return true;
222 | }
223 |
224 | return false;
225 | }
226 |
227 | protected virtual bool ExtractBasicCredentials(string authorizationHeader, ref string username, ref string password)
228 | {
229 | if (string.IsNullOrEmpty(authorizationHeader))
230 | {
231 | return false;
232 | }
233 |
234 | string verifiedAuthorizationHeader = authorizationHeader.Trim();
235 | if (verifiedAuthorizationHeader.IndexOf(HttpBasicSchemeName, StringComparison.InvariantCultureIgnoreCase) != 0)
236 | {
237 | return false;
238 | }
239 |
240 | // get the credential payload
241 | verifiedAuthorizationHeader = verifiedAuthorizationHeader.Substring(HttpBasicSchemeName.Length, verifiedAuthorizationHeader.Length - HttpBasicSchemeName.Length).Trim();
242 | // decode the base 64 encoded credential payload
243 | byte[] credentialBase64DecodedArray = Convert.FromBase64String(verifiedAuthorizationHeader);
244 | string decodedAuthorizationHeader = Encoding.UTF8.GetString(credentialBase64DecodedArray, 0, credentialBase64DecodedArray.Length);
245 |
246 | // get the username, password, and realm
247 | int separatorPosition = decodedAuthorizationHeader.IndexOf(HttpCredentialSeparator);
248 |
249 | if (separatorPosition <= 0)
250 | {
251 | return false;
252 | }
253 |
254 | username = decodedAuthorizationHeader.Substring(0, separatorPosition).Trim();
255 | password = decodedAuthorizationHeader.Substring(separatorPosition + 1, (decodedAuthorizationHeader.Length - separatorPosition - 1)).Trim();
256 |
257 | if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
258 | {
259 | return false;
260 | }
261 |
262 | return true;
263 | }
264 |
265 | public void Init(HttpApplication context)
266 | {
267 | var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
268 | var basicAuth = TraverseConfigSections(config.RootSectionGroup);
269 |
270 | if (basicAuth == null)
271 | {
272 | System.Diagnostics.Debug.WriteLine("BasicAuthenticationModule not started - Configuration not found. Make sure that BasicAuthenticationConfigurationSection section is defined.");
273 | return;
274 | }
275 |
276 | allowRedirects = basicAuth.AllowRedirects;
277 | allowLocal = basicAuth.AllowLocal;
278 |
279 | var appSetting = ConfigurationManager.AppSettings[EnabledAppSetting];
280 | if (appSetting != null)
281 | {
282 | isEnabled = appSetting == "true";
283 | }
284 |
285 | InitCredentials(basicAuth);
286 | InitExcludes(basicAuth);
287 |
288 | // Subscribe to the authenticate event to perform the authentication.
289 | context.AuthenticateRequest += AuthenticateUser;
290 |
291 | // Subscribe to the EndRequest event to issue the authentication challenge if necessary.
292 | context.EndRequest += IssueAuthenticationChallenge;
293 | }
294 |
295 | private void InitCredentials(Configuration.BasicAuthenticationConfigurationSection basicAuth)
296 | {
297 | activeUsers = new Dictionary();
298 |
299 | for (int i = 0; i < basicAuth.Credentials.Count; i++)
300 | {
301 | var credential = basicAuth.Credentials[i];
302 | activeUsers.Add(credential.UserName.ToLower(), credential.Password);
303 | }
304 | }
305 |
306 | private void InitExcludes(Configuration.BasicAuthenticationConfigurationSection basicAuth)
307 | {
308 | var excludesAsString = new Dictionary();
309 | excludes = new Dictionary();
310 | var allowAnyRegex = AllowAnyRegex.ToString();
311 |
312 | for (int i = 0; i < basicAuth.Excludes.Count; i++)
313 | {
314 | var excludeUrl = basicAuth.Excludes[i].Url;
315 | var excludeVerb = basicAuth.Excludes[i].Verb;
316 |
317 | if (string.IsNullOrEmpty(excludeUrl))
318 | {
319 | excludeUrl = allowAnyRegex;
320 | }
321 | if (string.IsNullOrEmpty(excludeVerb))
322 | {
323 | excludeVerb = allowAnyRegex;
324 | }
325 |
326 | excludesAsString[excludeUrl] = excludeVerb;
327 | }
328 |
329 | foreach (var url in excludesAsString.Keys)
330 | {
331 | var urlRegex = url == allowAnyRegex ? AllowAnyRegex : new Regex(url, RegexOptions.Compiled | RegexOptions.IgnoreCase);
332 | var verbRegex = excludesAsString[url] == allowAnyRegex ? AllowAnyRegex : new Regex(excludesAsString[url], RegexOptions.Compiled | RegexOptions.IgnoreCase);
333 |
334 | excludes[urlRegex] = verbRegex;
335 | }
336 | }
337 |
338 | private T TraverseConfigSections(ConfigurationSectionGroup group) where T : ConfigurationSection
339 | {
340 | foreach (ConfigurationSection section in group.Sections)
341 | {
342 | if (Type.GetType(section.SectionInformation.Type, false) == typeof(T))
343 | return (T)section;
344 | }
345 |
346 | foreach (ConfigurationSectionGroup g in group.SectionGroups)
347 | {
348 | var section = TraverseConfigSections(g);
349 | if (section != null)
350 | {
351 | return section;
352 | }
353 | }
354 |
355 | return null;
356 | }
357 |
358 | public void Dispose()
359 | {
360 | // Do nothing here
361 | }
362 | }
363 | }
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Config/basicAuthentication.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Configuration/BasicAuthenticationConfigurationSection.cs:
--------------------------------------------------------------------------------
1 | using System.Configuration;
2 |
3 | namespace Devbridge.BasicAuthentication.Configuration
4 | {
5 | public class BasicAuthenticationConfigurationSection : ConfigurationSection
6 | {
7 | private const string CredentialsNode = "credentials";
8 | private const string ExcludesNode = "excludes";
9 |
10 | ///
11 | /// Gets or sets the credentials.
12 | ///
13 | ///
14 | /// The credentials.
15 | ///
16 | [ConfigurationProperty(CredentialsNode, IsRequired = false)]
17 | public CredentialElementCollection Credentials
18 | {
19 | get { return (CredentialElementCollection)this[CredentialsNode]; }
20 | set { this[CredentialsNode] = value; }
21 | }
22 |
23 | ///
24 | /// Gets or sets a value indicating whether authenticaiton module should allow redirects without issuing auth challenge.
25 | ///
26 | ///
27 | /// true to allow redirects; otherwise, false.
28 | ///
29 | [ConfigurationProperty("allowRedirects", DefaultValue = "false", IsRequired = false)]
30 | public bool AllowRedirects
31 | {
32 | get { return (bool)this["allowRedirects"]; }
33 | set { this["allowRedirects"] = value; }
34 | }
35 |
36 | ///
37 | /// Gets or sets a value indicating whether authenticaiton module should allow local requests without issuing auth challenge.
38 | ///
39 | ///
40 | /// true to allow redirects; otherwise, false.
41 | ///
42 | [ConfigurationProperty("allowLocal", DefaultValue = "false", IsRequired = false)]
43 | public bool AllowLocal
44 | {
45 | get { return (bool)this["allowLocal"]; }
46 | set { this["allowLocal"] = value; }
47 | }
48 |
49 | ///
50 | /// Gets or sets the URL exclusions.
51 | ///
52 | ///
53 | /// The URL exclusions.
54 | ///
55 | [ConfigurationProperty(ExcludesNode, IsRequired = false)]
56 | public ExcludeElementCollection Excludes
57 | {
58 | get { return (ExcludeElementCollection)this[ExcludesNode]; }
59 | set { this[ExcludesNode] = value; }
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Configuration/CredentialElement.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 |
4 | namespace Devbridge.BasicAuthentication.Configuration
5 | {
6 | public class CredentialElement : ConfigurationElement
7 | {
8 | private const string UserNameAttribute = "username";
9 | private const string PasswordAttribute = "password";
10 |
11 | ///
12 | /// Gets or sets the username.
13 | ///
14 | ///
15 | /// The user name.
16 | ///
17 | [ConfigurationProperty(UserNameAttribute, IsRequired = true)]
18 | public string UserName
19 | {
20 | get { return Convert.ToString(this[UserNameAttribute]); }
21 | set { this[UserNameAttribute] = value; }
22 | }
23 |
24 | ///
25 | /// Gets or sets the password.
26 | ///
27 | ///
28 | /// The password.
29 | ///
30 | [ConfigurationProperty(PasswordAttribute, IsRequired = true)]
31 | public string Password
32 | {
33 | get { return Convert.ToString(this[PasswordAttribute]); }
34 | set { this[PasswordAttribute] = value; }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Configuration/CredentialElementCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Configuration;
2 |
3 | namespace Devbridge.BasicAuthentication.Configuration
4 | {
5 | [ConfigurationCollection(typeof(CredentialElement), CollectionType = ConfigurationElementCollectionType.BasicMap)]
6 | public class CredentialElementCollection : ConfigurationElementCollection
7 | {
8 | public CredentialElement this[int index]
9 | {
10 | get
11 | {
12 | return (CredentialElement)BaseGet(index);
13 | }
14 | set
15 | {
16 | if (BaseGet(index) != null)
17 | {
18 | BaseRemoveAt(index);
19 | }
20 | BaseAdd(index, value);
21 | }
22 | }
23 |
24 | protected override ConfigurationElement CreateNewElement()
25 | {
26 | return new CredentialElement();
27 | }
28 |
29 | protected override object GetElementKey(ConfigurationElement element)
30 | {
31 | return ((CredentialElement)element).UserName;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Configuration/ExcludeElement.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 |
4 | namespace Devbridge.BasicAuthentication.Configuration
5 | {
6 | public class ExcludeElement : ConfigurationElement
7 | {
8 | private const string UrlAttribute = "url";
9 | private const string VerbAttribute = "verb";
10 |
11 | ///
12 | /// Gets or sets the url to exclude.
13 | ///
14 | ///
15 | /// The url.
16 | ///
17 | [ConfigurationProperty(UrlAttribute, IsRequired = false, IsKey = false)]
18 | public string Url
19 | {
20 | get { return Convert.ToString(this[UrlAttribute]); }
21 | set { this[UrlAttribute] = value; }
22 | }
23 |
24 | ///
25 | /// Gets or sets the verb to exclude.
26 | ///
27 | ///
28 | /// The verb.
29 | ///
30 | [ConfigurationProperty(VerbAttribute, IsRequired = false, IsKey = false)]
31 | public string Verb
32 | {
33 | get { return Convert.ToString(this[VerbAttribute]); }
34 | set { this[VerbAttribute] = value; }
35 | }
36 |
37 | public override string ToString()
38 | {
39 | return string.Concat(Url, '_', Verb);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Configuration/ExcludeElementCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Configuration;
2 |
3 | namespace Devbridge.BasicAuthentication.Configuration
4 | {
5 | [ConfigurationCollection(typeof(ExcludeElement), CollectionType = ConfigurationElementCollectionType.BasicMap)]
6 | public class ExcludeElementCollection : ConfigurationElementCollection
7 | {
8 | public ExcludeElement this[int index]
9 | {
10 | get
11 | {
12 | return (ExcludeElement)BaseGet(index);
13 | }
14 | set
15 | {
16 | if (BaseGet(index) != null)
17 | {
18 | BaseRemoveAt(index);
19 | }
20 | BaseAdd(index, value);
21 | }
22 | }
23 |
24 | protected override ConfigurationElement CreateNewElement()
25 | {
26 | return new ExcludeElement();
27 | }
28 |
29 | protected override object GetElementKey(ConfigurationElement element)
30 | {
31 | return ((ExcludeElement)element).ToString();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Devbridge.BasicAuthentication.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {8B8D3FF3-9E4B-48D9-8BEF-52AB2651638A}
8 | Library
9 | Properties
10 | Devbridge.BasicAuthentication
11 | Devbridge.BasicAuthentication
12 | v4.0
13 | 512
14 |
15 | ..\
16 | true
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Properties\SharedAssemblyInfo.cs
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
69 |
70 |
71 |
72 |
79 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Devbridge.BasicAuthentication.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Devbridge.BasicAuthentication
5 | 1.0.0
6 | Devbridge Group
7 | Devbridge Group
8 | false
9 |
10 | This library contains basic authentification module, which can be mainly used for Azure websites. Not intended for production use.
11 |
12 | https://github.com/devbridge/AzurePowerTools
13 | Copyright 2017
14 | iis, basic authetification, azure
15 | en-US
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("DevBridge.BasicAuthentication")]
8 | [assembly: AssemblyDescription("")]
9 |
10 | // Setting ComVisible to false makes the types in this assembly not visible
11 | // to COM components. If you need to access a type in this assembly from
12 | // COM, set the ComVisible attribute to true on that type.
13 | [assembly: ComVisible(false)]
14 |
15 | // The following GUID is for the ID of the typelib if this project is exposed to COM
16 | [assembly: Guid("45346c62-265b-4c3d-9113-54e8f62a4904")]
17 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/web.config.install.xdt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Devbridge.BasicAuthentication/web.config.uninstall.xdt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/PowerShell/PublishCloudService.ps1:
--------------------------------------------------------------------------------
1 | Param( $serviceName = "",
2 | $storageAccountName = "",
3 | $packageLocation = "",
4 | $cloudConfigLocation = "",
5 | $environment = "Production",
6 | $deploymentLabel = "Development",
7 | $timeStampFormat = "g",
8 | $alwaysDeleteExistingDeployments = 1,
9 | $enableDeploymentUpgrade = 1,
10 | $selectedsubscription = "",
11 | $subscriptionDataFile = "cloud.publishsettings"
12 | )
13 |
14 | function Publish()
15 | {
16 | $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot -ErrorVariable a -ErrorAction silentlycontinue
17 | if ($a[0] -ne $null)
18 | {
19 | Write-Output "$(Get-Date –f $timeStampFormat) - No deployment is detected. Creating a new deployment. "
20 | }
21 | #check for existing deployment and then either upgrade, delete + deploy, or cancel according to $alwaysDeleteExistingDeployments and $enableDeploymentUpgrade boolean variables
22 | if ($deployment.Name -ne $null)
23 | {
24 | switch ($alwaysDeleteExistingDeployments)
25 | {
26 | 1
27 | {
28 | switch ($enableDeploymentUpgrade)
29 | {
30 | 1 #Update deployment inplace (usually faster, cheaper, won't destroy VIP)
31 | {
32 | Write-Output "$(Get-Date –f $timeStampFormat) - Deployment exists in $servicename. Upgrading deployment."
33 | UpgradeDeployment
34 | }
35 | 0 #Delete then create new deployment
36 | {
37 | Write-Output "$(Get-Date –f $timeStampFormat) - Deployment exists in $servicename. Deleting deployment."
38 | DeleteDeployment
39 | CreateNewDeployment
40 |
41 | }
42 | } # switch ($enableDeploymentUpgrade)
43 | }
44 | 0
45 | {
46 | Write-Output "$(Get-Date –f $timeStampFormat) - ERROR: Deployment exists in $servicename. Script execution cancelled."
47 | exit
48 | }
49 | } #switch ($alwaysDeleteExistingDeployments)
50 | } else {
51 | CreateNewDeployment
52 | }
53 | }
54 |
55 | function CreateNewDeployment()
56 | {
57 | write-progress -id 3 -activity "Creating New Deployment" -Status "In progress"
58 | Write-Output "$(Get-Date –f $timeStampFormat) - Creating New Deployment: In progress"
59 |
60 | $opstat = New-AzureDeployment -Slot $slot -Package $packageLocation -Configuration $cloudConfigLocation -label $deploymentLabel -ServiceName $serviceName
61 |
62 | $completeDeployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot -Verbose
63 | $completeDeploymentID = $completeDeployment.deploymentid
64 |
65 | write-progress -id 3 -activity "Creating New Deployment" -completed -Status "Complete"
66 | Write-Output "$(Get-Date –f $timeStampFormat) - Creating New Deployment: Complete, Deployment ID: $completeDeploymentID"
67 |
68 | StartInstances
69 | }
70 |
71 | function UpgradeDeployment()
72 | {
73 | write-progress -id 3 -activity "Upgrading Deployment" -Status "In progress"
74 | Write-Output "$(Get-Date –f $timeStampFormat) - Upgrading Deployment: In progress"
75 |
76 | # perform Update-Deployment
77 | $setdeployment = Set-AzureDeployment -Upgrade -Slot $slot -Package $packageLocation -Configuration $cloudConfigLocation -label $deploymentLabel -ServiceName $serviceName -Force
78 |
79 | $completeDeployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot
80 | $completeDeploymentID = $completeDeployment.deploymentid
81 |
82 | write-progress -id 3 -activity "Upgrading Deployment" -completed -Status "Complete"
83 | Write-Output "$(Get-Date –f $timeStampFormat) - Upgrading Deployment: Complete, Deployment ID: $completeDeploymentID"
84 | }
85 |
86 | function DeleteDeployment()
87 | {
88 | write-progress -id 2 -activity "Deleting Deployment" -Status "In progress"
89 | Write-Output "$(Get-Date –f $timeStampFormat) - Deleting Deployment: In progress"
90 |
91 | #WARNING - always deletes with force
92 | $removeDeployment = Remove-AzureDeployment -Slot $slot -ServiceName $serviceName -Force
93 |
94 | write-progress -id 2 -activity "Deleting Deployment: Complete" -completed -Status $removeDeployment
95 | Write-Output "$(Get-Date –f $timeStampFormat) - Deleting Deployment: Complete"
96 | }
97 |
98 | function StartInstances()
99 | {
100 | write-progress -id 4 -activity "Starting Instances" -status "In progress"
101 | Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instances: In progress"
102 |
103 | $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot
104 | $runstatus = $deployment.Status
105 |
106 | if ($runstatus -ne 'Running')
107 | {
108 | $run = Set-AzureDeployment -Slot $slot -ServiceName $serviceName -Status Running
109 | }
110 | $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot
111 | $oldStatusStr = @("") * $deployment.RoleInstanceList.Count
112 |
113 | while (-not(AllInstancesRunning($deployment.RoleInstanceList)))
114 | {
115 | $i = 1
116 | foreach ($roleInstance in $deployment.RoleInstanceList)
117 | {
118 | $instanceName = $roleInstance.InstanceName
119 | $instanceStatus = $roleInstance.InstanceStatus
120 |
121 | if ($oldStatusStr[$i - 1] -ne $roleInstance.InstanceStatus)
122 | {
123 | $oldStatusStr[$i - 1] = $roleInstance.InstanceStatus
124 | Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instance '$instanceName': $instanceStatus"
125 | }
126 |
127 | write-progress -id (4 + $i) -activity "Starting Instance '$instanceName'" -status "$instanceStatus"
128 | $i = $i + 1
129 | }
130 |
131 | sleep -Seconds 1
132 |
133 | $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot
134 | }
135 |
136 | $i = 1
137 | foreach ($roleInstance in $deployment.RoleInstanceList)
138 | {
139 | $instanceName = $roleInstance.InstanceName
140 | $instanceStatus = $roleInstance.InstanceStatus
141 |
142 | if ($oldStatusStr[$i - 1] -ne $roleInstance.InstanceStatus)
143 | {
144 | $oldStatusStr[$i - 1] = $roleInstance.InstanceStatus
145 | Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instance '$instanceName': $instanceStatus"
146 | }
147 |
148 | $i = $i + 1
149 | }
150 |
151 | $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot
152 | $opstat = $deployment.Status
153 |
154 | write-progress -id 4 -activity "Starting Instances" -completed -status $opstat
155 | Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instances: $opstat"
156 | }
157 |
158 | function AllInstancesRunning($roleInstanceList)
159 | {
160 | foreach ($roleInstance in $roleInstanceList)
161 | {
162 | if ($roleInstance.InstanceStatus -ne "ReadyRole")
163 | {
164 | return $false
165 | }
166 | }
167 |
168 | return $true
169 | }
170 |
171 | # specify path for Azure module (anyone knows how to configure PSModuleuPath?)
172 | $env:PSModulePath=$env:PSModulePath+";"+"C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell"
173 |
174 | # append timestamp to deployment label:
175 | $deploymentLabel=$deploymentLabel + " " + (Get-Date -f g)
176 |
177 | # it should list Azure in available modules list:
178 | Get-Module -ListAvailable
179 |
180 | #configure powershell with Azure 1.7 modules
181 | Import-Module Azure
182 |
183 | # configure powershell with publishsettings for your subscription
184 | $pubsettings = $subscriptionDataFile
185 | Import-AzurePublishSettingsFile $pubsettings
186 | Select-AzureSubscription -SubscriptionName $selectedsubscription
187 | Set-AzureSubscription -CurrentStorageAccount $storageAccountName -SubscriptionName $selectedsubscription
188 |
189 | # set remaining environment variables for Azure cmdlets
190 | $subscription = Get-AzureSubscription $selectedsubscription
191 | $subscriptionname = $subscription.subscriptionname
192 | $subscriptionid = $subscription.subscriptionid
193 | $slot = $environment
194 |
195 | # main driver - publish & write progress to activity log
196 | Write-Output "$(Get-Date –f $timeStampFormat) - Azure Cloud Service deploy script started."
197 | Write-Output "$(Get-Date –f $timeStampFormat) - Preparing deployment of $deploymentLabel for $subscriptionname with Subscription ID $subscriptionid."
198 |
199 | Publish
200 |
201 | $deployment = Get-AzureDeployment -slot $slot -serviceName $servicename
202 | $deploymentUrl = $deployment.Url
203 |
204 | Write-Output "$(Get-Date –f $timeStampFormat) - Azure Cloud Service deploy script finished."
205 | Write-Output "$(Get-Date –f $timeStampFormat) - Created Cloud Service with URL: "
206 | Write-Output "$deploymentUrl"
207 | exit 0
208 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DevBridge Azure Power Tools (http://www.devbridge.com)
2 | =======================================================================
3 | Our Azure Power Tools project is the collection of Windows Azure related tools and extensions. Here at DevBridge, we believe in open communication and like to share our knowledge with others who may find it helpful.
4 |
5 | You can also take a look at our [Standard Web Project Template](https://github.com/devbridge/StandardWebProjectTemplate).
6 |
7 | ## Basic authentication for Windows Azure websites
8 | Basic authentication for Windows Azure websites is a HTTP managed module that provides basic authentication for web applications hosted in Windows Azure websites. For more information please read this [blog post](http://www.devbridge.com/articles/basic-authentication-for-windows-azure-websites).
9 |
10 | Basic authentication module has relation to two projects:
11 | - Devbridge.BasicAuthentication project has the implementation for the basic authentication module.
12 | - Devbridge.BasicAuthentication.Test is simple test website that can be used to test basic authentication.
13 |
14 | ###Configuration Settings
15 | * `allowRedirects`: indicates whether redirects are allowed without authentication.
16 | * `excludes`: allows to configure rules to exclude certain parts of application from authentication.
17 |
18 | ####Sample excludes
19 | ```
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ```
31 |
--------------------------------------------------------------------------------
/SharedAssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyCompany("DevBridge Inc.")]
4 | [assembly: AssemblyProduct("DevBridge Azure Power Tools")]
5 | [assembly: AssemblyCopyright("Copyright © DevBridge Inc. 2012")]
6 | [assembly: AssemblyTrademark("")]
7 | [assembly: AssemblyCulture("")]
8 |
9 | // You can specify all the values or you can default the Build and Revision Numbers
10 | // by using the '*' as shown below:
11 | [assembly: AssemblyVersion("1.0.0.0")]
12 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | Copyright 2014 Devbridge Group
2 | http://www.devbridge.com/
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/packages/repositories.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------