|
@ -18,13 +18,9 @@ import ( |
|
|
"crypto/tls" |
|
|
"crypto/tls" |
|
|
"encoding/json" |
|
|
"encoding/json" |
|
|
"fmt" |
|
|
"fmt" |
|
|
"io/ioutil" |
|
|
|
|
|
"log" |
|
|
"log" |
|
|
"net/http" |
|
|
"net/http" |
|
|
"os" |
|
|
|
|
|
"path/filepath" |
|
|
|
|
|
"runtime/debug" |
|
|
"runtime/debug" |
|
|
"strings" |
|
|
|
|
|
"sync" |
|
|
"sync" |
|
|
"time" |
|
|
"time" |
|
|
|
|
|
|
|
@ -191,14 +187,6 @@ func (t *TLS) Provision(ctx caddy.Context) error { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// TODO: TEMPORARY UNTIL RELEASE CANDIDATES:
|
|
|
|
|
|
// MIGRATE MANAGED CERTIFICATE ASSETS TO NEW PATH
|
|
|
|
|
|
err = t.moveCertificates() |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
t.logger.Error("migrating certificates", zap.Error(err)) |
|
|
|
|
|
} |
|
|
|
|
|
// END TODO: TEMPORARY.
|
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -529,121 +517,3 @@ var ( |
|
|
_ caddy.Validator = (*TLS)(nil) |
|
|
_ caddy.Validator = (*TLS)(nil) |
|
|
_ caddy.CleanerUpper = (*TLS)(nil) |
|
|
_ caddy.CleanerUpper = (*TLS)(nil) |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
// TODO: This is temporary until the release candidates
|
|
|
|
|
|
// (beta 16 changed the storage path for certificates),
|
|
|
|
|
|
// after which this function can be deleted
|
|
|
|
|
|
func (t *TLS) moveCertificates() error { |
|
|
|
|
|
logger := t.logger.Named("automigrate") |
|
|
|
|
|
|
|
|
|
|
|
baseDir := caddy.AppDataDir() |
|
|
|
|
|
|
|
|
|
|
|
// if custom storage path was defined, use that instead
|
|
|
|
|
|
if fs, ok := t.ctx.Storage().(*certmagic.FileStorage); ok && fs.Path != "" { |
|
|
|
|
|
baseDir = fs.Path |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oldAcmeDir := filepath.Join(baseDir, "acme") |
|
|
|
|
|
oldAcmeCas, err := ioutil.ReadDir(oldAcmeDir) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
if os.IsNotExist(err) { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
return fmt.Errorf("listing used ACME CAs: %v", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// get list of used CAs
|
|
|
|
|
|
oldCANames := make([]string, 0, len(oldAcmeCas)) |
|
|
|
|
|
for _, fi := range oldAcmeCas { |
|
|
|
|
|
if !fi.IsDir() { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
oldCANames = append(oldCANames, fi.Name()) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for _, oldCA := range oldCANames { |
|
|
|
|
|
// make new destination path
|
|
|
|
|
|
newCAName := oldCA |
|
|
|
|
|
if strings.Contains(oldCA, "api.letsencrypt.org") && |
|
|
|
|
|
!strings.HasSuffix(oldCA, "-directory") { |
|
|
|
|
|
newCAName += "-directory" |
|
|
|
|
|
} |
|
|
|
|
|
newBaseDir := filepath.Join(baseDir, "certificates", newCAName) |
|
|
|
|
|
err := os.MkdirAll(newBaseDir, 0700) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return fmt.Errorf("making new certs directory: %v", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// list sites in old path
|
|
|
|
|
|
oldAcmeSitesDir := filepath.Join(oldAcmeDir, oldCA, "sites") |
|
|
|
|
|
oldAcmeSites, err := ioutil.ReadDir(oldAcmeSitesDir) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
if os.IsNotExist(err) { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
return fmt.Errorf("listing sites: %v", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if len(oldAcmeSites) > 0 { |
|
|
|
|
|
logger.Warn("certificate storage path has changed; attempting one-time auto-migration", |
|
|
|
|
|
zap.String("old_folder", oldAcmeSitesDir), |
|
|
|
|
|
zap.String("new_folder", newBaseDir), |
|
|
|
|
|
zap.String("details", "https://github.com/caddyserver/caddy/issues/2955")) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// for each site, move its folder and re-encode its metadata
|
|
|
|
|
|
for _, siteInfo := range oldAcmeSites { |
|
|
|
|
|
if !siteInfo.IsDir() { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// move the folder
|
|
|
|
|
|
oldPath := filepath.Join(oldAcmeSitesDir, siteInfo.Name()) |
|
|
|
|
|
newPath := filepath.Join(newBaseDir, siteInfo.Name()) |
|
|
|
|
|
logger.Info("moving certificate assets", |
|
|
|
|
|
zap.String("ca", oldCA), |
|
|
|
|
|
zap.String("site", siteInfo.Name()), |
|
|
|
|
|
zap.String("destination", newPath)) |
|
|
|
|
|
err = os.Rename(oldPath, newPath) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
logger.Error("failed moving site to new path; skipping", |
|
|
|
|
|
zap.String("old_path", oldPath), |
|
|
|
|
|
zap.String("new_path", newPath), |
|
|
|
|
|
zap.Error(err)) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// re-encode metadata file
|
|
|
|
|
|
metaFilePath := filepath.Join(newPath, siteInfo.Name()+".json") |
|
|
|
|
|
metaContents, err := ioutil.ReadFile(metaFilePath) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
logger.Error("could not read metadata file", |
|
|
|
|
|
zap.String("filename", metaFilePath), |
|
|
|
|
|
zap.Error(err)) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
if len(metaContents) == 0 { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
cr := certmagic.CertificateResource{ |
|
|
|
|
|
SANs: []string{siteInfo.Name()}, |
|
|
|
|
|
IssuerData: json.RawMessage(metaContents), |
|
|
|
|
|
} |
|
|
|
|
|
newMeta, err := json.MarshalIndent(cr, "", "\t") |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
logger.Error("encoding new metadata file", zap.Error(err)) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
err = ioutil.WriteFile(metaFilePath, newMeta, 0600) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
logger.Error("writing new metadata file", zap.Error(err)) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// delete now-empty old sites dir (OK if fails)
|
|
|
|
|
|
os.Remove(oldAcmeSitesDir) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|