Skip to content

Commit 46d601a

Browse files
Adds putting proxy files in a proxy-specific folder. Closes #40 (#65)
1 parent 1718bf6 commit 46d601a

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System.Reflection;
2+
using System.Security.Cryptography.X509Certificates;
3+
using Titanium.Web.Proxy.Helpers;
4+
using Titanium.Web.Proxy.Network;
5+
6+
namespace Microsoft.Graph.DeveloperProxy;
7+
8+
// based on https://github.com/justcoding121/titanium-web-proxy/blob/9e71608d204e5b67085656dd6b355813929801e4/src/Titanium.Web.Proxy/Certificates/Cache/DefaultCertificateDiskCache.cs
9+
public sealed class CertificateDiskCache : ICertificateCache {
10+
private const string DefaultCertificateDirectoryName = "crts";
11+
private const string DefaultCertificateFileExtension = ".pfx";
12+
private const string DefaultRootCertificateFileName = "rootCert" + DefaultCertificateFileExtension;
13+
private const string ProxyConfigurationFolderName = "msgraph-developer-proxy";
14+
15+
private string? rootCertificatePath;
16+
17+
public X509Certificate2? LoadRootCertificate(string pathOrName, string password, X509KeyStorageFlags storageFlags) {
18+
var path = GetRootCertificatePath(pathOrName, false);
19+
return LoadCertificate(path, password, storageFlags);
20+
}
21+
22+
public void SaveRootCertificate(string pathOrName, string password, X509Certificate2 certificate) {
23+
var path = GetRootCertificatePath(pathOrName, true);
24+
var exported = certificate.Export(X509ContentType.Pkcs12, password);
25+
File.WriteAllBytes(path, exported);
26+
}
27+
28+
/// <inheritdoc />
29+
public X509Certificate2? LoadCertificate(string subjectName, X509KeyStorageFlags storageFlags) {
30+
var filePath = Path.Combine(GetCertificatePath(false), subjectName + DefaultCertificateFileExtension);
31+
return LoadCertificate(filePath, string.Empty, storageFlags);
32+
}
33+
34+
/// <inheritdoc />
35+
public void SaveCertificate(string subjectName, X509Certificate2 certificate) {
36+
var filePath = Path.Combine(GetCertificatePath(true), subjectName + DefaultCertificateFileExtension);
37+
var exported = certificate.Export(X509ContentType.Pkcs12);
38+
File.WriteAllBytes(filePath, exported);
39+
}
40+
41+
public void Clear() {
42+
try {
43+
var path = GetCertificatePath(false);
44+
if (Directory.Exists(path)) Directory.Delete(path, true);
45+
}
46+
catch (Exception) {
47+
// do nothing
48+
}
49+
}
50+
51+
private X509Certificate2? LoadCertificate(string path, string password, X509KeyStorageFlags storageFlags) {
52+
byte[] exported;
53+
54+
if (!File.Exists(path)) return null;
55+
56+
try {
57+
exported = File.ReadAllBytes(path);
58+
}
59+
catch (IOException) {
60+
// file or directory not found
61+
return null;
62+
}
63+
64+
return new X509Certificate2(exported, password, storageFlags);
65+
}
66+
67+
private string GetRootCertificatePath(string pathOrName, bool create) {
68+
if (Path.IsPathRooted(pathOrName)) return pathOrName;
69+
70+
return Path.Combine(GetRootCertificateDirectory(create),
71+
string.IsNullOrEmpty(pathOrName) ? DefaultRootCertificateFileName : pathOrName);
72+
}
73+
74+
private string GetCertificatePath(bool create) {
75+
var path = GetRootCertificateDirectory(create);
76+
77+
var certPath = Path.Combine(path, DefaultCertificateDirectoryName);
78+
if (create && !Directory.Exists(certPath)) Directory.CreateDirectory(certPath);
79+
80+
return certPath;
81+
}
82+
83+
private string GetRootCertificateDirectory(bool create) {
84+
if (rootCertificatePath == null) {
85+
if (RunTime.IsUwpOnWindows) {
86+
rootCertificatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ProxyConfigurationFolderName);
87+
}
88+
else if (RunTime.IsLinux) {
89+
rootCertificatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ProxyConfigurationFolderName);
90+
}
91+
else if (RunTime.IsMac) {
92+
rootCertificatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ProxyConfigurationFolderName);
93+
}
94+
else {
95+
var assemblyLocation = GetType().Assembly.Location;
96+
97+
// dynamically loaded assemblies returns string.Empty location
98+
if (assemblyLocation == string.Empty) assemblyLocation = Assembly.GetEntryAssembly()?.Location;
99+
100+
#if NETSTANDARD2_1
101+
// single-file app returns string.Empty location
102+
if (assemblyLocation == string.Empty)
103+
{
104+
assemblyLocation = AppContext.BaseDirectory;
105+
}
106+
#endif
107+
108+
var path = Path.GetDirectoryName(assemblyLocation);
109+
110+
rootCertificatePath = path ?? throw new NullReferenceException();
111+
}
112+
}
113+
114+
if (create && !Directory.Exists(rootCertificatePath)) {
115+
Directory.CreateDirectory(rootCertificatePath);
116+
}
117+
118+
return rootCertificatePath;
119+
}
120+
}

msgraph-developer-proxy/ChaosEngine.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public async Task Run(CancellationToken? cancellationToken) {
9999
Console.WriteLine($"Configuring proxy for cloud {_config.Cloud} - {_config.HostName}");
100100
_proxyServer = new ProxyServer();
101101

102+
_proxyServer.CertificateManager.CertificateStorage = new CertificateDiskCache();
102103
_proxyServer.BeforeRequest += OnRequest;
103104
_proxyServer.BeforeResponse += OnResponse;
104105
_proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;

0 commit comments

Comments
 (0)