Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Trillian TLS support for ct_server #1551

Merged
merged 3 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## HEAD

* Add TLS support for Trillian: By using `--trillian_tls_ca_cert_file` flag, users can provide a CA certificate, that is used to establish a secure communication with Trillian log server. In https://github.com/google/certificate-transparency-go/pull/1525
* Add TLS support for Trillian: By using `--trillian_tls_ca_cert_file` flag, users can provide a CA certificate, that is used to establish a secure communication with Trillian log server. In https://github.com/google/certificate-transparency-go/pull/1551

* Add TLS support for ct_server: By using `--tls_certificate` and `--tls_key` flags, users can provide a service certificate and key, that enables the server to handle HTTPS requests. In https://github.com/google/certificate-transparency-go/pull/1523

Expand Down
59 changes: 35 additions & 24 deletions trillian/ctfe/ct_server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import (
clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/client/v3/naming/endpoints"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/resolver/manual"
"google.golang.org/protobuf/proto"
Expand All @@ -57,29 +58,30 @@ import (

// Global flags that affect all log instances.
var (
httpEndpoint = flag.String("http_endpoint", "localhost:6962", "Endpoint for HTTP (host:port)")
tlsCert = flag.String("tls_certificate", "", "Path to server TLS certificate")
tlsKey = flag.String("tls_key", "", "Path to server TLS private key")
metricsEndpoint = flag.String("metrics_endpoint", "", "Endpoint for serving metrics; if left empty, metrics will be visible on --http_endpoint")
rpcBackend = flag.String("log_rpc_server", "", "Backend specification; comma-separated list or etcd service name (if --etcd_servers specified). If unset backends are specified in config (as a LogMultiConfig proto)")
rpcDeadline = flag.Duration("rpc_deadline", time.Second*10, "Deadline for backend RPC requests")
getSTHInterval = flag.Duration("get_sth_interval", time.Second*180, "Interval between internal get-sth operations (0 to disable)")
logConfig = flag.String("log_config", "", "File holding log config in text proto format")
maxGetEntries = flag.Int64("max_get_entries", 0, "Max number of entries we allow in a get-entries request (0=>use default 1000)")
etcdServers = flag.String("etcd_servers", "", "A comma-separated list of etcd servers")
etcdHTTPService = flag.String("etcd_http_service", "trillian-ctfe-http", "Service name to announce our HTTP endpoint under")
etcdMetricsService = flag.String("etcd_metrics_service", "trillian-ctfe-metrics-http", "Service name to announce our HTTP metrics endpoint under")
maskInternalErrors = flag.Bool("mask_internal_errors", false, "Don't return error strings with Internal Server Error HTTP responses")
tracing = flag.Bool("tracing", false, "If true opencensus Stackdriver tracing will be enabled. See https://opencensus.io/.")
tracingProjectID = flag.String("tracing_project_id", "", "project ID to pass to stackdriver. Can be empty for GCP, consult docs for other platforms.")
tracingPercent = flag.Int("tracing_percent", 0, "Percent of requests to be traced. Zero is a special case to use the DefaultSampler")
quotaRemote = flag.Bool("quota_remote", true, "Enable requesting of quota for IP address sending incoming requests")
quotaIntermediate = flag.Bool("quota_intermediate", true, "Enable requesting of quota for intermediate certificates in submitted chains")
handlerPrefix = flag.String("handler_prefix", "", "If set e.g. to '/logs' will prefix all handlers that don't define a custom prefix")
pkcs11ModulePath = flag.String("pkcs11_module_path", "", "Path to the PKCS#11 module to use for keys that use the PKCS#11 interface")
cacheType = flag.String("cache_type", "noop", "Supported cache type: noop, lru (Default: noop)")
cacheSize = flag.Int("cache_size", -1, "Size parameter set to 0 makes cache of unlimited size")
cacheTTL = flag.Duration("cache_ttl", -1*time.Second, "Providing 0 TTL turns expiring off")
httpEndpoint = flag.String("http_endpoint", "localhost:6962", "Endpoint for HTTP (host:port)")
tlsCert = flag.String("tls_certificate", "", "Path to server TLS certificate")
tlsKey = flag.String("tls_key", "", "Path to server TLS private key")
metricsEndpoint = flag.String("metrics_endpoint", "", "Endpoint for serving metrics; if left empty, metrics will be visible on --http_endpoint")
rpcBackend = flag.String("log_rpc_server", "", "Backend specification; comma-separated list or etcd service name (if --etcd_servers specified). If unset backends are specified in config (as a LogMultiConfig proto)")
rpcDeadline = flag.Duration("rpc_deadline", time.Second*10, "Deadline for backend RPC requests")
getSTHInterval = flag.Duration("get_sth_interval", time.Second*180, "Interval between internal get-sth operations (0 to disable)")
logConfig = flag.String("log_config", "", "File holding log config in text proto format")
maxGetEntries = flag.Int64("max_get_entries", 0, "Max number of entries we allow in a get-entries request (0=>use default 1000)")
etcdServers = flag.String("etcd_servers", "", "A comma-separated list of etcd servers")
etcdHTTPService = flag.String("etcd_http_service", "trillian-ctfe-http", "Service name to announce our HTTP endpoint under")
etcdMetricsService = flag.String("etcd_metrics_service", "trillian-ctfe-metrics-http", "Service name to announce our HTTP metrics endpoint under")
maskInternalErrors = flag.Bool("mask_internal_errors", false, "Don't return error strings with Internal Server Error HTTP responses")
tracing = flag.Bool("tracing", false, "If true opencensus Stackdriver tracing will be enabled. See https://opencensus.io/.")
tracingProjectID = flag.String("tracing_project_id", "", "project ID to pass to stackdriver. Can be empty for GCP, consult docs for other platforms.")
tracingPercent = flag.Int("tracing_percent", 0, "Percent of requests to be traced. Zero is a special case to use the DefaultSampler")
quotaRemote = flag.Bool("quota_remote", true, "Enable requesting of quota for IP address sending incoming requests")
quotaIntermediate = flag.Bool("quota_intermediate", true, "Enable requesting of quota for intermediate certificates in submitted chains")
handlerPrefix = flag.String("handler_prefix", "", "If set e.g. to '/logs' will prefix all handlers that don't define a custom prefix")
pkcs11ModulePath = flag.String("pkcs11_module_path", "", "Path to the PKCS#11 module to use for keys that use the PKCS#11 interface")
cacheType = flag.String("cache_type", "noop", "Supported cache type: noop, lru (Default: noop)")
cacheSize = flag.Int("cache_size", -1, "Size parameter set to 0 makes cache of unlimited size")
cacheTTL = flag.Duration("cache_ttl", -1*time.Second, "Providing 0 TTL turns expiring off")
trillianTLSCACertFile = flag.String("trillian_tls_ca_cert_file", "", "CA certificate file to use for secure connections with Trillian server")
)

const unknownRemoteUser = "UNKNOWN_REMOTE"
Expand Down Expand Up @@ -135,7 +137,16 @@ func main() {
metricsAt = *httpEndpoint
}

dialOpts := []grpc.DialOption{grpc.WithInsecure()}
dialOpts := []grpc.DialOption{}
if *trillianTLSCACertFile != "" {
creds, err := credentials.NewClientTLSFromFile(*trillianTLSCACertFile, "")
if err != nil {
klog.Exitf("Failed to create TLS credentials from Trillian CA certificate: %v", err)
}
dialOpts = append(dialOpts, grpc.WithTransportCredentials(creds))
} else {
dialOpts = append(dialOpts, grpc.WithInsecure())
}
if len(*etcdServers) > 0 {
// Use etcd to provide endpoint resolution.
cfg := clientv3.Config{Endpoints: strings.Split(*etcdServers, ","), DialTimeout: 5 * time.Second}
Expand Down
37 changes: 1 addition & 36 deletions trillian/migrillian/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,16 @@ package main

import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"flag"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"time"

clientv3 "go.etcd.io/etcd/client/v3"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"k8s.io/klog/v2"

Expand Down Expand Up @@ -61,7 +57,6 @@ var (

maxIdleConnsPerHost = flag.Int("max_idle_conns_per_host", 10, "Max idle HTTP connections per host (0 = DefaultMaxIdleConnsPerHost)")
maxIdleConns = flag.Int("max_idle_conns", 100, "Max number of idle HTTP connections across all hosts (0 = unlimited)")
tlsCACertFile = flag.String("trillian_tls_ca_cert_file", "", "CA certificate file to use for secure connections with Trillian server")
)

func main() {
Expand All @@ -82,11 +77,7 @@ func main() {
}

klog.Infof("Dialling Trillian backend: %v", *backend)
creds, err := newTrillianTransportCredentialsFromFlags(*backend)
if err != nil {
klog.Exitf("Failed to get credentials: %v", err)
}
conn, err := grpc.Dial(*backend, grpc.WithTransportCredentials(creds), grpc.WithBlock())
conn, err := grpc.Dial(*backend, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
if err != nil {
klog.Exitf("Could not dial Trillian server: %v: %v", *backend, err)
}
Expand Down Expand Up @@ -126,32 +117,6 @@ func main() {
core.RunMigration(cctx, ctrls)
}

// newTrillianTransportCredentialsFromFlags returns "creds" of type credentials.TransportCredentials to be
// passed as credentials arguments to grpc.WithTransportCredentials. It configures TLS credentials
// if a CA certificate file is specified, otherwise it uses insecure credentials.
func newTrillianTransportCredentialsFromFlags(backend string) (credentials.TransportCredentials, error) {
var creds credentials.TransportCredentials

if len(*tlsCACertFile) > 0 {
tlsCaCert, err := os.ReadFile(filepath.Clean(*tlsCACertFile))
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(tlsCaCert) {
return nil, fmt.Errorf("failed to append CA certificate to pool")
}
creds = credentials.NewTLS(&tls.Config{
ServerName: backend,
RootCAs: certPool,
MinVersion: tls.VersionTLS12,
})
} else {
creds = insecure.NewCredentials()
}
return creds, nil
}

// getController creates a single log migration Controller.
func getController(
ctx context.Context,
Expand Down