Added 'DNSSEC' implementation
This commit is contained in:
@@ -63,7 +63,7 @@ default-deploy:
|
||||
tags:
|
||||
- docker
|
||||
- lnx
|
||||
- 64bit
|
||||
- server
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG == null
|
||||
script:
|
||||
@@ -122,7 +122,7 @@ core-deploy:
|
||||
tags:
|
||||
- docker
|
||||
- lnx
|
||||
- 64bit
|
||||
- server
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG =~ /^v[0-9.]+/
|
||||
script:
|
||||
@@ -182,7 +182,7 @@ extensions-deploy:
|
||||
tags:
|
||||
- docker
|
||||
- lnx
|
||||
- 64bit
|
||||
- server
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG =~ /^[a-z]+\/v[0-9.]+/
|
||||
script:
|
||||
|
||||
59
src/Extensions/Cloudflare.Dns/DnsDnssecExtensions.cs
Normal file
59
src/Extensions/Cloudflare.Dns/DnsDnssecExtensions.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Net.Api.Cloudflare.Dns.Internals;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for <see href="https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/">DNS DNSSEC records</see>.
|
||||
/// </summary>
|
||||
public static class DnsDnssecExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Delete DNSSEC.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
|
||||
/// <param name="zoneId">The zone identifier.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<string>> DeleteDnssecRecords(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
|
||||
return client.DeleteAsync<string>($"/zones/{zoneId}/dnssec", null, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable DNSSEC.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<DNSSEC>> EditDnssecStatus(this ICloudflareClient client, EditDnssecStatusRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
request.ZoneId.ValidateCloudflareId();
|
||||
|
||||
var req = new InternalEditDnssecStatusRequest
|
||||
{
|
||||
DnssecMultiSigner = request.DnssecMultiSigner,
|
||||
DnssecPresigned = request.DnssecPresigned,
|
||||
DnssecUseNsec3 = request.DnssecUseNsec3,
|
||||
Status = request.Status
|
||||
};
|
||||
|
||||
return client.PatchAsync<DNSSEC, InternalEditDnssecStatusRequest>($"/zones/{request.ZoneId}/dnssec", req, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Details about DNSSEC status and configuration.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
|
||||
/// <param name="zoneId">The zone identifier.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<DNSSEC>> DnssecDetails(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
|
||||
return client.GetAsync<DNSSEC>($"/zones/{zoneId}/dnssec", null, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Dns.Internals
|
||||
{
|
||||
internal class InternalEditDnssecStatusRequest
|
||||
{
|
||||
[JsonProperty("dnssec_multi_signer")]
|
||||
public bool? DnssecMultiSigner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, allows Cloudflare to transfer in a DNSSEC-signed zone including signatures from an external provider, without requiring Cloudflare to sign any records on the fly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that this feature has some limitations. See <see href="https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#dnssec">Cloudflare as Secondary</see> for details.
|
||||
/// </remarks>
|
||||
[JsonProperty("dnssec_presigned")]
|
||||
public bool? DnssecPresigned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, enables the use of NSEC3 together with DNSSEC on the zone.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Combined with setting <see cref="DnssecPresigned"/> to <see langword="true"/>, this enables the use of NSEC3 records when transferring in from an external provider.
|
||||
/// If <see cref="DnssecPresigned"/> is instead set to <see langword="false"/> (default), NSEC3 records will be generated and signed at request time.
|
||||
/// </remarks>
|
||||
[JsonProperty("dnssec_use_nsec3")]
|
||||
public bool? DnssecUseNsec3 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Status of DNSSEC, based on user-desired state and presence of necessary records.
|
||||
/// </summary>
|
||||
[JsonProperty("status")]
|
||||
public DnssecEditStatus? Status { get; set; }
|
||||
}
|
||||
}
|
||||
148
src/Extensions/Cloudflare.Dns/Models/DNSSEC.cs
Normal file
148
src/Extensions/Cloudflare.Dns/Models/DNSSEC.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents DNS Security Extensions (DNSSEC) information from Cloudflare.
|
||||
/// </summary>
|
||||
public class DNSSEC
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm key code.
|
||||
/// </summary>
|
||||
[JsonProperty("algorithm")]
|
||||
public string? Algorithm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Digest hash.
|
||||
/// </summary>
|
||||
[JsonProperty("digest")]
|
||||
public string? Digest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of digest algorithm.
|
||||
/// </summary>
|
||||
[JsonProperty("digest_algorithm")]
|
||||
public string? DigestAlgorithm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Coded type for digest algorithm.
|
||||
/// </summary>
|
||||
[JsonProperty("digest_type")]
|
||||
public string? DigestType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, multi-signer DNSSEC is enabled on the zone, allowing multiple providers to serve a DNSSEC-signed zone at the same time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required for DNSKEY records (except those automatically generated by Cloudflare) to be added to the zone.
|
||||
/// <br/>
|
||||
/// See <see href="https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/">Multi-signer DNSSEC</see> for details.
|
||||
/// </remarks>
|
||||
[JsonProperty("dnssec_multi_signer")]
|
||||
public bool? DnssecMultiSigner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, allows Cloudflare to transfer in a DNSSEC-signed zone including signatures from an external provider, without requiring Cloudflare to sign any records on the fly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that this feature has some limitations.
|
||||
/// See <see href="https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#dnssec">Cloudflare as Secondary</see> for details.
|
||||
/// </remarks>
|
||||
[JsonProperty("dnssec_presigned")]
|
||||
public bool? DnssecPresigned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, enables the use of NSEC3 together with DNSSEC on the zone.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Combined with setting <see cref="DnssecPresigned"/> to <see langword="true"/>, this enables the use of NSEC3 records when transferring in from an external provider.
|
||||
/// If <see cref="DnssecPresigned"/> is instead set to <see langword="false"/> (default), NSEC3 records will be generated and signed at request time.
|
||||
/// <br/>
|
||||
/// See <see href="https://developers.cloudflare.com/dns/dnssec/enable-nsec3/">DNSSEC with NSEC3</see> for details.
|
||||
/// </remarks>
|
||||
[JsonProperty("dnssec_use_nsec3")]
|
||||
public bool? DnssecUseNsec3 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Full DS record.
|
||||
/// </summary>
|
||||
[JsonProperty("ds")]
|
||||
public string? Ds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flag for DNSSEC record.
|
||||
/// </summary>
|
||||
[JsonProperty("flags")]
|
||||
public int? Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Code for key tag.
|
||||
/// </summary>
|
||||
[JsonProperty("key_tag")]
|
||||
public int? KeyTag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm key type.
|
||||
/// </summary>
|
||||
[JsonProperty("key_type")]
|
||||
public string? KeyType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When DNSSEC was last modified.
|
||||
/// </summary>
|
||||
[JsonProperty("modified_on")]
|
||||
public DateTime? ModifiedOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Public key for DS record.
|
||||
/// </summary>
|
||||
[JsonProperty("public_key")]
|
||||
public string? PublicKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Status of DNSSEC, based on user-desired state and presence of necessary records.
|
||||
/// </summary>
|
||||
[JsonProperty("status")]
|
||||
public DNSSECStatus? Status { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status of DNSSEC, based on user-desired state and presence of necessary records.
|
||||
/// <see href="https://github.com/cloudflare/cloudflare-typescript/blob/v4.4.1/src/resources/dns/dnssec.ts#L153">Source</see>
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum DNSSECStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Active.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "active")]
|
||||
Active = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Pending.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "pending")]
|
||||
Pending = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Disabled.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "disabled")]
|
||||
Disabled = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Pending disabled.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "pending-disabled")]
|
||||
PendingDisabled = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Error.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "error")]
|
||||
Error = 5
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,13 @@ This package contains the feature set of the _DNS_ section of the Cloudflare API
|
||||
|
||||
### [DNS]
|
||||
|
||||
### [DNSSEC]
|
||||
|
||||
- [Delete DNSSEC Records](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/delete/)
|
||||
- [Edit DNSSEC Status](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/)
|
||||
- [DNSSEC Details](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/get/)
|
||||
|
||||
|
||||
#### [Records]
|
||||
|
||||
- [Batch DNS Records](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/batch/)
|
||||
@@ -46,6 +53,7 @@ This package contains the feature set of the _DNS_ section of the Cloudflare API
|
||||
- [Show DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/get/)
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
Published under MIT License (see [choose a license])
|
||||
@@ -57,8 +65,8 @@ Published under MIT License (see [choose a license])
|
||||
[Account Custom Nameservers]: https://developers.cloudflare.com/api/resources/custom_nameservers/
|
||||
|
||||
[DNS]: https://developers.cloudflare.com/api/resources/dns/
|
||||
[Records]: https://developers.cloudflare.com/api/resources/dns/subresources/records/
|
||||
|
||||
[Settings]: https://developers.cloudflare.com/api/resources/dns/subresources/settings/
|
||||
[Account]: https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/
|
||||
[Zone]: https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/
|
||||
[DNSSEC]: https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/
|
||||
[Records]: https://developers.cloudflare.com/api/resources/dns/subresources/records/
|
||||
[Settings]: https://developers.cloudflare.com/api/resources/dns/subresources/settings/
|
||||
[Account]: https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/
|
||||
[Zone]: https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a request to edit the DNSSEC (Domain Name System Security Extensions) status for a domain.
|
||||
/// </summary>
|
||||
public class EditDnssecStatusRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EditDnssecStatusRequest"/> class.
|
||||
/// </summary>
|
||||
/// <param name="zoneId">The zone identifier.</param>
|
||||
public EditDnssecStatusRequest(string zoneId)
|
||||
{
|
||||
ZoneId = zoneId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The zone identifier.
|
||||
/// </summary>
|
||||
public string ZoneId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, multi-signer DNSSEC is enabled on the zone, allowing multiple providers to serve a DNSSEC-signed zone at the same time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required for DNSKEY records (except those automatically generated by Cloudflare) to be added to the zone.
|
||||
/// <br/>
|
||||
/// See <see href="https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/">Multi-signer DNSSEC</see> for details.
|
||||
/// </remarks>
|
||||
public bool? DnssecMultiSigner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, allows Cloudflare to transfer in a DNSSEC-signed zone including signatures from an external provider, without requiring Cloudflare to sign any records on the fly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that this feature has some limitations. See <see href="https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#dnssec">Cloudflare as Secondary</see> for details.
|
||||
/// </remarks>
|
||||
public bool? DnssecPresigned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see langword="true"/>, enables the use of NSEC3 together with DNSSEC on the zone.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Combined with setting <see cref="DnssecPresigned"/> to <see langword="true"/>, this enables the use of NSEC3 records when transferring in from an external provider.
|
||||
/// If <see cref="DnssecPresigned"/> is instead set to <see langword="false"/> (default), NSEC3 records will be generated and signed at request time.
|
||||
/// </remarks>
|
||||
public bool? DnssecUseNsec3 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Status of DNSSEC, based on user-desired state and presence of necessary records.
|
||||
/// </summary>
|
||||
public DnssecEditStatus? Status { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status of DNSSEC, based on user-desired state and presence of necessary records.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum DnssecEditStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// DNSSEC is enabled.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "active")]
|
||||
Active = 1,
|
||||
|
||||
/// <summary>
|
||||
/// DNSSEC is disabled.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "disabled")]
|
||||
Disabled = 3,
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.9.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.9.3" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.10.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.10.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Net.Api.Cloudflare;
|
||||
using AMWD.Net.Api.Cloudflare.Dns;
|
||||
using Moq;
|
||||
|
||||
namespace Cloudflare.Dns.Tests.DnsDnssecExtensions
|
||||
{
|
||||
[TestClass]
|
||||
public class DeleteDnssecRecordsTest
|
||||
{
|
||||
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
|
||||
|
||||
private Mock<ICloudflareClient> _clientMock;
|
||||
|
||||
private CloudflareResponse<string> _response;
|
||||
|
||||
private List<(string RequestPath, IQueryParameterFilter? QueryFilter)> _callbacks;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
_callbacks = [];
|
||||
|
||||
_response = new CloudflareResponse<string>
|
||||
{
|
||||
Success = true,
|
||||
Messages =
|
||||
[
|
||||
new ResponseInfo(1000, "Message 1")
|
||||
],
|
||||
Errors =
|
||||
[
|
||||
new ResponseInfo(1000, "Error 1")
|
||||
],
|
||||
Result = "023e105f4ecef8ad9ca31a8372d0c353"
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldDeleteDnssecRecords()
|
||||
{
|
||||
// Arrange
|
||||
var client = GetClient();
|
||||
|
||||
// Act
|
||||
var response = await client.DeleteDnssecRecords(ZoneId);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsTrue(response.Success);
|
||||
Assert.AreEqual(_response.Result, response.Result);
|
||||
|
||||
Assert.AreEqual(1, _callbacks.Count);
|
||||
|
||||
var callback = _callbacks.First();
|
||||
Assert.AreEqual($"/zones/{ZoneId}/dnssec", callback.RequestPath);
|
||||
Assert.IsNull(callback.QueryFilter);
|
||||
|
||||
_clientMock.Verify(m => m.DeleteAsync<string>(
|
||||
$"/zones/{ZoneId}/dnssec",
|
||||
null,
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
_clientMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
private ICloudflareClient GetClient()
|
||||
{
|
||||
_clientMock = new Mock<ICloudflareClient>();
|
||||
_clientMock
|
||||
.Setup(m => m.DeleteAsync<string>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<IQueryParameterFilter?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Callback<string, IQueryParameterFilter?, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
|
||||
.ReturnsAsync(() => _response);
|
||||
|
||||
return _clientMock.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Net.Api.Cloudflare;
|
||||
using AMWD.Net.Api.Cloudflare.Dns;
|
||||
using Moq;
|
||||
|
||||
namespace Cloudflare.Dns.Tests.DnsDnssecExtensions
|
||||
{
|
||||
[TestClass]
|
||||
public class DnssecDetailsTest
|
||||
{
|
||||
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
|
||||
|
||||
private Mock<ICloudflareClient> _clientMock;
|
||||
|
||||
private CloudflareResponse<DNSSEC> _response;
|
||||
|
||||
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
_callbacks = [];
|
||||
|
||||
_response = new CloudflareResponse<DNSSEC>
|
||||
{
|
||||
Success = true,
|
||||
Messages =
|
||||
[
|
||||
new ResponseInfo(1000, "Message 1")
|
||||
],
|
||||
Errors =
|
||||
[
|
||||
new ResponseInfo(1000, "Error 1")
|
||||
],
|
||||
Result = new DNSSEC
|
||||
{
|
||||
Algorithm = "ECDSAP256SHA256",
|
||||
Digest = "1234567890ABCDEF",
|
||||
DigestAlgorithm = "SHA256",
|
||||
DigestType = "2",
|
||||
DnssecMultiSigner = true,
|
||||
DnssecPresigned = false,
|
||||
DnssecUseNsec3 = true,
|
||||
Ds = "12345 13 2 1234567890ABCDEF",
|
||||
Flags = 257,
|
||||
KeyTag = 12345,
|
||||
KeyType = "ECDSAP256SHA256",
|
||||
ModifiedOn = DateTime.Parse("2025-08-02 10:20:30"),
|
||||
PublicKey = "ABCDEF1234567890",
|
||||
Status = DNSSECStatus.Active
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldGetDnssecDetails()
|
||||
{
|
||||
// Arrange
|
||||
var client = GetClient();
|
||||
|
||||
// Act
|
||||
var response = await client.DnssecDetails(ZoneId);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsTrue(response.Success);
|
||||
Assert.AreEqual(_response.Result, response.Result);
|
||||
|
||||
Assert.AreEqual(1, _callbacks.Count);
|
||||
|
||||
var callback = _callbacks.First();
|
||||
Assert.AreEqual($"/zones/{ZoneId}/dnssec", callback.RequestPath);
|
||||
Assert.IsNull(callback.QueryFilter);
|
||||
|
||||
_clientMock.Verify(m => m.GetAsync<DNSSEC>(
|
||||
$"/zones/{ZoneId}/dnssec",
|
||||
null,
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
_clientMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
private ICloudflareClient GetClient()
|
||||
{
|
||||
_clientMock = new Mock<ICloudflareClient>();
|
||||
_clientMock
|
||||
.Setup(m => m.GetAsync<DNSSEC>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<IQueryParameterFilter>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
|
||||
.ReturnsAsync(() => _response);
|
||||
|
||||
return _clientMock.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Net.Api.Cloudflare;
|
||||
using AMWD.Net.Api.Cloudflare.Dns;
|
||||
using AMWD.Net.Api.Cloudflare.Dns.Internals;
|
||||
using Moq;
|
||||
|
||||
namespace Cloudflare.Dns.Tests.DnsDnssecExtensions
|
||||
{
|
||||
[TestClass]
|
||||
public class EditDnssecStatusTest
|
||||
{
|
||||
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
|
||||
|
||||
private Mock<ICloudflareClient> _clientMock;
|
||||
|
||||
private CloudflareResponse<DNSSEC> _response;
|
||||
|
||||
private List<(string RequestPath, InternalEditDnssecStatusRequest Request)> _callbacks;
|
||||
|
||||
private EditDnssecStatusRequest _request;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
_callbacks = [];
|
||||
|
||||
_response = new CloudflareResponse<DNSSEC>
|
||||
{
|
||||
Success = true,
|
||||
Messages =
|
||||
[
|
||||
new ResponseInfo(1000, "Message 1")
|
||||
],
|
||||
Errors =
|
||||
[
|
||||
new ResponseInfo(1000, "Error 1")
|
||||
],
|
||||
Result = new DNSSEC
|
||||
{
|
||||
Algorithm = "ECDSAP256SHA256",
|
||||
Digest = "1234567890ABCDEF",
|
||||
DigestAlgorithm = "SHA256",
|
||||
DigestType = "2",
|
||||
DnssecMultiSigner = true,
|
||||
DnssecPresigned = false,
|
||||
DnssecUseNsec3 = true,
|
||||
Ds = "12345 13 2 1234567890ABCDEF",
|
||||
Flags = 257,
|
||||
KeyTag = 12345,
|
||||
KeyType = "ECDSAP256SHA256",
|
||||
ModifiedOn = DateTime.UtcNow,
|
||||
PublicKey = "ABCDEF1234567890",
|
||||
Status = DNSSECStatus.Active
|
||||
}
|
||||
};
|
||||
|
||||
_request = new EditDnssecStatusRequest(ZoneId)
|
||||
{
|
||||
DnssecMultiSigner = true,
|
||||
DnssecPresigned = false,
|
||||
DnssecUseNsec3 = true,
|
||||
Status = DnssecEditStatus.Active
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldEditDnssecStatus()
|
||||
{
|
||||
// Arrange
|
||||
var client = GetClient();
|
||||
|
||||
// Act
|
||||
var response = await client.EditDnssecStatus(_request);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsTrue(response.Success);
|
||||
Assert.AreEqual(_response.Result, response.Result);
|
||||
|
||||
Assert.AreEqual(1, _callbacks.Count);
|
||||
|
||||
var callback = _callbacks.First();
|
||||
Assert.AreEqual($"/zones/{ZoneId}/dnssec", callback.RequestPath);
|
||||
|
||||
Assert.IsNotNull(callback.Request);
|
||||
Assert.AreEqual(_request.DnssecMultiSigner, callback.Request.DnssecMultiSigner);
|
||||
Assert.AreEqual(_request.DnssecPresigned, callback.Request.DnssecPresigned);
|
||||
Assert.AreEqual(_request.DnssecUseNsec3, callback.Request.DnssecUseNsec3);
|
||||
Assert.AreEqual(_request.Status, callback.Request.Status);
|
||||
|
||||
_clientMock.Verify(m => m.PatchAsync<DNSSEC, InternalEditDnssecStatusRequest>(
|
||||
$"/zones/{ZoneId}/dnssec",
|
||||
It.IsAny<InternalEditDnssecStatusRequest>(),
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
_clientMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
private ICloudflareClient GetClient()
|
||||
{
|
||||
_clientMock = new Mock<ICloudflareClient>();
|
||||
_clientMock
|
||||
.Setup(m => m.PatchAsync<DNSSEC, InternalEditDnssecStatusRequest>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<InternalEditDnssecStatusRequest>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Callback<string, InternalEditDnssecStatusRequest, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
|
||||
.ReturnsAsync(() => _response);
|
||||
|
||||
return _clientMock.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user