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
-- | 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
}
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.
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
}
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)
(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
+ }
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)
-- Information required for creating a server connection.
data ServerConfig = ServerConfig
- { connDaemon :: GanetiDaemon
+ { connPermissions :: FilePermissions
, connConfig :: ConnectConfig
}
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 }
import System.Exit
import System.Posix.Files
import System.Posix.IO
-import System.Posix.User
import System.Time
-- * Debug functions
-- 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
}
-- 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
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
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