Commit c7c42554 authored by Hrvoje Ribicic's avatar Hrvoje Ribicic

Modify UDS server startup to set permissions for sockets

When opening domain sockets for communication, the Haskell daemons did
not set any permissions for the sockets, defaulting to 0700. This was
fine when all of them ran as root, but was bound to cause trouble in a
split-user setup. The first issue is RAPI access after master-failover,
where RAPI could not send make any inquiries until the watcher restored
the desired permissions of the socket.

This patch modifies Luxid to use a g+rw socket, and leaves other servers
to their default of 0600.
Signed-off-by: default avatarHrvoje Ribicic <riba@google.com>
Reviewed-by: default avatarKlaus Aehlig <aehlig@google.com>
parent ee0ea7d6
......@@ -123,6 +123,7 @@ import Ganeti.Path
import Ganeti.Query.Exec as Exec
import Ganeti.Rpc (executeRpcCall, ERpcError, logRpcErrors,
RpcCallJobqueueUpdate(..), RpcCallJobqueueRename(..))
import Ganeti.Runtime (GanetiDaemon(..), GanetiGroup(..), MiscGroup(..))
import Ganeti.Types
import Ganeti.Utils
import Ganeti.Utils.Atomic
......@@ -643,8 +644,8 @@ notifyJob pid = runResultT $ do
-- | Permissions for the archive directories.
queueDirPermissions :: FilePermissions
queueDirPermissions = FilePermissions { fpOwner = Just C.masterdUser
, fpGroup = Just C.daemonsGroup
queueDirPermissions = FilePermissions { fpOwner = Just GanetiMasterd
, fpGroup = Just $ ExtraGroup DaemonsGroup
, fpPermissions = 0o0750
}
......
......@@ -76,10 +76,11 @@ import Ganeti.UDSServer
import Ganeti.OpParams (pTagsObject)
import Ganeti.OpCodes
import qualified Ganeti.Query.Language as Qlang
import Ganeti.Runtime (GanetiDaemon(..))
import Ganeti.Runtime (GanetiDaemon(..), GanetiGroup(..), MiscGroup(..))
import Ganeti.THH
import Ganeti.THH.Field
import Ganeti.Types
import Ganeti.Utils
-- | Currently supported Luxi operations and JSON serialization.
......@@ -181,7 +182,13 @@ $(genStrOfOp ''LuxiOp "strOfOp")
luxiConnectConfig :: ServerConfig
luxiConnectConfig = ServerConfig GanetiLuxid
luxiConnectConfig = ServerConfig
-- The rapi daemon talks to the luxi one, and for this
-- purpose we need group rw permissions.
FilePermissions { fpOwner = Just GanetiLuxid
, fpGroup = Just $ ExtraGroup DaemonsGroup
, fpPermissions = 0o0660
}
ConnectConfig { recvTmo = luxiDefRwto
, sendTmo = luxiDefRwto
}
......
......@@ -43,9 +43,10 @@ import System.IO.Error (isEOFError)
import Ganeti.Path as Path
import Ganeti.Daemon (DaemonOptions, cleanupSocket, describeError)
import qualified Ganeti.Logging as Logging
import Ganeti.Runtime (GanetiDaemon(..))
import Ganeti.Runtime (GanetiDaemon(..), GanetiGroup(..), MiscGroup(..))
import Ganeti.UDSServer (Client, ConnectConfig(..), Server, ServerConfig(..))
import qualified Ganeti.UDSServer as UDSServer
import Ganeti.Utils (FilePermissions(..))
import Ganeti.Metad.Config as Config
import Ganeti.Metad.Types (InstanceParams)
......@@ -100,4 +101,15 @@ start _ config = do
(acceptClients config server)
(UDSServer.closeServer server)
where
metadConfig = ServerConfig GanetiMetad $ ConnectConfig 60 60
metadConfig =
ServerConfig
-- The permission 0600 is completely acceptable because only the node
-- daemon talks to the metadata daemon, and the node daemon runs as
-- root.
FilePermissions { fpOwner = Just GanetiMetad
, fpGroup = Just $ ExtraGroup DaemonsGroup
, fpPermissions = 0o0600
}
ConnectConfig { recvTmo = 60
, sendTmo = 60
}
......@@ -98,7 +98,6 @@ import Ganeti.BasicTypes
import Ganeti.Errors (GanetiException(..), ErrorResult)
import Ganeti.JSON
import Ganeti.Logging
import Ganeti.Runtime (GanetiDaemon(..), MiscGroup(..), GanetiGroup(..))
import Ganeti.THH
import Ganeti.Utils
import Ganeti.Constants (privateParametersBlacklist)
......@@ -143,7 +142,7 @@ $(genStrOfKey ''MsgKeys "strOfKey")
-- Information required for creating a server connection.
data ServerConfig = ServerConfig
{ connDaemon :: GanetiDaemon
{ connPermissions :: FilePermissions
, connConfig :: ConnectConfig
}
......@@ -226,8 +225,10 @@ connectClient conf tmo path = do
connectServer :: ServerConfig -> Bool -> FilePath -> IO Server
connectServer sconf setOwner path = do
s <- openServerSocket path
when setOwner . setOwnerAndGroupFromNames path (connDaemon sconf) $
ExtraGroup DaemonsGroup
when setOwner $ do
res <- ensurePermissions path (connPermissions sconf)
exitIfBad "Error - could not set socket properties" res
S.listen s 5 -- 5 is the max backlog
return Server { sSocket = s, sPath = path, serverConfig = connConfig sconf }
......
......@@ -122,7 +122,6 @@ import System.IO
import System.Exit
import System.Posix.Files
import System.Posix.IO
import System.Posix.User
import System.Time
-- * Debug functions
......@@ -694,8 +693,8 @@ watchFile fpath timeout old = watchFileBy fpath timeout (/= old)
-- directories and files. All parameters are optional, with nothing
-- meaning that the default value should be left untouched.
data FilePermissions = FilePermissions { fpOwner :: Maybe String
, fpGroup :: Maybe String
data FilePermissions = FilePermissions { fpOwner :: Maybe GanetiDaemon
, fpGroup :: Maybe GanetiGroup
, fpPermissions :: FileMode
}
......@@ -703,22 +702,29 @@ data FilePermissions = FilePermissions { fpOwner :: Maybe String
-- possibly ownerships, as required.
ensurePermissions :: FilePath -> FilePermissions -> IO (Result ())
ensurePermissions fpath perms = do
-- Fetch the list of entities
runtimeEnts <- runResultT getEnts
ents <- exitIfBad "Can't determine user/group ids" runtimeEnts
-- Get the existing file properties
eitherFileStatus <- try $ getFileStatus fpath
:: IO (Either IOError FileStatus)
-- And see if any modifications are needed
(flip $ either (return . Bad . show)) eitherFileStatus $ \fstat -> do
ownertry <- case fpOwner perms of
Nothing -> return $ Right ()
Just owner -> try $ do
ownerid <- userID `liftM` getUserEntryForName owner
let ownerid = reUserToUid ents M.! owner
unless (ownerid == fileOwner fstat) $ do
logDebug $ "Changing owner of " ++ fpath ++ " to " ++ owner
logDebug $ "Changing owner of " ++ fpath ++ " to " ++ show owner
setOwnerAndGroup fpath ownerid (-1)
grouptry <- case fpGroup perms of
Nothing -> return $ Right ()
Just grp -> try $ do
groupid <- groupID `liftM` getGroupEntryForName grp
let groupid = reGroupToGid ents M.! grp
unless (groupid == fileGroup fstat) $ do
logDebug $ "Changing group of " ++ fpath ++ " to " ++ grp
logDebug $ "Changing group of " ++ fpath ++ " to " ++ show grp
setOwnerAndGroup fpath (-1) groupid
let fp = fpPermissions perms
permtry <- if fileMode fstat == fp
......
......@@ -55,6 +55,7 @@ import Ganeti.THH.RPC
import Ganeti.UDSServer
import Ganeti.Errors (formatError)
import Ganeti.Runtime
import Ganeti.Utils
import Ganeti.Utils.Livelock (mkLivelockFile)
import Ganeti.WConfd.ConfigState
import Ganeti.WConfd.ConfigVerify
......@@ -109,7 +110,17 @@ prepMain _ _ = do
return (s, dh)
serverConfig :: ServerConfig
serverConfig = ServerConfig GanetiWConfd $ ConnectConfig 60 60
serverConfig = ServerConfig
-- All the daemons that need to talk to WConfd should be
-- running as the same user - the former master daemon user.
FilePermissions { fpOwner = Just GanetiWConfd
, fpGroup = Just $ ExtraGroup DaemonsGroup
, fpPermissions = 0o0600
}
ConnectConfig { recvTmo = 60
, sendTmo = 60
}
-- | Main function.
main :: MainFn () PrepResult
......
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