A-gent-0.11.0.6: src/Agent/Control/MAC.hs
{-# OPTIONS_GHC -Wall -Werror #-}
{-# LANGUAGE NoGeneralizedNewtypeDeriving #-}
{-# LANGUAGE Safe #-}
--------------------------------------------------------------------------------
-- |
-- Copyright : (c) 2026 SPISE MISU ApS
-- License : SSPL-1.0 OR AGPL-3.0-only
-- Maintainer : SPISE MISU <mail+hackage@spisemisu.com>
-- Stability : experimental
--
-- Mandatory Access Control (MAC)
--
-- https://en.wikipedia.org/wiki/Mandatory_access_control
--
-- In computer security, mandatory access control (MAC) refers to a type of
-- access control by which the operating system or database constrains the
-- ability of a subject or initiator to access or generally perform some sort of
-- operation on an object or target.[1] In the case of operating systems, a
-- subject is usually a process or thread; objects are constructs such as files,
-- directories, TCP/UDP ports, shared memory segments, IO devices, etc. Subjects
-- and objects each have a set of security attributes. Whenever a subject
-- attempts to access an object, an authorization rule enforced by the operating
-- system kernel examines these security attributes and decides whether the
-- access can take place. Any operation by any subject on any object is tested
-- against the set of authorization rules (aka policy) to determine if the
-- operation is allowed. A database management system, in its access control
-- mechanism, can also apply mandatory access control; in this case, the objects
-- are tables, views, procedures, etc.
--
-- With mandatory access control, this security policy is centrally controlled
-- by a security policy administrator; users do not have the ability to override
-- the policy and, for example, grant access to files that would otherwise be
-- restricted. By contrast, discretionary access control (DAC), which also
-- governs the ability of subjects to access objects, allows users the ability
-- to make policy decisions and/or assign security attributes. (The traditional
-- Unix system of users, groups, and read-write-execute permissions is an
-- example of DAC.) MAC-enabled systems allow policy administrators to implement
-- organization-wide security policies. Under MAC (and unlike DAC), users cannot
-- override or modify this policy, either accidentally or intentionally. This
-- allows security administrators to define a central policy that is guaranteed
-- (in principle) to be enforced for all users.
--
-- [1] Belim, S. V.; Belim, S. Yu. (December 2018). "Implementation of Mandatory
-- Access Control in Distributed Systems". Automatic Control and Computer
-- Sciences. 52 (8): 1124–1126. doi:10.3103/S0146411618080357. ISSN 0146-4116.
--------------------------------------------------------------------------------
module Agent.Control.MAC
( MAC (MAC, run)
, UID (UID, uid)
, RES (RES, res)
, join
, label
, unlabel
, value
)
where
--------------------------------------------------------------------------------
import Control.Monad ( ap, liftM )
import Control.Exception ( Exception, SomeException )
import qualified Control.Exception as Ex
import Agent.Control.IFC ( Flow )
--------------------------------------------------------------------------------
newtype MAC p a = MAC { run :: IO a }
instance Monad (MAC p) where
(>>=) m f = MAC $ run m >>= run . f
instance Applicative (MAC p) where
pure = MAC . pure
(<*>) = ap
instance Functor (MAC p) where
fmap = liftM
--------------------------------------------------------------------------------
-- UID: Unique identifier
-- RES: Resource
-- LAB: Label
newtype UID a = UID { uid :: a }
newtype RES p a = RES { res :: a }
type LAB p a = RES p ( UID a )
--------------------------------------------------------------------------------
value
:: LAB l a
-> a
value =
uid . res
label
:: Flow l h
=> a
-> MAC l (LAB h a)
label =
aux . pure . UID
where
aux io = RES <$> MAC io
unlabel
:: Flow l h
=> LAB l a
-> MAC h a
unlabel =
aux $ pure . uid
where
aux io = MAC . io . res
join
:: Flow l h
=> MAC h a
-> MAC l (LAB h a)
join m =
(MAC . run) (aux m) >>= label
where
aux x = catch x throw
--------------------------------------------------------------------------------
-- HELPERS
throw
:: SomeException
-> MAC l a
throw =
MAC . Ex.throw
catch
:: Exception e
=> MAC l a
-> (e -> MAC l a)
-> MAC l a
catch (MAC io) f =
MAC $ Ex.catch io $ run . f