diff --git a/code/hsec-core/src/Security/Advisories/Core/Advisory.hs b/code/hsec-core/src/Security/Advisories/Core/Advisory.hs index ca3f317..546f913 100644 --- a/code/hsec-core/src/Security/Advisories/Core/Advisory.hs +++ b/code/hsec-core/src/Security/Advisories/Core/Advisory.hs @@ -10,7 +10,7 @@ module Security.Advisories.Core.Advisory , AffectedVersionRange(..) , OS(..) , Keyword(..) - , Ecosystem(..) + , ComponentIdentifier(..) , GHCComponent(..) , ghcComponentToText , ghcComponentFromText @@ -48,7 +48,7 @@ data Advisory = Advisory } deriving stock (Show) -data Ecosystem = Hackage Text | GHC GHCComponent +data ComponentIdentifier = Hackage Text | GHC GHCComponent deriving stock (Show, Eq) -- Keep this list in sync with the 'ghcComponentFromText' below @@ -71,7 +71,7 @@ ghcComponentFromText c = case c of -- | An affected package (or package component). An 'Advisory' must -- mention one or more packages. data Affected = Affected - { affectedEcosystem :: Ecosystem + { affectedComponentIdentifier :: ComponentIdentifier , affectedCVSS :: CVSS.CVSS , affectedVersions :: [AffectedVersionRange] , affectedArchitectures :: Maybe [Architecture] diff --git a/code/hsec-tools/app/Main.hs b/code/hsec-tools/app/Main.hs index 95ec61a..2163aea 100644 --- a/code/hsec-tools/app/Main.hs +++ b/code/hsec-tools/app/Main.hs @@ -23,7 +23,7 @@ import Security.Advisories.Generate.HTML import Security.Advisories.Generate.Snapshot import Security.Advisories.Git import Security.Advisories.Queries (listVersionRangeAffectedBy) -import Security.Advisories.Filesystem (parseEcosystem) +import Security.Advisories.Filesystem (parseComponentIdentifier) import System.Exit (die, exitFailure, exitSuccess) import System.FilePath (takeBaseName) import System.IO (hPrint, hPutStrLn, stderr) @@ -169,13 +169,13 @@ withAdvisory go file = do oob <- runExceptT $ case file of Nothing -> throwE StdInHasNoOOB Just path -> do - ecosystem <- parseEcosystem path + ecosystem <- parseComponentIdentifier path withExceptT GitHasNoOOB $ do gitInfo <- ExceptT $ liftIO $ getAdvisoryGitInfo path pure OutOfBandAttributes { oobPublished = firstAppearanceCommitDate gitInfo , oobModified = lastModificationCommitDate gitInfo - , oobEcosystem = ecosystem + , oobComponentIdentifier = ecosystem } case parseAdvisory NoOverrides oob input of diff --git a/code/hsec-tools/src/Security/Advisories/Convert/OSV.hs b/code/hsec-tools/src/Security/Advisories/Convert/OSV.hs index 10be948..c63e0e7 100644 --- a/code/hsec-tools/src/Security/Advisories/Convert/OSV.hs +++ b/code/hsec-tools/src/Security/Advisories/Convert/OSV.hs @@ -30,14 +30,14 @@ convert adv = mkAffected :: Affected -> OSV.Affected Void Void Void mkAffected aff = OSV.Affected - { OSV.affectedPackage = mkPackage (affectedEcosystem aff) + { OSV.affectedPackage = mkPackage (affectedComponentIdentifier aff) , OSV.affectedRanges = pure $ mkRange (affectedVersions aff) , OSV.affectedSeverity = [OSV.Severity (affectedCVSS aff)] , OSV.affectedEcosystemSpecific = Nothing , OSV.affectedDatabaseSpecific = Nothing } -mkPackage :: Ecosystem -> OSV.Package +mkPackage :: ComponentIdentifier -> OSV.Package mkPackage ecosystem = OSV.Package { OSV.packageName = packageName , OSV.packageEcosystem = ecosystemName diff --git a/code/hsec-tools/src/Security/Advisories/Filesystem.hs b/code/hsec-tools/src/Security/Advisories/Filesystem.hs index 3f7a28e..897a7d2 100644 --- a/code/hsec-tools/src/Security/Advisories/Filesystem.hs +++ b/code/hsec-tools/src/Security/Advisories/Filesystem.hs @@ -21,7 +21,7 @@ module Security.Advisories.Filesystem , forAdvisory , listAdvisories , advisoryFromFile - , parseEcosystem + , parseComponentIdentifier ) where import Control.Applicative (liftA2) @@ -39,11 +39,11 @@ import System.Directory (doesDirectoryExist, pathIsSymbolicLink) import System.Directory.PathWalk import Validation (Validation (..)) -import Security.Advisories (Advisory, AttributeOverridePolicy (NoOverrides), OutOfBandAttributes (..), ParseAdvisoryError, parseAdvisory, Ecosystem(..)) +import Security.Advisories (Advisory, AttributeOverridePolicy (NoOverrides), OutOfBandAttributes (..), ParseAdvisoryError, parseAdvisory, ComponentIdentifier(..)) import Security.Advisories.Core.HsecId (HsecId, parseHsecId, placeholder) import Security.Advisories.Git(firstAppearanceCommitDate, getAdvisoryGitInfo, lastModificationCommitDate) import Control.Monad.Except (runExceptT, ExceptT (ExceptT), withExceptT) -import Security.Advisories.Parse (OOBError(GitHasNoOOB, PathHasNoEcosystem)) +import Security.Advisories.Parse (OOBError(GitHasNoOOB, PathHasNoComponentIdentifier)) import Security.Advisories.Core.Advisory (ghcComponentFromText) @@ -140,13 +140,13 @@ advisoryFromFile => FilePath -> m (Validation ParseAdvisoryError Advisory) advisoryFromFile advisoryPath = do oob <- runExceptT $ do - ecosystem <- parseEcosystem advisoryPath + ecosystem <- parseComponentIdentifier advisoryPath withExceptT GitHasNoOOB $ do gitInfo <- ExceptT $ liftIO $ getAdvisoryGitInfo advisoryPath pure OutOfBandAttributes { oobPublished = firstAppearanceCommitDate gitInfo , oobModified = lastModificationCommitDate gitInfo - , oobEcosystem = ecosystem + , oobComponentIdentifier = ecosystem } fileContent <- liftIO $ T.readFile advisoryPath pure @@ -176,9 +176,9 @@ _forFiles root go = Nothing -> pure mempty Just hsid -> go (dir file) hsid -parseEcosystem :: Monad m => FilePath -> ExceptT OOBError m (Maybe Ecosystem) -parseEcosystem fp = ExceptT . pure $ case drop 1 $ reverse $ splitDirectories fp of +parseComponentIdentifier :: Monad m => FilePath -> ExceptT OOBError m (Maybe ComponentIdentifier) +parseComponentIdentifier fp = ExceptT . pure $ case drop 1 $ reverse $ splitDirectories fp of package : "hackage" : _ -> pure (Just $ Hackage $ T.pack package) component : "ghc" : _ | Just ghc <- ghcComponentFromText (T.pack component) -> pure (Just $ GHC ghc) - _ : _ : "advisories" : _ -> Left PathHasNoEcosystem + _ : _ : "advisories" : _ -> Left PathHasNoComponentIdentifier _ -> pure Nothing diff --git a/code/hsec-tools/src/Security/Advisories/Format.hs b/code/hsec-tools/src/Security/Advisories/Format.hs index b7c58f0..a2fff80 100644 --- a/code/hsec-tools/src/Security/Advisories/Format.hs +++ b/code/hsec-tools/src/Security/Advisories/Format.hs @@ -154,7 +154,7 @@ instance Toml.FromValue Affected where decls <- maybe [] Map.toList <$> Toml.optKey "declarations" versions <- Toml.reqKey "versions" pure $ Affected - { affectedEcosystem = ecosystem + { affectedComponentIdentifier = ecosystem , affectedCVSS = cvss , affectedVersions = versions , affectedArchitectures = arch @@ -175,7 +175,7 @@ instance Toml.ToTable Affected where [ "arch" Toml..= y | Just y <- [affectedArchitectures x]] ++ [ "declarations" Toml..= asTable (affectedDeclarations x) | not (null (affectedDeclarations x))] where - ecosystem = case affectedEcosystem x of + ecosystem = case affectedComponentIdentifier x of Hackage pkg -> ["package" Toml..= pkg] GHC c -> ["ghc-component" Toml..= c] asTable kvs = Map.fromList [(T.unpack k, v) | (k,v) <- kvs] diff --git a/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs b/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs index e3e16ec..b28cfc6 100644 --- a/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs +++ b/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs @@ -35,7 +35,7 @@ import Validation (Validation (..)) import qualified Security.Advisories as Advisories import Security.Advisories.Filesystem (listAdvisories) import Security.Advisories.Generate.TH (readDirFilesTH) -import Security.Advisories.Core.Advisory (Ecosystem (..), ghcComponentToText) +import Security.Advisories.Core.Advisory (ComponentIdentifier (..), ghcComponentToText) -- * Actions @@ -88,7 +88,7 @@ data AdvisoryR = AdvisoryR deriving stock (Show) data AffectedPackageR = AffectedPackageR - { ecosystem :: Ecosystem, + { ecosystem :: ComponentIdentifier, introduced :: Text, fixed :: Maybe Text } @@ -237,7 +237,7 @@ toAdvisoryR x = toAffectedPackageR p = flip map (Advisories.affectedVersions p) $ \versionRange -> AffectedPackageR - { ecosystem = Advisories.affectedEcosystem p, + { ecosystem = Advisories.affectedComponentIdentifier p, introduced = T.pack $ prettyShow $ Advisories.affectedVersionRangeIntroduced versionRange, fixed = T.pack . prettyShow <$> Advisories.affectedVersionRangeFixed versionRange } diff --git a/code/hsec-tools/src/Security/Advisories/Parse.hs b/code/hsec-tools/src/Security/Advisories/Parse.hs index ff4500e..b16f7f7 100644 --- a/code/hsec-tools/src/Security/Advisories/Parse.hs +++ b/code/hsec-tools/src/Security/Advisories/Parse.hs @@ -16,7 +16,7 @@ , displayOOBError , AttributeOverridePolicy(..) , ParseAdvisoryError(..) - , validateEcosystem + , validateComponentIdentifier ) where @@ -64,7 +64,7 @@ type OOB = Either OOBError OutOfBandAttributes data OutOfBandAttributes = OutOfBandAttributes { oobModified :: UTCTime , oobPublished :: UTCTime - , oobEcosystem :: Maybe Ecosystem + , oobComponentIdentifier :: Maybe ComponentIdentifier } deriving (Show) @@ -94,14 +94,14 @@ instance Exception ParseAdvisoryError where -- @since 0.2.0.0 data OOBError = StdInHasNoOOB -- ^ we obtain the advisory via stdin and can hence not parse git history - | PathHasNoEcosystem -- ^ the path is missing 'hackage' or 'ghc' directory + | PathHasNoComponentIdentifier -- ^ the path is missing 'hackage' or 'ghc' directory | GitHasNoOOB GitError -- ^ processing oob info via git failed deriving stock (Eq, Show, Generic) displayOOBError :: OOBError -> String displayOOBError = \case StdInHasNoOOB -> "stdin doesn't provide out of band information" - PathHasNoEcosystem -> "the path is missing 'hackage' or 'ghc' directory" + PathHasNoComponentIdentifier -> "the path is missing 'hackage' or 'ghc' directory" GitHasNoOOB gitErr -> "no out of band information obtained with git error:\n" <> explainGitError gitErr @@ -191,7 +191,7 @@ parseAdvisoryTable oob policy doc summary details html tab = (amdModified (frontMatterAdvisory fm)) let affected = frontMatterAffected fm case oob of - Right (OutOfBandAttributes _ _ (Just ecosystem)) -> validateEcosystem ecosystem affected + Right (OutOfBandAttributes _ _ (Just ecosystem)) -> validateComponentIdentifier ecosystem affected _ -> pure () pure Advisory { advisoryId = amdId (frontMatterAdvisory fm) @@ -211,9 +211,9 @@ parseAdvisoryTable oob policy doc summary details html tab = } -- | Make sure one of the affected match the ecosystem -validateEcosystem :: MonadFail m => Ecosystem -> [Affected] -> m () -validateEcosystem ecosystem xs - | any (\affected -> affectedEcosystem affected == ecosystem) xs = pure () +validateComponentIdentifier :: MonadFail m => ComponentIdentifier -> [Affected] -> m () +validateComponentIdentifier ecosystem xs + | any (\affected -> affectedComponentIdentifier affected == ecosystem) xs = pure () | otherwise = fail $ "Expected an affected to match the ecosystem: " <> show ecosystem advisoryDoc :: Blocks -> Either Text (Text, [Block]) diff --git a/code/hsec-tools/src/Security/Advisories/Queries.hs b/code/hsec-tools/src/Security/Advisories/Queries.hs index 22323e4..06ed2b2 100644 --- a/code/hsec-tools/src/Security/Advisories/Queries.hs +++ b/code/hsec-tools/src/Security/Advisories/Queries.hs @@ -38,7 +38,7 @@ isAffectedByHelper checkWithRange queryPackageName queryVersionish = any checkAffected . advisoryAffected where checkAffected :: Affected -> Bool - checkAffected affected = case affectedEcosystem affected of + checkAffected affected = case affectedComponentIdentifier affected of Hackage pkg -> queryPackageName == pkg && checkWithRange queryVersionish (fromAffected affected) -- TODO: support GHC ecosystem query, e.g. by adding a cli flag _ -> False diff --git a/code/hsec-tools/test/Spec.hs b/code/hsec-tools/test/Spec.hs index 01d01f5..836e19e 100644 --- a/code/hsec-tools/test/Spec.hs +++ b/code/hsec-tools/test/Spec.hs @@ -47,7 +47,7 @@ doGoldenTest fp = goldenVsString fp (fp <> ".golden") (LText.encodeUtf8 <$> doCh attr = OutOfBandAttributes { oobPublished = fakeDate , oobModified = fakeDate - , oobEcosystem = Nothing + , oobComponentIdentifier = Nothing } res = parseAdvisory NoOverrides (Right attr) input osvExport = case res of diff --git a/code/hsec-tools/test/Spec/FormatSpec.hs b/code/hsec-tools/test/Spec/FormatSpec.hs index b40f05c..efd9345 100644 --- a/code/hsec-tools/test/Spec/FormatSpec.hs +++ b/code/hsec-tools/test/Spec/FormatSpec.hs @@ -70,15 +70,15 @@ genAdvisoryMetadata = genAffected :: Gen.Gen Affected genAffected = Affected - <$> genEcosystem + <$> genComponentIdentifier <*> genCVSS <*> Gen.list (Range.linear 0 5) genAffectedVersionRange <*> Gen.maybe (Gen.list (Range.linear 0 5) genArchitecture) <*> Gen.maybe (Gen.list (Range.linear 0 5) genOS) <*> (Map.toList . Map.fromList <$> Gen.list (Range.linear 0 5) ((,) <$> genText <*> genVersionRange)) -genEcosystem :: Gen.Gen Ecosystem -genEcosystem = Gen.choice $ +genComponentIdentifier :: Gen.Gen ComponentIdentifier +genComponentIdentifier = Gen.choice $ [ Hackage <$> genText , GHC <$> genGHCComponent ] diff --git a/code/hsec-tools/test/Spec/QueriesSpec.hs b/code/hsec-tools/test/Spec/QueriesSpec.hs index 80b105f..54be3d9 100644 --- a/code/hsec-tools/test/Spec/QueriesSpec.hs +++ b/code/hsec-tools/test/Spec/QueriesSpec.hs @@ -115,7 +115,7 @@ mkAdvisory versionRange = , advisoryRelated = [ "CVE-2022-YYYY" , "CVE-2022-ZZZZ" ] , advisoryAffected = [ Affected - { affectedEcosystem = Hackage packageName + { affectedComponentIdentifier = Hackage packageName , affectedCVSS = cvss , affectedVersions = mkAffectedVersions versionRange , affectedArchitectures = Nothing diff --git a/code/hsec-tools/test/golden/EXAMPLE_ADVISORY.md.golden b/code/hsec-tools/test/golden/EXAMPLE_ADVISORY.md.golden index 681af2e..62dda0c 100644 --- a/code/hsec-tools/test/golden/EXAMPLE_ADVISORY.md.golden +++ b/code/hsec-tools/test/golden/EXAMPLE_ADVISORY.md.golden @@ -17,7 +17,7 @@ Right ] , advisoryAffected = [ Affected - { affectedEcosystem = Hackage "package-name" + { affectedComponentIdentifier = Hackage "package-name" , affectedCVSS = CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H , affectedVersions = [ AffectedVersionRange