forked from projectkudu/kudu
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding support for HTTPS Protocol, Certificates and SNI.
- Loading branch information
Showing
67 changed files
with
2,376 additions
and
408 deletions.
There are no files selected for viewing
162 changes: 162 additions & 0 deletions
162
Kudu.SiteManagement.Test/Certificates/CertificateLookupFacts.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
using System.Collections.Generic; | ||
using System.Security.Cryptography.X509Certificates; | ||
using Kudu.SiteManagement.Certificates; | ||
using Kudu.SiteManagement.Certificates.Wrappers; | ||
using Kudu.SiteManagement.Test.Certificates.Fakes; | ||
using Moq; | ||
using Xunit; | ||
|
||
namespace Kudu.SiteManagement.Test.Certificates | ||
{ | ||
public class CertificateLookupFacts | ||
{ | ||
[Fact] | ||
public void ByThumbprint_OneMatching_ReturnsCertificate() | ||
{ | ||
Mock<IX509Store> storeMock = new Mock<IX509Store>(); | ||
IX509Certificate2Collection collectionFake = new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "FindMe") | ||
}; | ||
storeMock.Setup(mock => mock.Certificates).Returns(collectionFake); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My }, name => storeMock.Object) | ||
.ByThumbprint(); | ||
|
||
Assert.Equal(result.FriendlyName, "FindMe"); | ||
Assert.Equal(result.Thumbprint, "FindMe"); | ||
} | ||
|
||
[Fact] | ||
public void ByFriendlyName_OneMatching_ReturnsCertificate() | ||
{ | ||
Mock<IX509Store> storeMock = new Mock<IX509Store>(); | ||
storeMock.Setup(mock => mock.Certificates).Returns(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "FindMe") | ||
}); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My }, name => storeMock.Object) | ||
.ByFriendlyName(); | ||
|
||
Assert.Equal(result.FriendlyName, "FindMe"); | ||
Assert.Equal(result.Thumbprint, "FindMe"); | ||
} | ||
|
||
[Fact] | ||
public void ByThumbprint_NoneMatching_ReturnsNull() | ||
{ | ||
Mock<IX509Store> storeMock = new Mock<IX509Store>(); | ||
IX509Certificate2Collection collectionFake = new X509Certificate2CollectionFake { new X509Certificate2Fake() }; | ||
storeMock.Setup(mock => mock.Certificates).Returns(collectionFake); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My }, name => storeMock.Object) | ||
.ByThumbprint(); | ||
|
||
Assert.Null(result); | ||
} | ||
|
||
[Fact] | ||
public void ByFriendlyName_NoneMatching_ReturnsNull() | ||
{ | ||
Mock<IX509Store> storeMock = new Mock<IX509Store>(); | ||
storeMock.Setup(mock => mock.Certificates).Returns(new X509Certificate2CollectionFake { new X509Certificate2Fake() }); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My }, name => storeMock.Object) | ||
.ByFriendlyName(); | ||
|
||
Assert.Null(result); | ||
} | ||
|
||
[Fact] | ||
public void ByThumbprint_MultipleMatching_ReturnsFirstMatchingCertificate() | ||
{ | ||
Mock<IX509Store> storeMock = new Mock<IX509Store>(); | ||
storeMock.Setup(mock => mock.Certificates).Returns(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "FindMe"), | ||
new X509Certificate2Fake(friendlyName: "NotMe", thumbprint: "FindMe") | ||
}); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My }, name => storeMock.Object) | ||
.ByThumbprint(); | ||
|
||
Assert.Equal(result.FriendlyName, "FindMe"); | ||
Assert.Equal(result.Thumbprint, "FindMe"); | ||
} | ||
|
||
[Fact] | ||
public void ByFriendlyName_MultipleMatching_ReturnsFirstMatchingCertificate() | ||
{ | ||
Mock<IX509Store> storeMock = new Mock<IX509Store>(); | ||
storeMock.Setup(mock => mock.Certificates).Returns(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "FindMe"), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "NotMe") | ||
}); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My }, name => storeMock.Object) | ||
.ByFriendlyName(); | ||
|
||
Assert.Equal(result.FriendlyName, "FindMe"); | ||
Assert.Equal(result.Thumbprint, "FindMe"); | ||
} | ||
|
||
[Fact] | ||
public void ByThumbprint_OneMatchingInSecondaryStore_ReturnsCertificate() | ||
{ | ||
Dictionary<StoreName, Mock<IX509Store>> storeMocks = new Dictionary<StoreName, Mock<IX509Store>>(); | ||
storeMocks[StoreName.My] = CreateX509StoreMock(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake() | ||
}); | ||
storeMocks[StoreName.Root] = CreateX509StoreMock(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "FindMe") | ||
}); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My, StoreName.Root }, name => storeMocks[name].Object) | ||
.ByThumbprint(); | ||
|
||
Assert.Equal(result.FriendlyName, "FindMe"); | ||
Assert.Equal(result.Thumbprint, "FindMe"); | ||
} | ||
|
||
[Fact] | ||
public void ByFriendlyName_OneMatchingInSecondaryStore_ReturnsCertificate() | ||
{ | ||
Dictionary<StoreName, Mock<IX509Store>> storeMocks = new Dictionary<StoreName, Mock<IX509Store>>(); | ||
storeMocks[StoreName.My] = CreateX509StoreMock(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake() | ||
}); | ||
storeMocks[StoreName.Root] = CreateX509StoreMock(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(), | ||
new X509Certificate2Fake(friendlyName: "FindMe", thumbprint: "FindMe") | ||
}); | ||
|
||
Certificate result = new CertificateLookup("FindMe", new[] { StoreName.My, StoreName.Root }, name => storeMocks[name].Object) | ||
.ByFriendlyName(); | ||
|
||
Assert.Equal(result.FriendlyName, "FindMe"); | ||
Assert.Equal(result.Thumbprint, "FindMe"); | ||
} | ||
|
||
private static Mock<IX509Store> CreateX509StoreMock(IX509Certificate2Collection fake) | ||
{ | ||
Mock<IX509Store> mock = new Mock<IX509Store>(); | ||
mock.Setup(m => m.Certificates).Returns(fake); | ||
return mock; | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
Kudu.SiteManagement.Test/Certificates/CertificateSearcherFacts.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Cryptography.X509Certificates; | ||
using Kudu.SiteManagement.Certificates; | ||
using Kudu.SiteManagement.Certificates.Wrappers; | ||
using Kudu.SiteManagement.Configuration; | ||
using Kudu.SiteManagement.Test.Certificates.Fakes; | ||
using Moq; | ||
using Xunit; | ||
|
||
namespace Kudu.SiteManagement.Test.Certificates | ||
{ | ||
public class CertificateSearcherFacts | ||
{ | ||
[Fact] | ||
public void FindAll_MultipleStores_ReturnsFromAllStores() | ||
{ | ||
Mock<IKuduConfiguration> configMock = new Mock<IKuduConfiguration>(); | ||
configMock.Setup(mock => mock.CertificateStores) | ||
.Returns(new[] { new CertificateStoreConfiguration(StoreName.My), new CertificateStoreConfiguration(StoreName.Root) }); | ||
|
||
Dictionary<StoreName, Mock<IX509Store>> storeMocks = new Dictionary<StoreName, Mock<IX509Store>>(); | ||
storeMocks[StoreName.My] = CreateX509StoreMock(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(friendlyName: "My_CertA"), | ||
new X509Certificate2Fake(friendlyName: "My_CertB") | ||
}); | ||
storeMocks[StoreName.Root] = CreateX509StoreMock(new X509Certificate2CollectionFake | ||
{ | ||
new X509Certificate2Fake(friendlyName: "Root_CertA"), | ||
new X509Certificate2Fake(friendlyName: "Root_CertB") | ||
}); | ||
|
||
ICertificateSearcher searcher = new CertificateSearcher(configMock.Object, name => storeMocks[name].Object); | ||
Dictionary<string, Certificate> all = searcher.FindAll().ToDictionary(c => c.FriendlyName); | ||
|
||
Assert.Equal(all.Count, 4); | ||
Assert.NotNull(all["My_CertA"]); | ||
Assert.NotNull(all["My_CertB"]); | ||
Assert.NotNull(all["Root_CertA"]); | ||
Assert.NotNull(all["Root_CertB"]); | ||
} | ||
|
||
[Fact] | ||
public void Lookup_ReturnsCertificateLookupObject() | ||
{ | ||
Mock<IKuduConfiguration> configMock = new Mock<IKuduConfiguration>(); | ||
configMock.Setup(mock => mock.CertificateStores).Returns(new[] { new CertificateStoreConfiguration(StoreName.My) }); | ||
|
||
ICertificateSearcher searcher = new CertificateSearcher(configMock.Object, null); | ||
ICertificateLookup result = searcher.Lookup("FindMe"); | ||
|
||
Assert.IsType<CertificateLookup>(result); | ||
} | ||
|
||
private static Mock<IX509Store> CreateX509StoreMock(IX509Certificate2Collection fake) | ||
{ | ||
Mock<IX509Store> mock = new Mock<IX509Store>(); | ||
mock.Setup(m => m.Certificates).Returns(fake); | ||
return mock; | ||
} | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
Kudu.SiteManagement.Test/Certificates/Fakes/X509Certificate2CollectionFake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Cryptography.X509Certificates; | ||
using Kudu.SiteManagement.Certificates.Wrappers; | ||
|
||
namespace Kudu.SiteManagement.Test.Certificates.Fakes | ||
{ | ||
//Note: Simple Mock class instead of having to mock the interface, since IX509Certificate2 essentially is | ||
// a "data collection" and not a Service, this can sometimes be easier this way. | ||
public class X509Certificate2CollectionFake : List<IX509Certificate2>, IX509Certificate2Collection | ||
{ | ||
public X509Certificate2CollectionFake() | ||
{ | ||
} | ||
|
||
public X509Certificate2CollectionFake(IEnumerable<IX509Certificate2> collection) | ||
: base(collection) | ||
{ | ||
} | ||
|
||
public IX509Certificate2Collection Find(X509FindType findType, object findValue, bool validOnly) | ||
{ | ||
switch (findType) | ||
{ | ||
case X509FindType.FindByThumbprint: | ||
return new X509Certificate2CollectionFake(this.Where(c => c.Thumbprint == (string)findValue)); | ||
case X509FindType.FindBySubjectName: | ||
case X509FindType.FindBySubjectDistinguishedName: | ||
case X509FindType.FindByIssuerName: | ||
case X509FindType.FindByIssuerDistinguishedName: | ||
case X509FindType.FindBySerialNumber: | ||
case X509FindType.FindByTimeValid: | ||
case X509FindType.FindByTimeNotYetValid: | ||
case X509FindType.FindByTimeExpired: | ||
case X509FindType.FindByTemplateName: | ||
case X509FindType.FindByApplicationPolicy: | ||
case X509FindType.FindByCertificatePolicy: | ||
case X509FindType.FindByExtension: | ||
case X509FindType.FindByKeyUsage: | ||
case X509FindType.FindBySubjectKeyIdentifier: | ||
throw new NotImplementedException(); | ||
default: | ||
throw new ArgumentOutOfRangeException("findType"); | ||
} | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
Kudu.SiteManagement.Test/Certificates/Fakes/X509Certificate2Fake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using Kudu.SiteManagement.Certificates.Wrappers; | ||
|
||
namespace Kudu.SiteManagement.Test.Certificates.Fakes | ||
{ | ||
//Note: Simple Mock class instead of having to mock the interface, since IX509Certificate2 essentially is | ||
// a "data object" and not a Service, this can sometimes be easier this way. | ||
public class X509Certificate2Fake : IX509Certificate2 | ||
{ | ||
private byte[] hash; | ||
|
||
public string Thumbprint { get; private set; } | ||
public string FriendlyName { get; private set; } | ||
|
||
public X509Certificate2Fake(string friendlyName = "DummyFriendlyName", string thumbprint = "DummyThumbprint", byte[] hash = null) | ||
{ | ||
Thumbprint = thumbprint; | ||
FriendlyName = friendlyName; | ||
this.hash = hash ?? new byte[0]; | ||
} | ||
|
||
public byte[] GetCertHash() | ||
{ | ||
return hash; | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Kudu.SiteManagement.Test/Configuration/Fakes/ApplicationBindingConfigurationElementFake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Kudu.SiteManagement.Configuration.Section.Bindings; | ||
|
||
namespace Kudu.SiteManagement.Test.Configuration.Fakes | ||
{ | ||
public class ApplicationBindingConfigurationElementFake : ApplicationBindingConfigurationElement | ||
{ | ||
public ApplicationBindingConfigurationElementFake SetFake(string key, object value) | ||
{ | ||
this[key] = value; | ||
return this; | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Kudu.SiteManagement.Test/Configuration/Fakes/BindingsConfigurationElementCollectionFake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Kudu.SiteManagement.Configuration.Section.Bindings; | ||
|
||
namespace Kudu.SiteManagement.Test.Configuration.Fakes | ||
{ | ||
public class BindingsConfigurationElementCollectionFake : BindingsConfigurationElementCollection | ||
{ | ||
public BindingsConfigurationElementCollectionFake AddFake(BindingConfigurationElement element) | ||
{ | ||
base.Add(element); | ||
return this; | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Kudu.SiteManagement.Test/Configuration/Fakes/CertificateStoreConfigurationElementFake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Kudu.SiteManagement.Configuration.Section.Cert; | ||
|
||
namespace Kudu.SiteManagement.Test.Configuration.Fakes | ||
{ | ||
public class CertificateStoreConfigurationElementFake : CertificateStoreConfigurationElement | ||
{ | ||
public CertificateStoreConfigurationElementFake SetFake(string key, object value) | ||
{ | ||
this[key] = value; | ||
return this; | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
...anagement.Test/Configuration/Fakes/CertificateStoresConfigurationElementCollectionFake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using Kudu.SiteManagement.Configuration.Section.Cert; | ||
|
||
namespace Kudu.SiteManagement.Test.Configuration.Fakes | ||
{ | ||
public class CertificateStoresConfigurationElementCollectionFake : CertificateStoresConfigurationElementCollection | ||
{ | ||
public CertificateStoresConfigurationElementCollectionFake AddFake(CertificateStoreConfigurationElement element) | ||
{ | ||
base.Add(element); | ||
return this; | ||
} | ||
|
||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Kudu.SiteManagement.Test/Configuration/Fakes/KuduConfigurationSectionFake.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Kudu.SiteManagement.Configuration.Section; | ||
|
||
namespace Kudu.SiteManagement.Test.Configuration.Fakes | ||
{ | ||
public class KuduConfigurationSectionFake : KuduConfigurationSection | ||
{ | ||
public KuduConfigurationSectionFake SetFake(string key, object value) | ||
{ | ||
this[key] = value; | ||
return this; | ||
} | ||
} | ||
} |
Oops, something went wrong.