{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} module Main (main) where import Amazonka.IAM.Policy (Policy, Statement) import Data.Aeson (FromJSON) import Data.Semigroup ((<>)) import qualified Amazonka.IAM.Policy as Policy import qualified Data.Aeson as JSON import qualified Data.ByteString.Lazy as LBS import qualified Paths_amazonka_iam_policy as Path import qualified System.IO.Error as IO import qualified Test.Hspec as Hspec main :: IO () main = Hspec.hspec $ do test "iam-policy-simulator.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:GetGroup" , "iam:GetGroupPolicy" , "iam:GetPolicy" , "iam:GetPolicyVersion" , "iam:GetRole" , "iam:GetRolePolicy" , "iam:GetUser" , "iam:GetUserPolicy" , "iam:ListAttachedGroupPolicies" , "iam:ListAttachedRolePolicies" , "iam:ListAttachedUserPolicies" , "iam:ListGroups" , "iam:ListGroupPolicies" , "iam:ListGroupsForUser" , "iam:ListRolePolicies" , "iam:ListRoles" , "iam:ListUserPolicies" , "iam:ListUsers" ] , Policy.resource = Policy.any }) test "iam-policy-simulator.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:GetGroup" , "iam:GetGroupPolicy" , "iam:GetPolicy" , "iam:GetPolicyVersion" , "iam:GetRole" , "iam:GetRolePolicy" , "iam:GetUser" , "iam:GetUserPolicy" , "iam:ListAttachedGroupPolicies" , "iam:ListAttachedRolePolicies" , "iam:ListAttachedUserPolicies" , "iam:ListGroups" , "iam:ListGroupPolicies" , "iam:ListGroupsForUser" , "iam:ListRolePolicies" , "iam:ListRoles" , "iam:ListUserPolicies" , "iam:ListUsers" ] , Policy.resource = Policy.any }) test "iam-user-rotate-credentials.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:ListUsers" , "iam:GetAccountPasswordPolicy" ] , Policy.resource = Policy.any }) <> Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:*AccessKey*" , "iam:ChangePassword" , "iam:GetUser" , "iam:*ServiceSpecificCredential*" , "iam:*SigningCertificate*" ] , Policy.resource = Policy.some [ "arn:aws:iam::*:user/${aws:username}" ] }) test "policy-simulator-api.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:GetContextKeysForCustomPolicy" , "iam:GetContextKeysForPrincipalPolicy" , "iam:SimulateCustomPolicy" , "iam:SimulatePrincipalPolicy" ] , Policy.resource = Policy.any }) test "policy-simulator-console.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:GetPolicy" , "iam:GetUserPolicy" ] , Policy.resource = Policy.any }) <> Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:GetUser" , "iam:ListAttachedUserPolicies" , "iam:ListGroupsForUser" , "iam:ListUserPolicies" , "iam:ListUsers" ] , Policy.resource = Policy.some [ "arn:aws:iam:::user//*" ] }) test "rds-region-admin.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some ["rds:*"] , Policy.resource = Policy.some [ "arn:aws:rds:::*" ] }) <> Policy.singleton (Policy.allow { Policy.action = Policy.some ["rds:Describe*"] , Policy.resource = Policy.any }) test "self-managed-mfa.json" $ Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:CreateVirtualMFADevice" , "iam:EnableMFADevice" , "iam:ResyncMFADevice" , "iam:DeleteVirtualMFADevice" ] , Policy.resource = Policy.some [ "arn:aws:iam::*:mfa/${aws:username}" , "arn:aws:iam::*:user/${aws:username}" ] }) <> Policy.singleton (Policy.allow { Policy.sid = Just "AllowUsersToDeactivateTheirOwnVirtualMFADevice" , Policy.action = Policy.some [ "iam:DeactivateMFADevice" ] , Policy.resource = Policy.some [ "arn:aws:iam::*:mfa/${aws:username}" , "arn:aws:iam::*:user/${aws:username}" ] , Policy.condition = Just $ Policy.Bool "aws:MultiFactorAuthPresent" True }) <> Policy.singleton (Policy.allow { Policy.action = Policy.some [ "iam:ListMFADevices" , "iam:ListVirtualMFADevices" , "iam:ListUsers" ] , Policy.resource = Policy.any }) test :: String -> Policy Statement -> Hspec.Spec test name actual = Hspec.describe name $ Hspec.it "should equal the serialized haskell value" $ parseFile ("test/golden/" ++ name) >>= Hspec.shouldBe actual parseFile :: FromJSON a => String -> IO a parseFile name = do path <- Path.getDataFileName name lbs <- LBS.readFile path case JSON.eitherDecode' lbs of Right x -> pure x Left e -> IO.ioError $ IO.userError ("Failed parsing " ++ path ++ ": " ++ e)