-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
7 changed files
with
1,294 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
branches: | ||
- master | ||
|
||
name: run tests | ||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Install Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: 1.16.x | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
- name: Run linters | ||
uses: golangci/golangci-lint-action@v2 | ||
with: | ||
version: v1.29 | ||
- name: Run tests | ||
run: go test -v -covermode=count |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 Jan Delgado | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,56 @@ | ||
# IONOS DNS module for Caddy | ||
|
||
This package contains a DNS provider module for IONOS DNS. It can be used to | ||
manage DNS records with IONOS accounts. | ||
This package contains a DNS provider module for | ||
[Caddy](https://github.com/caddyserver/caddy). It is used to manage DNS records | ||
with the [IONOS DNS API](https://developer.hosting.ionos.com/docs/dns) using | ||
[libdns-ionos](https://github.com/libdns/ionos).. | ||
|
||
## Caddy module name | ||
|
||
``` | ||
dns.providers.ionos | ||
``` | ||
|
||
## Config examples | ||
|
||
To use this module for the ACME DNS challenge, [configure the ACME issuer in your Caddy JSON](https://caddyserver.com/docs/json/apps/tls/automation/policies/issuer/acme/) like so: | ||
|
||
```json | ||
{ | ||
"module": "acme", | ||
"challenges": { | ||
"dns": { | ||
"provider": { | ||
"name": "ionos", | ||
"api_token": "YOUR_IONOS_AUTH_API_TOKEN" | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
or with the Caddyfile: | ||
|
||
``` | ||
your.domain.com { | ||
respond "Hello World" # replace with whatever config you need... | ||
tls { | ||
dns ionos {env.YOUR_IONOS_AUTH_API_TOKEN} | ||
} | ||
} | ||
``` | ||
|
||
You can replace `{env.YOUR_IONOS_AUTH_API_TOKEN}` with the actual auth token if | ||
you prefer to put it directly in your config instead of an environment | ||
variable. | ||
|
||
## Authenticating | ||
|
||
See [the associated README in the libdns package](https://github.com/libdns/ionos#authenticating) | ||
for information about obtaining credentials. | ||
|
||
## Author | ||
|
||
(c) Copyright 2021 by Jan Delgado | ||
License: MIT | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module github.com/caddy-dns/ionos | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/caddyserver/caddy/v2 v2.4.3 | ||
github.com/libdns/ionos v1.0.0 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package ionos | ||
|
||
import ( | ||
caddy "github.com/caddyserver/caddy/v2" | ||
caddyfile "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" | ||
"github.com/libdns/ionos" | ||
) | ||
|
||
// Provider wraps the provider implementation as a Caddy module. | ||
type Provider struct{ *ionos.Provider } | ||
|
||
func init() { | ||
caddy.RegisterModule(Provider{}) | ||
} | ||
|
||
// CaddyModule returns the Caddy module information. | ||
func (Provider) CaddyModule() caddy.ModuleInfo { | ||
return caddy.ModuleInfo{ | ||
ID: "dns.providers.ionos", | ||
New: func() caddy.Module { return &Provider{new(ionos.Provider)} }, | ||
} | ||
} | ||
|
||
// Before using the provider config, resolve placeholders in the API token. | ||
// Implements caddy.Provisioner. | ||
func (p *Provider) Provision(ctx caddy.Context) error { | ||
repl := caddy.NewReplacer() | ||
p.Provider.AuthAPIToken = repl.ReplaceAll(p.Provider.AuthAPIToken, "") | ||
return nil | ||
} | ||
|
||
// UnmarshalCaddyfile sets up the DNS provider from Caddyfile tokens. Syntax: | ||
// | ||
// ionos [<api_token>] { | ||
// api_token <api_token> | ||
// } | ||
// | ||
func (p *Provider) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { | ||
for d.Next() { | ||
if d.NextArg() { | ||
p.Provider.AuthAPIToken = d.Val() | ||
} | ||
if d.NextArg() { | ||
return d.ArgErr() | ||
} | ||
for nesting := d.Nesting(); d.NextBlock(nesting); { | ||
switch d.Val() { | ||
case "api_token": | ||
if p.Provider.AuthAPIToken != "" { | ||
return d.Err("API token already set") | ||
} | ||
if d.NextArg() { | ||
p.Provider.AuthAPIToken = d.Val() | ||
} | ||
if d.NextArg() { | ||
return d.ArgErr() | ||
} | ||
default: | ||
return d.Errf("unrecognized subdirective '%s'", d.Val()) | ||
} | ||
} | ||
} | ||
if p.Provider.AuthAPIToken == "" { | ||
return d.Err("missing API token") | ||
} | ||
return nil | ||
} | ||
|
||
// Interface guards | ||
var ( | ||
_ caddyfile.Unmarshaler = (*Provider)(nil) | ||
_ caddy.Provisioner = (*Provider)(nil) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// some unit/explanatory tests for the IONOS DNS plugin | ||
// (c) copyright 2021 by Jan Delgado | ||
package ionos | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"testing" | ||
|
||
caddy "github.com/caddyserver/caddy/v2" | ||
caddyfile "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" | ||
"github.com/libdns/ionos" | ||
) | ||
|
||
func TestUnmarshalCaddyFileExtractsApiToken(t *testing.T) { | ||
tests := []string{ | ||
"ionos token { }", | ||
`ionos { | ||
api_token token | ||
}`} | ||
|
||
for i, tc := range tests { | ||
t.Run(fmt.Sprintf("test case %d", i), func(t *testing.T) { | ||
// given | ||
dispenser := caddyfile.NewTestDispenser(tc) | ||
p := Provider{&ionos.Provider{}} | ||
// when | ||
err := p.UnmarshalCaddyfile(dispenser) | ||
// then | ||
if err != nil { | ||
t.Errorf("UnmarshalCaddyfile failed with %v", err) | ||
return | ||
} | ||
|
||
expected := "token" | ||
actual := p.Provider.AuthAPIToken | ||
if expected != actual { | ||
t.Errorf("Expected AuthAPIToken to be '%s' but got '%s'", expected, actual) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestUnmarshalCaddyFileReportsErrorConditions(t *testing.T) { | ||
|
||
tests := []struct{ test, expected string }{ | ||
{"ionos token invalid", "Wrong argument count"}, | ||
{"ionos { }", "missing API token"}, | ||
{`ionos token { api_token token }`, "API token already set"}, | ||
{`ionos { api_token token invalid }`, "Wrong argument count"}, | ||
{`ionos token { invalid token }`, "unrecognized subdirective 'invalid'"}, | ||
} | ||
|
||
for i, tc := range tests { | ||
t.Run(fmt.Sprintf("test case %d", i), func(t *testing.T) { | ||
// given | ||
dispenser := caddyfile.NewTestDispenser(tc.test) | ||
p := Provider{&ionos.Provider{}} | ||
// when | ||
err := p.UnmarshalCaddyfile(dispenser) | ||
// then | ||
if err == nil || !strings.Contains(err.Error(), tc.expected) { | ||
t.Errorf("expected error with '%s' but got '%s'", tc.expected, err.Error()) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestProvisionTransformsAPIToken(t *testing.T) { | ||
// given | ||
expected := "{value}" | ||
p := Provider{&ionos.Provider{}} | ||
p.Provider.AuthAPIToken = "\\{value\\}" | ||
// when | ||
_ = p.Provision(caddy.Context{}) | ||
// then | ||
actual := p.Provider.AuthAPIToken | ||
if expected != actual { | ||
t.Errorf("expected AuthAPIToken to be %s but got %s", expected, actual) | ||
} | ||
} |