Skip to content

Commit

Permalink
feat: ssl config
Browse files Browse the repository at this point in the history
  • Loading branch information
potoo0 committed Jul 10, 2024
1 parent e9a2434 commit c5fa611
Show file tree
Hide file tree
Showing 11 changed files with 559 additions and 75 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,7 @@ jobs:
uses: golangci/golangci-lint-action@v6
with:
version: latest
args: --exclude-use-default=true --exclude='Error return value of .(w\.Write). is not checked'
args: |
--exclude-use-default=true
--exclude='Error return value of .(w\.Write). is not checked'
--exclude='Error return value of `io\.Copy` is not checked'
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

This is a pure go implementation of the
[configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy)
written in nodejs.
written in nodejs. The goal is drop-in replacement of the nodejs version.

[![Go Report Card](https://goreportcard.com/badge/github.com/potoo0/configurable-http-proxy)](https://goreportcard.com/report/github.com/potoo0/configurable-http-proxy)

## Install

Expand All @@ -18,9 +20,13 @@ Download the latest release from the releases page.

## Features

Basically synchronized with nodejs version, but
Basically synchronized with nodejs version.

Ignored SSL args:
- `--ssl-ciphers`: hard to convert openssl cipher strings to golang's cipher suites, use golang's default ciphers
- `--ssl-dhparam`: Diffie-Hellman parameters is not supported in golang's tls package

Missing features (yet):

- Proxy server: `--keep-alive-timeout`, `--timeout`
- Metrics server: `--metrics-port`, `--metrics-ip`
- SSL for proxy, client, API: `--ssl-*`, `--api-ssl-*`, `--client-ssl-*`
82 changes: 42 additions & 40 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"context"
"crypto/tls"
"fmt"
"github.com/potoo0/configurable-http-proxy/lib"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -92,14 +93,25 @@ and CONFIGPROXY_AUTH_TOKEN to set a token for REST API authentication.`,
func run(cmd *cobra.Command, args []string) {
options := initConfig()

proxy := lib.NewConfigurableProxy(options)
go listen(options.Ssl, listenerCfg.ip, listenerCfg.port, proxy.ProxyServer.Handler())
go listen(options.ApiSsl, listenerCfg.apiIp, listenerCfg.apiPort, proxy.ApiServer.Handler())
proxy, err := lib.NewConfigurableProxy(options)
if err != nil {
panic(err)
}
proxyTlsCfg, err := tlsConfig(options.Ssl)
if err != nil {
panic(fmt.Errorf("parsing proxy ssl error: %w", err))
}
apiTlsCfg, err := tlsConfig(options.ApiSsl)
if err != nil {
panic(fmt.Errorf("parsing api ssl error: %w", err))
}
go listen(proxyTlsCfg, listenerCfg.ip, listenerCfg.port, proxy.ProxyServer.Handler())
go listen(apiTlsCfg, listenerCfg.apiIp, listenerCfg.apiPort, proxy.ApiServer.Handler())

log.Info(fmt.Sprintf("Proxying %s://%s:%d to %s", schema(options.Ssl),
defaultIfEmpty(listenerCfg.ip, "*"), listenerCfg.port,
defaultIfEmpty(options.DefaultTarget, "(no default)")))
log.Info(fmt.Sprintf("Proxy API at %s://%s:%d/api/routes", schema(options.Ssl),
log.Info(fmt.Sprintf("Proxy API at %s://%s:%d/api/routes", schema(options.ApiSsl),
defaultIfEmpty(listenerCfg.apiIp, "*"), listenerCfg.apiPort))
if listenerCfg.metricsPort != 0 {
log.Warn("Metrics server not implemented yet")
Expand Down Expand Up @@ -159,20 +171,23 @@ func defaultIfEmpty(s, d string) string {

func schema(ssl *lib.SslConfig) string {
if ssl == nil {
return "https"
return "http"
}
return "http"
return "https"
}

func listen(ssl *lib.SslConfig, ip string, port int, handler http.Handler) {
func listen(tlsConfig *tls.Config, ip string, port int, handler http.Handler) {
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", ip, port),
Handler: handler,
}
// todo
//if ssl != nil {
// server.TLSConfig = &tls.Config{}
//}
if tlsConfig != nil {
server.TLSConfig = tlsConfig
if err := server.ListenAndServeTLS("", ""); err != nil {
panic(err)
}
return
}
if err := server.ListenAndServe(); err != nil {
panic(err)
}
Expand Down Expand Up @@ -273,37 +288,27 @@ func initConfig() *lib.Config {
// ssl cfg
if sslKey != "" || sslCert != "" {
cfg.Ssl = new(lib.SslConfig)
if sslKey != "" {
cfg.Ssl.Key = readFilePanicIfErr(sslKey)
cfg.Ssl.Passphrase = os.Getenv("CONFIGPROXY_SSL_KEY_PASSPHRASE")
}
cfg.Ssl.Key = readFilePanicIfErr(sslKey)
cfg.Ssl.Passphrase = os.Getenv("CONFIGPROXY_SSL_KEY_PASSPHRASE")
cfg.Ssl.Cert = readFilePanicIfErr(sslCert)
cfg.Ssl.Ca = readFilePanicIfErr(sslCa)
cfg.Ssl.Dhparam = readFilePanicIfErr(sslDhparam)
if sslProtocol != "" {
cfg.Ssl.SecureProtocol = sslProtocol + "_method"
}
cfg.Ssl.SecureProtocol = sslProtocol
cfg.Ssl.Ciphers = sslCiphers
cfg.Ssl.HonorCipherOrder = true
cfg.Ssl.RequestCert = sslRequestCert
cfg.Ssl.RejectUnauthorized = sslRejectUnauthorized
}

// ssl cfg for the API interface
if apiSslKey != "" || apiSslCert != "" {
cfg.ApiSsl = new(lib.SslConfig)
if apiSslKey != "" {
cfg.ApiSsl.Key = readFilePanicIfErr(apiSslKey)
cfg.ApiSsl.Passphrase = os.Getenv("CONFIGPROXY_API_SSL_KEY_PASSPHRASE")
}
cfg.ApiSsl.Key = readFilePanicIfErr(apiSslKey)
cfg.ApiSsl.Passphrase = os.Getenv("CONFIGPROXY_API_SSL_KEY_PASSPHRASE")
cfg.ApiSsl.Cert = readFilePanicIfErr(apiSslCert)
cfg.ApiSsl.Ca = loadSslCa(apiSslCa)
cfg.ApiSsl.Ca = readFilePanicIfErr(apiSslCa)
cfg.ApiSsl.Dhparam = readFilePanicIfErr(sslDhparam)
if sslProtocol != "" {
cfg.ApiSsl.SecureProtocol = sslProtocol + "_method"
}
cfg.ApiSsl.SecureProtocol = sslProtocol
cfg.ApiSsl.Ciphers = sslCiphers
cfg.ApiSsl.HonorCipherOrder = true
cfg.ApiSsl.RequestCert = apiSslRequestCert
cfg.ApiSsl.RejectUnauthorized = apiSslRejectUnauthorized
}
Expand All @@ -313,13 +318,10 @@ func initConfig() *lib.Config {
cfg.ClientSsl = new(lib.SslConfig)
cfg.ClientSsl.Key = readFilePanicIfErr(clientSslKey)
cfg.ClientSsl.Cert = readFilePanicIfErr(clientSslCert)
cfg.ClientSsl.Ca = loadSslCa(clientSslCa)
cfg.ClientSsl.Ca = readFilePanicIfErr(clientSslCa)
cfg.ClientSsl.Dhparam = readFilePanicIfErr(sslDhparam)
if sslProtocol != "" {
cfg.ClientSsl.SecureProtocol = sslProtocol + "_method"
}
cfg.ClientSsl.SecureProtocol = sslProtocol
cfg.ClientSsl.Ciphers = sslCiphers
cfg.ClientSsl.HonorCipherOrder = true
cfg.ClientSsl.RequestCert = clientSslRequestCert
cfg.ClientSsl.RejectUnauthorized = clientSslRejectUnauthorized
}
Expand Down Expand Up @@ -400,13 +402,6 @@ func readFilePanicIfErr(name string) []byte {
return bytes
}

func loadSslCa(name string) []byte {
if name == "" {
return nil
}
return nil
}

func headersMap(headers []string) map[string]string {
m := make(map[string]string)
for _, header := range headers {
Expand Down Expand Up @@ -438,3 +433,10 @@ func writePidFile(pidFile string) error {
// or the pid in it doesn't belong to the user running this app.
return os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", os.Getpid())), 0664)
}

func tlsConfig(sslConfig *lib.SslConfig) (*tls.Config, error) {
if sslConfig == nil {
return nil, nil
}
return sslConfig.TlsConfig(true)
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ go 1.22
require (
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
golang.org/x/net v0.26.0
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo=
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
Loading

0 comments on commit c5fa611

Please sign in to comment.