aboutsummaryrefslogtreecommitdiff
path: root/core/https/https_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/https/https_test.go')
-rw-r--r--core/https/https_test.go332
1 files changed, 332 insertions, 0 deletions
diff --git a/core/https/https_test.go b/core/https/https_test.go
new file mode 100644
index 000000000..40b67367e
--- /dev/null
+++ b/core/https/https_test.go
@@ -0,0 +1,332 @@
+package https
+
+import (
+ "io/ioutil"
+ "net/http"
+ "os"
+ "testing"
+
+ "github.com/miekg/coredns/middleware/redirect"
+ "github.com/miekg/coredns/server"
+ "github.com/xenolf/lego/acme"
+)
+
+func TestHostQualifies(t *testing.T) {
+ for i, test := range []struct {
+ host string
+ expect bool
+ }{
+ {"localhost", false},
+ {"127.0.0.1", false},
+ {"127.0.1.5", false},
+ {"::1", false},
+ {"[::1]", false},
+ {"[::]", false},
+ {"::", false},
+ {"", false},
+ {" ", false},
+ {"0.0.0.0", false},
+ {"192.168.1.3", false},
+ {"10.0.2.1", false},
+ {"169.112.53.4", false},
+ {"foobar.com", true},
+ {"sub.foobar.com", true},
+ } {
+ if HostQualifies(test.host) && !test.expect {
+ t.Errorf("Test %d: Expected '%s' to NOT qualify, but it did", i, test.host)
+ }
+ if !HostQualifies(test.host) && test.expect {
+ t.Errorf("Test %d: Expected '%s' to qualify, but it did NOT", i, test.host)
+ }
+ }
+}
+
+func TestConfigQualifies(t *testing.T) {
+ for i, test := range []struct {
+ cfg server.Config
+ expect bool
+ }{
+ {server.Config{Host: ""}, false},
+ {server.Config{Host: "localhost"}, false},
+ {server.Config{Host: "123.44.3.21"}, false},
+ {server.Config{Host: "example.com"}, true},
+ {server.Config{Host: "example.com", TLS: server.TLSConfig{Manual: true}}, false},
+ {server.Config{Host: "example.com", TLS: server.TLSConfig{LetsEncryptEmail: "off"}}, false},
+ {server.Config{Host: "example.com", TLS: server.TLSConfig{LetsEncryptEmail: "foo@bar.com"}}, true},
+ {server.Config{Host: "example.com", Scheme: "http"}, false},
+ {server.Config{Host: "example.com", Port: "80"}, false},
+ {server.Config{Host: "example.com", Port: "1234"}, true},
+ {server.Config{Host: "example.com", Scheme: "https"}, true},
+ {server.Config{Host: "example.com", Port: "80", Scheme: "https"}, false},
+ } {
+ if test.expect && !ConfigQualifies(test.cfg) {
+ t.Errorf("Test %d: Expected config to qualify, but it did NOT: %#v", i, test.cfg)
+ }
+ if !test.expect && ConfigQualifies(test.cfg) {
+ t.Errorf("Test %d: Expected config to NOT qualify, but it did: %#v", i, test.cfg)
+ }
+ }
+}
+
+func TestRedirPlaintextHost(t *testing.T) {
+ cfg := redirPlaintextHost(server.Config{
+ Host: "example.com",
+ BindHost: "93.184.216.34",
+ Port: "1234",
+ })
+
+ // Check host and port
+ if actual, expected := cfg.Host, "example.com"; actual != expected {
+ t.Errorf("Expected redir config to have host %s but got %s", expected, actual)
+ }
+ if actual, expected := cfg.BindHost, "93.184.216.34"; actual != expected {
+ t.Errorf("Expected redir config to have bindhost %s but got %s", expected, actual)
+ }
+ if actual, expected := cfg.Port, "80"; actual != expected {
+ t.Errorf("Expected redir config to have port '%s' but got '%s'", expected, actual)
+ }
+
+ // Make sure redirect handler is set up properly
+ if cfg.Middleware == nil || len(cfg.Middleware) != 1 {
+ t.Fatalf("Redir config middleware not set up properly; got: %#v", cfg.Middleware)
+ }
+
+ handler, ok := cfg.Middleware[0](nil).(redirect.Redirect)
+ if !ok {
+ t.Fatalf("Expected a redirect.Redirect middleware, but got: %#v", handler)
+ }
+ if len(handler.Rules) != 1 {
+ t.Fatalf("Expected one redirect rule, got: %#v", handler.Rules)
+ }
+
+ // Check redirect rule for correctness
+ if actual, expected := handler.Rules[0].FromScheme, "http"; actual != expected {
+ t.Errorf("Expected redirect rule to be from scheme '%s' but is actually from '%s'", expected, actual)
+ }
+ if actual, expected := handler.Rules[0].FromPath, "/"; actual != expected {
+ t.Errorf("Expected redirect rule to be for path '%s' but is actually for '%s'", expected, actual)
+ }
+ if actual, expected := handler.Rules[0].To, "https://{host}:1234{uri}"; actual != expected {
+ t.Errorf("Expected redirect rule to be to URL '%s' but is actually to '%s'", expected, actual)
+ }
+ if actual, expected := handler.Rules[0].Code, http.StatusMovedPermanently; actual != expected {
+ t.Errorf("Expected redirect rule to have code %d but was %d", expected, actual)
+ }
+
+ // browsers can infer a default port from scheme, so make sure the port
+ // doesn't get added in explicitly for default ports like 443 for https.
+ cfg = redirPlaintextHost(server.Config{Host: "example.com", Port: "443"})
+ handler, ok = cfg.Middleware[0](nil).(redirect.Redirect)
+ if actual, expected := handler.Rules[0].To, "https://{host}{uri}"; actual != expected {
+ t.Errorf("(Default Port) Expected redirect rule to be to URL '%s' but is actually to '%s'", expected, actual)
+ }
+}
+
+func TestSaveCertResource(t *testing.T) {
+ storage = Storage("./le_test_save")
+ defer func() {
+ err := os.RemoveAll(string(storage))
+ if err != nil {
+ t.Fatalf("Could not remove temporary storage directory (%s): %v", storage, err)
+ }
+ }()
+
+ domain := "example.com"
+ certContents := "certificate"
+ keyContents := "private key"
+ metaContents := `{
+ "domain": "example.com",
+ "certUrl": "https://example.com/cert",
+ "certStableUrl": "https://example.com/cert/stable"
+}`
+
+ cert := acme.CertificateResource{
+ Domain: domain,
+ CertURL: "https://example.com/cert",
+ CertStableURL: "https://example.com/cert/stable",
+ PrivateKey: []byte(keyContents),
+ Certificate: []byte(certContents),
+ }
+
+ err := saveCertResource(cert)
+ if err != nil {
+ t.Fatalf("Expected no error, got: %v", err)
+ }
+
+ certFile, err := ioutil.ReadFile(storage.SiteCertFile(domain))
+ if err != nil {
+ t.Errorf("Expected no error reading certificate file, got: %v", err)
+ }
+ if string(certFile) != certContents {
+ t.Errorf("Expected certificate file to contain '%s', got '%s'", certContents, string(certFile))
+ }
+
+ keyFile, err := ioutil.ReadFile(storage.SiteKeyFile(domain))
+ if err != nil {
+ t.Errorf("Expected no error reading private key file, got: %v", err)
+ }
+ if string(keyFile) != keyContents {
+ t.Errorf("Expected private key file to contain '%s', got '%s'", keyContents, string(keyFile))
+ }
+
+ metaFile, err := ioutil.ReadFile(storage.SiteMetaFile(domain))
+ if err != nil {
+ t.Errorf("Expected no error reading meta file, got: %v", err)
+ }
+ if string(metaFile) != metaContents {
+ t.Errorf("Expected meta file to contain '%s', got '%s'", metaContents, string(metaFile))
+ }
+}
+
+func TestExistingCertAndKey(t *testing.T) {
+ storage = Storage("./le_test_existing")
+ defer func() {
+ err := os.RemoveAll(string(storage))
+ if err != nil {
+ t.Fatalf("Could not remove temporary storage directory (%s): %v", storage, err)
+ }
+ }()
+
+ domain := "example.com"
+
+ if existingCertAndKey(domain) {
+ t.Errorf("Did NOT expect %v to have existing cert or key, but it did", domain)
+ }
+
+ err := saveCertResource(acme.CertificateResource{
+ Domain: domain,
+ PrivateKey: []byte("key"),
+ Certificate: []byte("cert"),
+ })
+ if err != nil {
+ t.Fatalf("Expected no error, got: %v", err)
+ }
+
+ if !existingCertAndKey(domain) {
+ t.Errorf("Expected %v to have existing cert and key, but it did NOT", domain)
+ }
+}
+
+func TestHostHasOtherPort(t *testing.T) {
+ configs := []server.Config{
+ {Host: "example.com", Port: "80"},
+ {Host: "sub1.example.com", Port: "80"},
+ {Host: "sub1.example.com", Port: "443"},
+ }
+
+ if hostHasOtherPort(configs, 0, "80") {
+ t.Errorf(`Expected hostHasOtherPort(configs, 0, "80") to be false, but got true`)
+ }
+ if hostHasOtherPort(configs, 0, "443") {
+ t.Errorf(`Expected hostHasOtherPort(configs, 0, "443") to be false, but got true`)
+ }
+ if !hostHasOtherPort(configs, 1, "443") {
+ t.Errorf(`Expected hostHasOtherPort(configs, 1, "443") to be true, but got false`)
+ }
+}
+
+func TestMakePlaintextRedirects(t *testing.T) {
+ configs := []server.Config{
+ // Happy path = standard redirect from 80 to 443
+ {Host: "example.com", TLS: server.TLSConfig{Managed: true}},
+
+ // Host on port 80 already defined; don't change it (no redirect)
+ {Host: "sub1.example.com", Port: "80", Scheme: "http"},
+ {Host: "sub1.example.com", TLS: server.TLSConfig{Managed: true}},
+
+ // Redirect from port 80 to port 5000 in this case
+ {Host: "sub2.example.com", Port: "5000", TLS: server.TLSConfig{Managed: true}},
+
+ // Can redirect from 80 to either 443 or 5001, but choose 443
+ {Host: "sub3.example.com", Port: "443", TLS: server.TLSConfig{Managed: true}},
+ {Host: "sub3.example.com", Port: "5001", Scheme: "https", TLS: server.TLSConfig{Managed: true}},
+ }
+
+ result := MakePlaintextRedirects(configs)
+ expectedRedirCount := 3
+
+ if len(result) != len(configs)+expectedRedirCount {
+ t.Errorf("Expected %d redirect(s) to be added, but got %d",
+ expectedRedirCount, len(result)-len(configs))
+ }
+}
+
+func TestEnableTLS(t *testing.T) {
+ configs := []server.Config{
+ {Host: "example.com", TLS: server.TLSConfig{Managed: true}},
+ {}, // not managed - no changes!
+ }
+
+ EnableTLS(configs, false)
+
+ if !configs[0].TLS.Enabled {
+ t.Errorf("Expected config 0 to have TLS.Enabled == true, but it was false")
+ }
+ if configs[1].TLS.Enabled {
+ t.Errorf("Expected config 1 to have TLS.Enabled == false, but it was true")
+ }
+}
+
+func TestGroupConfigsByEmail(t *testing.T) {
+ if groupConfigsByEmail([]server.Config{}, false) == nil {
+ t.Errorf("With empty input, returned map was nil, but expected non-nil map")
+ }
+
+ configs := []server.Config{
+ {Host: "example.com", TLS: server.TLSConfig{LetsEncryptEmail: "", Managed: true}},
+ {Host: "sub1.example.com", TLS: server.TLSConfig{LetsEncryptEmail: "foo@bar", Managed: true}},
+ {Host: "sub2.example.com", TLS: server.TLSConfig{LetsEncryptEmail: "", Managed: true}},
+ {Host: "sub3.example.com", TLS: server.TLSConfig{LetsEncryptEmail: "foo@bar", Managed: true}},
+ {Host: "sub4.example.com", TLS: server.TLSConfig{LetsEncryptEmail: "", Managed: true}},
+ {Host: "sub5.example.com", TLS: server.TLSConfig{LetsEncryptEmail: ""}}, // not managed
+ }
+ DefaultEmail = "test@example.com"
+
+ groups := groupConfigsByEmail(configs, true)
+
+ if groups == nil {
+ t.Fatalf("Returned map was nil, but expected values")
+ }
+
+ if len(groups) != 2 {
+ t.Errorf("Expected 2 groups, got %d: %#v", len(groups), groups)
+ }
+ if len(groups["foo@bar"]) != 2 {
+ t.Errorf("Expected 2 configs for foo@bar, got %d: %#v", len(groups["foobar"]), groups["foobar"])
+ }
+ if len(groups[DefaultEmail]) != 3 {
+ t.Errorf("Expected 3 configs for %s, got %d: %#v", DefaultEmail, len(groups["foobar"]), groups["foobar"])
+ }
+}
+
+func TestMarkQualified(t *testing.T) {
+ // TODO: TestConfigQualifies and this test share the same config list...
+ configs := []server.Config{
+ {Host: ""},
+ {Host: "localhost"},
+ {Host: "123.44.3.21"},
+ {Host: "example.com"},
+ {Host: "example.com", TLS: server.TLSConfig{Manual: true}},
+ {Host: "example.com", TLS: server.TLSConfig{LetsEncryptEmail: "off"}},
+ {Host: "example.com", TLS: server.TLSConfig{LetsEncryptEmail: "foo@bar.com"}},
+ {Host: "example.com", Scheme: "http"},
+ {Host: "example.com", Port: "80"},
+ {Host: "example.com", Port: "1234"},
+ {Host: "example.com", Scheme: "https"},
+ {Host: "example.com", Port: "80", Scheme: "https"},
+ }
+ expectedManagedCount := 4
+
+ MarkQualified(configs)
+
+ count := 0
+ for _, cfg := range configs {
+ if cfg.TLS.Managed {
+ count++
+ }
+ }
+
+ if count != expectedManagedCount {
+ t.Errorf("Expected %d managed configs, but got %d", expectedManagedCount, count)
+ }
+}
.gravatar.com/avatar/2b4542a486c35ab53c505a1070ba1f64?s=13&d=retro' width='13' height='13' alt='Gravatar' /> Okiki 7-215/+521 2022-04-26[ci] release (#3182)create-astro@0.10.0astro@1.0.0-beta.18@astrojs/vercel@0.1.4@astrojs/tailwind@0.2.1@astrojs/svelte@0.1.2@astrojs/netlify@0.3.3Gravatar github-actions[bot] 54-146/+130 2022-04-26[ci] formatGravatar matthewp 1-1/+1 2022-04-26fix(vercel): `trailingSlash` fix for non-html pages (#3185)Gravatar Juan Martín Seery 2-29/+42 2022-04-26Prevent watcher from running during the build (#3207)Gravatar Matthew Phillips 2-0/+9 2022-04-26Fix lockfile (#3210)Gravatar Juan Martín Seery 1-6/+0 2022-04-26Add missing is:raw in AstroBuiltinAttributes (#3209)Gravatar Erika 2-0/+6 2022-04-26Feat: support `astro add` without npm installing (#3183)Gravatar Ben Holmes 6-30/+49 2022-04-26Add Astro attributes to svg elements (#3205)Gravatar Erika 2-1/+9 2022-04-26[ci] formatGravatar bholmesdev 2-9/+9 2022-04-26Feat: `create astro` add install step (#3190)Gravatar Ben Holmes 7-162/+299 2022-04-26[ci] collect statsGravatar FredKSchott 1-0/+1 2022-04-25fix(markdown): file.url fixes (#3198)Gravatar Juan Martín Seery 11-10/+149 2022-04-25[ci] collect statsGravatar FredKSchott 1-0/+1 2022-04-24add vite to licenseGravatar Fred K. Schott 2-24/+29 2022-04-24feat(markdown): Improved types (#3191)Gravatar Juan Martín Seery 3-6/+47 2022-04-24[ci] collect statsGravatar FredKSchott 1-0/+1 2022-04-23[ci] collect statsGravatar FredKSchott 1-0/+1