From b0c5ffbe1d2dbbf1f9c460be0b4f18500c50a90f Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Thu, 1 Dec 2016 22:32:09 +0300 Subject: BREAKING: Allow !include in config file This changes semantics of these options: - key - oauth2..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. --- sproxy.yml.example | 16 ++++++++-------- src/Sproxy/Config.hs | 4 ++-- src/Sproxy/Server.hs | 21 ++++++--------------- 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 -- cgit v1.2.3