aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2016-12-01 22:32:09 +0300
committerIgor Pashev <pashev.igor@gmail.com>2016-12-01 22:43:08 +0300
commitb0c5ffbe1d2dbbf1f9c460be0b4f18500c50a90f (patch)
tree41417f4dd08e3fc541b02ac07cc0e9494a8fceb5
parented878508e2425ae902a7427b4e7726d35f8d29ce (diff)
downloadsproxy2-b0c5ffbe1d2dbbf1f9c460be0b4f18500c50a90f.tar.gz
BREAKING: Allow !include in config file
This changes semantics of these options: - key - oauth2.<provider>.client_secret They are no longer files, but strings. To read content from files, use !include. The point of being files or read from files is to segregate secrets from non-sensitive easily discoverable settings. With !include it is much more simple and flexible.
-rw-r--r--sproxy.yml.example16
-rw-r--r--src/Sproxy/Config.hs4
-rw-r--r--src/Sproxy/Server.hs21
3 files changed, 16 insertions, 25 deletions
diff --git a/sproxy.yml.example b/sproxy.yml.example
index 1df82aa..a9cf9cc 100644
--- a/sproxy.yml.example
+++ b/sproxy.yml.example
@@ -1,5 +1,7 @@
--- # Sproxy configuration. Don't remove this line. This is YAML: https://en.wikipedia.org/wiki/YAML
+# NOTE: You can use the !include directive to import parts of this file.
+
# Logging level: debug, info, warn, error.
# Optional. Default is debug.
#
@@ -101,34 +103,32 @@ ssl_key: /path/key.pem
# datafile: /path/data.yml
-# A file with arbitrary content used to sign sproxy cookie and other things (secret!).
+# Arbitrary string used to sign sproxy cookie and other things (secret!).
# Optional. If not specified, a random key is generated on startup, and
# as a consequence, restaring sproxy will invalidate existing user sessions.
# This option could be useful for load-balancing with multiple sproxy instances,
# when all instances must understand cookies created by each other.
# This should not be very large, a few random bytes are fine.
#
-# key: /run/keys/sproxy.secret
+# key: !include /run/keys/sproxy.secret
# Credentials for supported OAuth2 providers.
# Currently supported: "google", "linkedin"
# At least one provider is required.
# Attributes:
-# client_id - OAuth2 client ID (string)
-# client_secret - OAuth2 client secret. Regardless of its name, this is a file.
-# The secret is read from the file which you should keep secret.
-# Only the first line of this file is read.
+# client_id - OAuth2 client ID.
+# client_secret - OAuth2 client secret.
#
# Example:
# oauth2:
# google:
# client_id: "XXXXXXXXXXXX-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.apps.googleusercontent.com"
-# client_secret: "/run/keys/XXXXXXXXXXXX-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.apps.googleusercontent.com"
+# client_secret: !include /run/keys/XXXXXXXXXXXX-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.apps.googleusercontent.com
#
# linkedin:
# client_id: "xxxxxxxxxxxxxx"
-# client_secret: "/run/keys/xxxxxxxxxxxxxx"
+# client_secret: !include "/run/keys/xxxxxxxxxxxxxx"
#
#
# oauth2:
diff --git a/src/Sproxy/Config.hs b/src/Sproxy/Config.hs
index 4cae025..e0f35a3 100644
--- a/src/Sproxy/Config.hs
+++ b/src/Sproxy/Config.hs
@@ -24,7 +24,7 @@ data ConfigFile = ConfigFile {
, cfSslCert :: Maybe FilePath
, cfSslKey :: Maybe FilePath
, cfSslCertChain :: [FilePath]
-, cfKey :: Maybe FilePath
+, cfKey :: Maybe String
, cfListen80 :: Maybe Bool
, cfHttpsPort :: Maybe Word16
, cfBackends :: [BackendConf]
@@ -83,7 +83,7 @@ instance FromJSON BackendConf where
data OAuth2Conf = OAuth2Conf {
oa2ClientId :: String
-, oa2ClientSecret :: FilePath
+, oa2ClientSecret :: String
} deriving (Show)
instance FromJSON OAuth2Conf where
diff --git a/src/Sproxy/Server.hs b/src/Sproxy/Server.hs
index 6e24bfd..7b65f32 100644
--- a/src/Sproxy/Server.hs
+++ b/src/Sproxy/Server.hs
@@ -5,13 +5,12 @@ module Sproxy.Server (
import Control.Concurrent (forkIO)
import Control.Exception (bracketOnError)
import Control.Monad (void, when)
-import Data.ByteString as BS (hGetLine, readFile)
import Data.ByteString.Char8 (pack)
import Data.HashMap.Strict as HM (fromList, lookup, toList)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Word (Word16)
-import Data.Yaml (decodeFileEither)
+import Data.Yaml.Include (decodeFileEither)
import Network.HTTP.Client (Manager, ManagerSettings(..), defaultManagerSettings, newManager, socketConnection)
import Network.HTTP.Client.Internal (Connection)
import Network.Socket ( Socket, Family(AF_INET, AF_UNIX), SockAddr(SockAddrInet, SockAddrUnix),
@@ -25,7 +24,7 @@ import System.Entropy (getEntropy)
import System.Environment (setEnv)
import System.Exit (exitFailure)
import System.FilePath.Glob (compile)
-import System.IO (IOMode(ReadMode), hIsEOF, hPutStrLn, stderr, withFile)
+import System.IO (hPutStrLn, stderr)
import System.Posix.User ( GroupEntry(..), UserEntry(..),
getAllGroupEntries, getRealUserID,
getUserEntryForName, setGroupID, setGroups, setUserID )
@@ -47,7 +46,6 @@ server :: FilePath -> IO ()
server configFile = do
cf <- readConfigFile configFile
Log.start $ cfLogLevel cf
- Log.debug $ show cf
sock <- socket AF_INET Stream 0
setSocketOption sock ReuseAddr 1
@@ -78,7 +76,7 @@ server configFile = do
key <- maybe
(Log.info "using new random key" >> getEntropy 32)
- (\f -> Log.info ("reading key from " ++ f) >> BS.readFile f)
+ (return . pack)
(cfKey cf)
let
@@ -139,16 +137,9 @@ newOAuth2Client (name, cfg) =
exitFailure
Just provider -> do
Log.info $ "oauth2: adding " ++ show name
- client_secret <- withFile secret_file ReadMode $ \h -> do
- empty <- hIsEOF h
- if empty then do
- Log.error $ "oauth2: empty secret file for "
- ++ show name ++ ": " ++ show secret_file
- return $ pack ""
- else BS.hGetLine h
- return (name, provider (pack client_id, client_secret))
- where client_id = oa2ClientId cfg
- secret_file = oa2ClientSecret cfg
+ return (name, provider (client_id, client_secret))
+ where client_id = pack $ oa2ClientId cfg
+ client_secret = pack $ oa2ClientSecret cfg
newBackendManager :: BackendConf -> IO Manager