Added ZoneTransfer implementation

This commit is contained in:
2025-10-28 21:10:24 +01:00
parent 6eed338ea8
commit 591b2f8899
51 changed files with 4176 additions and 0 deletions

View File

@@ -0,0 +1,584 @@
using System.Linq;
using System.Net.Sockets;
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/zone_transfers/">DNS Zone Transfers</see>.
/// </summary>
public static class DnsZoneTransfersExtensions
{
#region ACLs
/// <summary>
/// Create ACL.
/// </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<ACL>> CreateACL(this ICloudflareClient client, CreateACLRequest request, CancellationToken cancellationToken = default)
{
request.AccountId.ValidateCloudflareId();
if (request.IpRangeBaseAddress.AddressFamily == AddressFamily.InterNetwork && request.IpRangeSubnet < 24)
throw new ArgumentOutOfRangeException(nameof(request.IpRange), "CIDRs are limited to a maximum of /24 for IPv4.");
if (request.IpRangeBaseAddress.AddressFamily == AddressFamily.InterNetworkV6 && request.IpRangeSubnet < 64)
throw new ArgumentOutOfRangeException(nameof(request.IpRange), "CIDRs are limited to a maximum of /64 for IPv6.");
var req = new InternalDnsZoneTransferAclRequest
{
Name = request.Name,
IpRange = request.IpRange
};
return client.PostAsync<ACL, InternalDnsZoneTransferAclRequest>($"/accounts/{request.AccountId}/secondary_dns/acls", req, null, cancellationToken);
}
/// <summary>
/// Delete ACL.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="aclId">The access control list identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<Identifier>> DeleteACL(this ICloudflareClient client, string accountId, string aclId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
aclId.ValidateCloudflareId();
return client.DeleteAsync<Identifier>($"/accounts/{accountId}/secondary_dns/acls/{aclId}", null, cancellationToken);
}
/// <summary>
/// Get ACL.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="aclId">The access control list identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<ACL>> ACLDetails(this ICloudflareClient client, string accountId, string aclId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
aclId.ValidateCloudflareId();
return client.GetAsync<ACL>($"/accounts/{accountId}/secondary_dns/acls/{aclId}", null, cancellationToken);
}
/// <summary>
/// List ACLs.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<IReadOnlyCollection<ACL>>> ListACLs(this ICloudflareClient client, string accountId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
return client.GetAsync<IReadOnlyCollection<ACL>>($"/accounts/{accountId}/secondary_dns/acls", null, cancellationToken);
}
/// <summary>
/// Update ACL.
/// </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<ACL>> UpdateACL(this ICloudflareClient client, UpdateDnsZoneTransferAclRequest request, CancellationToken cancellationToken = default)
{
request.AccountId.ValidateCloudflareId();
request.AclId.ValidateCloudflareId();
if (request.IpRangeBaseAddress.AddressFamily == AddressFamily.InterNetwork && request.IpRangeSubnet < 24)
throw new ArgumentOutOfRangeException(nameof(request.IpRange), "CIDRs are limited to a maximum of /24 for IPv4.");
if (request.IpRangeBaseAddress.AddressFamily == AddressFamily.InterNetworkV6 && request.IpRangeSubnet < 64)
throw new ArgumentOutOfRangeException(nameof(request.IpRange), "CIDRs are limited to a maximum of /64 for IPv6.");
var req = new InternalDnsZoneTransferAclRequest
{
Name = request.Name,
IpRange = request.IpRange
};
return client.PutAsync<ACL, InternalDnsZoneTransferAclRequest>($"/accounts/{request.AccountId}/secondary_dns/acls/{request.AclId}", req, cancellationToken);
}
#endregion ACLs
#region Force AXFR
/// <summary>
/// Sends AXFR zone transfer request to primary nameserver(s).
/// </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>> ForceAXFR(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.PostAsync<string, object>($"/zones/{zoneId}/secondary_dns/force_axfr", null, null, cancellationToken);
}
#endregion Force AXFR
#region Incoming
/// <summary>
/// Create secondary zone configuration for incoming zone transfers.
/// </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<IncomingZoneConfiguration>> CreateSecondaryZoneConfiguration(this ICloudflareClient client, SecondaryZoneConfigurationRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The zone name is required.");
if (request.AutoRefreshSeconds < 0)
throw new ArgumentOutOfRangeException(nameof(request.AutoRefreshSeconds), "Auto refresh seconds must be greater than or equal to 0.");
if (request.Peers.Count == 0)
throw new ArgumentOutOfRangeException(nameof(request.Peers), "At least one peer is required.");
foreach (string peer in request.Peers)
peer.ValidateCloudflareId();
var req = new InternalSecondaryZoneConfigurationRequest
{
Name = request.Name,
AutoRefreshSeconds = request.AutoRefreshSeconds,
Peers = request.Peers.ToList()
};
return client.PostAsync<IncomingZoneConfiguration, InternalSecondaryZoneConfigurationRequest>($"/zones/{request.ZoneId}/secondary_dns/incoming", req, null, cancellationToken);
}
/// <summary>
/// Delete secondary zone configuration for incoming zone transfers.
/// </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<Identifier>> DeleteSecondaryZoneConfiguration(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.DeleteAsync<Identifier>($"/zones/{zoneId}/secondary_dns/incoming", null, cancellationToken);
}
/// <summary>
/// Get secondary zone configuration for incoming zone transfers.
/// </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<IncomingZoneConfiguration>> SecondaryZoneConfigurationDetails(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.GetAsync<IncomingZoneConfiguration>($"/zones/{zoneId}/secondary_dns/incoming", null, cancellationToken);
}
/// <summary>
/// Update secondary zone configuration for incoming zone transfers.
/// </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<IncomingZoneConfiguration>> UpdateSecondaryZoneConfiguration(this ICloudflareClient client, SecondaryZoneConfigurationRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The zone name is required.");
if (request.AutoRefreshSeconds < 0)
throw new ArgumentOutOfRangeException(nameof(request.AutoRefreshSeconds), "Auto refresh seconds must be greater than or equal to 0.");
if (request.Peers.Count == 0)
throw new ArgumentOutOfRangeException(nameof(request.Peers), "At least one peer is required.");
foreach (string peer in request.Peers)
peer.ValidateCloudflareId();
var req = new InternalSecondaryZoneConfigurationRequest
{
Name = request.Name,
AutoRefreshSeconds = request.AutoRefreshSeconds,
Peers = request.Peers.ToList()
};
return client.PutAsync<IncomingZoneConfiguration, InternalSecondaryZoneConfigurationRequest>($"/zones/{request.ZoneId}/secondary_dns/incoming", req, cancellationToken);
}
#endregion Incoming
#region Outgoing
/// <summary>
/// Create primary zone configuration for outgoing zone transfers.
/// </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<OutgoingZoneConfiguration>> CreatePrimaryZoneConfiguration(this ICloudflareClient client, PrimaryZoneConfigurationRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The zone name is required.");
if (request.Peers.Count == 0)
throw new ArgumentOutOfRangeException(nameof(request.Peers), "At least one peer is required.");
foreach (string peer in request.Peers)
peer.ValidateCloudflareId();
var req = new InternalPrimaryZoneConfigurationRequest
{
Name = request.Name,
Peers = request.Peers.ToList()
};
return client.PostAsync<OutgoingZoneConfiguration, InternalPrimaryZoneConfigurationRequest>($"/zones/{request.ZoneId}/secondary_dns/outgoing", req, null, cancellationToken);
}
/// <summary>
/// Delete primary zone configuration for outgoing zone transfers.
/// </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<Identifier>> DeletePrimaryZoneConfiguration(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.DeleteAsync<Identifier>($"/zones/{zoneId}/secondary_dns/outgoing", null, cancellationToken);
}
/// <summary>
/// Disable outgoing zone transfers for primary zone and clears IXFR backlog of primary zone.
/// </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>
/// <returns>
/// Referring to the
/// <see href="https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/disable/">documentation</see>,
/// the text value should be <em>Disabled</em>.
/// </returns>
public static Task<CloudflareResponse<string>> DisableOutgoingZoneTransfers(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.PostAsync<string, object>($"/zones/{zoneId}/secondary_dns/outgoing/disable", null, null, cancellationToken);
}
/// <summary>
/// Enable outgoing zone transfers for primary zone.
/// </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>
/// <returns>
/// Referring to the
/// <see href="https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/enable/">documentation</see>,
/// the text value should be <em>Enabled</em>.
/// </returns>
public static Task<CloudflareResponse<string>> EnableOutgoingZoneTransfers(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.PostAsync<string, object>($"/zones/{zoneId}/secondary_dns/outgoing/enable", null, null, cancellationToken);
}
/// <summary>
/// Get primary zone configuration for outgoing zone transfers
/// </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<OutgoingZoneConfiguration>> PrimaryZoneConfigurationDetails(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.GetAsync<OutgoingZoneConfiguration>($"/zones/{zoneId}/secondary_dns/outgoing", null, cancellationToken);
}
/// <summary>
/// Update primary zone configuration for outgoing zone transfers.
/// </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<OutgoingZoneConfiguration>> UpdatePrimaryZoneConfiguration(this ICloudflareClient client, PrimaryZoneConfigurationRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The zone name is required.");
if (request.Peers.Count == 0)
throw new ArgumentOutOfRangeException(nameof(request.Peers), "At least one peer is required.");
foreach (string peer in request.Peers)
peer.ValidateCloudflareId();
var req = new InternalPrimaryZoneConfigurationRequest
{
Name = request.Name,
Peers = request.Peers.ToList()
};
return client.PutAsync<OutgoingZoneConfiguration, InternalPrimaryZoneConfigurationRequest>($"/zones/{request.ZoneId}/secondary_dns/outgoing", req, cancellationToken);
}
/// <summary>
/// Notifies the secondary nameserver(s) and clears IXFR backlog of primary zone.
/// </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>
/// <returns>
/// Referring to the
/// <see href="https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/force_notify/">documentation</see>,
/// the text value should be <em>OK</em>.
/// </returns>
public static Task<CloudflareResponse<string>> ForceDNSNotify(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.PostAsync<string, object>($"/zones/{zoneId}/secondary_dns/outgoing/force_notify", null, null, cancellationToken);
}
/// <summary>
/// Enable outgoing zone transfers for primary zone.
/// </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>
/// <returns>
/// Referring to the
/// <see href="https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/subresources/status/methods/get/">documentation</see>,
/// the text value should be <em>Enabled</em> or <em>Disabled</em>.
/// </returns>
public static Task<CloudflareResponse<string>> GetOutgoingZoneTransferStatus(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.GetAsync<string>($"/zones/{zoneId}/secondary_dns/outgoing/status", null, cancellationToken);
}
#endregion Outgoing
#region Peers
/// <summary>
/// List Peers.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<IReadOnlyCollection<Peer>>> ListPeers(this ICloudflareClient client, string accountId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
return client.GetAsync<IReadOnlyCollection<Peer>>($"/accounts/{accountId}/secondary_dns/peers", null, cancellationToken);
}
/// <summary>
/// Get Peer.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="peerId">The peer identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<Peer>> PeerDetails(this ICloudflareClient client, string accountId, string peerId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
peerId.ValidateCloudflareId();
return client.GetAsync<Peer>($"/accounts/{accountId}/secondary_dns/peers/{peerId}", null, cancellationToken);
}
/// <summary>
/// Create Peer.
/// </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<Peer>> CreatePeer(this ICloudflareClient client, CreatePeerRequest request, CancellationToken cancellationToken = default)
{
request.AccountId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The peer name is required.");
var req = new InternalCreatePeerRequest
{
Name = request.Name
};
return client.PostAsync<Peer, InternalCreatePeerRequest>($"/accounts/{request.AccountId}/secondary_dns/peers", req, null, cancellationToken);
}
/// <summary>
/// Modify Peer.
/// </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<Peer>> UpdatePeer(this ICloudflareClient client, UpdatePeerRequest request, CancellationToken cancellationToken = default)
{
request.AccountId.ValidateCloudflareId();
request.PeerId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The peer name is required.");
if (request.Port < 0 || 65535 < request.Port)
throw new ArgumentOutOfRangeException(nameof(request.Port), "The port must be between 0 and 65535.");
var req = new InternalUpdatePeerRequest
{
Name = request.Name,
Ip = request.IpAddress,
IxfrEnable = request.IXFREnable,
Port = request.Port,
TSigId = request.TSIGId
};
return client.PutAsync<Peer, InternalUpdatePeerRequest>($"/accounts/{request.AccountId}/secondary_dns/peers/{request.PeerId}", req, cancellationToken);
}
/// <summary>
/// Delete Peer.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="peerId">The peer identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<Identifier>> DeletePeer(this ICloudflareClient client, string accountId, string peerId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
peerId.ValidateCloudflareId();
return client.DeleteAsync<Identifier>($"/accounts/{accountId}/secondary_dns/peers/{peerId}", null, cancellationToken);
}
#endregion Peers
#region TSIGs
/// <summary>
/// List TSIGs.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<IReadOnlyCollection<TSIG>>> ListTSIGs(this ICloudflareClient client, string accountId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
return client.GetAsync<IReadOnlyCollection<TSIG>>($"/accounts/{accountId}/secondary_dns/tsigs", null, cancellationToken);
}
/// <summary>
/// Get TSIG.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="tsigId">The TSIG identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<TSIG>> TSIGDetails(this ICloudflareClient client, string accountId, string tsigId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
tsigId.ValidateCloudflareId();
return client.GetAsync<TSIG>($"/accounts/{accountId}/secondary_dns/tsigs/{tsigId}", null, cancellationToken);
}
/// <summary>
/// Create TSIG.
/// </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<TSIG>> CreateTSIG(this ICloudflareClient client, CreateTSIGRequest request, CancellationToken cancellationToken = default)
{
request.AccountId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The TSIG name is required.");
if (!Enum.IsDefined(typeof(TSigAlgorithm), request.Algorithm))
throw new ArgumentOutOfRangeException(nameof(request.Algorithm), "The TSIG algorithm is invalid.");
if (string.IsNullOrWhiteSpace(request.Secret))
throw new ArgumentNullException(nameof(request.Secret), "The TSIG secret is required.");
var req = new InternalTSIGRequest
{
Name = request.Name,
Algorithm = request.Algorithm,
Secret = request.Secret
};
return client.PostAsync<TSIG, InternalTSIGRequest>($"/accounts/{request.AccountId}/secondary_dns/tsigs", req, null, cancellationToken);
}
/// <summary>
/// Modify TSIG.
/// </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<TSIG>> UpdateTSIG(this ICloudflareClient client, UpdateTSIGRequest request, CancellationToken cancellationToken = default)
{
request.AccountId.ValidateCloudflareId();
request.TSigId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name), "The TSIG name is required.");
if (!Enum.IsDefined(typeof(TSigAlgorithm), request.Algorithm))
throw new ArgumentOutOfRangeException(nameof(request.Algorithm), "The TSIG algorithm is invalid.");
if (string.IsNullOrWhiteSpace(request.Secret))
throw new ArgumentNullException(nameof(request.Secret), "The TSIG secret is required.");
var req = new InternalTSIGRequest
{
Name = request.Name,
Algorithm = request.Algorithm,
Secret = request.Secret
};
return client.PutAsync<TSIG, InternalTSIGRequest>($"/accounts/{request.AccountId}/secondary_dns/tsigs/{request.TSigId}", req, cancellationToken);
}
/// <summary>
/// Delete TSIG.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/> instance.</param>
/// <param name="accountId">The account identifier.</param>
/// <param name="tsigId">The TSIG identifier.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<Identifier>> DeleteTSIG(this ICloudflareClient client, string accountId, string tsigId, CancellationToken cancellationToken = default)
{
accountId.ValidateCloudflareId();
tsigId.ValidateCloudflareId();
return client.DeleteAsync<Identifier>($"/accounts/{accountId}/secondary_dns/tsigs/{tsigId}", null, cancellationToken);
}
#endregion TSIGs
}
}

View File

@@ -0,0 +1,100 @@
using System.Runtime.Serialization;
using Newtonsoft.Json.Converters;
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Available TSIG algorithms as <see href="https://www.rfc-editor.org/rfc/rfc8945.html#section-6">recommended by IANA</see>.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum TSigAlgorithm
{
/// <summary>
/// HMAC SHA1.
/// </summary>
/// <remarks>
/// Implementation: <strong>must</strong>
/// <br/>
/// Use: <em>not recommended</em>
/// </remarks>
[EnumMember(Value = "hmac-sha1")]
HMAC_SHA1 = 1,
/// <summary>
/// HMAC SHA224.
/// </summary>
/// <remarks>
/// Implementation: <strong>may</strong>
/// <br/>
/// Use: <em>may</em>
/// </remarks>
[EnumMember(Value = "hmac-sha224")]
HMAC_SHA224 = 2,
/// <summary>
/// HMAC SHA256.
/// </summary>
/// <remarks>
/// Implementation: <strong>must</strong>
/// <br/>
/// Use: <em>recommended</em>
/// </remarks>
[EnumMember(Value = "hmac-sha256")]
HMAC_SHA256 = 3,
/// <summary>
/// HMAC SHA384.
/// </summary>
/// <remarks>
/// Implementation: <strong>may</strong>
/// <br/>
/// Use: <em>may</em>
/// </remarks>
[EnumMember(Value = "hmac-sha384")]
HMAC_SHA384 = 4,
/// <summary>
/// HMAC SHA512.
/// </summary>
/// <remarks>
/// Implementation: <strong>may</strong>
/// <br/>
/// Use: <em>may</em>
/// </remarks>
[EnumMember(Value = "hmac-sha512")]
HMAC_SHA512 = 5,
/// <summary>
/// HMAC SHA256 128.
/// </summary>
/// <remarks>
/// Implementation: <strong>may</strong>
/// <br/>
/// Use: <em>may</em>
/// </remarks>
[EnumMember(Value = "hmac-sha256-128")]
HMAC_SHA256_128 = 6,
/// <summary>
/// HMAC SHA384 192.
/// </summary>
/// <remarks>
/// Implementation: <strong>may</strong>
/// <br/>
/// Use: <em>may</em>
/// </remarks>
[EnumMember(Value = "hmac-sha384-192")]
HMAC_SHA384_192 = 7,
/// <summary>
/// HMAC SHA512 256.
/// </summary>
/// <remarks>
/// Implementation: <strong>may</strong>
/// <br/>
/// Use: <em>may</em>
/// </remarks>
[EnumMember(Value = "hmac-sha512-256")]
HMAC_SHA512_256 = 8,
}
}

View File

@@ -0,0 +1,8 @@
namespace AMWD.Net.Api.Cloudflare.Dns.Internals
{
internal class InternalCreatePeerRequest
{
[JsonProperty("name")]
public string? Name { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
internal class InternalDnsZoneTransferAclRequest
{
[JsonProperty("ip_range")]
public string? IpRange { get; set; }
[JsonProperty("name")]
public string? Name { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace AMWD.Net.Api.Cloudflare.Dns.Internals
{
internal class InternalPrimaryZoneConfigurationRequest
{
[JsonProperty("name")]
public string? Name { get; set; }
[JsonProperty("peers")]
public IReadOnlyCollection<string>? Peers { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace AMWD.Net.Api.Cloudflare.Dns.Internals
{
internal class InternalSecondaryZoneConfigurationRequest
{
[JsonProperty("name")]
public string? Name { get; set; }
[JsonProperty("auto_refresh_seconds")]
public int? AutoRefreshSeconds { get; set; }
[JsonProperty("peers")]
public IReadOnlyCollection<string>? Peers { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace AMWD.Net.Api.Cloudflare.Dns.Internals
{
internal class InternalTSIGRequest
{
[JsonProperty("algo")]
public TSigAlgorithm? Algorithm { get; set; }
[JsonProperty("name")]
public string? Name { get; set; }
[JsonProperty("secret")]
public string? Secret { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
namespace AMWD.Net.Api.Cloudflare.Dns.Internals
{
internal class InternalUpdatePeerRequest : InternalCreatePeerRequest
{
[JsonProperty("ip")]
public string? Ip { get; set; }
[JsonProperty("ixfr_enable")]
public bool? IxfrEnable { get; set; }
[JsonProperty("port")]
public int? Port { get; set; }
[JsonProperty("tsig_id")]
public string? TSigId { get; set; }
}
}

View File

@@ -0,0 +1,31 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents an Access Control List (ACL) entry, which defines the allowed IP ranges for DNS zone transfers.
/// </summary>
public class ACL
{
/// <summary>
/// The unique identifier.
/// </summary>
[JsonProperty("id")]
public string? Id { get; set; }
/// <summary>
/// Allowed IPv4/IPv6 address range of primary or secondary nameservers.
/// This will be applied for the entire account.
/// </summary>
/// <remarks>
/// The IP range is used to allow additional NOTIFY IPs for secondary zones and IPs Cloudflare allows AXFR/IXFR requests from for primary zones.
/// CIDRs are limited to a maximum of /24 for IPv4 and /64 for IPv6 respectively.
/// </remarks>
[JsonProperty("ip_range")]
public string? IpRange { get; set; }
/// <summary>
/// The name of the ACL.
/// </summary>
[JsonProperty("name")]
public string? Name { get; set; }
}
}

View File

@@ -0,0 +1,57 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a response of a secondary zone configuration.
/// </summary>
public class IncomingZoneConfiguration
{
/// <summary>
/// The unique identifier.
/// </summary>
[JsonProperty("id")]
public string? Id { get; set; }
/// <summary>
/// How often should a secondary zone auto refresh regardless of DNS NOTIFY.
/// Not applicable for primary zones.
/// </summary>
[JsonProperty("auto_refresh_seconds")]
public int? AutoRefreshSeconds { get; set; }
/// <summary>
/// The time for a specific event.
/// </summary>
[JsonProperty("checked_time")]
public DateTime? CheckedTime { get; set; }
/// <summary>
/// The time for a specific event.
/// </summary>
[JsonProperty("created_time")]
public DateTime? CreatedTime { get; set; }
/// <summary>
/// The time for a specific event.
/// </summary>
[JsonProperty("modified_time")]
public DateTime? ModifiedTime { get; set; }
/// <summary>
/// The zone name.
/// </summary>
[JsonProperty("name")]
public string? Name { get; set; }
/// <summary>
/// A list of peer tags.
/// </summary>
[JsonProperty("peers")]
public IReadOnlyCollection<string>? Peers { get; set; }
/// <summary>
/// The serial number of the SOA for the given zone.
/// </summary>
[JsonProperty("soa_serial")]
public int? SoaSerial { get; set; }
}
}

View File

@@ -0,0 +1,50 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a response of a secondary zone configuration.
/// </summary>
public class OutgoingZoneConfiguration
{
/// <summary>
/// The unique identifier.
/// </summary>
[JsonProperty("id")]
public string? Id { get; set; }
/// <summary>
/// The time for a specific event.
/// </summary>
[JsonProperty("checked_time")]
public DateTime? CheckedTime { get; set; }
/// <summary>
/// The time for a specific event.
/// </summary>
[JsonProperty("created_time")]
public DateTime? CreatedTime { get; set; }
/// <summary>
/// The time for a specific event.
/// </summary>
[JsonProperty("last_transferred_time")]
public DateTime? LastTransferredTime { get; set; }
/// <summary>
/// The zone name.
/// </summary>
[JsonProperty("name")]
public string? Name { get; set; }
/// <summary>
/// A list of peer tags.
/// </summary>
[JsonProperty("peers")]
public IReadOnlyCollection<string>? Peers { get; set; }
/// <summary>
/// The serial number of the SOA for the given zone.
/// </summary>
[JsonProperty("soa_serial")]
public int? SoaSerial { get; set; }
}
}

View File

@@ -0,0 +1,61 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// A Cloudflare peer.
/// <see href="https://github.com/cloudflare/cloudflare-typescript/blob/v4.4.1/src/resources/dns/zone-transfers/peers.ts#L119">Source</see>
/// </summary>
public class Peer
{
/// <summary>
/// Initializes a new instance of the <see cref="Peer"/> class.
/// </summary>
/// <param name="id">The unique identifier.</param>
/// <param name="name">The name of the peer.</param>
public Peer(string id, string name)
{
Id = id;
Name = name;
}
/// <summary>
/// The unique identifier.
/// </summary>
[JsonProperty("id")]
public string Id { get; set; }
/// <summary>
/// The name of the peer.
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// IPv4/IPv6 address of primary or secondary nameserver, depending on what zone this peer is linked to.
/// <list type="bullet">
/// <item>For primary zones this IP defines the IP of the secondary nameserver Cloudflare will NOTIFY upon zone changes.</item>
/// <item>For secondary zones this IP defines the IP of the primary nameserver Cloudflare will send AXFR/IXFR requests to.</item>
/// </list>
/// </summary>
[JsonProperty("ip")]
public string? IpAddress { get; set; }
/// <summary>
/// Enable IXFR transfer protocol, default is AXFR.
/// <em>Only applicable to secondary zones.</em>
/// </summary>
[JsonProperty("ixfr_enable")]
public bool? IXFREnabled { get; set; }
/// <summary>
/// DNS port of primary or secondary nameserver, depending on what zone this peer is linked to.
/// </summary>
[JsonProperty("port")]
public int? Port { get; set; }
/// <summary>
/// TSIG authentication will be used for zone transfer if configured.
/// </summary>
[JsonProperty("tsig_id")]
public string? TSIGId { get; set; }
}
}

View File

@@ -0,0 +1,35 @@
using System.Runtime.Serialization;
using Newtonsoft.Json.Converters;
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a Transaction Signature (TSIG) used for securing DNS messages.
/// </summary>
public class TSIG
{
/// <summary>
/// The unique identifier.
/// </summary>
[JsonProperty("id")]
public string? Id { get; set; }
/// <summary>
/// TSIG algorithm.
/// </summary>
[JsonProperty("algo")]
public TSigAlgorithm? Algorithm { get; set; }
/// <summary>
/// TSIG key name.
/// </summary>
[JsonProperty("name")]
public string? Name { get; set; }
/// <summary>
/// TSIG secret.
/// </summary>
[JsonProperty("secret")]
public string? Secret { get; set; }
}
}

View File

@@ -59,6 +59,59 @@ 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/)
#### [Zone Transfers]
##### [ACLs]
- [List ACLs](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/acls/methods/list/)
- [ACL Details](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/acls/methods/get/)
- [Create ACL](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/acls/methods/create/)
- [Update ACL](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/acls/methods/update/)
- [Delete ACL](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/acls/methods/delete/)
##### Force AXFR
- [Force AXFR](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/force_axfr/methods/create/)
##### [Incoming]
- [Create Secondary Zone Configuration](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/incoming/methods/create/)
- [Delete Secondary Zone Configuration](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/incoming/methods/delete/)
- [Secondary Zone Configuration Details](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/incoming/methods/get/)
- [Update Secondary Zone Configuration](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/incoming/methods/update/)
##### [Outgoing]
- [Create Primary Zone Configuration](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/create/)
- [Delete Primary Zone Configuration](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/delete/)
- [Disable Outgoing Zone Transfers](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/disable/)
- [Enable Outgoing Zone Transfers](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/enable/)
- [Primary Zone Configuration Details](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/get/)
- [Update Primary Zone Configuration](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/update/)
- [Force DNS Notify](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/methods/force_notify/)
- [Get Outgoing Zone Transfer Status](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/subresources/status/methods/get/)
##### [Peers]
- [List Peers](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/peers/methods/list/)
- [Peer Details](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/peers/methods/get/)
- [Create Peer](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/peers/methods/create/)
- [Update Peer](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/peers/methods/update/)
- [Delete Peer](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/peers/methods/delete/)
##### [TSIGs] (Transaction SIGnatures)
- [List TSIGs](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/tsigs/methods/list/)
- [TSIG Details](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/tsigs/methods/get/)
- [Create TSIG](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/tsigs/methods/create/)
- [Update TSIG](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/tsigs/methods/update/)
- [Delete TSIG](https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/tsigs/methods/delete/)
---
@@ -77,3 +130,9 @@ Published under MIT License (see [choose a license])
[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/
[Zone Transfers]: https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/
[ACLs]: https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/acls/
[Incoming]: https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/incoming/
[Outgoing]: https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/outgoing/
[Peers]: https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/peers/
[TSIGs]: https://developers.cloudflare.com/api/resources/dns/subresources/zone_transfers/subresources/tsigs/

View File

@@ -0,0 +1,77 @@
using System.Net;
using System.Net.Sockets;
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to create a DNS zone transfer access control list (ACL).
/// </summary>
public class CreateACLRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="CreateACLRequest"/> class.
/// </summary>
/// <param name="accountId">The account identifier.</param>
/// <param name="ipRange">Allowed IPv4/IPv6 address range of primary or secondary nameservers (CIDR).</param>
/// <param name="name">The name of the ACL.</param>
public CreateACLRequest(string accountId, string ipRange, string name)
{
IpRangeBaseAddress = IPAddress.None;
IpRangeSubnet = 0;
AccountId = accountId;
IpRange = ipRange;
Name = name;
}
/// <summary>
/// The account identifier.
/// </summary>
public string AccountId { get; set; }
/// <summary>
/// Allowed IPv4/IPv6 address range of primary or secondary nameservers.
/// This will be applied for the entire account.
/// </summary>
/// <remarks>
/// The IP range is used to allow additional NOTIFY IPs for secondary zones and IPs Cloudflare allows AXFR/IXFR requests from for primary zones.
/// CIDRs are limited to a maximum of /24 for IPv4 and /64 for IPv6 respectively.
/// </remarks>
public string IpRange
{
get => $"{IpRangeBaseAddress}/{IpRangeSubnet}";
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException(nameof(value), $"{nameof(IpRange)} cannot be null or empty.");
string[] parts = value.Split('/');
if (parts.Length != 2)
throw new FormatException("Invalid IP range format.");
var prefix = IPAddress.Parse(parts[0]);
if (!int.TryParse(parts[1], out int prefixLength))
throw new FormatException("Invalid IP range subnet format.");
if (prefix.AddressFamily == AddressFamily.InterNetwork && (prefixLength < 0 || 32 < prefixLength))
throw new FormatException("Invalid subnet length for IPv4.");
if (prefix.AddressFamily == AddressFamily.InterNetworkV6 && (prefixLength < 0 || 128 < prefixLength))
throw new FormatException("Invalid subnet length for IPv6.");
IpRangeBaseAddress = prefix;
IpRangeSubnet = prefixLength;
}
}
/// <summary>
/// The name of the ACL.
/// </summary>
public string Name { get; set; }
internal IPAddress IpRangeBaseAddress { get; set; }
internal int IpRangeSubnet { get; set; }
}
}

View File

@@ -0,0 +1,29 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to create a new peer within a specific account.
/// </summary>
public class CreatePeerRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="CreatePeerRequest"/> class.
/// </summary>
/// <param name="accountId">The account identifier.</param>
/// <param name="name">The name of the peer.</param>
public CreatePeerRequest(string accountId, string name)
{
AccountId = accountId;
Name = name;
}
/// <summary>
/// The account identifier.
/// </summary>
public string AccountId { get; set; }
/// <summary>
/// The name of the peer.
/// </summary>
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to create a TSIG (Transaction Signature) key for DNS operations.
/// </summary>
public class CreateTSIGRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="CreateTSIGRequest"/> class.
/// </summary>
/// <param name="accountId">The account identifier.</param>
/// <param name="name">TSIG key name.</param>
/// <param name="secret">TSIG secret.</param>
public CreateTSIGRequest(string accountId, string name, string secret)
{
Algorithm = TSigAlgorithm.HMAC_SHA256;
AccountId = accountId;
Name = name;
Secret = secret;
}
/// <summary>
/// The account identifier.
/// </summary>
public string AccountId { get; set; }
/// <summary>
/// TSIG algorithm.
/// </summary>
public TSigAlgorithm Algorithm { get; set; }
/// <summary>
/// TSIG key name.
/// </summary>
public string Name { get; set; }
/// <summary>
/// TSIG secret.
/// </summary>
public string Secret { get; set; }
}
}

View File

@@ -0,0 +1,34 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to create a primary zone configuration.
/// </summary>
public class PrimaryZoneConfigurationRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="PrimaryZoneConfigurationRequest"/> class.
/// </summary>
/// <param name="zoneId">The zone identifier.</param>
/// <param name="name">The zone name.</param>
public PrimaryZoneConfigurationRequest(string zoneId, string name)
{
ZoneId = zoneId;
Name = name;
}
/// <summary>
/// The zone identifier.
/// </summary>
public string ZoneId { get; set; }
/// <summary>
/// The zone name.
/// </summary>
public string Name { get; set; }
/// <summary>
/// A list of peer tags.
/// </summary>
public IReadOnlyCollection<string> Peers { get; set; } = [];
}
}

View File

@@ -0,0 +1,41 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to create a secondary zone configuration.
/// </summary>
public class SecondaryZoneConfigurationRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="SecondaryZoneConfigurationRequest"/> class.
/// </summary>
/// <param name="zoneId">The zone identifier.</param>
/// <param name="name">The zone name.</param>
public SecondaryZoneConfigurationRequest(string zoneId, string name)
{
ZoneId = zoneId;
Name = name;
Peers = [];
}
/// <summary>
/// The zone identifier.
/// </summary>
public string ZoneId { get; set; }
/// <summary>
/// The Zone name.
/// </summary>
public string Name { get; set; }
/// <summary>
/// How often should a secondary zone auto refresh regardless of DNS NOTIFY. Not applicable for primary zones.
/// </summary>
public int AutoRefreshSeconds { get; set; }
/// <summary>
/// A list of peer tags.
/// </summary>
public IReadOnlyCollection<string> Peers { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to update an existing DNS zone transfer access control list (ACL).
/// </summary>
public class UpdateDnsZoneTransferAclRequest : CreateACLRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="UpdateDnsZoneTransferAclRequest"/> class.
/// </summary>
/// <param name="accountId">The account identifier.</param>
/// <param name="aclId">The access control list identifier.</param>
/// <param name="ipRange">Allowed IPv4/IPv6 address range of primary or secondary nameservers (CIDR).</param>
/// <param name="name">The name of the ACL.</param>
public UpdateDnsZoneTransferAclRequest(string accountId, string aclId, string ipRange, string name)
: base(accountId, ipRange, name)
{
AclId = aclId;
}
/// <summary>
/// The access control list identifier.
/// </summary>
public string AclId { get; set; }
}
}

View File

@@ -0,0 +1,49 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to update an existing peer with new configuration details.
/// </summary>
public class UpdatePeerRequest : CreatePeerRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="UpdatePeerRequest"/> class.
/// </summary>
/// <param name="accountId">The account identifier.</param>
/// <param name="peerId">The peer identifier.</param>
/// <param name="name">The name of the peer</param>
public UpdatePeerRequest(string accountId, string peerId, string name)
: base(accountId, name)
{
PeerId = peerId;
}
/// <summary>
/// The peer identifier.
/// </summary>
public string PeerId { get; set; }
/// <summary>
/// IPv4/IPv6 address of primary or secondary nameserver, depending on what zone this peer is linked to.
/// <list type="bullet">
/// <item>For primary zones this IP defines the IP of the secondary nameserver Cloudflare will NOTIFY upon zone changes.</item>
/// <item>For secondary zones this IP defines the IP of the primary nameserver Cloudflare will send AXFR/IXFR requests to.</item>
/// </list>
/// </summary>
public string? IpAddress { get; set; }
/// <summary>
/// Enable IXFR transfer protocol, default is AXFR. Only applicable to secondary zones.
/// </summary>
public bool? IXFREnable { get; set; }
/// <summary>
/// DNS port of primary or secondary nameserver, depending on what zone this peer is linked to.
/// </summary>
public int? Port { get; set; }
/// <summary>
/// TSIG authentication will be used for zone transfer if configured.
/// </summary>
public string? TSIGId { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
namespace AMWD.Net.Api.Cloudflare.Dns
{
/// <summary>
/// Represents a request to update an existing TSIG (Transaction Signature) key.
/// </summary>
public class UpdateTSIGRequest : CreateTSIGRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="UpdateTSIGRequest"/> class.
/// </summary>
/// <param name="accountId">The account identifier.</param>
/// <param name="tsigId">The TSIG identifier.</param>
/// <param name="name">TSIG key name.</param>
/// <param name="secret">TSIG secret.</param>
public UpdateTSIGRequest(string accountId, string tsigId, string name, string secret)
: base(accountId, name, secret)
{
TSigId = tsigId;
}
/// <summary>
/// The TSIG identifier.
/// </summary>
public string TSigId { get; set; }
}
}