diff --git a/cmd/app/serve.go b/cmd/app/serve.go index 016e42ba0..499de9085 100644 --- a/cmd/app/serve.go +++ b/cmd/app/serve.go @@ -18,6 +18,7 @@ package app import ( "bytes" "context" + "crypto/tls" "crypto/x509" "errors" "flag" @@ -108,6 +109,7 @@ func newServeCmd() *cobra.Command { cmd.Flags().String("grpc-tls-certificate", "", "the certificate file to use for secure connections - only applies to grpc-port") cmd.Flags().String("grpc-tls-key", "", "the private key file to use for secure connections (without passphrase) - only applies to grpc-port") cmd.Flags().Duration("idle-connection-timeout", 30*time.Second, "The time allowed for connections (HTTP or gRPC) to go idle before being closed by the server") + cmd.Flags().String("ct-log.tls-ca-cert", "", "Path to TLS CA certificate used to connect to ct-log") // convert "http-host" flag to "host" and "http-port" flag to be "port" cmd.Flags().SetNormalizeFunc(func(_ *pflag.FlagSet, name string) pflag.NormalizedName { @@ -273,7 +275,33 @@ func runServeCmd(cmd *cobra.Command, args []string) { //nolint: revive } opts.PublicKey = string(pemPubKey) } - ctClient, err = ctclient.New(logURL, &http.Client{Timeout: 30 * time.Second}, opts) + var httpClient *http.Client + if tlsCaCertPath := viper.GetString("ct-log.tls-ca-cert"); tlsCaCertPath != "" { + tlsCaCert, err := os.ReadFile(filepath.Clean(tlsCaCertPath)) + if err != nil { + log.Logger.Fatal(err) + } + caCertPool := x509.NewCertPool() + if ok := caCertPool.AppendCertsFromPEM(tlsCaCert); !ok { + log.Logger.Fatal("failed to append TLS CA certificate") + } + tlsConfig := &tls.Config{ + RootCAs: caCertPool, + MinVersion: tls.VersionTLS12, + } + transport := &http.Transport{ + TLSClientConfig: tlsConfig, + } + httpClient = &http.Client{ + Timeout: 30 * time.Second, + Transport: transport, + } + } else { + httpClient = &http.Client{ + Timeout: 30 * time.Second, + } + } + ctClient, err = ctclient.New(logURL, httpClient, opts) if err != nil { log.Logger.Fatal(err) } diff --git a/config/tls/ca.crt b/config/tls/ca.crt new file mode 100644 index 000000000..f6cd2b249 --- /dev/null +++ b/config/tls/ca.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFAzCCAuugAwIBAgIUCroIEpa8ZFgrBpmwERTYRbp1TEkwDQYJKoZIhvcNAQEL +BQAwEDEOMAwGA1UEAwwFTXkgQ0EwIBcNMjQwNzMwMTg1OTMzWhgPMjEyNDA3MDYx +ODU5MzNaMBAxDjAMBgNVBAMMBU15IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAtBEZLtAbR9guZMEDHFu4rDEkrJVFcpl3IBkvXMlpXQSP8CXSa0do +8UPNUsq6ptui1FKvi54nX0BeAahytfWvYem0a6yl4RijPZA55GxHSk7/uueeCLZs +G3K1bWiJe4qGChjc/g8putrWFsd0KFYCifEGjlxmKtr8NaZlw6YcMaKWZ/IO/eWC +z0v7sq0zA8YtSjyyQCJR+3Wh5QWEf+Wk4xM+A8crIjV62nDC7dYMZpNWr/1K+WsR +IuL/p7pMUvurDCsruI/0XhkkphYfV+9jdbN5SDid6WlJ+U1ZoJdUpkHufoQ5j0tC +tpC0A2sNjquD7qmpjkRC4MJuyOzmoVu0RFRiUedwJzRAF7oZ6zKpc0B6yLQs1AMb +Q8MyLrnz5VCY3UGzVYeZGXka8UxQ4T/GH3mqnOAXGWu1217/JzMu7pPO4IVP4Lz5 +SdPMhEvEMHeoC5LUnaB2zPLFsvvagW/BT/Obuf5Srs3U/WObthxfsoiWeAGL/+AN +OeAvUILpUceUv9AHEYL7UMbVwId78rTcw4pWdlb47yMpTAMqs6Oa4ZncTxoNvZAj +8SvJdB5SSMz5QBWMz/mgZGqAUibNsz2CUO3yQ/DClRbBDuvndIDW0e1AcqTO55IF +/s5EmWNSdxNTVNQuJmul5BLkNnr2w2UxiCwC196U15OFGGaJfa2Q97cCAwEAAaNT +MFEwHQYDVR0OBBYEFP7xzrRK6+7Rzzgzvw8fV061WmB+MB8GA1UdIwQYMBaAFP7x +zrRK6+7Rzzgzvw8fV061WmB+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggIBAIXdvX+Qu/T3lMoU699KKE/C/N7uND+cAPeU7y7INOknTeh3cKJOcVVz +zT8ag1Dvy2vnYqS8jDG/qvAgEZDStb9xwNJkk4BW2xLjcPe17aDEyMIdPn6Ey3Xc +SIyG8+UWBkplGfOUkaTadDGldOYUWEoEuLlDRz4RUE5AzEbx6xOaBjC2ZL6prLTN +fPykWoC2I/damo/BxPKLw3fEjjyqY5/jmNho8eGC/dIAtw0gu4yajaE3GNjSvQPT +Xa+ClGFU4xXc7rrHTZ+iiE+Ek3NlUH8DaIx0XBuKRgx8yvRulUflLD0ajIRob+Gn +F/A/pw3zbLhdAWkWgWW4hCaoa009WXaSwfLMc/gDD6+51UACepAHUP+VQAXQHRC/ +eOZjhdKbhZebkbWsQYXkz/BYY3tMCW17VrGlYtyfy+r6WzEw9rqBEs54yM8xuUEW +vT1xuxG++ptfB4X7uZVqvrZKX7zc8nQ2ptf4ATwb5EN5CaVil1w/IMuIyxpx0jTU +p4DCeZTx3eamaq376UodhT6HxyrM28f8gui8yIWkGdqw9fNA/Pe1rjqew9IQVYEo +gyEHjjfkJFyxCjhmzmtRMqJKh7SRLXqBaloYdUlTjz6CL0nc53WLvm4/h9znFXBc +36+nBlgXk/WTiuWkmX/a6Xf//3sv1rCxtCXj/EH6S7FMBD9gljtO +-----END CERTIFICATE----- diff --git a/config/tls/key_cert_generation.md b/config/tls/key_cert_generation.md new file mode 100644 index 000000000..5a16f62da --- /dev/null +++ b/config/tls/key_cert_generation.md @@ -0,0 +1,21 @@ +# Generation of ct_server key/cert and CA certficate + +## Commands + +``` +# 1. Generate CA's private key and self-signed certificate +openssl req -x509 -newkey rsa:4096 -days 36500 -nodes -keyout ca.key -out ca.crt -subj "/CN=My CA" + +# 2. Generate ct_server's private key and certificate signing request (CSR) +openssl req -newkey rsa:4096 -nodes -keyout tls.key -out server-req.pem -subj "/=Server TLS/OU=Server/CN=*/emailAddress=tls@gmail.com" + +# 3. SAN +echo "subjectAltName=DNS:*,DNS:ct_server,IP:0.0.0.0" > server-ext.cnf + +# 3. Use CA's private key to sign ct_server's CSR and get back the signed certificate +openssl x509 -req -in server-req.pem -days 60 -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt -extfile server-ext.cnf + +# 4. Clean-up +rm ca.key ca.srl server-ext.cnf server-req.pem + +``` \ No newline at end of file diff --git a/config/tls/tls.crt b/config/tls/tls.crt new file mode 100644 index 000000000..8c5838c0d --- /dev/null +++ b/config/tls/tls.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFOjCCAyKgAwIBAgIUZOAUTUGnvAbSwp/zNyatzPCYR4cwDQYJKoZIhvcNAQEL +BQAwEDEOMAwGA1UEAwwFTXkgQ0EwHhcNMjQwNzMwMTg1OTQ3WhcNMjQwOTI4MTg1 +OTQ3WjA7MQ8wDQYDVQQLDAZTZXJ2ZXIxCjAIBgNVBAMMASoxHDAaBgkqhkiG9w0B +CQEWDXRsc0BnbWFpbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCfMw5FC5oRh7psbcZ+YqLWsXxBGWe0NZFCt6hy3Rl1ib0pXSF2PfOc6Qaq8e1A +7b0tv5wH08fpWHJnMn/OD7oLhbdWyBw8q76wV7rG6TzB/39v1pFBGaNhL9786QOu +X1LjmyaL0FbAdw/b36/ul+lxu87BylvwHKnz7E9LpqWsxt+Xc9nNLgiBcxcV7AVI +MiuhDf91BzGA8Ab7SOWcqmLx1b26uVzGbw9CC6VBrQlhqFSL/2epMMtGKWjYGyr1 +lfmYejJ2jOgub+onaJu3kg64+Lp5ZoEsXAqE/Unq1k0K9khvoM2t5U7onaqRlU9E +CoeVk2EZUnwOLapJ18a025FCBJsMn1gd9cuiuMeANISRkLIxa9i4MtpAYNWbG0k1 +laOuSZHVOpy31U5p7WDOHNf6Ni8GMSC2ilvtYTmg7bmwXFLwj7OVA29MgWDLJhAk +hs1BuLH/IoWZZtr3jIbJKEtn6d5Y3XjoVQh7YpQi1s8omO3PTIlnpHk6nQSS5y6R +TyLUuSeLh2FOvPO7maBET/Ni/Qq8SGHC3B4LRF6ckTmHxOVFzeawZyfxUZRHYnjo +cmqMwBNRJYmXYHmVghgyCwK+dndgB1bCVhPu7T5bUgpYHAAXzO0fwS+plQg4hLkY +OQZztD0/44jP+xAFnrjAnUyWYbCJWU4E0hne3LBpBquhdwIDAQABo2EwXzAdBgNV +HREEFjAUggEqggljdF9zZXJ2ZXKHBAAAAAAwHQYDVR0OBBYEFDC/TAlqsr1HrSjD +jD148oH2otnpMB8GA1UdIwQYMBaAFP7xzrRK6+7Rzzgzvw8fV061WmB+MA0GCSqG +SIb3DQEBCwUAA4ICAQBJX2Wb21pdS1hKvkagCQS+FB49Up54NVisrGxVrKjxZW+9 ++SMknPH/BtJeJlCFcztLA025kqfrh+u8zvzgsit9tHyybm/3iGfiNjJWoLaHlVzk +L+orUFmPt7bzU68wZIj3URWRDxO5/bvXHkIBHTr5xNUD5QPOwnLZdNRox9A3hv6v +P332RrIQCCDbiOc3fY7PZSfBnJMHGV+HZkS21tJfwLR7hgY8nFcXjl4KpA4XFoaj +HaN7pfVNQpXn46VXZSAQEM5sR+JKCz9+DoGdOELmik0vcDpms0YUuYZ8ZSKVamXZ +yNFg9o8/c9xpkYFMMvKfaAkfrSzu7FLFLX5nI4oSzP7kx4cFl3/2qDFLF+MRx2n7 +d81zbeWLfqWj1rcWi4f5umxBBgBCXF4C4B03SoilYwwrpjxEZZcH71m/Jcz8GOYW +B77kSMXqo1rJoy1fs3YAZ4f/lvgyRPeoCvWIQNx8UTMI/43HJI7fN86BdBZIgQJU +8qJghrHvZisMcLJP6Uyo+2MDdrCfWK04V+47YyzwBDvfCRha3gzJPlTrUubkF4tv +8o7fYSerkzo04IeM3lAggruYmhABWaubP75ZS70nkHlB2kL6BYV81j21BOPGk/ug +nfnjFG7BfeZmFpJB1DcRxCzeM+yLtP8qKn9zwDOey+6TpUZoP2S+vUBZGuyr0A== +-----END CERTIFICATE----- diff --git a/config/tls/tls.key b/config/tls/tls.key new file mode 100644 index 000000000..c43830336 --- /dev/null +++ b/config/tls/tls.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +YG3/wgjXsCDRkdewm5fvGUXUEt5rbA== +-----END PRIVATE KEY----- diff --git a/docker-compose.yml b/docker-compose.yml index a720943c9..6228ac7f0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,7 +26,8 @@ services: "--port=5555", "--grpc-port=5554", "--ca=ephemeralca", - "--ct-log-url=http://ct_server:6962/test", + "--ct-log-url=https://ct_server:6962/test", + "--ct-log.tls-ca-cert=/config/tls/ca.crt", # Uncomment this for production logging # "--log_type=prod", ] @@ -38,6 +39,7 @@ services: volumes: - ~/.config/gcloud:/root/.config/gcloud/:z # for GCP authentication - ${FULCIO_CONFIG:-./config/identity/config.yaml}:/etc/fulcio-config/config.yaml:z + - ./config/tls:/config/tls:z healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5555/healthz"] interval: 10s @@ -79,10 +81,13 @@ services: image: gcr.io/trillian-opensource-ci/ctfe volumes: - ctfeConfig:/etc/config/:ro + - ./config/tls:/config/tls:z command: [ "--log_config" ,"/etc/config/ct_server.cfg", "--log_rpc_server", "trillian-log-server:8096", "--http_endpoint", "0.0.0.0:6962", + "--tls_certificate", "/config/tls/tls.crt", + "--tls_key", "/config/tls/tls.key", "--alsologtostderr", ] restart: always # retry while ctfe_init is running