From 1dfe1e5adabbdf4693098112aa918b7c4442df28 Mon Sep 17 00:00:00 2001 From: Luna Duclos Date: Tue, 23 Aug 2016 22:58:33 +0200 Subject: [PATCH] Add plugin capabilities for tls storage. To use a plugged in storage, specify "storage storage_name" in the tls block of the Caddyfile, by default, file storage will be used --- caddyhttp/caddyhttp_test.go | 2 +- caddytls/config.go | 33 ++++++++++++++++----------------- caddytls/config_test.go | 27 +++++++++++---------------- caddytls/filestorage.go | 4 ++++ caddytls/setup.go | 10 ++++++++++ caddytls/tls.go | 8 ++++++++ 6 files changed, 50 insertions(+), 34 deletions(-) diff --git a/caddyhttp/caddyhttp_test.go b/caddyhttp/caddyhttp_test.go index b228ab18..2d3a411c 100644 --- a/caddyhttp/caddyhttp_test.go +++ b/caddyhttp/caddyhttp_test.go @@ -11,7 +11,7 @@ import ( // ensure that the standard plugins are in fact plugged in // and registered properly; this is a quick/naive way to do it. func TestStandardPlugins(t *testing.T) { - numStandardPlugins := 25 // importing caddyhttp plugs in this many plugins + numStandardPlugins := 26 // importing caddyhttp plugs in this many plugins s := caddy.DescribePlugins() if got, want := strings.Count(s, "\n"), numStandardPlugins+5; got != want { t.Errorf("Expected all standard plugins to be plugged in, got:\n%s", s) diff --git a/caddytls/config.go b/caddytls/config.go index 18cb8d21..cef90aa3 100644 --- a/caddytls/config.go +++ b/caddytls/config.go @@ -99,12 +99,10 @@ type Config struct { // certificates KeyType acme.KeyType - // The explicitly set storage creator or nil; use - // StorageFor() to get a guaranteed non-nil Storage - // instance. Note, Caddy may call this frequently so - // implementors are encouraged to cache any heavy - // instantiations. - StorageCreator StorageCreator + // The storage creator; use StorageFor() to get a guaranteed + // non-nil Storage instance. Note, Caddy may call this frequently + // so implementors are encouraged to cache any heavy instantiations. + StorageProvider string // The state needed to operate on-demand TLS OnDemandState OnDemandState @@ -285,19 +283,20 @@ func (c *Config) StorageFor(caURL string) (Storage, error) { // Create the storage based on the URL var s Storage - if c.StorageCreator != nil { - s, err = c.StorageCreator(u) - if err != nil { - return nil, fmt.Errorf("%s: unable to create custom storage: %v", caURL, err) - } + if c.StorageProvider == "" { + c.StorageProvider = "file" } - if s == nil { - // We trust that this does not return a nil s when there's a nil err - s, err = FileStorageCreator(u) - if err != nil { - return nil, fmt.Errorf("%s: unable to create file storage: %v", caURL, err) - } + + creator, ok := storageProviders[c.StorageProvider] + if !ok { + return nil, fmt.Errorf("%s: Unknown storage: %v", caURL, c.StorageProvider) } + + s, err = creator(u) + if err != nil { + return nil, fmt.Errorf("%s: unable to create custom storage '%v': %v", caURL, c.StorageProvider, err) + } + return s, nil } diff --git a/caddytls/config_test.go b/caddytls/config_test.go index f5450bb7..be7c204a 100644 --- a/caddytls/config_test.go +++ b/caddytls/config_test.go @@ -38,11 +38,12 @@ func TestStorageForNoURL(t *testing.T) { func TestStorageForLowercasesAndPrefixesScheme(t *testing.T) { resultStr := "" + RegisterStorageProvider("fake-TestStorageForLowercasesAndPrefixesScheme", func(caURL *url.URL) (Storage, error) { + resultStr = caURL.String() + return nil, nil + }) c := &Config{ - StorageCreator: func(caURL *url.URL) (Storage, error) { - resultStr = caURL.String() - return nil, nil - }, + StorageProvider: "fake-TestStorageForLowercasesAndPrefixesScheme", } if _, err := c.StorageFor("EXAMPLE.COM/BLAH"); err != nil { t.Fatal(err) @@ -71,11 +72,10 @@ func TestStorageForDefault(t *testing.T) { } func TestStorageForCustom(t *testing.T) { - storage := fakeStorage("fake") + storage := fakeStorage("fake-TestStorageForCustom") + RegisterStorageProvider("fake-TestStorageForCustom", func(caURL *url.URL) (Storage, error) { return storage, nil }) c := &Config{ - StorageCreator: func(caURL *url.URL) (Storage, error) { - return storage, nil - }, + StorageProvider: "fake-TestStorageForCustom", } s, err := c.StorageFor("example.com") if err != nil { @@ -87,10 +87,9 @@ func TestStorageForCustom(t *testing.T) { } func TestStorageForCustomError(t *testing.T) { + RegisterStorageProvider("fake-TestStorageForCustomError", func(caURL *url.URL) (Storage, error) { return nil, errors.New("some error") }) c := &Config{ - StorageCreator: func(caURL *url.URL) (Storage, error) { - return nil, errors.New("some error") - }, + StorageProvider: "fake-TestStorageForCustomError", } if _, err := c.StorageFor("example.com"); err == nil { t.Fatal("Expecting error") @@ -99,11 +98,7 @@ func TestStorageForCustomError(t *testing.T) { func TestStorageForCustomNil(t *testing.T) { // Should fall through to the default - c := &Config{ - StorageCreator: func(caURL *url.URL) (Storage, error) { - return nil, nil - }, - } + c := &Config{StorageProvider: ""} s, err := c.StorageFor("example.com") if err != nil { t.Fatal(err) diff --git a/caddytls/filestorage.go b/caddytls/filestorage.go index bb86958a..4e9d3f5c 100644 --- a/caddytls/filestorage.go +++ b/caddytls/filestorage.go @@ -9,6 +9,10 @@ import ( "strings" ) +func init() { + RegisterStorageProvider("file", FileStorageCreator) +} + // storageBasePath is the root path in which all TLS/ACME assets are // stored. Do not change this value during the lifetime of the program. var storageBasePath = filepath.Join(caddy.AssetsPath(), "acme") diff --git a/caddytls/setup.go b/caddytls/setup.go index c225d41e..e782e04e 100644 --- a/caddytls/setup.go +++ b/caddytls/setup.go @@ -146,6 +146,16 @@ func setupTLS(c *caddy.Controller) error { return c.Errf("Unsupported DNS provider '%s'", args[0]) } config.DNSProvider = args[0] + case "storage": + args := c.RemainingArgs() + if len(args) != 1 { + return c.ArgErr() + } + storageProvName := args[0] + if _, ok := storageProviders[storageProvName]; !ok { + return c.Errf("Unsupported Storage provider '%s'", args[0]) + } + config.StorageProvider = args[0] default: return c.Errf("Unknown keyword '%s'", c.Val()) } diff --git a/caddytls/tls.go b/caddytls/tls.go index a5c67c31..607dfe46 100644 --- a/caddytls/tls.go +++ b/caddytls/tls.go @@ -168,3 +168,11 @@ var ( // when no other key type is specified. DefaultKeyType = acme.RSA2048 ) + +var storageProviders = make(map[string]StorageCreator) + +// RegisterStorageProvider registers provider by name for storing tls data +func RegisterStorageProvider(name string, provider StorageCreator) { + storageProviders[name] = provider + caddy.RegisterPlugin("tls.storage."+name, caddy.Plugin{}) +}