{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE MultiParamTypeClasses #-} module Deploy.HostSectionKey ( HostID(..) , SectionID(..) , KeyID(..) , sections ) where import Data.KeyStore import qualified Data.Text as T import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as LBS import qualified Text.RawString.QQ as RS import Control.Monad.RWS.Strict import Text.Printf data HostID = H_live_eu | H_staging_eu | H_live_us | H_staging_us | H_dev deriving (Show, Ord, Eq, Bounded, Enum) data SectionID = S_top | S_signing | S_eu_admin | S_eu_deploy | S_eu_staging | S_us_admin | S_us_deploy | S_us_staging | S_dev deriving (Show, Ord, Eq, Bounded, Enum) dev, staging, deploy, admin :: SectionID -> Bool dev = (`elem` [S_dev ] ) staging = (`elem` [S_eu_staging,S_us_staging] ) deploy = (`elem` [S_eu_deploy ,S_us_deploy ] ) admin = (`elem` [S_eu_admin ,S_us_admin ] ) data KeyID = K_admin_init_pw | K_super_api | K_api | K_cloudfront | K_s3 | K_mail | K_logger | K_ssl deriving (Show,Eq,Ord,Bounded,Enum) instance Code HostID where encode = drop 2 . show instance Code SectionID where encode = drop 2 . show instance Code KeyID where encode = drop 2 . show instance Sections HostID SectionID KeyID where hostDeploySection = host_deploy_section sectionType = section_type superSections = super_sections keyIsHostIndexed = key_is_host_indexed keyIsInSection = key_is_in_section getKeyData = get_key_data sectionSettings = section_settings describeKey = describe_key describeSection = describe_section sections :: SECTIONS HostID SectionID KeyID sections = SECTIONS host_deploy_section :: HostID -> SectionID host_deploy_section h = case h of H_live_eu -> S_eu_admin H_staging_eu -> S_eu_staging H_live_us -> S_us_admin H_staging_us -> S_us_staging H_dev -> S_dev section_type :: SectionID -> SectionType section_type s = case s of S_top -> ST_top S_signing -> ST_signing _ -> ST_keys super_sections :: SectionID -> [SectionID] super_sections s = case s of S_top -> [ ] S_signing -> [S_top ] S_eu_admin -> [S_top ] S_eu_deploy -> [S_eu_admin ] S_eu_staging -> [S_eu_deploy ] S_us_admin -> [S_top ] S_us_deploy -> [S_us_admin ] S_us_staging -> [S_us_deploy ] S_dev -> [S_eu_staging,S_us_staging] key_is_host_indexed :: KeyID -> Maybe (HostID->Bool) key_is_host_indexed k = case k of K_ssl -> Just is_ssl _ -> Nothing key_is_in_section :: KeyID -> SectionID -> Bool key_is_in_section k = case k of K_admin_init_pw -> f [dev,staging ,admin] K_super_api -> f [dev,staging ,admin] K_api -> f [dev,staging,deploy ] K_cloudfront -> f [dev ,deploy ] K_s3 -> f [dev,staging,deploy ] K_mail -> f [dev ,deploy ] K_logger -> f [dev ] K_ssl -> f [dev,staging,deploy ] where f = foldr (\p p' s->p s || p' s) (const False) generation :: String generation = "first" get_key_data :: Maybe HostID -> SectionID -> KeyID -> IO KeyData get_key_data mb_h s k = return KeyData { kd_identity = Identity $ T.pack $ mk "id" , kd_comment = Comment $ T.pack $ mk "comment" , kd_secret = B.pack $ mk "secret" } where mk tag = printf "%s:%s-%s-%s:%s" (tag::String ) (maybe "*" encode mb_h) (encode s ) (encode k ) generation section_settings :: Maybe SectionID -> IO Settings section_settings Nothing = e2io $ settingsFromBytes ourSettings section_settings (Just _) = return mempty ourSettings :: LBS.ByteString ourSettings = [RS.r| { "debug.enabled" : true , "verify.enabled" : true , "hash.comment" : "pbkdf_sha512_20000_64" , "hash.prf" : "sha512" , "hash.iterations" : 1 , "hash.width_octets": 64 , "hash.salt_octets" : 16 , "crypt.cipher" : "aes256" , "crypt.prf" : "sha512" , "crypt.iterations" : 1 , "crypt.salt_octets": 16 } |] describe_key :: KeyID -> String describe_key k = case k of K_admin_init_pw -> "the starting password for the administrator" K_super_api -> "the 'super_api' key will authenticate any request" K_api -> "the api key is needed to make requests when the client has not credentials (e.g., to login)" K_cloudfront -> "the AWS CloudFront signing key" K_s3 -> "the AWS S3 access key" K_mail -> "the sendmail access key" K_logger -> "the access key for the logging service" K_ssl -> "the SSL Host key and certificate" describe_section :: SectionID -> String describe_section s = case s of S_top -> "the top section has access to all keys" S_signing -> "just contains the keystore signing key" S_eu_admin -> "contains adminsitrative keys for the 'eu' live server not required for deployment" ++ "(e.g., the 'super_api' key)" S_eu_deploy -> "has access to all of the keys needed for the 'eu' live server deployment" S_eu_staging -> "has access to all of the keys needed for the 'eu' staging server deployment" S_us_admin -> "contains adminsitrative keys for the 'us' live server not required for deployment" ++ "(e.g., the 'super_api' key)" S_us_deploy -> "has access to all of the keys needed for the 'us' live server deployment" S_us_staging -> "has access to all of the keys needed for the 'us' staging server deployment" S_dev -> "contains all of the keys needed to deploy a development server" is_ssl :: HostID -> Bool is_ssl h = case h of H_live_eu -> True H_staging_eu -> True H_live_us -> True H_staging_us -> True H_dev -> False