Skip to content

Commit

Permalink
feat: add server public url
Browse files Browse the repository at this point in the history
* Specify server public http url in a environment variable

Fixes: #37
Related: #58
  • Loading branch information
aymanbagabas committed Feb 22, 2022
1 parent 19d0156 commit 506448b
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 39 deletions.
5 changes: 4 additions & 1 deletion docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ services:
To set up TLS under Docker, consider using a reverse proxy such as
[traefik](https://doc.traefik.io/traefik/https/overview/) or a web server with
automatic HTTPS like [caddy](https://caddyserver.com/docs/automatic-https).
automatic HTTPS like [caddy](https://caddyserver.com/docs/automatic-https). If
you're using a reverse proxy, you will need to set `CHARM_SERVER_HOST` to your
public host, and `CHARM_SERVER_PUBLIC_URL` to the full public URL of your
reverse proxy i.e. `CHARM_SERVER_PUBLIC_URL=https://cloud.charm.sh:35354`.

***

Expand Down
3 changes: 2 additions & 1 deletion server/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ func (me *SSHServer) handleAPIAuth(s ssh.Session) {
me.errorLog.Printf("Error fetching encrypt keys: %s\n", err)
return
}
httpScheme := me.config.httpURL().Scheme
_ = me.sendJSON(s, charm.Auth{
JWT: j,
ID: u.CharmID,
HTTPScheme: me.config.httpScheme,
HTTPScheme: httpScheme,
PublicKey: u.PublicKey.Key,
EncryptKeys: eks,
})
Expand Down
59 changes: 33 additions & 26 deletions server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ const resultsPerPage = 50

// HTTPServer is the HTTP server for the Charm Cloud backend.
type HTTPServer struct {
db db.DB
fstore storage.FileStore
cfg *Config
handler http.Handler
server *http.Server
health *http.Server
db db.DB
fstore storage.FileStore
cfg *Config
server *http.Server
health *http.Server
httpScheme string
}

type providerJSON struct {
Expand All @@ -59,13 +59,24 @@ func NewHTTPServer(cfg *Config) (*HTTPServer, error) {
}
mux := goji.NewMux()
s := &HTTPServer{
cfg: cfg,
handler: mux,
health: health,
cfg: cfg,
health: health,
httpScheme: "http",
}
s.server = &http.Server{
Addr: fmt.Sprintf("%s:%d", s.cfg.BindAddr, s.cfg.HTTPPort),
Handler: mux,
ErrorLog: s.cfg.errorLog,
}
if cfg.UseTLS {
s.httpScheme = "https"
s.health.TLSConfig = s.cfg.tlsConfig
s.server.TLSConfig = s.cfg.tlsConfig
}

jwtMiddleware, err := JWTMiddleware(
cfg.jwtKeyPair.JWK.Public(),
cfg.httpURL(),
cfg.httpURL().String(),
[]string{"charm"},
)
if err != nil {
Expand Down Expand Up @@ -97,24 +108,19 @@ func NewHTTPServer(cfg *Config) (*HTTPServer, error) {

// Start start the HTTP and health servers on the ports specified in the Config.
func (s *HTTPServer) Start() {
useTLS := s.cfg.httpScheme == "https"
listenAddr := fmt.Sprintf("%s:%d", s.cfg.BindAddr, s.cfg.HTTPPort)
s.server = &http.Server{
Addr: listenAddr,
Handler: s.handler,
TLSConfig: s.cfg.tlsConfig,
ErrorLog: s.cfg.errorLog,
}

scheme := strings.ToUpper(s.httpScheme)
go func() {
log.Printf("Starting HTTP health server on: %s", s.health.Addr)
if err := s.health.ListenAndServe(); err != nil {
log.Fatalf("http health endpoint server exited with error: %s", err)
log.Printf("Starting %s health server on: %s", scheme, s.health.Addr)
if s.cfg.UseTLS {
log.Fatalf("http health endpoint server exited with error: %s",
s.health.ListenAndServeTLS(s.cfg.TLSCertFile, s.cfg.TLSKeyFile))
} else {
log.Fatalf("http health endpoint server exited with error: %s", s.health.ListenAndServe())
}
}()

log.Printf("Starting %s server on: %s", strings.ToUpper(s.cfg.httpScheme), listenAddr)
if useTLS {
log.Printf("Starting %s server on: %s", scheme, s.server.Addr)
if s.cfg.UseTLS {
log.Fatalf("Server crashed: %s", s.server.ListenAndServeTLS(s.cfg.TLSCertFile, s.cfg.TLSKeyFile))
} else {
log.Fatalf("Server crashed: %s", s.server.ListenAndServe())
Expand All @@ -123,8 +129,9 @@ func (s *HTTPServer) Start() {

// Shutdown gracefully shut down the HTTP and health servers.
func (s *HTTPServer) Shutdown(ctx context.Context) error {
log.Printf("Stopping %s server on %s", strings.ToUpper(s.cfg.httpScheme), s.server.Addr)
log.Printf("Stopping HTTP health server on %s", s.health.Addr)
scheme := strings.ToUpper(s.httpScheme)
log.Printf("Stopping %s server on %s", scheme, s.server.Addr)
log.Printf("Stopping %s health server on %s", scheme, s.health.Addr)
if err := s.health.Shutdown(ctx); err != nil {
return err
}
Expand Down
22 changes: 14 additions & 8 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"crypto/tls"
"fmt"
"log"
"net/url"
"path/filepath"

"github.com/caarlos0/env/v6"
Expand All @@ -29,8 +30,10 @@ type Config struct {
StatsPort int `env:"CHARM_SERVER_STATS_PORT" envDefault:"35355"`
HealthPort int `env:"CHARM_SERVER_HEALTH_PORT" envDefault:"35356"`
DataDir string `env:"CHARM_SERVER_DATA_DIR" envDefault:"data"`
UseTLS bool `env:"CHARM_SERVER_USE_TLS" envDefault:"false"`
TLSKeyFile string `env:"CHARM_SERVER_TLS_KEY_FILE"`
TLSCertFile string `env:"CHARM_SERVER_TLS_CERT_FILE"`
PublicURL string `env:"CHARM_SERVER_PUBLIC_URL"`
errorLog *log.Logger
PublicKey []byte
PrivateKey []byte
Expand Down Expand Up @@ -105,8 +108,17 @@ func (cfg *Config) WithLinkQueue(q charm.LinkQueue) *Config {
return cfg
}

func (cfg *Config) httpURL() string {
return fmt.Sprintf("%s://%s:%d", cfg.httpScheme, cfg.Host, cfg.HTTPPort)
func (cfg *Config) httpURL() *url.URL {
s := fmt.Sprintf("%s://%s:%d", cfg.httpScheme, cfg.Host, cfg.HTTPPort)
if cfg.PublicURL != "" {
s = cfg.PublicURL
}
url, err := url.Parse(s)
if err != nil {
log.Fatalf("could not parse URL: %s", err)
}
log.Print(url.String())
return url
}

// NewServer returns a *Server with the specified Config.
Expand All @@ -119,12 +131,6 @@ func NewServer(cfg *Config) (*Server, error) {
return nil, err
}
cfg.jwtKeyPair = NewJSONWebKeyPair(pk.(*ed25519.PrivateKey))

// Use HTTPS when TLS is configured.
if cfg.tlsConfig != nil || (cfg.TLSCertFile != "" && cfg.TLSKeyFile != "") {
cfg.httpScheme = "https"
}

ss, err := NewSSHServer(cfg)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion server/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (me *SSHServer) newJWT(charmID string, audience ...string) (string, error)
claims := &jwt.RegisteredClaims{
Subject: charmID,
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
Issuer: me.config.httpURL(),
Issuer: me.config.httpURL().String(),
Audience: audience,
}
token := jwt.NewWithClaims(&jwt.SigningMethodEd25519{}, claims)
Expand Down
4 changes: 2 additions & 2 deletions systemd.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ in the systemd service file as described below.

## TLS

To set up TLS, you should set `CHARM_SERVER_HTTP_SCHEME` environment variable to
`https` and specify `CHARM_SERVER_HOST`, `CHARM_SERVER_TLS_KEY_FILE`, and
To set up TLS, you should set `CHARM_SERVER_USE_TLS` to `true`, and specify
`CHARM_SERVER_HOST`, `CHARM_SERVER_TLS_KEY_FILE`, and
`CHARM_SERVER_TLS_CERT_FILE` file paths.

***
Expand Down

0 comments on commit 506448b

Please sign in to comment.