From 520e19b6d50ea36d9838c5b9a454da0671255edb Mon Sep 17 00:00:00 2001 From: Dave Crane Date: Fri, 23 Jun 2017 09:24:46 -0400 Subject: [PATCH] Add ClouDNS provider extension, #257 --- .../ACMESharp.Providers-test.csproj | 5 + .../ACMESharp.Providers-test/ClouDNSTests.cs | 148 ++++++++++++++++++ .../ACMESharp.Providers.ClouDNS.csproj | 81 ++++++++++ .../ACMESharp.Providers.ClouDNS.psd1 | 112 +++++++++++++ .../ClouDNSChallengeHandler.cs | 48 ++++++ .../ClouDNSChallengeHandlerProvider.cs | 68 ++++++++ .../ClouDNSHelper.cs | 141 +++++++++++++++++ .../Properties/AssemblyInfo.cs | 33 ++++ .../Results/DnsRecord.cs | 11 ++ .../Results/ZoneRecord.cs | 10 ++ .../packages.config | 4 + ACMESharp/ACMESharp.sln | 10 +- 12 files changed, 669 insertions(+), 2 deletions(-) create mode 100644 ACMESharp/ACMESharp.Providers-test/ClouDNSTests.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.csproj create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.psd1 create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandler.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandlerProvider.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSHelper.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/Properties/AssemblyInfo.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/Results/DnsRecord.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/Results/ZoneRecord.cs create mode 100644 ACMESharp/ACMESharp.Providers.ClouDNS/packages.config diff --git a/ACMESharp/ACMESharp.Providers-test/ACMESharp.Providers-test.csproj b/ACMESharp/ACMESharp.Providers-test/ACMESharp.Providers-test.csproj index a3c81014..e62cd830 100644 --- a/ACMESharp/ACMESharp.Providers-test/ACMESharp.Providers-test.csproj +++ b/ACMESharp/ACMESharp.Providers-test/ACMESharp.Providers-test.csproj @@ -64,6 +64,7 @@ + @@ -95,6 +96,10 @@ {63ae964a-79a4-4c7d-a686-dd9b2389af3f} ACMESharp.Providers.CloudFlare + + {529518fe-9546-4ec1-8e1f-9bc9239f0c7e} + ACMESharp.Providers.ClouDNS + {944ec9bd-81a1-484e-ba29-360bc155bf51} ACMESharp.Providers.IIS diff --git a/ACMESharp/ACMESharp.Providers-test/ClouDNSTests.cs b/ACMESharp/ACMESharp.Providers-test/ClouDNSTests.cs new file mode 100644 index 00000000..363c43f5 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers-test/ClouDNSTests.cs @@ -0,0 +1,148 @@ +using ACMESharp.ACME; +using ACMESharp.Providers.ClouDNS; +using ACMESharp.Util; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace ACMESharp.Providers +{ + [TestClass] + public class ClouDNSTests + { + public static readonly IReadOnlyDictionary EMPTY_PARAMS = + new Dictionary() + { + ["DomainName"] = "", + ["AuthId"] = "", + ["AuthPassword"] = "", + }; + + private static IReadOnlyDictionary _handlerParams = EMPTY_PARAMS; + + private static IReadOnlyDictionary GetParams() + { + return _handlerParams; + } + + [ClassInitialize] + public static void Init(TestContext tctx) + { + var file = new FileInfo("Config\\ClouDNSHandlerParams.json"); + if (file.Exists) + { + using (var fs = new FileStream(file.FullName, FileMode.Open)) + { + _handlerParams = JsonHelper.Load>(fs); + } + } + } + + public static ClouDNSChallengeHandlerProvider GetProvider() + { + return new ClouDNSChallengeHandlerProvider(); + } + + public static ClouDNSChallengeHandler GetHandler(Challenge challenge) + { + return (ClouDNSChallengeHandler)GetProvider().GetHandler(challenge, null); + } + + public static ClouDNSHelper GetHelper() + { + var p = GetParams(); + var h = new ClouDNSHelper( + (string)p["AuthId"], + (string)p["AuthPassword"], + (string)p["DomainName"] + ); + return h; + } + + [TestMethod] + public void TestParameterDescriptions() + { + var p = GetProvider(); + var dp = p.DescribeParameters(); + + Assert.IsNotNull(dp); + Assert.IsTrue(dp.Any()); + } + + [TestMethod] + public void TestSupportedChallenges() + { + var p = GetProvider(); + + Assert.IsTrue(p.IsSupported(TestCommon.DNS_CHALLENGE)); + Assert.IsFalse(p.IsSupported(TestCommon.HTTP_CHALLENGE)); + Assert.IsFalse(p.IsSupported(TestCommon.TLS_SNI_CHALLENGE)); + Assert.IsFalse(p.IsSupported(TestCommon.FAKE_CHALLENGE)); + } + + [TestMethod] + [ExpectedException(typeof(KeyNotFoundException))] + public void TestRequiredParams() + { + var p = GetProvider(); + var c = TestCommon.DNS_CHALLENGE; + var h = p.GetHandler(c, new Dictionary()); + } + + [TestMethod] + public void TestHandlerLifetime() + { + var p = GetProvider(); + var c = TestCommon.DNS_CHALLENGE; + var h = p.GetHandler(c, GetParams()); + + Assert.IsNotNull(h); + Assert.IsFalse(h.IsDisposed); + h.Dispose(); + Assert.IsTrue(h.IsDisposed); + } + + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void TestHandlerDisposedAccess() + { + var p = GetProvider(); + var c = TestCommon.DNS_CHALLENGE; + var h = p.GetHandler(c, GetParams()); + + h.Dispose(); + h.Handle(null); + } + + [TestMethod] + public void TestAddDnsRecord() + { + var h = GetHelper(); + var rrName = "acmesharp-test." + GetParams()["DomainName"]; + var rrValue = "testrr-" + DateTime.Now.ToString("yyyyMMddHHmmss #1"); + + h.AddOrUpdateDnsRecord(rrName, rrValue); + } + + [TestMethod] + public void TestUpdateDnsRecord() + { + var h = GetHelper(); + var rrName = "acmesharp-test." + GetParams()["DomainName"]; + var rrValue = "testrr-" + DateTime.Now.ToString("yyyyMMddHHmmss #2"); + + h.AddOrUpdateDnsRecord(rrName, rrValue); + } + + [TestMethod] + public void TestDeleteDnsRecord() + { + var h = GetHelper(); + var rrName = "acmesharp-test." + GetParams()["DomainName"]; + + h.DeleteDnsRecord(rrName); + } + } +} diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.csproj b/ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.csproj new file mode 100644 index 00000000..626cea4b --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.csproj @@ -0,0 +1,81 @@ + + + + + Debug + AnyCPU + {529518FE-9546-4EC1-8E1F-9BC9239F0C7E} + Library + Properties + ACMESharp.Providers.ClouDNS + ACMESharp.Providers.ClouDNS + v4.5 + 512 + + + + true + full + false + bin\$(Configuration)\ACMESharp.Providers.ClouDNS\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\$(Configuration)\ACMESharp.Providers.ClouDNS\ + TRACE + prompt + 4 + + + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + + + + + + + + + + + + + + Properties\SharedGlobalSuppressions.cs + + + + + + + + + + + {d551234b-0a8d-4dee-8178-a81998df0edb} + ACMESharp + False + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.psd1 b/ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.psd1 new file mode 100644 index 00000000..3e7c1c1a --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/ACMESharp.Providers.ClouDNS.psd1 @@ -0,0 +1,112 @@ + +## For a reference of this file's elements, see: +## https://technet.microsoft.com/library/hh849709.aspx +## https://technet.microsoft.com/en-us/library/dd878297(v=vs.85).aspx + +## 64-bit: +## %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe +## 32-bit: +## %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe + +@{ + ## This is a manifest-only module so we don't define any root + #RootModule = '' + + ModuleVersion = '0.8.0' + GUID = '7F6533CB-B35A-4E08-BD31-7561D0CC2A7B' + + Author = 'https://github.com/ebekker' + + CompanyName = 'https://github.com/ebekker/ACMESharp' + + Copyright = '(c) 2017 Dave Crane. All rights reserved.' + + Description = "ClouDNS Provider extension library for ACMESharp Client." + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + DefaultCommandPrefix = 'ACME' + + ## Minimum version of the Windows PowerShell engine required by this module + ## This does not appear to be enforce for versions > 2.0 as per + ## https://technet.microsoft.com/en-us/library/dd878297(v=vs.85).aspx + PowerShellVersion = '3.0' + + DotNetFrameworkVersion = '4.5' + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @('pki','ssl','tls','security','certificates','letsencrypt','acme','powershell','acmesharp','cloudns','acmesharp_ext') + + # A URL to the license for this module. + LicenseUri = 'https://raw.githubusercontent.com/ebekker/ACMESharp/master/LICENSE' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/ebekker/ACMESharp' + + # A URL to an icon representing this module. + IconUri = 'https://cdn.rawgit.com/ebekker/ACMESharp/master/artwork/ACMESharp-logo-square64.png' + + # ReleaseNotes of this module + ReleaseNotes = 'Please see the release notes from the release distribution page: https://github.com/ebekker/ACMESharp/releases' + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # Modules that must be imported into the global environment prior to importing this module + RequiredModules = @( ## FYI -- If one module uses the Hashtable spec, they all have to + + ## The minimum version of ACMESharp that supports our form of a Provider + ## extension as a dynamically installed and *enabled* POSH Extension Module + , @{ModuleName="ACMESharp";ModuleVersion="0.8.2"} + ) + + + ############################################################ + ## Unused manifest elements reserved for possible future use + ############################################################ + + # HelpInfo URI of this module for updateable help + # HelpInfoURI = '' + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module + # FunctionsToExport = '*' + + # Cmdlets to export from this module + # CmdletsToExport = '*' + + # Variables to export from this module + # VariablesToExport = '*' + + # Aliases to export from this module + # AliasesToExport = '*' + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + +} diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandler.cs b/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandler.cs new file mode 100644 index 00000000..fb923c33 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandler.cs @@ -0,0 +1,48 @@ +using ACMESharp.ACME; +using System; +using System.Text.RegularExpressions; + +namespace ACMESharp.Providers.ClouDNS +{ + public class ClouDNSChallengeHandler : IChallengeHandler + { + public string AuthPassword { get; set; } + public string AuthId { get; set; } + public string DomainName { get; set; } + public void Handle(Challenge c) + { + AssertNotDisposed(); + DnsChallenge challenge = (DnsChallenge)c; + var helper = new ClouDNSHelper(AuthId, AuthPassword, DomainName); + helper.AddOrUpdateDnsRecord(challenge.RecordName, GetCleanedRecordValue(challenge.RecordValue)); + } + + public void CleanUp(Challenge c) + { + AssertNotDisposed(); + DnsChallenge challenge = (DnsChallenge)c; + var helper = new ClouDNSHelper(AuthId, AuthPassword, DomainName); + helper.DeleteDnsRecord(challenge.RecordName); + } + + private string GetCleanedRecordValue(string recordValue) + { + var dnsValue = Regex.Replace(recordValue, "\\s", ""); + var dnsValues = string.Join("\" \"", Regex.Replace(dnsValue, "(.{100,100})", "$1\n").Split('\n')); + return dnsValues; + } + + private void AssertNotDisposed() + { + if (IsDisposed) + throw new InvalidOperationException("ClouDNS Challenge Handler is disposed"); + } + + public void Dispose() + { + IsDisposed = true; + } + + public bool IsDisposed { get; private set; } + } +} \ No newline at end of file diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandlerProvider.cs b/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandlerProvider.cs new file mode 100644 index 00000000..61eb894c --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSChallengeHandlerProvider.cs @@ -0,0 +1,68 @@ +using ACMESharp.ACME; +using ACMESharp.Ext; +using System.Collections.Generic; +using System.Linq; + +namespace ACMESharp.Providers.ClouDNS +{ + [ChallengeHandlerProvider( + "ClouDNS", + ChallengeTypeKind.DNS, + Label = "ClouDNS", + Description = "Provider for handling challenges that manages DNS entries hosted in a ClouDNS zone")] + public class ClouDNSChallengeHandlerProvider : IChallengeHandlerProvider + { + public static readonly ParameterDetail DomainName = + new ParameterDetail(nameof(ClouDNSChallengeHandler.DomainName), ParameterType.TEXT, isRequired: true, + label: "Domain name", desc: "The domain name to operate against."); + + public static readonly ParameterDetail AuthId = + new ParameterDetail(nameof(ClouDNSChallengeHandler.AuthId), ParameterType.TEXT, isRequired: true, + label: "Authenticaton ID", desc: "The authentication ID of the ClouDNS account to operate against"); + + public static readonly ParameterDetail AuthPassword = + new ParameterDetail(nameof(ClouDNSChallengeHandler.AuthPassword), ParameterType.TEXT, isRequired: true, + label: "Authentication Password", desc: "The authentication password of the ClouDNS account to operate against"); + + private static readonly ParameterDetail[] Params = + { + DomainName, + AuthId, + AuthPassword + }; + public IEnumerable DescribeParameters() + { + return Params; + } + + public bool IsSupported(Challenge c) + { + return c is DnsChallenge; + } + + public IChallengeHandler GetHandler(Challenge c, IReadOnlyDictionary initParams) + { + var handler = new ClouDNSChallengeHandler(); + if (initParams == null) + { + initParams = new Dictionary(); + } + ValidateParameters(initParams); + handler.DomainName = (string)initParams[DomainName.Name]; + handler.AuthId = (string)initParams[AuthId.Name]; + handler.AuthPassword = (string)initParams[AuthPassword.Name]; + return handler; + } + + private void ValidateParameters(IReadOnlyDictionary parameters) + { + foreach (ParameterDetail detail in Params.Where(x => x.IsRequired)) + { + if (!parameters.ContainsKey(detail.Name)) + { + throw new KeyNotFoundException($"Missing required parameter [{detail.Name}]"); + } + } + } + } +} \ No newline at end of file diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSHelper.cs b/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSHelper.cs new file mode 100644 index 00000000..7ae374dd --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/ClouDNSHelper.cs @@ -0,0 +1,141 @@ +using ACMESharp.Providers.ClouDNS.Results; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Diagnostics; + +namespace ACMESharp.Providers.ClouDNS +{ + public class ClouDNSHelper + { + private string _authId; + private string _authPassword; + private string _domainName; + + private const string _ttl = "3600"; + private const string _type = "TXT"; + + /* private const string ListZonesUrl = baseUrl + "list-zones.json?auth-id={0}&auth-password={1}&domain={2}&page={3}&rows-per-page={4}"; */ + private const string baseUrl = "https://api.cloudns.net/dns/"; + private const string GetZoneInfoUrl = baseUrl + "get-zone-info.json?auth-id={0}&auth-password={1}&domain-name={2}"; + private const string CreateRecordUrl = baseUrl + "add-record.json?auth-id={0}&auth-password={1}&domain-name={2}&record-type={3}&host={4}&record={5}&ttl={6}"; + private const string ListRecordsUrl = baseUrl + "records.json?auth-id={0}&auth-password={1}&domain-name={2}&host={3}&type={4}"; + private const string DeleteRecordUrl = baseUrl + "delete-record.json?auth-id={0}&auth-password={1}&domain-name={2}&record-id={3}"; + private const string UpdateRecordUrl = baseUrl + "mod-record.json?auth-id={0}&auth-password={1}&domain-name={2}&record-id={3}&host={4}&record={5}&ttl={6}"; + + public ClouDNSHelper(string AuthId, string AuthPassword, string DomainName) + { + _authId = AuthId; + _authPassword = AuthPassword; + _domainName = DomainName; + } + + private void GetZoneInfo() + { + HttpClient client = new HttpClient(); + var request = new HttpRequestMessage(HttpMethod.Get, string.Format(GetZoneInfoUrl, _authId, _authPassword, _domainName)); + var result = client.SendAsync(request).GetAwaiter().GetResult(); + if (result.IsSuccessStatusCode) + { + var content = result.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + ZoneRecord resultObj = JsonConvert.DeserializeObject(content); + Debug.WriteLine(string.Format("Zone is {0}, type is {1}", resultObj.Name, resultObj.Type)); + } + else + { + throw new Exception($"Could not get DNS records for zone {_domainName}. Result: {result.StatusCode} - {result.Content.ReadAsStringAsync().GetAwaiter().GetResult()}"); + } + } + + private DnsRecord GetDnsRecord(string host) + { + HttpClient client = new HttpClient(); + var request = new HttpRequestMessage(HttpMethod.Get, string.Format(ListRecordsUrl, _authId, _authPassword, _domainName, host, _type)); + var result = client.SendAsync(request).GetAwaiter().GetResult(); + if (result.IsSuccessStatusCode) + { + var content = result.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + Debug.WriteLine(content); + var res = JsonConvert.DeserializeObject>(content); ; + foreach (var r in res) + { + Debug.WriteLine("Id = {0}, Host = {1}", r.Key, r.Value.Host); + if (r.Value.Host == host) + { + return r.Value; + } + } + return null; + } + else + { + throw new Exception($"Could not get DNS records for zone {_domainName}. Result: {result.StatusCode} - {result.Content.ReadAsStringAsync().GetAwaiter().GetResult()}"); + } + } + + public void AddDnsRecord(string host, string recordValue) + { + HttpClient client = new HttpClient(); + string fullUrl = string.Format(CreateRecordUrl, _authId, _authPassword, _domainName, _type, host, recordValue, _ttl); + Debug.WriteLine(fullUrl); + var request = new HttpRequestMessage(HttpMethod.Get, fullUrl); + var result = client.SendAsync(request).GetAwaiter().GetResult(); + if (result.IsSuccessStatusCode) + { + var content = result.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + Debug.WriteLine(content); + } + else + { + throw new Exception($"Could not add DNS records for zone {_domainName}. Result: {result.StatusCode} - {result.Content.ReadAsStringAsync().GetAwaiter().GetResult()}"); + } + } + + public void UpdateDnsRecord(string recordId, string host, string recordValue) + { + HttpClient client = new HttpClient(); + var request = new HttpRequestMessage(HttpMethod.Get, string.Format(UpdateRecordUrl, _authId, _authPassword, _domainName, recordId, host, recordValue, _ttl)); + var result = client.SendAsync(request).GetAwaiter().GetResult(); + if (result.IsSuccessStatusCode) + { + var content = result.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + Debug.WriteLine(content); + } + else + { + throw new Exception($"Could not add DNS records for zone {_domainName}. Result: {result.StatusCode} - {result.Content.ReadAsStringAsync().GetAwaiter().GetResult()}"); + } + } + + public void DeleteDnsRecord(string host) + { + DnsRecord rec = GetDnsRecord(host); + HttpClient client = new HttpClient(); + var request = new HttpRequestMessage(HttpMethod.Get, string.Format(DeleteRecordUrl, _authId, _authPassword, _domainName, rec.Id)); + var result = client.SendAsync(request).GetAwaiter().GetResult(); + if (result.IsSuccessStatusCode) + { + var content = result.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + Debug.WriteLine(content); + } + else + { + throw new Exception($"Could not delete DNS records for zone {_domainName}. Result: {result.StatusCode} - {result.Content.ReadAsStringAsync().GetAwaiter().GetResult()}"); + } + } + + public void AddOrUpdateDnsRecord(string host, string recordValue) + { + DnsRecord rec = GetDnsRecord(host); + if (rec != null) + { + UpdateDnsRecord(rec.Id, host, recordValue); + } + else + { + AddDnsRecord(host, recordValue); + } + } + } +} diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/Properties/AssemblyInfo.cs b/ACMESharp/ACMESharp.Providers.ClouDNS/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..ff7e58f8 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ACMESharp ClouDNS Provider")] +[assembly: AssemblyDescription("ClouDNS Provider extension for ACMESharp")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("github.com/ebekker/ACMESharp")] +[assembly: AssemblyProduct("ACMESharp.Providers.ClouDNS")] +[assembly: AssemblyCopyright("Copyright © 2017 Dave Crane. All rights reserved")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a9d514f4-a2f2-420f-ba1e-121d38939575")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/Results/DnsRecord.cs b/ACMESharp/ACMESharp.Providers.ClouDNS/Results/DnsRecord.cs new file mode 100644 index 00000000..6e92b64a --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/Results/DnsRecord.cs @@ -0,0 +1,11 @@ +namespace ACMESharp.Providers.ClouDNS +{ +class DnsRecord + { + public string Id { get; set; } + public string Type { get; set; } + public string Host { get; set; } + public string Record { get; set; } + public string Ttl { get; set; } + public string Status { get; set; } + }} \ No newline at end of file diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/Results/ZoneRecord.cs b/ACMESharp/ACMESharp.Providers.ClouDNS/Results/ZoneRecord.cs new file mode 100644 index 00000000..bf453cdd --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/Results/ZoneRecord.cs @@ -0,0 +1,10 @@ +namespace ACMESharp.Providers.ClouDNS.Results +{ + class ZoneRecord + { + public string Name { get; set; } + public string Type { get; set; } + public string Zone { get; set; } + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/ACMESharp/ACMESharp.Providers.ClouDNS/packages.config b/ACMESharp/ACMESharp.Providers.ClouDNS/packages.config new file mode 100644 index 00000000..e1fae9c6 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.ClouDNS/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ACMESharp/ACMESharp.sln b/ACMESharp/ACMESharp.sln index 561c9a2f..d0dc36f8 100644 --- a/ACMESharp/ACMESharp.sln +++ b/ACMESharp/ACMESharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp", "ACMESharp\ACMESharp.csproj", "{D551234B-0A8D-4DEE-8178-A81998DF0EDB}" EndProject @@ -75,6 +75,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp.Providers.Windows EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp.PKI.Providers.OpenSslLib", "ACMESharp.PKI.Providers.OpenSslLib\ACMESharp.PKI.Providers.OpenSslLib.csproj", "{86961A92-474A-4C0C-9A7D-F6EDD57EFD56}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp.Providers.ClouDNS", "ACMESharp.Providers.ClouDNS\ACMESharp.Providers.ClouDNS.csproj", "{529518FE-9546-4EC1-8E1F-9BC9239F0C7E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -149,6 +151,10 @@ Global {86961A92-474A-4C0C-9A7D-F6EDD57EFD56}.Debug|Any CPU.Build.0 = Debug|Any CPU {86961A92-474A-4C0C-9A7D-F6EDD57EFD56}.Release|Any CPU.ActiveCfg = Release|Any CPU {86961A92-474A-4C0C-9A7D-F6EDD57EFD56}.Release|Any CPU.Build.0 = Release|Any CPU + {529518FE-9546-4EC1-8E1F-9BC9239F0C7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {529518FE-9546-4EC1-8E1F-9BC9239F0C7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {529518FE-9546-4EC1-8E1F-9BC9239F0C7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {529518FE-9546-4EC1-8E1F-9BC9239F0C7E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE