parent
0ab507339b
commit
c4f7fb580d
|
|
@ -1,7 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/jmhodges/clock"
|
||||
|
|
@ -10,7 +12,6 @@ import (
|
|||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
bgrpc "github.com/letsencrypt/boulder/grpc"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/policy"
|
||||
"github.com/letsencrypt/boulder/ra"
|
||||
|
|
@ -19,79 +20,149 @@ import (
|
|||
|
||||
const clientName = "RA"
|
||||
|
||||
func main() {
|
||||
app := cmd.NewAppShell("boulder-ra", "Handles service orchestration")
|
||||
app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) {
|
||||
// Validate PA config and set defaults if needed
|
||||
cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration")
|
||||
type config struct {
|
||||
RA struct {
|
||||
cmd.ServiceConfig
|
||||
cmd.HostnamePolicyConfig
|
||||
|
||||
go cmd.DebugServer(c.RA.DebugAddr)
|
||||
RateLimitPoliciesFilename string
|
||||
|
||||
pa, err := policy.New(c.PA.Challenges)
|
||||
cmd.FailOnError(err, "Couldn't create PA")
|
||||
MaxConcurrentRPCServerRequests int64
|
||||
|
||||
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")
|
||||
MaxContactsPerRegistration int
|
||||
|
||||
go cmd.ProfileCmd("RA", stats)
|
||||
// UseIsSafeDomain determines whether to call VA.IsSafeDomain
|
||||
UseIsSafeDomain bool // TODO: remove after va IsSafeDomain deploy
|
||||
|
||||
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")
|
||||
}
|
||||
// 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
|
||||
|
||||
cac, err := rpc.NewCertificateAuthorityClient(clientName, amqpConf, stats)
|
||||
cmd.FailOnError(err, "Unable to create CA client")
|
||||
VAService *cmd.GRPCClientConfig
|
||||
|
||||
sac, err := rpc.NewStorageAuthorityClient(clientName, amqpConf, stats)
|
||||
cmd.FailOnError(err, "Unable to create SA client")
|
||||
MaxNames int
|
||||
DoNotForceCN bool
|
||||
|
||||
rai := ra.NewRegistrationAuthorityImpl(clock.Default(), logger, stats,
|
||||
c.RA.MaxContactsPerRegistration, c.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")
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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 {
|
||||
ServiceConfig
|
||||
DBConfig
|
||||
|
|
|
|||
|
|
@ -100,12 +100,6 @@ func (as *AppShell) Run() {
|
|||
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 {
|
||||
config.SA.AMQP = config.AMQP
|
||||
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": {
|
||||
"dbConnectFile": "test/secrets/sa_dburl",
|
||||
"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": {
|
||||
"dbConnectFile": "test/secrets/sa_dburl",
|
||||
"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