diff --git a/README.md b/README.md index f601919f3..74ab1301c 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Stash can run over HTTPS with some additional work. First you must generate a S This command would need customizing for your environment. [This link](https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl) might be useful. -Once you have a certificate and key file name them `stash.crt` and `stash.key` and place them in the `~/.stash` directory. Stash detects these and starts up using HTTPS rather than HTTP. +Once you have a certificate and key file name them `stash.crt` and `stash.key` and place them in the same directory as the `config.yml` file, or the `~/.stash` directory. Stash detects these and starts up using HTTPS rather than HTTP. # Customization diff --git a/pkg/api/server.go b/pkg/api/server.go index ee9063287..823dae457 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -27,7 +27,6 @@ import ( "github.com/stashapp/stash/pkg/logger" "github.com/stashapp/stash/pkg/manager" "github.com/stashapp/stash/pkg/manager/config" - "github.com/stashapp/stash/pkg/manager/paths" "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/session" "github.com/stashapp/stash/pkg/utils" @@ -286,34 +285,31 @@ func Start() { displayAddress := displayHost + ":" + strconv.Itoa(c.GetPort()) address := c.GetHost() + ":" + strconv.Itoa(c.GetPort()) - if tlsConfig := makeTLSConfig(); tlsConfig != nil { - httpsServer := &http.Server{ - Addr: address, - Handler: r, - TLSConfig: tlsConfig, - } + tlsConfig, err := makeTLSConfig(c) + if err != nil { + // assume we don't want to start with a broken TLS configuration + panic(fmt.Errorf("error loading TLS config: %s", err.Error())) + } - go func() { - printVersion() - printLatestVersion() - logger.Infof("stash is listening on " + address) + server := &http.Server{ + Addr: address, + Handler: r, + TLSConfig: tlsConfig, + } + + go func() { + printVersion() + printLatestVersion() + logger.Infof("stash is listening on " + address) + + if tlsConfig != nil { logger.Infof("stash is running at https://" + displayAddress + "/") - logger.Error(httpsServer.ListenAndServeTLS("", "")) - }() - } else { - server := &http.Server{ - Addr: address, - Handler: r, - } - - go func() { - printVersion() - printLatestVersion() - logger.Infof("stash is listening on " + address) + logger.Error(server.ListenAndServeTLS("", "")) + } else { logger.Infof("stash is running at http://" + displayAddress + "/") logger.Error(server.ListenAndServe()) - }() - } + } + }() } func printVersion() { @@ -328,27 +324,44 @@ func GetVersion() (string, string, string) { return version, githash, buildstamp } -func makeTLSConfig() *tls.Config { - cert, err := ioutil.ReadFile(paths.GetSSLCert()) - if err != nil { - return nil +func makeTLSConfig(c *config.Instance) (*tls.Config, error) { + c.InitTLS() + certFile, keyFile := c.GetTLSFiles() + + if certFile == "" && keyFile == "" { + // assume http configuration + return nil, nil } - key, err := ioutil.ReadFile(paths.GetSSLKey()) + // ensure both files are present + if certFile == "" { + return nil, errors.New("SSL certificate file must be present if key file is present") + } + + if keyFile == "" { + return nil, errors.New("SSL key file must be present if certificate file is present") + } + + cert, err := ioutil.ReadFile(certFile) if err != nil { - return nil + return nil, fmt.Errorf("error reading SSL certificate file %s: %s", certFile, err.Error()) + } + + key, err := ioutil.ReadFile(keyFile) + if err != nil { + return nil, fmt.Errorf("error reading SSL key file %s: %s", keyFile, err.Error()) } certs := make([]tls.Certificate, 1) certs[0], err = tls.X509KeyPair(cert, key) if err != nil { - return nil + return nil, fmt.Errorf("error parsing key pair: %s", err.Error()) } tlsConfig := &tls.Config{ Certificates: certs, } - return tlsConfig + return tlsConfig, nil } type contextKey struct { diff --git a/pkg/ffmpeg/downloader.go b/pkg/ffmpeg/downloader.go index e99716cbf..da5b2dbaf 100644 --- a/pkg/ffmpeg/downloader.go +++ b/pkg/ffmpeg/downloader.go @@ -16,17 +16,6 @@ import ( "github.com/stashapp/stash/pkg/utils" ) -func findInPaths(paths []string, baseName string) string { - for _, p := range paths { - filePath := filepath.Join(p, baseName) - if exists, _ := utils.FileExists(filePath); exists { - return filePath - } - } - - return "" -} - func GetPaths(paths []string) (string, string) { var ffmpegPath, ffprobePath string @@ -38,10 +27,10 @@ func GetPaths(paths []string) (string, string) { // Check if ffmpeg exists in the config directory if ffmpegPath == "" { - ffmpegPath = findInPaths(paths, getFFMPEGFilename()) + ffmpegPath = utils.FindInPaths(paths, getFFMPEGFilename()) } if ffprobePath == "" { - ffprobePath = findInPaths(paths, getFFProbeFilename()) + ffprobePath = utils.FindInPaths(paths, getFFProbeFilename()) } return ffmpegPath, ffprobePath diff --git a/pkg/manager/config/config.go b/pkg/manager/config/config.go index c97f5ec67..c412880ca 100644 --- a/pkg/manager/config/config.go +++ b/pkg/manager/config/config.go @@ -157,18 +157,11 @@ func (e MissingConfigError) Error() string { return fmt.Sprintf("missing the following mandatory settings: %s", strings.Join(e.missingFields, ", ")) } -func HasTLSConfig() bool { - ret, _ := utils.FileExists(paths.GetSSLCert()) - if ret { - ret, _ = utils.FileExists(paths.GetSSLKey()) - } - - return ret -} - type Instance struct { cpuProfilePath string isNewSystem bool + certFile string + keyFile string sync.RWMutex //deadlock.RWMutex // for deadlock testing/issues } @@ -192,6 +185,26 @@ func (i *Instance) SetConfigFile(fn string) { viper.SetConfigFile(fn) } +func (i *Instance) InitTLS() { + configDirectory := i.GetConfigPath() + tlsPaths := []string{ + configDirectory, + paths.GetStashHomeDirectory(), + } + + i.certFile = utils.FindInPaths(tlsPaths, "stash.crt") + i.keyFile = utils.FindInPaths(tlsPaths, "stash.key") +} + +func (i *Instance) GetTLSFiles() (certFile, keyFile string) { + return i.certFile, i.keyFile +} + +func (i *Instance) HasTLSConfig() bool { + certFile, keyFile := i.GetTLSFiles() + return certFile != "" && keyFile != "" +} + // GetCPUProfilePath returns the path to the CPU profile file to output // profiling info to. This is set only via a commandline flag. Returns an // empty string if not set. diff --git a/pkg/manager/paths/paths.go b/pkg/manager/paths/paths.go index 0d06af2c0..d3216b6bc 100644 --- a/pkg/manager/paths/paths.go +++ b/pkg/manager/paths/paths.go @@ -29,11 +29,3 @@ func GetStashHomeDirectory() string { func GetDefaultDatabaseFilePath() string { return filepath.Join(GetStashHomeDirectory(), "stash-go.sqlite") } - -func GetSSLKey() string { - return filepath.Join(GetStashHomeDirectory(), "stash.key") -} - -func GetSSLCert() string { - return filepath.Join(GetStashHomeDirectory(), "stash.crt") -} diff --git a/pkg/plugin/plugins.go b/pkg/plugin/plugins.go index eff6d88ba..844834339 100644 --- a/pkg/plugin/plugins.go +++ b/pkg/plugin/plugins.go @@ -133,7 +133,7 @@ func (c Cache) makeServerConnection(ctx context.Context) common.StashServerConne Dir: c.config.GetConfigPath(), } - if config.HasTLSConfig() { + if c.config.HasTLSConfig() { serverConnection.Scheme = "https" } diff --git a/pkg/utils/file.go b/pkg/utils/file.go index 81cd75598..87f7538b3 100644 --- a/pkg/utils/file.go +++ b/pkg/utils/file.go @@ -346,3 +346,14 @@ func IsFsPathCaseSensitive(path string) (bool, error) { } return false, fmt.Errorf("can not determine case sensitivity of path %s", path) } + +func FindInPaths(paths []string, baseName string) string { + for _, p := range paths { + filePath := filepath.Join(p, baseName) + if exists, _ := FileExists(filePath); exists { + return filePath + } + } + + return "" +} diff --git a/ui/v2.5/src/components/Changelog/versions/v090.md b/ui/v2.5/src/components/Changelog/versions/v090.md index 9ffbe3d98..49be1d202 100644 --- a/ui/v2.5/src/components/Changelog/versions/v090.md +++ b/ui/v2.5/src/components/Changelog/versions/v090.md @@ -12,6 +12,7 @@ * Added not equals/greater than/less than modifiers for resolution criteria. ([#1568](https://github.com/stashapp/stash/pull/1568)) ### 🎨 Improvements +* Added support for loading TLS/SSL configuration files from the configuration directory. ([#1678](https://github.com/stashapp/stash/pull/1678)) * Added total scenes duration to Stats page. ([#1626](https://github.com/stashapp/stash/pull/1626)) * Move Play Selected Scenes, and Add/Remove Gallery Image buttons to button toolbar. ([#1673](https://github.com/stashapp/stash/pull/1673)) * Added image and gallery counts to tag list view. ([#1672](https://github.com/stashapp/stash/pull/1672))