Commit 15b279a4 authored by Jason Hoch's avatar Jason Hoch
Browse files

Adds TLS flags for pdns provider

parent e34bf552
master Raffo-patch-1 add-infoblox-maintainers bugfix/style-faq changelog-for-v0.7.3 correctly-update-aws-records-when-type-changes dansimone/support-prefer-ingress-annotations dependabot/go_modules/github.com/Azure/azure-sdk-for-go-61.4.0incompatible dependabot/go_modules/github.com/aliyun/alibaba-cloud-sdk-go-1.61.1473 dependabot/go_modules/github.com/exoscale/egoscale-1.19.0 dependabot/go_modules/github.com/projectcontour/contour-1.20.0 dependabot/go_modules/k8s.io/apimachinery-0.23.3 eval-target-health fix-1820 gh-pages go-1.12.7 gometalinter-timeout google-panic-assignment incubator-kep infoblox-multiple-A-records-fix labeler linki-patch-2 linki-patch-3 linki-patch-4 linki-patch-6 njuettner-patch-1 njuettner/go_modules/github.com/akamai/AkamaiOPEN-edgegrid-golang-0.9.11 njuettner/go_modules/github.com/alecthomas/kingpin-2.2.6incompatible njuettner/go_modules/github.com/digitalocean/godo-1.34.0 njuettner/go_modules/github.com/pkg/errors-0.9.1 njuettner/go_modules/github.com/prometheus/client_golang-1.5.1 normalize pagination-cloudflare-zones pagination-cloudflare-zones-patch pr/624 pr/674 pr/675 pr/697 pr/702 provider-specific provider-specific2 raffo-fix-2348 raffo/add-dependabot raffo/add-kustomize-base raffo/add-trivy-scanning raffo/arm raffo/arm32v7 raffo/bump-ci-timeout raffo/bump-cloudbuild-timeout raffo/bump-deps-sec raffo/bump-kustomize raffo/bump-kustomize-1 raffo/bump-kustomize-version-0.7.5 raffo/bump-modules raffo/codeQL raffo/drop-the-changelog raffo/e2e-aws raffo/edit-infoblox-maintainers raffo/fix-1820 raffo/fix-1936 raffo/fix-build raffo/fix-dependabot raffo/fix-ns-deletion raffo/fix-scaleway-security raffo/fix-that-typo raffo/fix-trivy raffo/fix-trivy-again raffo/fix-vulnerabilities raffo/goarm raffo/gpr-docker-image raffo/knolog raffo/kustomize-endpoints raffo/multiarch raffo/multiarch-docs raffo/new-ingress-resource raffo/new-maintainers raffo/provider-structure-refactor raffo/release-conventions raffo/release-note-patch raffo/release-script raffo/release-script-update raffo/release-v0.7.2 raffo/remove-azure-test raffo/remove-broken-link raffo/remove-incubator-readme raffo/remove-masters raffo/revert-tzdata raffo/split-sources raffo/update-kustomize-080 raffo/update-v0.10-role raffo/use-actions raffo/v0.7.6 ratelimit revert-736-fix-domainfilter revert-963-ns1-provider-ammended sagor999/infoblox-multiple-A-records stability-matrix test-things travis-test update-changelog v0.5.15 v0.5.17 v0.5.9-changelog validate-txt-prefix v1.0.0-mf v0.10.2 v0.10.1 v0.10.0 v0.9.0 v0.8.0 v0.7.6 v0.7.5 v0.7.4 v0.7.3 v0.7.2 v0.7.1 v0.7.0 v0.6.0 v0.5.18 v0.5.17 v0.5.16 v0.5.15 v0.5.14 v0.5.13 v0.5.12 v0.5.11 v0.5.10 v0.5.9 v0.5.8 v0.5.7 v0.5.6 v0.5.5 v0.5.4 external-dns-helm-chart-1.7.1 external-dns-helm-chart-1.7.0 external-dns-helm-chart-1.6.0 external-dns-helm-chart-1.5.0 external-dns-helm-chart-1.4.1 external-dns-helm-chart-1.4.0 external-dns-helm-chart-1.3.2 external-dns-helm-chart-1.3.1 external-dns-helm-chart-1.3.0 external-dns-helm-chart-1.2.0
No related merge requests found
Showing with 370 additions and 19 deletions
+370 -19
-----BEGIN CERTIFICATE-----
MIIDwDCCAqigAwIBAgIUYsFawvERY3xGTHmKWq/78Cp70AIwDQYJKoZIhvcNAQEL
BQAweDEQMA4GA1UEBhMHQ291bnRyeTERMA8GA1UEBxMITG9jYWxpdHkxFTATBgNV
BAoTDE9yZ2FuaXphdGlvbjEbMBkGA1UECxMST3JnYW5pemF0aW9uYWxVbml0MR0w
GwYDVQQDExRleHRlcm5hbC1kbnMgdGVzdCBDQTAeFw0xODA2MTQyMTE5MDBaFw0y
MzA2MTMyMTE5MDBaMHgxEDAOBgNVBAYTB0NvdW50cnkxETAPBgNVBAcTCExvY2Fs
aXR5MRUwEwYDVQQKEwxPcmdhbml6YXRpb24xGzAZBgNVBAsTEk9yZ2FuaXphdGlv
bmFsVW5pdDEdMBsGA1UEAxMUZXh0ZXJuYWwtZG5zIHRlc3QgQ0EwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMEaMix69YrVXPtfUsOgz5RJqaAlitw+HV
BaYv7BbcChiidYQ+/iKo26HA5vjBP5xOMNYTnVowXA+q+RmMGfhSc+j9CiJeADP0
oxjSNq/w5Xb/IFIHSjr+dEdavcdsV95y3BYB8PkopjXEmNgbEgPbHNuJMQkd89rC
2ztSIPHbjhorrauAGm8cgzdKK6Tnxhey9yQralIgdrOHXMTOZrWywTPiUtIuxrn5
XfIaylfqQO+Q79rEGhk9YQuFUqs+GDDp/PiCGC56/IbF7NVLEdrJIc6Tf9Rg2/K/
9ydeZ5hcaM542Q2UoXIbRp8jn/J1Xr3mcxhpnhJN4TcjLalnSY6tAgMBAAGjQjBA
MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTym+5y
SEghmx5Xr+wd5Z0V+9AWxDANBgkqhkiG9w0BAQsFAAOCAQEAlGaKZY40apdmROAx
usSLJjgVIw5GjX7lNw6BqorbQavexPjghfhB1TSpFOvHCz7s164Eq18+wfbzfnR5
L+Xza+eibvkgO8ZojGMFXR+5NCbM2cPBTmWZVNVRoZQX6j5RT/DeLcjEKDBWZBdP
IxAQCFprxHgBZeHOfzvombzdbDM5To9ff+3gaunMbWs7YAmpv1czRc0F0arXg+mA
AzG4fc94lJ5oMF6sClZ1rbJjLcohtINx6HstUzLxlAcgJMJcvvJrrdTkzJSCOmE6
a52RJX6qVaZNHCXDooiy2uDapXyA4sPCt4n3KhRfP+JGp6Xmg10rm7ga8+ZUCYae
UyE4mA==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAykDCIA6Q0p8HJLx3njenAqvKvHGwJzjLP+tw4iq8J3//aEon
e23t9CwGW9YVNTM4Xu6n0+exUsUK4LweHRTYLmYkTHUc+pB9+XpQ+wKutmxv+zhk
uWi+4u6pqC6e8TSuURs3c9ML2TxCTIRubd3hPRGMizo3POuQ8iaRo8icfdQcv/XE
bieB8ma5ZUkRxkY+Mu+MYOsleoIpSByej18ycJkVkipV6CeSxenCsQaeAaJPTOVO
9rYZL3F3fNHXezIpCmw3sgCiudQ1MvPKGs4G5UahCO0OSp42IMUodYxvQ0G1o5uZ
9k9R8Xcumso61xHM/ZCkzqJ89P/2zXyUC7c2OQIDAQABAoIBABoHL3RUq4qPcKnn
nzU7UEDlvtd1ggfqJS36rLJOcZxbupC/Skl2IjNUHxVefag1CUIeUHbS0F0ognfd
fbqcXh3Kg01bnPkZ8zxR424KMFXFqruXzE6YDkjCEg9UwJul/fDuIbrEJDg2qwmR
2WxGK6BiS8X3Hfi3EBY5pHCBdrIyiVWZn8CYYmiBhJehdNHEwtIk+Bo8mWBTOOpS
x9e1czYICM39zyZQtuLvI/CIcSg1uyRL19r7KrAoBS2o6ijDrp5KqCyAVL9UYq5m
B3k/KltYi6d3HtcHwuMHPKNpWfOQCKu7MDX+ZNi7E6LrPxWqrPoiZ5xzAQPQHD3B
e3fmt6ECgYEA5z5z3kxjF6EYttzDMylUghTfPs/vyhecFKzbcipdMJNs8o9KnHF9
WgH7JaPU8cYe8CluQWZn6ByxdaB7G56wfHrYYCm5pbsuxlkoqqLMmAmVBPZVMhEy
thoxi4PxAdcs5HsqwYbazpToYZ6ktvknIUKOp24oQgYUG5T0mkNm910CgYEA3+fE
4Mh2rikegQLYar9gsFAXpBjxiMRQlUH23Qk9p21AkczTjGpYeV4v2LxxTYKiaZRJ
8X4Ab745j+yLbsYMxZKihNCQSLTK44FSgK6fSEs+yHLpQjT4V5IyvD+tHMan9n/s
YqDppse1GHGGxF7N4FatrQk5Kz8FG9EYa6BNWI0CgYBYXALGRIXwt3vME9r6p6ZE
9li/lZDYteDL/aj0nL9zGkIdBSfLU4pEZFFk9o8du0iDGDGrB8hYZu5gNewUh7SE
PCSFyivH6hhbbiId4Ysv5Slt9fpj4TJxZtzbpJTo0SG0RGP4AuGE4l1RP99MkzOi
f94ml+8GG3B/gZFdiLfFeQKBgQC9pDxoduGuWT1w38wVfcqTCwM7BbVttXjbMme4
hx8lM6/Azc9P2rLc+R1lYRZGJCMTcXm/hI0yF9gBQsRGKpCetrfX7h6Gtjoxv1L1
kvFt9e1TMaDHZr4Azd8S+ovRF6Ejcu3wC4JatEN6VI1kvTd6j2/CY1F8g3/8M3mP
jtJz8QKBgCL2XDev1Vls2hzqrNqjNehYVAqTNdNNr2jzCR1g8AMFqSy7k/4gFtu/
bXBnSKnGrtmb+VWKDMwNy7oe6g6haFLTjPbnl8/afKBbH0WQzlvVJgKWSX1faWTG
1WMRAqD8nIdcYbfj7AhmNGL6zYGr0g+YP9CF+j6je2Rb0so+S5cZ
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIUJxJZIg35oCO6747gR3c9ZkQc8TMwDQYJKoZIhvcNAQEL
BQAweDEQMA4GA1UEBhMHQ291bnRyeTERMA8GA1UEBxMITG9jYWxpdHkxFTATBgNV
BAoTDE9yZ2FuaXphdGlvbjEbMBkGA1UECxMST3JnYW5pemF0aW9uYWxVbml0MR0w
GwYDVQQDExRleHRlcm5hbC1kbnMgdGVzdCBDQTAeFw0xODA2MTQyMTIzMDBaFw0y
MzA2MTMyMTIzMDBaMIGIMRAwDgYDVQQGEwdDb3VudHJ5MREwDwYDVQQHEwhMb2Nh
bGl0eTEVMBMGA1UEChMMT3JnYW5pemF0aW9uMRswGQYDVQQLExJPcmdhbml6YXRp
b25hbFVuaXQxLTArBgNVBAMTJGV4dGVybmFsLWRucyB0ZXN0IGNsaWVudCBjZXJ0
aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMpAwiAOkNKf
ByS8d543pwKryrxxsCc4yz/rcOIqvCd//2hKJ3tt7fQsBlvWFTUzOF7up9PnsVLF
CuC8Hh0U2C5mJEx1HPqQffl6UPsCrrZsb/s4ZLlovuLuqagunvE0rlEbN3PTC9k8
QkyEbm3d4T0RjIs6NzzrkPImkaPInH3UHL/1xG4ngfJmuWVJEcZGPjLvjGDrJXqC
KUgcno9fMnCZFZIqVegnksXpwrEGngGiT0zlTva2GS9xd3zR13syKQpsN7IAornU
NTLzyhrOBuVGoQjtDkqeNiDFKHWMb0NBtaObmfZPUfF3LprKOtcRzP2QpM6ifPT/
9s18lAu3NjkCAwEAAaOBgzCBgDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI
KwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUA+Do/9mVdkyYJAPYUzbr
9FBi8gMwHwYDVR0jBBgwFoAU8pvuckhIIZseV6/sHeWdFfvQFsQwCwYDVR0RBAQw
AoIAMA0GCSqGSIb3DQEBCwUAA4IBAQBFzN/cqkVjGYaQzCpOWVgizIwBhGFRfYGY
Cw5m9HaZIMjbSxt55NhRTFm6Q5qFfD2KXXPueEUL4U5iPg+LPHrUfNmKiJtUcKc8
M2FJimb7nRsw46F+tRt0lgM5sDeqe2QUlNTKFKaxnHUDqWt4mW7adzog3sX7UfGB
yvbJR9Y6cEMlG2it3rl9/ZiAJnTJSvCqBV9QlBAkCCh0JgJEtPLubz97BVGkMORh
+ZgHCw/A9sew/7Krpbyp/NtHeFVsa8tH8wivnaGeITGD4J23U9E3YYUaNPN7kBcX
DuFCSEKHGsbAvH2Igxkk+rD5T8d6RwJ98jkXOYXCxGmGBuDEkyGZ
-----END CERTIFICATE-----
...@@ -156,7 +156,20 @@ func main() { ...@@ -156,7 +156,20 @@ func main() {
case "designate": case "designate":
p, err = provider.NewDesignateProvider(domainFilter, cfg.DryRun) p, err = provider.NewDesignateProvider(domainFilter, cfg.DryRun)
case "pdns": case "pdns":
p, err = provider.NewPDNSProvider(cfg.PDNSServer, cfg.PDNSAPIKey, domainFilter, cfg.DryRun) p, err = provider.NewPDNSProvider(
provider.PDNSConfig{
DomainFilter: domainFilter,
DryRun: cfg.DryRun,
Server: cfg.PDNSServer,
APIKey: cfg.PDNSAPIKey,
TLSConfig: provider.TLSConfig{
TLSEnabled: cfg.PDNSTLSEnabled,
CAFilePath: cfg.TLSCA,
ClientCertFilePath: cfg.TLSClientCert,
ClientCertKeyFilePath: cfg.TLSClientCertKey,
},
},
)
default: default:
log.Fatalf("unknown dns provider: %s", cfg.Provider) log.Fatalf("unknown dns provider: %s", cfg.Provider)
} }
......
...@@ -69,6 +69,10 @@ type Config struct { ...@@ -69,6 +69,10 @@ type Config struct {
InMemoryZones []string InMemoryZones []string
PDNSServer string PDNSServer string
PDNSAPIKey string PDNSAPIKey string
PDNSTLSEnabled bool
TLSCA string
TLSClientCert string
TLSClientCertKey string
Policy string Policy string
Registry string Registry string
TXTOwnerID string TXTOwnerID string
...@@ -111,6 +115,10 @@ var defaultConfig = &Config{ ...@@ -111,6 +115,10 @@ var defaultConfig = &Config{
InMemoryZones: []string{}, InMemoryZones: []string{},
PDNSServer: "http://localhost:8081", PDNSServer: "http://localhost:8081",
PDNSAPIKey: "", PDNSAPIKey: "",
PDNSTLSEnabled: false,
TLSCA: "",
TLSClientCert: "",
TLSClientCertKey: "",
Policy: "sync", Policy: "sync",
Registry: "txt", Registry: "txt",
TXTOwnerID: "default", TXTOwnerID: "default",
...@@ -138,6 +146,9 @@ func (cfg *Config) String() string { ...@@ -138,6 +146,9 @@ func (cfg *Config) String() string {
if temp.InfobloxWapiPassword != "" { if temp.InfobloxWapiPassword != "" {
temp.InfobloxWapiPassword = passwordMask temp.InfobloxWapiPassword = passwordMask
} }
if temp.PDNSAPIKey != "" {
temp.PDNSAPIKey = ""
}
return fmt.Sprintf("%+v", temp) return fmt.Sprintf("%+v", temp)
} }
...@@ -195,7 +206,13 @@ func (cfg *Config) ParseFlags(args []string) error { ...@@ -195,7 +206,13 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("inmemory-zone", "Provide a list of pre-configured zones for the inmemory provider; specify multiple times for multiple zones (optional)").Default("").StringsVar(&cfg.InMemoryZones) app.Flag("inmemory-zone", "Provide a list of pre-configured zones for the inmemory provider; specify multiple times for multiple zones (optional)").Default("").StringsVar(&cfg.InMemoryZones)
app.Flag("pdns-server", "When using the PowerDNS/PDNS provider, specify the URL to the pdns server (required when --provider=pdns)").Default(defaultConfig.PDNSServer).StringVar(&cfg.PDNSServer) app.Flag("pdns-server", "When using the PowerDNS/PDNS provider, specify the URL to the pdns server (required when --provider=pdns)").Default(defaultConfig.PDNSServer).StringVar(&cfg.PDNSServer)
app.Flag("pdns-api-key", "When using the PowerDNS/PDNS provider, specify the URL to the pdns server (required when --provider=pdns)").Default(defaultConfig.PDNSAPIKey).StringVar(&cfg.PDNSAPIKey) app.Flag("pdns-api-key", "When using the PowerDNS/PDNS provider, specify the API key to use to authorize requests (required when --provider=pdns)").Default(defaultConfig.PDNSAPIKey).StringVar(&cfg.PDNSAPIKey)
app.Flag("pdns-tls-enabled", "When using the PowerDNS/PDNS provider, specify whether to use TLS (default: false, requires --tls-ca, optionally specify --tls-client-cert and --tls-client-cert-key)").Default(strconv.FormatBool(defaultConfig.PDNSTLSEnabled)).BoolVar(&cfg.PDNSTLSEnabled)
// Flags related to TLS communication
app.Flag("tls-ca", "When using TLS communication, the path to the certificate authority to verify server communications (optionally specify --tls-client-cert for two-way TLS)").Default(defaultConfig.TLSCA).StringVar(&cfg.TLSCA)
app.Flag("tls-client-cert", "When using TLS communication, the path to the certificate to present as a client (not required for TLS)").Default(defaultConfig.TLSClientCert).StringVar(&cfg.TLSClientCert)
app.Flag("tls-client-cert-key", "When using TLS communication, the path to the certificate key to use with the client certificate (not required for TLS)").Default(defaultConfig.TLSClientCertKey).StringVar(&cfg.TLSClientCertKey)
// Flags related to policies // Flags related to policies
app.Flag("policy", "Modify how DNS records are sychronized between sources and providers (default: sync, options: sync, upsert-only)").Default(defaultConfig.Policy).EnumVar(&cfg.Policy, "sync", "upsert-only") app.Flag("policy", "Modify how DNS records are sychronized between sources and providers (default: sync, options: sync, upsert-only)").Default(defaultConfig.Policy).EnumVar(&cfg.Policy, "sync", "upsert-only")
......
...@@ -94,6 +94,10 @@ var ( ...@@ -94,6 +94,10 @@ var (
InMemoryZones: []string{"example.org", "company.com"}, InMemoryZones: []string{"example.org", "company.com"},
PDNSServer: "http://ns.example.com:8081", PDNSServer: "http://ns.example.com:8081",
PDNSAPIKey: "some-secret-key", PDNSAPIKey: "some-secret-key",
PDNSTLSEnabled: true,
TLSCA: "/path/to/ca.crt",
TLSClientCert: "/path/to/cert.pem",
TLSClientCertKey: "/path/to/key.pem",
Policy: "upsert-only", Policy: "upsert-only",
Registry: "noop", Registry: "noop",
TXTOwnerID: "owner-1", TXTOwnerID: "owner-1",
...@@ -150,6 +154,10 @@ func TestParseFlags(t *testing.T) { ...@@ -150,6 +154,10 @@ func TestParseFlags(t *testing.T) {
"--inmemory-zone=company.com", "--inmemory-zone=company.com",
"--pdns-server=http://ns.example.com:8081", "--pdns-server=http://ns.example.com:8081",
"--pdns-api-key=some-secret-key", "--pdns-api-key=some-secret-key",
"--pdns-tls-enabled",
"--tls-ca=/path/to/ca.crt",
"--tls-client-cert=/path/to/cert.pem",
"--tls-client-cert-key=/path/to/key.pem",
"--no-infoblox-ssl-verify", "--no-infoblox-ssl-verify",
"--domain-filter=example.org", "--domain-filter=example.org",
"--domain-filter=company.com", "--domain-filter=company.com",
...@@ -199,6 +207,10 @@ func TestParseFlags(t *testing.T) { ...@@ -199,6 +207,10 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_DOMAIN_FILTER": "example.org\ncompany.com", "EXTERNAL_DNS_DOMAIN_FILTER": "example.org\ncompany.com",
"EXTERNAL_DNS_PDNS_SERVER": "http://ns.example.com:8081", "EXTERNAL_DNS_PDNS_SERVER": "http://ns.example.com:8081",
"EXTERNAL_DNS_PDNS_API_KEY": "some-secret-key", "EXTERNAL_DNS_PDNS_API_KEY": "some-secret-key",
"EXTERNAL_DNS_PDNS_TLS_ENABLED": "1",
"EXTERNAL_DNS_TLS_CA": "/path/to/ca.crt",
"EXTERNAL_DNS_TLS_CLIENT_CERT": "/path/to/cert.pem",
"EXTERNAL_DNS_TLS_CLIENT_CERT_KEY": "/path/to/key.pem",
"EXTERNAL_DNS_ZONE_ID_FILTER": "/hostedzone/ZTST1\n/hostedzone/ZTST2", "EXTERNAL_DNS_ZONE_ID_FILTER": "/hostedzone/ZTST1\n/hostedzone/ZTST2",
"EXTERNAL_DNS_AWS_ZONE_TYPE": "private", "EXTERNAL_DNS_AWS_ZONE_TYPE": "private",
"EXTERNAL_DNS_AWS_ASSUME_ROLE": "some-other-role", "EXTERNAL_DNS_AWS_ASSUME_ROLE": "some-other-role",
...@@ -253,10 +265,12 @@ func TestPasswordsNotLogged(t *testing.T) { ...@@ -253,10 +265,12 @@ func TestPasswordsNotLogged(t *testing.T) {
cfg := Config{ cfg := Config{
DynPassword: "dyn-pass", DynPassword: "dyn-pass",
InfobloxWapiPassword: "infoblox-pass", InfobloxWapiPassword: "infoblox-pass",
PDNSAPIKey: "pdns-api-key",
} }
s := cfg.String() s := cfg.String()
assert.False(t, strings.Contains(s, "dyn-pass")) assert.False(t, strings.Contains(s, "dyn-pass"))
assert.False(t, strings.Contains(s, "infoblox-pass")) assert.False(t, strings.Contains(s, "infoblox-pass"))
assert.False(t, strings.Contains(s, "pdns-api-key"))
} }
...@@ -91,7 +91,7 @@ func (c *cache) Get(link string) *endpoint.Endpoint { ...@@ -91,7 +91,7 @@ func (c *cache) Get(link string) *endpoint.Endpoint {
return result.ep return result.ep
} }
// DynConfig hold connection parameters to dyn.com and interanl state // DynConfig hold connection parameters to dyn.com and internal state
type DynConfig struct { type DynConfig struct {
DomainFilter DomainFilter DomainFilter DomainFilter
ZoneIDFilter ZoneIDFilter ZoneIDFilter ZoneIDFilter
......
...@@ -32,6 +32,10 @@ import ( ...@@ -32,6 +32,10 @@ import (
pgo "github.com/ffledgling/pdns-go" pgo "github.com/ffledgling/pdns-go"
"github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/endpoint"
"github.com/kubernetes-incubator/external-dns/plan" "github.com/kubernetes-incubator/external-dns/plan"
"net"
"crypto/tls"
"crypto/x509"
"io/ioutil"
) )
type pdnsChangeType string type pdnsChangeType string
...@@ -57,6 +61,106 @@ const ( ...@@ -57,6 +61,106 @@ const (
retryAfterTime = 250 * time.Millisecond retryAfterTime = 250 * time.Millisecond
) )
type PDNSConfig struct {
DomainFilter DomainFilter
DryRun bool
Server string
APIKey string
TLSConfig TLSConfig
}
type TLSConfig struct {
TLSEnabled bool
CAFilePath string
ClientCertFilePath string
ClientCertKeyFilePath string
}
func (tlsConfig *TLSConfig) setHttpClient(pdnsClientConfig *pgo.Configuration) error {
if !tlsConfig.TLSEnabled {
if tlsConfig.CAFilePath != "" {
return errors.New("certificate authority file path was specified, but TLS was not enabled")
}
if tlsConfig.ClientCertFilePath != "" {
return errors.New("client certificate file path was specified, but TLS was not enabled")
}
if tlsConfig.ClientCertKeyFilePath != "" {
return errors.New("client certificate key file path was specified, but TLS was not enabled")
}
return nil;
}
log.Debug("Configuring TLS for PDNS Provider.")
if tlsConfig.CAFilePath == "" {
return errors.New("certificate authority file path must be specified if TLS is enabled")
}
if tlsConfig.ClientCertFilePath == "" && tlsConfig.ClientCertKeyFilePath != "" ||
tlsConfig.ClientCertFilePath != "" && tlsConfig.ClientCertKeyFilePath == "" {
return errors.New("client certificate and client certificate key should be specified together if at all")
}
certificateAuthority, err := loadCertificateAuthority(tlsConfig.CAFilePath)
if err != nil {
return err
}
certificate, err := loadCertificate(tlsConfig.ClientCertFilePath, tlsConfig.ClientCertKeyFilePath)
if err != nil {
return err
}
// Timeouts taken from net.http.DefaultTransport
transporter := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: certificate,
RootCAs: certificateAuthority,
},
}
pdnsClientConfig.HTTPClient = &http.Client{
Transport: transporter,
}
return nil
}
func loadCertificateAuthority(certificateAuthorityFilePath string) (*x509.CertPool, error) {
pool := x509.NewCertPool()
pem, err := ioutil.ReadFile(certificateAuthorityFilePath)
if err != nil {
return nil, err
}
ok := pool.AppendCertsFromPEM(pem)
if !ok {
return nil, errors.New("error appending certificate to pool")
}
return pool, nil
}
func loadCertificate(certificateFilePath string, certificateKeyFilePath string) ([]tls.Certificate, error) {
if certificateFilePath == "" || certificateKeyFilePath == "" {
return []tls.Certificate{}, nil
}
certificate, err := tls.LoadX509KeyPair(certificateFilePath, certificateKeyFilePath)
if err != nil {
return nil, err
}
return []tls.Certificate{certificate}, nil
}
// Function for debug printing // Function for debug printing
func stringifyHTTPResponseBody(r *http.Response) (body string) { func stringifyHTTPResponseBody(r *http.Response) (body string) {
...@@ -151,37 +255,40 @@ type PDNSProvider struct { ...@@ -151,37 +255,40 @@ type PDNSProvider struct {
} }
// NewPDNSProvider initializes a new PowerDNS based Provider. // NewPDNSProvider initializes a new PowerDNS based Provider.
func NewPDNSProvider(server string, apikey string, domainFilter DomainFilter, dryRun bool) (*PDNSProvider, error) { func NewPDNSProvider(config PDNSConfig) (*PDNSProvider, error) {
// Do some input validation // Do some input validation
if apikey == "" { if config.APIKey == "" {
return nil, errors.New("Missing API Key for PDNS. Specify using --pdns-api-key=") return nil, errors.New("Missing API Key for PDNS. Specify using --pdns-api-key=")
} }
// The default for when no --domain-filter is passed is [""], instead of [], so we check accordingly. // The default for when no --domain-filter is passed is [""], instead of [], so we check accordingly.
if len(domainFilter.filters) != 1 && domainFilter.filters[0] != "" { if len(config.DomainFilter.filters) != 1 && config.DomainFilter.filters[0] != "" {
return nil, errors.New("PDNS Provider does not support domain filter") return nil, errors.New("PDNS Provider does not support domain filter")
} }
// We do not support dry running, exit safely instead of surprising the user // We do not support dry running, exit safely instead of surprising the user
// TODO: Add Dry Run support // TODO: Add Dry Run support
if dryRun { if config.DryRun {
return nil, errors.New("PDNS Provider does not currently support dry-run") return nil, errors.New("PDNS Provider does not currently support dry-run")
} }
if server == "localhost" { if config.Server == "localhost" {
log.Warnf("PDNS Server is set to localhost, this may not be what you want. Specify using --pdns-server=") log.Warnf("PDNS Server is set to localhost, this may not be what you want. Specify using --pdns-server=")
} }
cfg := pgo.NewConfiguration() pdnsClientConfig := pgo.NewConfiguration()
cfg.Host = server pdnsClientConfig.Host = config.Server
cfg.BasePath = server + apiBase pdnsClientConfig.BasePath = config.Server + apiBase
if err := config.TLSConfig.setHttpClient(pdnsClientConfig); err != nil {
return nil, err
}
provider := &PDNSProvider{ provider := &PDNSProvider{
client: &PDNSAPIClient{ client: &PDNSAPIClient{
dryRun: dryRun, dryRun: config.DryRun,
authCtx: context.WithValue(context.TODO(), pgo.ContextAPIKey, pgo.APIKey{Key: apikey}), authCtx: context.WithValue(context.TODO(), pgo.ContextAPIKey, pgo.APIKey{Key: config.APIKey}),
client: pgo.NewAPIClient(cfg), client: pgo.NewAPIClient(pdnsClientConfig),
}, },
} }
......
...@@ -476,22 +476,148 @@ type NewPDNSProviderTestSuite struct { ...@@ -476,22 +476,148 @@ type NewPDNSProviderTestSuite struct {
} }
func (suite *NewPDNSProviderTestSuite) TestPDNSProviderCreate() { func (suite *NewPDNSProviderTestSuite) TestPDNSProviderCreate() {
// Function definition: NewPDNSProvider(server string, apikey string, domainFilter DomainFilter, dryRun bool) (*PDNSProvider, error)
_, err := NewPDNSProvider("http://localhost:8081", "", NewDomainFilter([]string{""}), false) _, err := NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
DomainFilter: NewDomainFilter([]string{""}),
})
assert.Error(suite.T(), err, "--pdns-api-key should be specified") assert.Error(suite.T(), err, "--pdns-api-key should be specified")
_, err = NewPDNSProvider("http://localhost:8081", "foo", NewDomainFilter([]string{"example.com", "example.org"}), false) _, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{"example.com", "example.org"}),
})
assert.Error(suite.T(), err, "--domainfilter should raise an error") assert.Error(suite.T(), err, "--domainfilter should raise an error")
_, err = NewPDNSProvider("http://localhost:8081", "foo", NewDomainFilter([]string{""}), true) _, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
DryRun: true,
})
assert.Error(suite.T(), err, "--dry-run should raise an error") assert.Error(suite.T(), err, "--dry-run should raise an error")
// This is our "regular" code path, no error should be thrown // This is our "regular" code path, no error should be thrown
_, err = NewPDNSProvider("http://localhost:8081", "foo", NewDomainFilter([]string{""}), false) _, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
})
assert.Nil(suite.T(), err, "Regular case should raise no error") assert.Nil(suite.T(), err, "Regular case should raise no error")
} }
func (suite *NewPDNSProviderTestSuite) TestPDNSProviderCreateTLS() {
_, err := NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
})
assert.Nil(suite.T(), err, "Omitted TLS Config case should raise no error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: false,
},
})
assert.Nil(suite.T(), err, "Disabled TLS Config should raise no error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: false,
CAFilePath: "/path/to/ca.crt",
},
})
assert.Error(suite.T(), err, "Disabled TLS Config with --tls-ca should raise an error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: false,
ClientCertFilePath: "/path/to/cert.pem",
},
})
assert.Error(suite.T(), err, "Disabled TLS Config with --tls-client-cert should raise an error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: false,
ClientCertKeyFilePath: "/path/to/cert-key.pem",
},
})
assert.Error(suite.T(), err, "Disabled TLS Config with --tls-client-cert-key should raise an error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: true,
},
})
assert.Error(suite.T(), err, "Enabled TLS Config without --tls-ca should raise an error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: true,
CAFilePath: "../internal/testresources/ca.pem",
},
})
assert.Nil(suite.T(), err, "Enabled TLS Config with --tls-ca should raise no error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: true,
CAFilePath: "../internal/testresources/ca.pem",
ClientCertFilePath: "../internal/testresources/client-cert.pem",
},
})
assert.Error(suite.T(), err, "Enabled TLS Config with --tls-client-cert only should raise an error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: true,
CAFilePath: "../internal/testresources/ca.pem",
ClientCertKeyFilePath: "../internal/testresources/client-cert-key.pem",
},
})
assert.Error(suite.T(), err, "Enabled TLS Config with --tls-client-cert-key only should raise an error")
_, err = NewPDNSProvider(PDNSConfig{
Server: "http://localhost:8081",
APIKey: "foo",
DomainFilter: NewDomainFilter([]string{""}),
TLSConfig: TLSConfig{
TLSEnabled: true,
CAFilePath: "../internal/testresources/ca.pem",
ClientCertFilePath: "../internal/testresources/client-cert.pem",
ClientCertKeyFilePath: "../internal/testresources/client-cert-key.pem",
},
})
assert.Nil(suite.T(), err, "Enabled TLS Config with all flags should raise no error")
}
func (suite *NewPDNSProviderTestSuite) TestPDNSRRSetToEndpoints() { func (suite *NewPDNSProviderTestSuite) TestPDNSRRSetToEndpoints() {
// Function definition: convertRRSetToEndpoints(rr pgo.RrSet) (endpoints []*endpoint.Endpoint, _ error) // Function definition: convertRRSetToEndpoints(rr pgo.RrSet) (endpoints []*endpoint.Endpoint, _ error)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment