/** * This creates a new certificates pool that can be used to validate user * certificate and synchronizes concurrent access to that pool. * This is expected since ServerHTTP run on their own goroutine * @param path is the path to retrieve CA certificates * @param c is the channel to write to * @see #PopulateCertPool(string) */ func CaCertPoolManager(path string, c chan *x509.CertPool) { var logger = NewPrefixed("security#CaCertPoolManager") caCertPool := new(x509.CertPool) caCertPool, err := populateCertPool(path) if err != nil { logger.Fatal(err.Error()) } for { select { case c <- caCertPool: logger.Finest("Written caCertPool: %v", len(caCertPool.Subjects())) } } }
/** * This is the standard main function */ func main() { SetLoggerLevel(conf.LoggerLevel) var logger = NewPrefixed("main#main") confFilePath := "" baseName := filepath.Base(os.Args[0]) jsonConfFileName := baseName + ".json" dirName, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { logger.Fatal("%v", err) } if len(os.Args) > 1 { confFilePath = os.Args[1] } jsonConfFile, err := os.Open(confFilePath) if err != nil { logger.Debug("Can't find json conf file : %v", confFilePath) confFilePath, err = filepath.Abs(dirName + "/../conf/" + jsonConfFileName) } jsonConfFile, err = os.Open(confFilePath) if err != nil { logger.Debug("Can't find json conf file : %v", confFilePath) confFilePath = "/etc/" + jsonConfFileName } jsonConfFile, err = os.Open(confFilePath) if err != nil { logger.Fatal("Can't find json conf file : %v", confFilePath) } decoder := json.NewDecoder(jsonConfFile) err = decoder.Decode(&conf) if err != nil { fmt.Println("error:", err) } logger.Info("%v", conf) if conf.CACertPath == "" { logger.Warn("CA certificate path is not set: X509 credentials refused") } if conf.CertPath == "" { logger.Fatal("server certificate path is not set") } if conf.KeyPath == "" { logger.Fatal("server key path is not set") } oauthConfigurationChannels = make(map[string]chan *oauth2.Config) hostName := GetLocalHostName() for _, s := range conf.OAuthServers { if len(s.Name) < 1 || len(s.Clientid) < 1 || len(s.Clientsecret) < 1 || len(s.RedirectUrl) < 1 || len(s.AuthUrl) < 1 || len(s.TokenUrl) < 1 { logger.Warn("Ignoring %v : incorrect configuration", s.Name) continue } // // start OAuth config manager // logger.Info("s.Name = %v", s.Name) oauthConfigurationChannels[s.Name] = make(chan *oauth2.Config) go OAuthConfigurationManager( s.Clientid, s.Clientsecret, s.RedirectUrl, s.AuthUrl, s.TokenUrl, oauthConfigurationChannels[s.Name]) } // // start CA cert pool manager // var caCertPool *x509.CertPool caChannel = nil caCertPool = nil if conf.CACertPath != "" { caChannel = make(chan *x509.CertPool) go CaCertPoolManager(conf.CACertPath, caChannel) // // get CA cert pool // caCertPool := <-caChannel logger.Debug("CA pool length = %v", len(caCertPool.Subjects())) } // // Retrieve certificate // cert, err := TLSCerficateFromPEMs(conf.CertPath, conf.KeyPath) if err != nil { logger.Fatal(err.Error()) } logger.Debug("serverCert.Subject = %v", cert.Leaf.Subject) logger.Debug("serverCert.Issuer = %v", cert.Leaf.Issuer) // // Verify cert against known CA // if caCertPool != nil { vOpts := x509.VerifyOptions{Roots: caCertPool} _, err = cert.Leaf.Verify(vOpts) if err != nil { logger.Warn("failed to parse server certificate: " + err.Error()) } } tlsConfig := TLSConfig(cert, caCertPool) os.Create(backendfile) defer os.Remove(backendfile) backend, err = httpauth.NewGobFileAuthBackend(backendfile) if err != nil { logger.Fatal("can't create backend %v", err) } // create some default roles roles = make(map[string]httpauth.Role) roles["user"] = 30 roles["admin"] = 80 httpAuthorizer, err = httpauth.NewAuthorizer(backend, []byte("cookie-encryption-key"), "user", roles) // set up routers and route handlers r := mux.NewRouter() // r.HandleFunc("/", handlePage).Methods("GET") // authorized page r.HandleFunc("/logout", handleLogout) r.HandleFunc(ROOTURL, X509Authenticator) r.HandleFunc(OAUTHURL, OAuthenticationPage) for _, s := range conf.OAuthServers { r.HandleFunc(OAUTHURL+s.Name, OAuthAuthenticator) } r.HandleFunc(APPSURL, handlePage) r.HandleFunc(JWTURL, JWTAuthenticator) server := http.Server{Addr: hostName + ":" + conf.PortNumber, TLSConfig: tlsConfig, Handler: r} // start https logger.Info("Listening HTTPS : " + hostName + ":" + conf.PortNumber) server.ListenAndServeTLS(conf.CertPath, conf.KeyPath) }