mirror of
https://github.com/caddyserver/caddy.git
synced 2026-05-26 00:32:31 -04:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 08aee56c57 | |||
| aea4013a56 | |||
| 44d078b670 | |||
| 051e73aefc | |||
| 9f7148392a | |||
| 320c57291d | |||
| aa3d20be3e | |||
| 54d03ced48 | |||
| 89ed5f44de | |||
| 105eee671c | |||
| 737936c06b | |||
| a6d488a15b |
@@ -424,6 +424,13 @@ func replaceLocalAdminServer(cfg *Config, ctx Context) error {
|
||||
|
||||
handler := cfg.Admin.newAdminHandler(addr, false, ctx)
|
||||
|
||||
// run the provisioners for loaded modules to make sure local
|
||||
// state is properly re-initialized in the new admin server
|
||||
err = cfg.Admin.provisionAdminRouters(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ln, err := addr.Listen(context.TODO(), 0, net.ListenConfig{})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -545,6 +552,13 @@ func replaceRemoteAdminServer(ctx Context, cfg *Config) error {
|
||||
// because we are using TLS authentication instead
|
||||
handler := cfg.Admin.newAdminHandler(addr, true, ctx)
|
||||
|
||||
// run the provisioners for loaded modules to make sure local
|
||||
// state is properly re-initialized in the new admin server
|
||||
err = cfg.Admin.provisionAdminRouters(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create client certificate pool for TLS mutual auth, and extract public keys
|
||||
// so that we can enforce access controls at the application layer
|
||||
clientCertPool := x509.NewCertPool()
|
||||
|
||||
@@ -505,14 +505,6 @@ func provisionContext(newCfg *Config, replaceAdminServer bool) (Context, error)
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// start the admin endpoint (and stop any prior one)
|
||||
if replaceAdminServer {
|
||||
err = replaceLocalAdminServer(newCfg, ctx)
|
||||
if err != nil {
|
||||
return ctx, fmt.Errorf("starting caddy administration endpoint: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// create the new filesystem map
|
||||
newCfg.fileSystems = &filesystems.FileSystemMap{}
|
||||
|
||||
@@ -544,6 +536,14 @@ func provisionContext(newCfg *Config, replaceAdminServer bool) (Context, error)
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// start the admin endpoint (and stop any prior one)
|
||||
if replaceAdminServer {
|
||||
err = replaceLocalAdminServer(newCfg, ctx)
|
||||
if err != nil {
|
||||
return ctx, fmt.Errorf("starting caddy administration endpoint: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Load and Provision each app and their submodules
|
||||
err = func() error {
|
||||
for appName := range newCfg.AppsRaw {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
pki {
|
||||
ca custom-ca {
|
||||
name "Custom CA"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acme.example.com {
|
||||
acme_server {
|
||||
ca custom-ca
|
||||
allow {
|
||||
domains host-1.internal.example.com host-2.internal.example.com
|
||||
}
|
||||
}
|
||||
}
|
||||
----------
|
||||
{
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"srv0": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"acme.example.com"
|
||||
]
|
||||
}
|
||||
],
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"ca": "custom-ca",
|
||||
"handler": "acme_server",
|
||||
"policy": {
|
||||
"allow": {
|
||||
"domains": [
|
||||
"host-1.internal.example.com",
|
||||
"host-2.internal.example.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"pki": {
|
||||
"certificate_authorities": {
|
||||
"custom-ca": {
|
||||
"name": "Custom CA"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
pki {
|
||||
ca custom-ca {
|
||||
name "Custom CA"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acme.example.com {
|
||||
acme_server {
|
||||
ca custom-ca
|
||||
allow {
|
||||
domains host-1.internal.example.com host-2.internal.example.com
|
||||
}
|
||||
deny {
|
||||
domains dc.internal.example.com
|
||||
}
|
||||
}
|
||||
}
|
||||
----------
|
||||
{
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"srv0": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"acme.example.com"
|
||||
]
|
||||
}
|
||||
],
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"ca": "custom-ca",
|
||||
"handler": "acme_server",
|
||||
"policy": {
|
||||
"allow": {
|
||||
"domains": [
|
||||
"host-1.internal.example.com",
|
||||
"host-2.internal.example.com"
|
||||
]
|
||||
},
|
||||
"deny": {
|
||||
"domains": [
|
||||
"dc.internal.example.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"pki": {
|
||||
"certificate_authorities": {
|
||||
"custom-ca": {
|
||||
"name": "Custom CA"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
pki {
|
||||
ca custom-ca {
|
||||
name "Custom CA"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acme.example.com {
|
||||
acme_server {
|
||||
ca custom-ca
|
||||
deny {
|
||||
domains dc.internal.example.com
|
||||
}
|
||||
}
|
||||
}
|
||||
----------
|
||||
{
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"srv0": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"acme.example.com"
|
||||
]
|
||||
}
|
||||
],
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"ca": "custom-ca",
|
||||
"handler": "acme_server",
|
||||
"policy": {
|
||||
"deny": {
|
||||
"domains": [
|
||||
"dc.internal.example.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"pki": {
|
||||
"certificate_authorities": {
|
||||
"custom-ca": {
|
||||
"name": "Custom CA"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -809,9 +809,3 @@ func configFileWithRespectToDefault(logger *zap.Logger, configFile string) (stri
|
||||
// default config file does not exist or is irrelevant
|
||||
return configFile, nil
|
||||
}
|
||||
|
||||
type moduleInfo struct {
|
||||
caddyModuleID string
|
||||
goModule *debug.Module
|
||||
err error
|
||||
}
|
||||
|
||||
@@ -395,51 +395,6 @@ is always printed to stdout.
|
||||
},
|
||||
})
|
||||
|
||||
RegisterCommand(Command{
|
||||
Name: "upgrade",
|
||||
Short: "Upgrade Caddy (EXPERIMENTAL)",
|
||||
Long: `
|
||||
Downloads an updated Caddy binary with the same modules/plugins at the
|
||||
latest versions. EXPERIMENTAL: May be changed or removed.
|
||||
`,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().BoolP("keep-backup", "k", false, "Keep the backed up binary, instead of deleting it")
|
||||
cmd.RunE = WrapCommandFuncForCobra(cmdUpgrade)
|
||||
},
|
||||
})
|
||||
|
||||
RegisterCommand(Command{
|
||||
Name: "add-package",
|
||||
Usage: "<package[@version]...>",
|
||||
Short: "Adds Caddy packages (EXPERIMENTAL)",
|
||||
Long: `
|
||||
Downloads an updated Caddy binary with the specified packages (module/plugin)
|
||||
added, with an optional version specified (e.g., "package@version"). Retains
|
||||
existing packages. Returns an error if any of the specified packages are already
|
||||
included. EXPERIMENTAL: May be changed or removed.
|
||||
`,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().BoolP("keep-backup", "k", false, "Keep the backed up binary, instead of deleting it")
|
||||
cmd.RunE = WrapCommandFuncForCobra(cmdAddPackage)
|
||||
},
|
||||
})
|
||||
|
||||
RegisterCommand(Command{
|
||||
Name: "remove-package",
|
||||
Func: cmdRemovePackage,
|
||||
Usage: "<packages...>",
|
||||
Short: "Removes Caddy packages (EXPERIMENTAL)",
|
||||
Long: `
|
||||
Downloads an updated Caddy binaries without the specified packages (module/plugin).
|
||||
Returns an error if any of the packages are not included.
|
||||
EXPERIMENTAL: May be changed or removed.
|
||||
`,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().BoolP("keep-backup", "k", false, "Keep the backed up binary, instead of deleting it")
|
||||
cmd.RunE = WrapCommandFuncForCobra(cmdRemovePackage)
|
||||
},
|
||||
})
|
||||
|
||||
defaultFactory.Use(func(rootCmd *cobra.Command) {
|
||||
rootCmd.AddCommand(caddyCmdToCobra(Command{
|
||||
Name: "manpage",
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package caddycmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
)
|
||||
|
||||
type moduleInfo struct {
|
||||
caddyModuleID string
|
||||
goModule *debug.Module
|
||||
err error
|
||||
}
|
||||
|
||||
func getModules() (standard, nonstandard, unknown []moduleInfo, err error) {
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
err = fmt.Errorf("no build info")
|
||||
return
|
||||
}
|
||||
|
||||
for _, modID := range caddy.Modules() {
|
||||
modInfo, err := caddy.GetModule(modID)
|
||||
if err != nil {
|
||||
// that's weird, shouldn't happen
|
||||
unknown = append(unknown, moduleInfo{caddyModuleID: modID, err: err})
|
||||
continue
|
||||
}
|
||||
|
||||
// to get the Caddy plugin's version info, we need to know
|
||||
// the package that the Caddy module's value comes from; we
|
||||
// can use reflection but we need a non-pointer value (I'm
|
||||
// not sure why), and since New() should return a pointer
|
||||
// value, we need to dereference it first
|
||||
iface := any(modInfo.New())
|
||||
if rv := reflect.ValueOf(iface); rv.Kind() == reflect.Ptr {
|
||||
iface = reflect.New(reflect.TypeOf(iface).Elem()).Elem().Interface()
|
||||
}
|
||||
modPkgPath := reflect.TypeOf(iface).PkgPath()
|
||||
|
||||
// now we find the Go module that the Caddy module's package
|
||||
// belongs to; we assume the Caddy module package path will
|
||||
// be prefixed by its Go module path, and we will choose the
|
||||
// longest matching prefix in case there are nested modules
|
||||
var matched *debug.Module
|
||||
for _, dep := range bi.Deps {
|
||||
if strings.HasPrefix(modPkgPath, dep.Path) {
|
||||
if matched == nil || len(dep.Path) > len(matched.Path) {
|
||||
matched = dep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
caddyModGoMod := moduleInfo{caddyModuleID: modID, goModule: matched}
|
||||
|
||||
if strings.HasPrefix(modPkgPath, caddy.ImportPath) {
|
||||
standard = append(standard, caddyModGoMod)
|
||||
} else {
|
||||
nonstandard = append(nonstandard, caddyModGoMod)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
// Copyright 2015 Matthew Holt and The Caddy Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package caddycmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
)
|
||||
|
||||
func cmdUpgrade(fl Flags) (int, error) {
|
||||
_, nonstandard, _, err := getModules()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("unable to enumerate installed plugins: %v", err)
|
||||
}
|
||||
pluginPkgs, err := getPluginPackages(nonstandard)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
return upgradeBuild(pluginPkgs, fl)
|
||||
}
|
||||
|
||||
func splitModule(arg string) (module, version string, err error) {
|
||||
const versionSplit = "@"
|
||||
|
||||
// accommodate module paths that have @ in them, but we can only tolerate that if there's also
|
||||
// a version, otherwise we don't know if it's a version separator or part of the file path
|
||||
lastVersionSplit := strings.LastIndex(arg, versionSplit)
|
||||
if lastVersionSplit < 0 {
|
||||
module = arg
|
||||
} else {
|
||||
module, version = arg[:lastVersionSplit], arg[lastVersionSplit+1:]
|
||||
}
|
||||
|
||||
if module == "" {
|
||||
err = fmt.Errorf("module name is required")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func cmdAddPackage(fl Flags) (int, error) {
|
||||
if len(fl.Args()) == 0 {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("at least one package name must be specified")
|
||||
}
|
||||
_, nonstandard, _, err := getModules()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("unable to enumerate installed plugins: %v", err)
|
||||
}
|
||||
pluginPkgs, err := getPluginPackages(nonstandard)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
for _, arg := range fl.Args() {
|
||||
module, version, err := splitModule(arg)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid module name: %v", err)
|
||||
}
|
||||
// only allow a version to be specified if it's different from the existing version
|
||||
if _, ok := pluginPkgs[module]; ok && !(version != "" && pluginPkgs[module].Version != version) {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("package is already added")
|
||||
}
|
||||
pluginPkgs[module] = pluginPackage{Version: version, Path: module}
|
||||
}
|
||||
|
||||
return upgradeBuild(pluginPkgs, fl)
|
||||
}
|
||||
|
||||
func cmdRemovePackage(fl Flags) (int, error) {
|
||||
if len(fl.Args()) == 0 {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("at least one package name must be specified")
|
||||
}
|
||||
_, nonstandard, _, err := getModules()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("unable to enumerate installed plugins: %v", err)
|
||||
}
|
||||
pluginPkgs, err := getPluginPackages(nonstandard)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
for _, arg := range fl.Args() {
|
||||
module, _, err := splitModule(arg)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid module name: %v", err)
|
||||
}
|
||||
if _, ok := pluginPkgs[module]; !ok {
|
||||
// package does not exist
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("package is not added")
|
||||
}
|
||||
delete(pluginPkgs, arg)
|
||||
}
|
||||
|
||||
return upgradeBuild(pluginPkgs, fl)
|
||||
}
|
||||
|
||||
func upgradeBuild(pluginPkgs map[string]pluginPackage, fl Flags) (int, error) {
|
||||
l := caddy.Log()
|
||||
|
||||
thisExecPath, err := os.Executable()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("determining current executable path: %v", err)
|
||||
}
|
||||
thisExecStat, err := os.Stat(thisExecPath)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("retrieving current executable permission bits: %v", err)
|
||||
}
|
||||
if thisExecStat.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
symSource := thisExecPath
|
||||
// we are a symlink; resolve it
|
||||
thisExecPath, err = filepath.EvalSymlinks(thisExecPath)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("resolving current executable symlink: %v", err)
|
||||
}
|
||||
l.Info("this executable is a symlink", zap.String("source", symSource), zap.String("target", thisExecPath))
|
||||
}
|
||||
l.Info("this executable will be replaced", zap.String("path", thisExecPath))
|
||||
|
||||
// build the request URL to download this custom build
|
||||
qs := url.Values{
|
||||
"os": {runtime.GOOS},
|
||||
"arch": {runtime.GOARCH},
|
||||
}
|
||||
for _, pkgInfo := range pluginPkgs {
|
||||
qs.Add("p", pkgInfo.String())
|
||||
}
|
||||
|
||||
// initiate the build
|
||||
resp, err := downloadBuild(qs)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("download failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// back up the current binary, in case something goes wrong we can replace it
|
||||
backupExecPath := thisExecPath + ".tmp"
|
||||
l.Info("build acquired; backing up current executable",
|
||||
zap.String("current_path", thisExecPath),
|
||||
zap.String("backup_path", backupExecPath))
|
||||
err = os.Rename(thisExecPath, backupExecPath)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("backing up current binary: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err2 := os.Rename(backupExecPath, thisExecPath)
|
||||
if err2 != nil {
|
||||
l.Error("restoring original executable failed; will need to be restored manually",
|
||||
zap.String("backup_path", backupExecPath),
|
||||
zap.String("original_path", thisExecPath),
|
||||
zap.Error(err2))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// download the file; do this in a closure to close reliably before we execute it
|
||||
err = writeCaddyBinary(thisExecPath, &resp.Body, thisExecStat)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
l.Info("download successful; displaying new binary details", zap.String("location", thisExecPath))
|
||||
|
||||
// use the new binary to print out version and module info
|
||||
fmt.Print("\nModule versions:\n\n")
|
||||
if err = listModules(thisExecPath); err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("download succeeded, but unable to execute 'caddy list-modules': %v", err)
|
||||
}
|
||||
fmt.Println("\nVersion:")
|
||||
if err = showVersion(thisExecPath); err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("download succeeded, but unable to execute 'caddy version': %v", err)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// clean up the backup file
|
||||
if !fl.Bool("keep-backup") {
|
||||
if err = removeCaddyBinary(backupExecPath); err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("download succeeded, but unable to clean up backup binary: %v", err)
|
||||
}
|
||||
} else {
|
||||
l.Info("skipped cleaning up the backup file", zap.String("backup_path", backupExecPath))
|
||||
}
|
||||
|
||||
l.Info("upgrade successful; please restart any running Caddy instances", zap.String("executable", thisExecPath))
|
||||
|
||||
return caddy.ExitCodeSuccess, nil
|
||||
}
|
||||
|
||||
func getModules() (standard, nonstandard, unknown []moduleInfo, err error) {
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
err = fmt.Errorf("no build info")
|
||||
return
|
||||
}
|
||||
|
||||
for _, modID := range caddy.Modules() {
|
||||
modInfo, err := caddy.GetModule(modID)
|
||||
if err != nil {
|
||||
// that's weird, shouldn't happen
|
||||
unknown = append(unknown, moduleInfo{caddyModuleID: modID, err: err})
|
||||
continue
|
||||
}
|
||||
|
||||
// to get the Caddy plugin's version info, we need to know
|
||||
// the package that the Caddy module's value comes from; we
|
||||
// can use reflection but we need a non-pointer value (I'm
|
||||
// not sure why), and since New() should return a pointer
|
||||
// value, we need to dereference it first
|
||||
iface := any(modInfo.New())
|
||||
if rv := reflect.ValueOf(iface); rv.Kind() == reflect.Ptr {
|
||||
iface = reflect.New(reflect.TypeOf(iface).Elem()).Elem().Interface()
|
||||
}
|
||||
modPkgPath := reflect.TypeOf(iface).PkgPath()
|
||||
|
||||
// now we find the Go module that the Caddy module's package
|
||||
// belongs to; we assume the Caddy module package path will
|
||||
// be prefixed by its Go module path, and we will choose the
|
||||
// longest matching prefix in case there are nested modules
|
||||
var matched *debug.Module
|
||||
for _, dep := range bi.Deps {
|
||||
if strings.HasPrefix(modPkgPath, dep.Path) {
|
||||
if matched == nil || len(dep.Path) > len(matched.Path) {
|
||||
matched = dep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
caddyModGoMod := moduleInfo{caddyModuleID: modID, goModule: matched}
|
||||
|
||||
if strings.HasPrefix(modPkgPath, caddy.ImportPath) {
|
||||
standard = append(standard, caddyModGoMod)
|
||||
} else {
|
||||
nonstandard = append(nonstandard, caddyModGoMod)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func listModules(path string) error {
|
||||
cmd := exec.Command(path, "list-modules", "--versions", "--skip-standard")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func showVersion(path string) error {
|
||||
cmd := exec.Command(path, "version")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func downloadBuild(qs url.Values) (*http.Response, error) {
|
||||
l := caddy.Log()
|
||||
l.Info("requesting build",
|
||||
zap.String("os", qs.Get("os")),
|
||||
zap.String("arch", qs.Get("arch")),
|
||||
zap.Strings("packages", qs["p"]))
|
||||
resp, err := http.Get(fmt.Sprintf("%s?%s", downloadPath, qs.Encode()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("secure request failed: %v", err)
|
||||
}
|
||||
if resp.StatusCode >= 400 {
|
||||
var details struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Error struct {
|
||||
Message string `json:"message"`
|
||||
ID string `json:"id"`
|
||||
} `json:"error"`
|
||||
}
|
||||
err2 := json.NewDecoder(resp.Body).Decode(&details)
|
||||
if err2 != nil {
|
||||
return nil, fmt.Errorf("download and error decoding failed: HTTP %d: %v", resp.StatusCode, err2)
|
||||
}
|
||||
return nil, fmt.Errorf("download failed: HTTP %d: %s (id=%s)", resp.StatusCode, details.Error.Message, details.Error.ID)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func getPluginPackages(modules []moduleInfo) (map[string]pluginPackage, error) {
|
||||
pluginPkgs := make(map[string]pluginPackage)
|
||||
for _, mod := range modules {
|
||||
if mod.goModule.Replace != nil {
|
||||
return nil, fmt.Errorf("cannot auto-upgrade when Go module has been replaced: %s => %s",
|
||||
mod.goModule.Path, mod.goModule.Replace.Path)
|
||||
}
|
||||
pluginPkgs[mod.goModule.Path] = pluginPackage{Version: mod.goModule.Version, Path: mod.goModule.Path}
|
||||
}
|
||||
return pluginPkgs, nil
|
||||
}
|
||||
|
||||
func writeCaddyBinary(path string, body *io.ReadCloser, fileInfo os.FileInfo) error {
|
||||
l := caddy.Log()
|
||||
destFile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileInfo.Mode())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open destination file: %v", err)
|
||||
}
|
||||
defer destFile.Close()
|
||||
|
||||
l.Info("downloading binary", zap.String("destination", path))
|
||||
|
||||
_, err = io.Copy(destFile, *body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to download file: %v", err)
|
||||
}
|
||||
|
||||
err = destFile.Sync()
|
||||
if err != nil {
|
||||
return fmt.Errorf("syncing downloaded file to device: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const downloadPath = "https://caddyserver.com/api/download"
|
||||
|
||||
type pluginPackage struct {
|
||||
Version string
|
||||
Path string
|
||||
}
|
||||
|
||||
func (p pluginPackage) String() string {
|
||||
if p.Version == "" {
|
||||
return p.Path
|
||||
}
|
||||
return p.Path + "@" + p.Version
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2015 Matthew Holt and The Caddy Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package caddycmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// removeCaddyBinary removes the Caddy binary at the given path.
|
||||
//
|
||||
// On any non-Windows OS, this simply calls os.Remove, since they should
|
||||
// probably not exhibit any issue with processes deleting themselves.
|
||||
func removeCaddyBinary(path string) error {
|
||||
return os.Remove(path)
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright 2015 Matthew Holt and The Caddy Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package caddycmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// removeCaddyBinary removes the Caddy binary at the given path.
|
||||
//
|
||||
// On Windows, this uses a syscall to indirectly remove the file,
|
||||
// because otherwise we get an "Access is denied." error when trying
|
||||
// to delete the binary while Caddy is still running and performing
|
||||
// the upgrade. "cmd.exe /C" executes a command specified by the
|
||||
// following arguments, i.e. "del" which will run as a separate process,
|
||||
// which avoids the "Access is denied." error.
|
||||
func removeCaddyBinary(path string) error {
|
||||
var sI syscall.StartupInfo
|
||||
var pI syscall.ProcessInformation
|
||||
argv, err := syscall.UTF16PtrFromString(filepath.Join(os.Getenv("windir"), "system32", "cmd.exe") + " /C del " + path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return syscall.CreateProcess(nil, argv, nil, nil, true, 0, nil, nil, &sI, &pI)
|
||||
}
|
||||
+2
-2
@@ -577,11 +577,11 @@ func (ctx Context) Slogger() *slog.Logger {
|
||||
if err != nil {
|
||||
panic("config missing, unable to create dev logger: " + err.Error())
|
||||
}
|
||||
return slog.New(zapslog.NewHandler(l.Core(), nil))
|
||||
return slog.New(zapslog.NewHandler(l.Core()))
|
||||
}
|
||||
mod := ctx.Module()
|
||||
if mod == nil {
|
||||
return slog.New(zapslog.NewHandler(Log().Core(), nil))
|
||||
return slog.New(zapslog.NewHandler(Log().Core()))
|
||||
}
|
||||
return slog.New(zapslog.NewHandler(ctx.cfg.Logging.Logger(mod).Core(),
|
||||
zapslog.WithName(string(mod.CaddyModule().ID)),
|
||||
|
||||
@@ -19,7 +19,7 @@ require (
|
||||
github.com/klauspost/cpuid/v2 v2.2.10
|
||||
github.com/mholt/acmez/v3 v3.1.2
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/quic-go/quic-go v0.50.1
|
||||
github.com/quic-go/quic-go v0.51.0
|
||||
github.com/smallstep/certificates v0.26.1
|
||||
github.com/smallstep/nosql v0.6.1
|
||||
github.com/smallstep/truststore v0.13.0
|
||||
|
||||
@@ -397,8 +397,8 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
|
||||
github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
||||
github.com/quic-go/quic-go v0.51.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
|
||||
+3
-1
@@ -162,7 +162,9 @@ func (logging *Logging) setupNewDefault(ctx Context) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting up default log: %v", err)
|
||||
}
|
||||
newDefault.logger = zap.New(newDefault.CustomLog.core, options...)
|
||||
|
||||
filteringCore := &filteringCore{newDefault.CustomLog.core, newDefault.CustomLog}
|
||||
newDefault.logger = zap.New(filteringCore, options...)
|
||||
|
||||
// redirect the default caddy logs
|
||||
defaultLoggerMu.Lock()
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// Copyright 2015 Matthew Holt and The Caddy Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package caddy
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCustomLog_loggerAllowed(t *testing.T) {
|
||||
type fields struct {
|
||||
BaseLog BaseLog
|
||||
Include []string
|
||||
Exclude []string
|
||||
}
|
||||
type args struct {
|
||||
name string
|
||||
isModule bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "include",
|
||||
fields: fields{
|
||||
Include: []string{"foo"},
|
||||
},
|
||||
args: args{
|
||||
name: "foo",
|
||||
isModule: true,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "exclude",
|
||||
fields: fields{
|
||||
Exclude: []string{"foo"},
|
||||
},
|
||||
args: args{
|
||||
name: "foo",
|
||||
isModule: true,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "include and exclude",
|
||||
fields: fields{
|
||||
Include: []string{"foo"},
|
||||
Exclude: []string{"foo"},
|
||||
},
|
||||
args: args{
|
||||
name: "foo",
|
||||
isModule: true,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "include and exclude (longer namespace)",
|
||||
fields: fields{
|
||||
Include: []string{"foo.bar"},
|
||||
Exclude: []string{"foo"},
|
||||
},
|
||||
args: args{
|
||||
name: "foo.bar",
|
||||
isModule: true,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "excluded module is not printed",
|
||||
fields: fields{
|
||||
Include: []string{"admin.api.load"},
|
||||
Exclude: []string{"admin.api"},
|
||||
},
|
||||
args: args{
|
||||
name: "admin.api",
|
||||
isModule: false,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cl := &CustomLog{
|
||||
BaseLog: tt.fields.BaseLog,
|
||||
Include: tt.fields.Include,
|
||||
Exclude: tt.fields.Exclude,
|
||||
}
|
||||
if got := cl.loggerAllowed(tt.args.name, tt.args.isModule); got != tt.want {
|
||||
t.Errorf("CustomLog.loggerAllowed() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
<path d="M9 7l4 0"/>
|
||||
<path d="M9 11l4 0"/>
|
||||
</svg>
|
||||
{{- else if .HasExt ".jpg" ".jpeg" ".png" ".gif" ".webp" ".tiff" ".bmp" ".heif" ".heic" ".svg"}}
|
||||
{{- else if .HasExt ".jpg" ".jpeg" ".png" ".gif" ".webp" ".tiff" ".bmp" ".heif" ".heic" ".svg" ".avif"}}
|
||||
{{- if eq .Tpl.Layout "grid"}}
|
||||
<img loading="lazy" src="{{.Name | pathEscape}}">
|
||||
{{- else}}
|
||||
@@ -802,7 +802,7 @@ footer {
|
||||
<b>{{.NumFiles}}</b> file{{if ne 1 .NumFiles}}s{{end}}
|
||||
</span>
|
||||
<span class="meta-item">
|
||||
<b>{{.HumanTotalFileSize}}</b> total
|
||||
<b>{{.HumanTotalFileSize}}</b> total
|
||||
</span>
|
||||
{{- if ne 0 .Limit}}
|
||||
<span class="meta-item">
|
||||
@@ -868,7 +868,7 @@ footer {
|
||||
</svg>
|
||||
</a>
|
||||
{{- end}}
|
||||
|
||||
|
||||
{{- if and (eq .Sort "name") (ne .Order "desc")}}
|
||||
<a href="?sort=name&order=desc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">
|
||||
Name
|
||||
|
||||
@@ -353,7 +353,7 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
||||
h.NetworkProxyRaw = caddyconfig.JSONModuleObject(u, "from", "url", nil)
|
||||
}
|
||||
if len(h.NetworkProxyRaw) != 0 {
|
||||
proxyMod, err := caddyCtx.LoadModule(h, "ForwardProxyRaw")
|
||||
proxyMod, err := caddyCtx.LoadModule(h, "NetworkProxyRaw")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load network_proxy module: %v", err)
|
||||
}
|
||||
@@ -382,6 +382,36 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("making TLS client config: %v", err)
|
||||
}
|
||||
|
||||
// servername has a placeholder, so we need to replace it
|
||||
if strings.Contains(h.TLS.ServerName, "{") {
|
||||
rt.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
// reuses the dialer from above to establish a plaintext connection
|
||||
conn, err := dialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// but add our own handshake logic
|
||||
repl := ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
||||
tlsConfig := rt.TLSClientConfig.Clone()
|
||||
tlsConfig.ServerName = repl.ReplaceAll(tlsConfig.ServerName, "")
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
|
||||
// complete the handshake before returning the connection
|
||||
if rt.TLSHandshakeTimeout != 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, rt.TLSHandshakeTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
err = tlsConn.HandshakeContext(ctx)
|
||||
if err != nil {
|
||||
_ = tlsConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return tlsConn, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if h.KeepAlive != nil {
|
||||
@@ -453,45 +483,9 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
// replaceTLSServername checks TLS servername to see if it needs replacing
|
||||
// if it does need replacing, it creates a new cloned HTTPTransport object to avoid any races
|
||||
// and does the replacing of the TLS servername on that and returns the new object
|
||||
// if no replacement is necessary it returns the original
|
||||
func (h *HTTPTransport) replaceTLSServername(repl *caddy.Replacer) *HTTPTransport {
|
||||
// check whether we have TLS and need to replace the servername in the TLSClientConfig
|
||||
if h.TLSEnabled() && strings.Contains(h.TLS.ServerName, "{") {
|
||||
// make a new h, "copy" the parts we don't need to touch, add a new *tls.Config and replace servername
|
||||
newtransport := &HTTPTransport{
|
||||
Resolver: h.Resolver,
|
||||
TLS: h.TLS,
|
||||
KeepAlive: h.KeepAlive,
|
||||
Compression: h.Compression,
|
||||
MaxConnsPerHost: h.MaxConnsPerHost,
|
||||
DialTimeout: h.DialTimeout,
|
||||
FallbackDelay: h.FallbackDelay,
|
||||
ResponseHeaderTimeout: h.ResponseHeaderTimeout,
|
||||
ExpectContinueTimeout: h.ExpectContinueTimeout,
|
||||
MaxResponseHeaderSize: h.MaxResponseHeaderSize,
|
||||
WriteBufferSize: h.WriteBufferSize,
|
||||
ReadBufferSize: h.ReadBufferSize,
|
||||
Versions: h.Versions,
|
||||
Transport: h.Transport.Clone(),
|
||||
h2cTransport: h.h2cTransport,
|
||||
}
|
||||
newtransport.Transport.TLSClientConfig.ServerName = repl.ReplaceAll(newtransport.Transport.TLSClientConfig.ServerName, "")
|
||||
return newtransport
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// RoundTrip implements http.RoundTripper.
|
||||
func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
// Try to replace TLS servername if needed
|
||||
repl := req.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
||||
transport := h.replaceTLSServername(repl)
|
||||
|
||||
transport.SetScheme(req)
|
||||
h.SetScheme(req)
|
||||
|
||||
// use HTTP/3 if enabled (TODO: This is EXPERIMENTAL)
|
||||
if h.h3Transport != nil {
|
||||
@@ -507,7 +501,7 @@ func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return h.h2cTransport.RoundTrip(req)
|
||||
}
|
||||
|
||||
return transport.Transport.RoundTrip(req)
|
||||
return h.Transport.RoundTrip(req)
|
||||
}
|
||||
|
||||
// SetScheme ensures that the outbound request req
|
||||
|
||||
@@ -91,19 +91,17 @@ func parseACMEServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||
acmeServer.Policy.AllowWildcardNames = true
|
||||
case "allow":
|
||||
r := &RuleSet{}
|
||||
for h.Next() {
|
||||
for h.NextBlock(h.Nesting() - 1) {
|
||||
if h.CountRemainingArgs() == 0 {
|
||||
return nil, h.ArgErr() // TODO:
|
||||
}
|
||||
switch h.Val() {
|
||||
case "domains":
|
||||
r.Domains = append(r.Domains, h.RemainingArgs()...)
|
||||
case "ip_ranges":
|
||||
r.IPRanges = append(r.IPRanges, h.RemainingArgs()...)
|
||||
default:
|
||||
return nil, h.Errf("unrecognized 'allow' subdirective: %s", h.Val())
|
||||
}
|
||||
for nesting := h.Nesting(); h.NextBlock(nesting); {
|
||||
if h.CountRemainingArgs() == 0 {
|
||||
return nil, h.ArgErr() // TODO:
|
||||
}
|
||||
switch h.Val() {
|
||||
case "domains":
|
||||
r.Domains = append(r.Domains, h.RemainingArgs()...)
|
||||
case "ip_ranges":
|
||||
r.IPRanges = append(r.IPRanges, h.RemainingArgs()...)
|
||||
default:
|
||||
return nil, h.Errf("unrecognized 'allow' subdirective: %s", h.Val())
|
||||
}
|
||||
}
|
||||
if acmeServer.Policy == nil {
|
||||
@@ -112,19 +110,17 @@ func parseACMEServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||
acmeServer.Policy.Allow = r
|
||||
case "deny":
|
||||
r := &RuleSet{}
|
||||
for h.Next() {
|
||||
for h.NextBlock(h.Nesting() - 1) {
|
||||
if h.CountRemainingArgs() == 0 {
|
||||
return nil, h.ArgErr() // TODO:
|
||||
}
|
||||
switch h.Val() {
|
||||
case "domains":
|
||||
r.Domains = append(r.Domains, h.RemainingArgs()...)
|
||||
case "ip_ranges":
|
||||
r.IPRanges = append(r.IPRanges, h.RemainingArgs()...)
|
||||
default:
|
||||
return nil, h.Errf("unrecognized 'deny' subdirective: %s", h.Val())
|
||||
}
|
||||
for nesting := h.Nesting(); h.NextBlock(nesting); {
|
||||
if h.CountRemainingArgs() == 0 {
|
||||
return nil, h.ArgErr() // TODO:
|
||||
}
|
||||
switch h.Val() {
|
||||
case "domains":
|
||||
r.Domains = append(r.Domains, h.RemainingArgs()...)
|
||||
case "ip_ranges":
|
||||
r.IPRanges = append(r.IPRanges, h.RemainingArgs()...)
|
||||
default:
|
||||
return nil, h.Errf("unrecognized 'deny' subdirective: %s", h.Val())
|
||||
}
|
||||
}
|
||||
if acmeServer.Policy == nil {
|
||||
|
||||
@@ -220,7 +220,7 @@ func (iss *ACMEIssuer) makeIssuerTemplate(ctx caddy.Context) (certmagic.ACMEIssu
|
||||
}
|
||||
|
||||
if len(iss.NetworkProxyRaw) != 0 {
|
||||
proxyMod, err := ctx.LoadModule(iss, "ForwardProxyRaw")
|
||||
proxyMod, err := ctx.LoadModule(iss, "NetworkProxyRaw")
|
||||
if err != nil {
|
||||
return template, fmt.Errorf("failed to load network_proxy module: %v", err)
|
||||
}
|
||||
|
||||
@@ -144,9 +144,9 @@ func (hcg HTTPCertGetter) GetCertificate(ctx context.Context, hello *tls.ClientH
|
||||
qs.Set("server_name", hello.ServerName)
|
||||
qs.Set("signature_schemes", strings.Join(sigs, ","))
|
||||
qs.Set("cipher_suites", strings.Join(suites, ","))
|
||||
remoteIP, _, err := net.SplitHostPort(hello.Conn.RemoteAddr().String())
|
||||
if err == nil && remoteIP != "" {
|
||||
qs.Set("remote_ip", remoteIP)
|
||||
localIP, _, err := net.SplitHostPort(hello.Conn.LocalAddr().String())
|
||||
if err == nil && localIP != "" {
|
||||
qs.Set("local_ip", localIP)
|
||||
}
|
||||
parsed.RawQuery = qs.Encode()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user