parent
0ab507339b
commit
c4f7fb580d
|
|
@ -1,7 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jmhodges/clock"
|
"github.com/jmhodges/clock"
|
||||||
|
|
@ -10,7 +12,6 @@ import (
|
||||||
"github.com/letsencrypt/boulder/cmd"
|
"github.com/letsencrypt/boulder/cmd"
|
||||||
"github.com/letsencrypt/boulder/core"
|
"github.com/letsencrypt/boulder/core"
|
||||||
bgrpc "github.com/letsencrypt/boulder/grpc"
|
bgrpc "github.com/letsencrypt/boulder/grpc"
|
||||||
blog "github.com/letsencrypt/boulder/log"
|
|
||||||
"github.com/letsencrypt/boulder/metrics"
|
"github.com/letsencrypt/boulder/metrics"
|
||||||
"github.com/letsencrypt/boulder/policy"
|
"github.com/letsencrypt/boulder/policy"
|
||||||
"github.com/letsencrypt/boulder/ra"
|
"github.com/letsencrypt/boulder/ra"
|
||||||
|
|
@ -19,79 +20,149 @@ import (
|
||||||
|
|
||||||
const clientName = "RA"
|
const clientName = "RA"
|
||||||
|
|
||||||
func main() {
|
type config struct {
|
||||||
app := cmd.NewAppShell("boulder-ra", "Handles service orchestration")
|
RA struct {
|
||||||
app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) {
|
cmd.ServiceConfig
|
||||||
// Validate PA config and set defaults if needed
|
cmd.HostnamePolicyConfig
|
||||||
cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration")
|
|
||||||
|
|
||||||
go cmd.DebugServer(c.RA.DebugAddr)
|
RateLimitPoliciesFilename string
|
||||||
|
|
||||||
pa, err := policy.New(c.PA.Challenges)
|
MaxConcurrentRPCServerRequests int64
|
||||||
cmd.FailOnError(err, "Couldn't create PA")
|
|
||||||
|
|
||||||
if c.RA.HostnamePolicyFile == "" {
|
MaxContactsPerRegistration int
|
||||||
cmd.FailOnError(fmt.Errorf("HostnamePolicyFile must be provided."), "")
|
|
||||||
}
|
|
||||||
err = pa.SetHostnamePolicyFile(c.RA.HostnamePolicyFile)
|
|
||||||
cmd.FailOnError(err, "Couldn't load hostname policy file")
|
|
||||||
|
|
||||||
go cmd.ProfileCmd("RA", stats)
|
// UseIsSafeDomain determines whether to call VA.IsSafeDomain
|
||||||
|
UseIsSafeDomain bool // TODO: remove after va IsSafeDomain deploy
|
||||||
|
|
||||||
amqpConf := c.RA.AMQP
|
// The number of times to try a DNS query (that has a temporary error)
|
||||||
var vac core.ValidationAuthority
|
// before giving up. May be short-circuited by deadlines. A zero value
|
||||||
if c.RA.VAService != nil {
|
// will be turned into 1.
|
||||||
conn, err := bgrpc.ClientSetup(c.RA.VAService)
|
DNSTries int
|
||||||
cmd.FailOnError(err, "Unable to create VA client")
|
|
||||||
vac = bgrpc.NewValidationAuthorityGRPCClient(conn)
|
|
||||||
} else {
|
|
||||||
vac, err = rpc.NewValidationAuthorityClient(clientName, amqpConf, stats)
|
|
||||||
cmd.FailOnError(err, "Unable to create VA client")
|
|
||||||
}
|
|
||||||
|
|
||||||
cac, err := rpc.NewCertificateAuthorityClient(clientName, amqpConf, stats)
|
VAService *cmd.GRPCClientConfig
|
||||||
cmd.FailOnError(err, "Unable to create CA client")
|
|
||||||
|
|
||||||
sac, err := rpc.NewStorageAuthorityClient(clientName, amqpConf, stats)
|
MaxNames int
|
||||||
cmd.FailOnError(err, "Unable to create SA client")
|
DoNotForceCN bool
|
||||||
|
|
||||||
rai := ra.NewRegistrationAuthorityImpl(clock.Default(), logger, stats,
|
// Controls behaviour of the RA when asked to create a new authz for
|
||||||
c.RA.MaxContactsPerRegistration, c.KeyPolicy(),
|
// a name/regID that already has a valid authz. False preserves historic
|
||||||
c.RA.MaxNames, c.RA.DoNotForceCN, c.RA.ReuseValidAuthz)
|
// behaviour and ignores the existing authz and creates a new one. True
|
||||||
policyErr := rai.SetRateLimitPoliciesFile(c.RA.RateLimitPoliciesFilename)
|
// instructs the RA to reuse the previously created authz in lieu of
|
||||||
cmd.FailOnError(policyErr, "Couldn't load rate limit policies file")
|
// creating another.
|
||||||
rai.PA = pa
|
ReuseValidAuthz bool
|
||||||
raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout)
|
|
||||||
cmd.FailOnError(err, "Couldn't parse RA DNS timeout")
|
|
||||||
scoped := metrics.NewStatsdScope(stats, "RA", "DNS")
|
|
||||||
dnsTries := c.RA.DNSTries
|
|
||||||
if dnsTries < 1 {
|
|
||||||
dnsTries = 1
|
|
||||||
}
|
|
||||||
if !c.Common.DNSAllowLoopbackAddresses {
|
|
||||||
rai.DNSResolver = bdns.NewDNSResolverImpl(
|
|
||||||
raDNSTimeout,
|
|
||||||
[]string{c.Common.DNSResolver},
|
|
||||||
nil,
|
|
||||||
scoped,
|
|
||||||
clock.Default(),
|
|
||||||
dnsTries)
|
|
||||||
} else {
|
|
||||||
rai.DNSResolver = bdns.NewTestDNSResolverImpl(raDNSTimeout, []string{c.Common.DNSResolver}, scoped, clock.Default(), dnsTries)
|
|
||||||
}
|
|
||||||
|
|
||||||
rai.VA = vac
|
|
||||||
rai.CA = cac
|
|
||||||
rai.SA = sac
|
|
||||||
|
|
||||||
ras, err := rpc.NewAmqpRPCServer(amqpConf, c.RA.MaxConcurrentRPCServerRequests, stats, logger)
|
|
||||||
cmd.FailOnError(err, "Unable to create RA RPC server")
|
|
||||||
err = rpc.NewRegistrationAuthorityServer(ras, rai, logger)
|
|
||||||
cmd.FailOnError(err, "Unable to setup RA RPC server")
|
|
||||||
|
|
||||||
err = ras.Start(amqpConf)
|
|
||||||
cmd.FailOnError(err, "Unable to run RA RPC server")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Run()
|
*cmd.AllowedSigningAlgos
|
||||||
|
|
||||||
|
PA cmd.PAConfig
|
||||||
|
|
||||||
|
cmd.StatsdConfig
|
||||||
|
|
||||||
|
cmd.SyslogConfig
|
||||||
|
|
||||||
|
Common struct {
|
||||||
|
DNSResolver string
|
||||||
|
DNSTimeout string
|
||||||
|
DNSAllowLoopbackAddresses bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
configFile := flag.String("config", "", "File path to the configuration file for this service")
|
||||||
|
flag.Parse()
|
||||||
|
if *configFile == "" {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var c config
|
||||||
|
err := cmd.ReadJSONFile(*configFile, &c)
|
||||||
|
cmd.FailOnError(err, "Reading JSON config file into config structure")
|
||||||
|
|
||||||
|
go cmd.DebugServer(c.RA.DebugAddr)
|
||||||
|
|
||||||
|
stats, logger := cmd.StatsAndLogging(c.StatsdConfig, c.SyslogConfig)
|
||||||
|
defer logger.AuditPanic()
|
||||||
|
logger.Info(cmd.VersionString(clientName))
|
||||||
|
|
||||||
|
// Validate PA config and set defaults if needed
|
||||||
|
cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration")
|
||||||
|
|
||||||
|
pa, err := policy.New(c.PA.Challenges)
|
||||||
|
cmd.FailOnError(err, "Couldn't create PA")
|
||||||
|
|
||||||
|
if c.RA.HostnamePolicyFile == "" {
|
||||||
|
cmd.FailOnError(fmt.Errorf("HostnamePolicyFile must be provided."), "")
|
||||||
|
}
|
||||||
|
err = pa.SetHostnamePolicyFile(c.RA.HostnamePolicyFile)
|
||||||
|
cmd.FailOnError(err, "Couldn't load hostname policy file")
|
||||||
|
|
||||||
|
go cmd.ProfileCmd("RA", stats)
|
||||||
|
|
||||||
|
amqpConf := c.RA.AMQP
|
||||||
|
var vac core.ValidationAuthority
|
||||||
|
if c.RA.VAService != nil {
|
||||||
|
conn, err := bgrpc.ClientSetup(c.RA.VAService)
|
||||||
|
cmd.FailOnError(err, "Unable to create VA client")
|
||||||
|
vac = bgrpc.NewValidationAuthorityGRPCClient(conn)
|
||||||
|
} else {
|
||||||
|
vac, err = rpc.NewValidationAuthorityClient(clientName, amqpConf, stats)
|
||||||
|
cmd.FailOnError(err, "Unable to create VA client")
|
||||||
|
}
|
||||||
|
|
||||||
|
cac, err := rpc.NewCertificateAuthorityClient(clientName, amqpConf, stats)
|
||||||
|
cmd.FailOnError(err, "Unable to create CA client")
|
||||||
|
|
||||||
|
sac, err := rpc.NewStorageAuthorityClient(clientName, amqpConf, stats)
|
||||||
|
cmd.FailOnError(err, "Unable to create SA client")
|
||||||
|
|
||||||
|
rai := ra.NewRegistrationAuthorityImpl(
|
||||||
|
clock.Default(),
|
||||||
|
logger,
|
||||||
|
stats,
|
||||||
|
c.RA.MaxContactsPerRegistration,
|
||||||
|
c.AllowedSigningAlgos.KeyPolicy(),
|
||||||
|
c.RA.MaxNames,
|
||||||
|
c.RA.DoNotForceCN,
|
||||||
|
c.RA.ReuseValidAuthz)
|
||||||
|
|
||||||
|
policyErr := rai.SetRateLimitPoliciesFile(c.RA.RateLimitPoliciesFilename)
|
||||||
|
cmd.FailOnError(policyErr, "Couldn't load rate limit policies file")
|
||||||
|
rai.PA = pa
|
||||||
|
|
||||||
|
raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout)
|
||||||
|
cmd.FailOnError(err, "Couldn't parse RA DNS timeout")
|
||||||
|
scoped := metrics.NewStatsdScope(stats, "RA", "DNS")
|
||||||
|
dnsTries := c.RA.DNSTries
|
||||||
|
if dnsTries < 1 {
|
||||||
|
dnsTries = 1
|
||||||
|
}
|
||||||
|
if !c.Common.DNSAllowLoopbackAddresses {
|
||||||
|
rai.DNSResolver = bdns.NewDNSResolverImpl(
|
||||||
|
raDNSTimeout,
|
||||||
|
[]string{c.Common.DNSResolver},
|
||||||
|
nil,
|
||||||
|
scoped,
|
||||||
|
clock.Default(),
|
||||||
|
dnsTries)
|
||||||
|
} else {
|
||||||
|
rai.DNSResolver = bdns.NewTestDNSResolverImpl(
|
||||||
|
raDNSTimeout,
|
||||||
|
[]string{c.Common.DNSResolver},
|
||||||
|
scoped,
|
||||||
|
clock.Default(),
|
||||||
|
dnsTries)
|
||||||
|
}
|
||||||
|
|
||||||
|
rai.VA = vac
|
||||||
|
rai.CA = cac
|
||||||
|
rai.SA = sac
|
||||||
|
|
||||||
|
ras, err := rpc.NewAmqpRPCServer(amqpConf, c.RA.MaxConcurrentRPCServerRequests, stats, logger)
|
||||||
|
cmd.FailOnError(err, "Unable to create RA RPC server")
|
||||||
|
err = rpc.NewRegistrationAuthorityServer(ras, rai, logger)
|
||||||
|
cmd.FailOnError(err, "Unable to setup RA RPC server")
|
||||||
|
|
||||||
|
err = ras.Start(amqpConf)
|
||||||
|
cmd.FailOnError(err, "Unable to run RA RPC server")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,37 +27,6 @@ type Config struct {
|
||||||
|
|
||||||
CA CAConfig
|
CA CAConfig
|
||||||
|
|
||||||
RA struct {
|
|
||||||
ServiceConfig
|
|
||||||
HostnamePolicyConfig
|
|
||||||
|
|
||||||
RateLimitPoliciesFilename string
|
|
||||||
|
|
||||||
MaxConcurrentRPCServerRequests int64
|
|
||||||
|
|
||||||
MaxContactsPerRegistration int
|
|
||||||
|
|
||||||
// UseIsSafeDomain determines whether to call VA.IsSafeDomain
|
|
||||||
UseIsSafeDomain bool // TODO(jmhodges): remove after va IsSafeDomain deploy
|
|
||||||
|
|
||||||
// The number of times to try a DNS query (that has a temporary error)
|
|
||||||
// before giving up. May be short-circuited by deadlines. A zero value
|
|
||||||
// will be turned into 1.
|
|
||||||
DNSTries int
|
|
||||||
|
|
||||||
VAService *GRPCClientConfig
|
|
||||||
|
|
||||||
MaxNames int
|
|
||||||
DoNotForceCN bool
|
|
||||||
|
|
||||||
// Controls behaviour of the RA when asked to create a new authz for
|
|
||||||
// a name/regID that already has a valid authz. False preserves historic
|
|
||||||
// behaviour and ignores the existing authz and creates a new one. True
|
|
||||||
// instructs the RA to reuse the previously created authz in lieu of
|
|
||||||
// creating another.
|
|
||||||
ReuseValidAuthz bool
|
|
||||||
}
|
|
||||||
|
|
||||||
SA struct {
|
SA struct {
|
||||||
ServiceConfig
|
ServiceConfig
|
||||||
DBConfig
|
DBConfig
|
||||||
|
|
|
||||||
|
|
@ -100,12 +100,6 @@ func (as *AppShell) Run() {
|
||||||
config.CA.AMQP.ServiceQueue = config.AMQP.CA.Server
|
config.CA.AMQP.ServiceQueue = config.AMQP.CA.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if config.RA.AMQP == nil {
|
|
||||||
config.RA.AMQP = config.AMQP
|
|
||||||
if config.RA.AMQP != nil && config.AMQP.RA != nil {
|
|
||||||
config.RA.AMQP.ServiceQueue = config.AMQP.RA.Server
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config.SA.AMQP == nil {
|
if config.SA.AMQP == nil {
|
||||||
config.SA.AMQP = config.AMQP
|
config.SA.AMQP = config.AMQP
|
||||||
if config.SA.AMQP != nil && config.AMQP.SA != nil {
|
if config.SA.AMQP != nil && config.AMQP.SA != nil {
|
||||||
|
|
|
||||||
|
|
@ -137,43 +137,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"ra": {
|
|
||||||
"rateLimitPoliciesFilename": "test/rate-limit-policies.yml",
|
|
||||||
"maxConcurrentRPCServerRequests": 16,
|
|
||||||
"maxContactsPerRegistration": 100,
|
|
||||||
"dnsTries": 3,
|
|
||||||
"debugAddr": "localhost:8002",
|
|
||||||
"hostnamePolicyFile": "test/hostname-policy.json",
|
|
||||||
"maxNames": 1000,
|
|
||||||
"doNotForceCN": true,
|
|
||||||
"reuseValidAuthz": true,
|
|
||||||
"vaService": {
|
|
||||||
"serverAddresses": ["boulder:9092"],
|
|
||||||
"serverIssuerPath": "test/grpc-creds/ca.pem",
|
|
||||||
"clientCertificatePath": "test/grpc-creds/client.pem",
|
|
||||||
"clientKeyPath": "test/grpc-creds/key.pem",
|
|
||||||
"timeout": "90s"
|
|
||||||
},
|
|
||||||
"amqp": {
|
|
||||||
"serverURLFile": "test/secrets/amqp_url",
|
|
||||||
"insecure": true,
|
|
||||||
"serviceQueue": "RA.server",
|
|
||||||
"VA": {
|
|
||||||
"server": "VA.server",
|
|
||||||
"rpcTimeout": "60s"
|
|
||||||
},
|
|
||||||
"SA": {
|
|
||||||
"server": "SA.server",
|
|
||||||
"rpcTimeout": "15s"
|
|
||||||
},
|
|
||||||
"CA": {
|
|
||||||
"server": "CA.server",
|
|
||||||
"rpcTimeout": "15s"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"sa": {
|
"sa": {
|
||||||
"dbConnectFile": "test/secrets/sa_dburl",
|
"dbConnectFile": "test/secrets/sa_dburl",
|
||||||
"maxDBConns": 10,
|
"maxDBConns": 10,
|
||||||
|
|
|
||||||
|
|
@ -135,35 +135,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"ra": {
|
|
||||||
"rateLimitPoliciesFilename": "test/rate-limit-policies.yml",
|
|
||||||
"maxConcurrentRPCServerRequests": 16,
|
|
||||||
"maxContactsPerRegistration": 100,
|
|
||||||
"dnsTries": 3,
|
|
||||||
"debugAddr": "localhost:8002",
|
|
||||||
"hostnamePolicyFile": "test/hostname-policy.json",
|
|
||||||
"maxNames": 1000,
|
|
||||||
"doNotForceCN": true,
|
|
||||||
"amqp": {
|
|
||||||
"serverURLFile": "test/secrets/amqp_url",
|
|
||||||
"insecure": true,
|
|
||||||
"serviceQueue": "RA.server",
|
|
||||||
"VA": {
|
|
||||||
"server": "VA.server",
|
|
||||||
"rpcTimeout": "60s"
|
|
||||||
},
|
|
||||||
"SA": {
|
|
||||||
"server": "SA.server",
|
|
||||||
"rpcTimeout": "15s"
|
|
||||||
},
|
|
||||||
"CA": {
|
|
||||||
"server": "CA.server",
|
|
||||||
"rpcTimeout": "15s"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"sa": {
|
"sa": {
|
||||||
"dbConnectFile": "test/secrets/sa_dburl",
|
"dbConnectFile": "test/secrets/sa_dburl",
|
||||||
"maxDBConns": 10,
|
"maxDBConns": 10,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
{
|
||||||
|
"ra": {
|
||||||
|
"rateLimitPoliciesFilename": "test/rate-limit-policies.yml",
|
||||||
|
"maxConcurrentRPCServerRequests": 16,
|
||||||
|
"maxContactsPerRegistration": 100,
|
||||||
|
"dnsTries": 3,
|
||||||
|
"debugAddr": "localhost:8002",
|
||||||
|
"hostnamePolicyFile": "test/hostname-policy.json",
|
||||||
|
"maxNames": 1000,
|
||||||
|
"doNotForceCN": true,
|
||||||
|
"reuseValidAuthz": true,
|
||||||
|
"vaService": {
|
||||||
|
"serverAddresses": ["boulder:9092"],
|
||||||
|
"serverIssuerPath": "test/grpc-creds/ca.pem",
|
||||||
|
"clientCertificatePath": "test/grpc-creds/client.pem",
|
||||||
|
"clientKeyPath": "test/grpc-creds/key.pem",
|
||||||
|
"timeout": "90s"
|
||||||
|
},
|
||||||
|
"amqp": {
|
||||||
|
"serverURLFile": "test/secrets/amqp_url",
|
||||||
|
"insecure": true,
|
||||||
|
"serviceQueue": "RA.server",
|
||||||
|
"VA": {
|
||||||
|
"server": "VA.server",
|
||||||
|
"rpcTimeout": "60s"
|
||||||
|
},
|
||||||
|
"SA": {
|
||||||
|
"server": "SA.server",
|
||||||
|
"rpcTimeout": "15s"
|
||||||
|
},
|
||||||
|
"CA": {
|
||||||
|
"server": "CA.server",
|
||||||
|
"rpcTimeout": "15s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"allowedSigningAlgos": {
|
||||||
|
"rsa": true,
|
||||||
|
"ecdsanistp256": true,
|
||||||
|
"ecdsanistp384": true,
|
||||||
|
"ecdsanistp521": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"pa": {
|
||||||
|
"challenges": {
|
||||||
|
"http-01": true,
|
||||||
|
"tls-sni-01": true,
|
||||||
|
"dns-01": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"statsd": {
|
||||||
|
"server": "localhost:8125",
|
||||||
|
"prefix": "Boulder"
|
||||||
|
},
|
||||||
|
|
||||||
|
"syslog": {
|
||||||
|
"stdoutlevel": 6,
|
||||||
|
"sysloglevel": 4
|
||||||
|
},
|
||||||
|
|
||||||
|
"common": {
|
||||||
|
"dnsResolver": "127.0.0.1:8053",
|
||||||
|
"dnsTimeout": "10s",
|
||||||
|
"dnsAllowLoopbackAddresses": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"ra": {
|
||||||
|
"rateLimitPoliciesFilename": "test/rate-limit-policies.yml",
|
||||||
|
"maxConcurrentRPCServerRequests": 16,
|
||||||
|
"maxContactsPerRegistration": 100,
|
||||||
|
"dnsTries": 3,
|
||||||
|
"debugAddr": "localhost:8002",
|
||||||
|
"hostnamePolicyFile": "test/hostname-policy.json",
|
||||||
|
"maxNames": 1000,
|
||||||
|
"doNotForceCN": true,
|
||||||
|
"amqp": {
|
||||||
|
"serverURLFile": "test/secrets/amqp_url",
|
||||||
|
"insecure": true,
|
||||||
|
"serviceQueue": "RA.server",
|
||||||
|
"VA": {
|
||||||
|
"server": "VA.server",
|
||||||
|
"rpcTimeout": "60s"
|
||||||
|
},
|
||||||
|
"SA": {
|
||||||
|
"server": "SA.server",
|
||||||
|
"rpcTimeout": "15s"
|
||||||
|
},
|
||||||
|
"CA": {
|
||||||
|
"server": "CA.server",
|
||||||
|
"rpcTimeout": "15s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"allowedSigningAlgos": {
|
||||||
|
"rsa": true,
|
||||||
|
"ecdsanistp256": true,
|
||||||
|
"ecdsanistp384": true,
|
||||||
|
"ecdsanistp521": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"pa": {
|
||||||
|
"challenges": {
|
||||||
|
"http-01": true,
|
||||||
|
"tls-sni-01": true,
|
||||||
|
"dns-01": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"statsd": {
|
||||||
|
"server": "localhost:8125",
|
||||||
|
"prefix": "Boulder"
|
||||||
|
},
|
||||||
|
|
||||||
|
"syslog": {
|
||||||
|
"network": "",
|
||||||
|
"server": "",
|
||||||
|
"stdoutlevel": 6
|
||||||
|
},
|
||||||
|
|
||||||
|
"common": {
|
||||||
|
"dnsResolver": "127.0.0.1:8053",
|
||||||
|
"dnsTimeout": "10s",
|
||||||
|
"dnsAllowLoopbackAddresses": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue