propellor

propellor config for hosts.
git clone git://git.ricketyspace.net/propellor.git
Log | Files | Refs | LICENSE

Sudo.hs (2496B)


      1 module Propellor.Property.Sudo where
      2 
      3 import Data.List
      4 
      5 import Propellor.Base
      6 import Propellor.Property.File
      7 import qualified Propellor.Property.Apt as Apt
      8 import Propellor.Property.User
      9 
     10 -- | Allows a user to run any command with sudo.
     11 -- If the user has a password, sudo is configured to require it.
     12 -- If not, NOPASSWORD is enabled for the user.
     13 --
     14 -- Writes to the file /etc/sudoers.d/000users rather than the main sudoers
     15 -- file. This file should come before other include files that may eg,
     16 -- allow running more specific commands without a password, since sudo
     17 -- uses the last matching configuration line.
     18 --
     19 -- If the main sudoers file contains a conflicting line for
     20 -- the user for ALL commands, the line will be removed.
     21 --
     22 -- Also ensures that the main sudoers file includes /etc/sudoers.d/
     23 enabledFor :: User -> RevertableProperty DebianLike DebianLike
     24 enabledFor user@(User u) = setup `requires` Apt.installed ["sudo"] <!> cleanup
     25   where
     26 	setup :: Property UnixLike
     27 	setup = property' desc $ \w -> do
     28 		locked <- liftIO $ isLockedPassword user
     29 		ensureProperty w $ combineProperties desc $ props
     30 			& containsLine sudoers "#includedir /etc/sudoers.d"
     31 			& fileProperty desc
     32 				(modify locked . filter (wanted locked))
     33 				dfile
     34 			& removeconflicting sudoers
     35 	  where
     36 		desc = u ++ " is sudoer"
     37 	
     38 	cleanup :: Property DebianLike
     39 	cleanup = tightenTargets $ combineProperties desc $ props
     40 		& removeconflicting sudoers
     41 		& removeconflicting dfile
     42 	  where
     43 		desc = u ++ " is not sudoer"
     44 	
     45 	removeconflicting = fileProperty "remove conflicting" (filter notuserline)
     46 
     47 	sudoers = "/etc/sudoers"
     48 	dfile = "/etc/sudoers.d/000users"
     49 	sudobaseline = u ++ " ALL=(ALL:ALL)"
     50 	notuserline l = not (sudobaseline `isPrefixOf` l)
     51 	sudoline True = sudobaseline ++ " NOPASSWD:ALL"
     52 	sudoline False = sudobaseline ++ " ALL"
     53 	wanted locked l
     54 		| notuserline l = True
     55 		| "NOPASSWD" `isInfixOf` l = locked
     56 		| otherwise = True
     57 	modify locked ls
     58 		| sudoline locked `elem` ls = ls
     59 		| otherwise = ls ++ [sudoline locked]
     60 
     61 -- | Sets up a file in /etc/sudoers.d/, which /etc/sudoers includes,
     62 -- with the specified content.
     63 --
     64 -- The FilePath can be relative to that directory.
     65 sudoersDFile :: FilePath -> [Line] -> RevertableProperty DebianLike Linux
     66 sudoersDFile dfile content = setup `requires` Apt.installed ["sudo"] <!> cleanup
     67   where
     68 	f = "/etc/sudoers.d" </> dfile
     69 	-- sudoers.d files should not be world readable
     70 	setup = hasContentProtected f content
     71 	cleanup = tightenTargets $ notPresent f