Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate GandiProvider to new LiveDns api #639

Merged
merged 3 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions KeyVault.Acmebot/Options/AcmebotOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class AcmebotOptions

public GandiOptions Gandi { get; set; }

public GandiLiveDnsOptions GandiLiveDns { get; set; }

public GoDaddyOptions GoDaddy { get; set; }

public GoogleDnsOptions GoogleDns { get; set; }
Expand Down
7 changes: 7 additions & 0 deletions KeyVault.Acmebot/Options/GandiLiveDnsOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace KeyVault.Acmebot.Options;

public class GandiLiveDnsOptions
{
public string ApiKey { get; set; }

}
156 changes: 156 additions & 0 deletions KeyVault.Acmebot/Providers/GandiLiveDnsProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

using KeyVault.Acmebot.Internal;
using KeyVault.Acmebot.Options;

using Newtonsoft.Json;

namespace KeyVault.Acmebot.Providers;

public class GandiLiveDnsProvider : IDnsProvider
{
public GandiLiveDnsProvider(GandiLiveDnsOptions options)
{
_client = new GandiClient(options.ApiKey);
}

private readonly GandiClient _client;

public string Name => "Gandi LiveDNS";

public int PropagationSeconds => 300;

public async Task<IReadOnlyList<DnsZone>> ListZonesAsync()
{
var zones = await _client.ListZonesAsync();

return zones.Select(x => new DnsZone(this) { Id = x.Fqdn, Name = x.FqdnUnicode }).ToArray();
}

public Task CreateTxtRecordAsync(DnsZone zone, string relativeRecordName, IEnumerable<string> values)
{
return _client.AddRecordAsync(zone.Name, relativeRecordName, values);
}

public Task DeleteTxtRecordAsync(DnsZone zone, string relativeRecordName)
{
return _client.DeleteRecordAsync(zone.Name, relativeRecordName);
}

private class GandiClient
bhubert marked this conversation as resolved.
Show resolved Hide resolved
{
public GandiClient(string apiKey)
{
ArgumentNullException.ThrowIfNull(apiKey);

_httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.gandi.net/v5/")
};

_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + apiKey);
}

private readonly HttpClient _httpClient;

public async Task<IReadOnlyList<Domain>> ListZonesAsync()
{
var response = await _httpClient.GetAsync("domain/domains");

response.EnsureSuccessStatusCode();
var domains = await response.Content.ReadAsAsync<Domain[]>();

return domains.Where(x => x.Nameserver.Current == "livedns").ToArray();
}

public async Task DeleteRecordAsync(string zoneName, string relativeRecordName)
{
var response = await _httpClient.DeleteAsync($"livedns/domains/{zoneName}/records/{relativeRecordName}/TXT");

if (response.StatusCode != HttpStatusCode.NotFound)
{
response.EnsureSuccessStatusCode();
}
}

public async Task AddRecordAsync(string zoneName, string relativeRecordName, IEnumerable<string> values)
{
var response = await _httpClient.PostAsync($"livedns/domains/{zoneName}/records/{relativeRecordName}/TXT", new
{
rrset_values = values.ToArray(),
rrset_ttl = 300 //300 is the minimal value
});

response.EnsureSuccessStatusCode();
}
}
public class Domain
{
[JsonProperty("fqdn")]
public string Fqdn { get; set; }

[JsonProperty("tld")]
public string Tld { get; set; }

[JsonProperty("status")]
public List<string> Status { get; set; }

[JsonProperty("dates")]
public Dates Dates { get; set; }

[JsonProperty("nameserver")]
public Nameserver Nameserver { get; set; }

[JsonProperty("autorenew")]
public bool Autorenew { get; set; }

[JsonProperty("domain_owner")]
public string DomainOwner { get; set; }

[JsonProperty("orga_owner")]
public string OrgaOwner { get; set; }

[JsonProperty("owner")]
public string Owner { get; set; }

[JsonProperty("id")]
public string Id { get; set; }

[JsonProperty("tags")]
public List<string> Tags { get; set; }

[JsonProperty("href")]
public string Href { get; set; }

[JsonProperty("fqdn_unicode")]
public string FqdnUnicode { get; set; }
}

public class Dates
{
[JsonProperty("created_at")]
public DateTime CreatedAt { get; set; }

[JsonProperty("registry_created_at")]
public DateTime RegistryCreatedAt { get; set; }

[JsonProperty("registry_ends_at")]
public DateTime RegistryEndsAt { get; set; }

[JsonProperty("updated_at")]
public DateTime UpdatedAt { get; set; }
}

public class Nameserver
{
[JsonProperty("current")]
public string Current { get; set; }
}
}
1 change: 1 addition & 0 deletions KeyVault.Acmebot/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public override void Configure(IFunctionsHostBuilder builder)
dnsProviders.TryAdd(options.CustomDns, o => new CustomDnsProvider(o));
dnsProviders.TryAdd(options.DnsMadeEasy, o => new DnsMadeEasyProvider(o));
dnsProviders.TryAdd(options.Gandi, o => new GandiProvider(o));
dnsProviders.TryAdd(options.GandiLiveDns, o => new GandiLiveDnsProvider(o));
dnsProviders.TryAdd(options.GoDaddy, o => new GoDaddyProvider(o));
dnsProviders.TryAdd(options.GoogleDns, o => new GoogleDnsProvider(o));
dnsProviders.TryAdd(options.Route53, o => new Route53Provider(o));
Expand Down