Commit e8ae1a7c authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Disallow non-HTTPS URLs in production mode unless TLS is explicitly disabled

parent 9b7a55c1
......@@ -139,6 +139,16 @@ func (s *Server) verifyConfiguration(configuration *server.Configuration) error
if !strings.HasSuffix(s.conf.URL, "/") {
s.conf.URL = s.conf.URL + "/"
}
if !strings.HasPrefix(s.conf.URL, "https://") {
if !s.conf.Production || s.conf.DisableTLS {
s.conf.DisableTLS = true
s.conf.Logger.Warnf("TLS is not enabled on the url \"%s\" to which the IRMA app will connect. "+
"Ensure that attributes are encrypted in transit by either enabling TLS or adding TLS in a reverse proxy.", s.conf.URL)
} else {
return server.LogError(errors.Errorf("Running without TLS in production mode is unsafe without a reverse proxy. " +
"Either use a https:// URL or explicitly disable TLS."))
}
}
} else {
s.conf.Logger.Warn("No url parameter specified in configuration; unless an url is elsewhere prepended in the QR, the IRMA client will not be able to connect")
}
......
......@@ -43,6 +43,10 @@ type Configuration struct {
IssuerPrivateKeys map[irma.IssuerIdentifier]*gabi.PrivateKey `json:"-"`
// URL at which the IRMA app can reach this server during sessions
URL string `json:"url" mapstructure:"url"`
// Required to be set to true if URL does not begin with https:// in production mode.
// In this case, the server would communicate with IRMA apps over plain HTTP. You must otherwise
// ensure (using eg a reverse proxy with TLS enabled) that the attributes are protected in transit.
DisableTLS bool
// (Optional) email address of server admin, for incidental notifications such as breaking API changes
// See https://github.com/privacybydesign/irmago/tree/master/server#specifying-an-email-address
// for more information
......@@ -58,6 +62,9 @@ type Configuration struct {
LogJSON bool `json:"log_json" mapstructure:"log_json"`
// Custom logger instance. If specified, Verbose, Quiet and LogJSON are ignored.
Logger *logrus.Logger `json:"-"`
// Production mode: enables safer and stricter defaults and config checking
Production bool `json:"production" mapstructure:"production"`
}
type SessionPackage struct {
......
......@@ -104,6 +104,7 @@ func setFlags(cmd *cobra.Command) error {
flags.String("client-tls-cert-file", "", "path to TLS certificate (chain) for IRMA app server")
flags.String("client-tls-privkey", "", "TLS private key for IRMA app server")
flags.String("client-tls-privkey-file", "", "path to TLS private key for IRMA app server")
flags.Bool("no-tls", false, "Disable TLS")
flags.Lookup("tls-cert").Header = "TLS configuration (leave empty to disable TLS)"
flags.StringP("email", "e", "", "Email address of server admin, for incidental notifications such as breaking API changes")
......@@ -178,13 +179,15 @@ func configure(cmd *cobra.Command) error {
SchemesUpdateInterval: viper.GetInt("schemes-update"),
DisableSchemesUpdate: viper.GetInt("schemes-update") == 0,
IssuerPrivateKeysPath: viper.GetString("privkeys"),
URL: viper.GetString("url"),
Email: viper.GetString("email"),
EnableSSE: viper.GetBool("sse"),
Verbose: viper.GetInt("verbose"),
Quiet: viper.GetBool("quiet"),
LogJSON: viper.GetBool("log-json"),
Logger: logger,
URL: viper.GetString("url"),
DisableTLS: viper.GetBool("no-tls"),
Email: viper.GetString("email"),
EnableSSE: viper.GetBool("sse"),
Verbose: viper.GetInt("verbose"),
Quiet: viper.GetBool("quiet"),
LogJSON: viper.GetBool("log-json"),
Logger: logger,
Production: viper.GetBool("production"),
},
Permissions: requestorserver.Permissions{
Disclosing: handlePermission("disclose-perms"),
......@@ -212,8 +215,6 @@ func configure(cmd *cobra.Command) error {
ClientTlsCertificateFile: viper.GetString("client-tls-cert-file"),
ClientTlsPrivateKey: viper.GetString("client-tls-privkey"),
ClientTlsPrivateKeyFile: viper.GetString("client-tls-privkey-file"),
Production: viper.GetBool("production"),
}
if conf.Production {
......
......@@ -65,8 +65,6 @@ type Configuration struct {
// Host static files under this URL prefix
StaticPrefix string `json:"static_prefix" mapstructure:"static_prefix"`
Production bool `json:"production" mapstructure:"production"`
jwtPrivateKey *rsa.PrivateKey
}
......@@ -247,10 +245,6 @@ func (conf *Configuration) initialize() error {
conf.URL = "https://" + conf.URL[len("http://"):]
}
}
if !strings.HasPrefix(conf.URL, "https://") {
conf.Logger.Warnf("TLS is not enabled on the url \"%s\" to which the IRMA app will connect. "+
"Ensure that attributes are encrypted in transit by either enabling TLS or adding TLS in a reverse proxy.", conf.URL)
}
}
return nil
......
......@@ -194,8 +194,12 @@ func (s *Server) Handler() http.Handler {
}
func (s *Server) StaticFilesHandler() http.Handler {
url := s.conf.URL[:len(s.conf.URL)-6] + s.conf.StaticPrefix
s.conf.Logger.Infof("Hosting files at %s under %s", s.conf.StaticPath, url)
if len(s.conf.URL) > 6 {
url := s.conf.URL[:len(s.conf.URL)-6] + s.conf.StaticPrefix
s.conf.Logger.Infof("Hosting files at %s under %s", s.conf.StaticPath, url)
} else { // URL not known, don't log it but otherwise continue
s.conf.Logger.Infof("Hosting files at %s", s.conf.StaticPath)
}
// Hook up chi middleware logger with our own logger
middleware.DefaultLogger = middleware.RequestLogger(&middleware.DefaultLogFormatter{
Logger: log.New(s.conf.Logger.WriterLevel(logrus.TraceLevel), "static: ", 0),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment