From ccc53b4ee2b34579a8a8fd3cffe911443fab0f08 Mon Sep 17 00:00:00 2001 From: Sven Tennie Date: Tue, 16 Jan 2024 15:50:52 +0100 Subject: [PATCH 1/6] Upload Bombon files to Deptrack This avoids cluttering our release artifact page. And, Security gets the files where they need them. --- hack/bin/bombon.hs | 123 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 14 deletions(-) diff --git a/hack/bin/bombon.hs b/hack/bin/bombon.hs index 36f87a7493..7e1e991bdb 100755 --- a/hack/bin/bombon.hs +++ b/hack/bin/bombon.hs @@ -1,17 +1,112 @@ -#!/usr/bin/env -S nix -Lv run github:wireapp/ghc-flakr/ecb1f45f1549e06c92d71164e305ce501eb0e36e --extra-experimental-features flakes -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE ImportQualifiedPost #-} -{-# LANGUAGE OverloadedStrings #-} +#!/usr/bin/env -S nix -Lv run github:wireapp/ghc-flakr/a14de7ecd0c24192bc8d5cb534e8a0e21bbd91fa --extra-experimental-features flakes +{-# LANGUAGE DataKinds #-} -import Data.Text qualified as T -import Turtle +import Data.Aeson +import Data.Proxy +import GHC.Generics +import Network.HTTP.Client qualified as HTTP +import Options.Applicative +import Servant.API +import Servant.Client +data Payload = Payload + { bom :: String, + projectName :: String, + projectVersion :: String, + autoCreate :: Bool + } + deriving (Generic, Show) + +instance ToJSON Payload + +data ApiResponse = ApiResponse + { token :: String + } + deriving (Generic, Show) + +instance FromJSON ApiResponse + +type DependenyTrackAPI = + "api" + :> "v1" + :> "bom" + :> ReqBody '[JSON] Payload + :> Header "X-Api-Key" String + :> Put '[JSON] ApiResponse + +api :: Proxy DependenyTrackAPI +api = Proxy + +putBOM :: Payload -> Maybe String -> ClientM ApiResponse +putBOM = client api + +data CliOptions = CliOptions + { opBomPath :: String, + opProjectName :: String, + opProjectVersion :: String, + opAutoCreate :: Bool, + opApiKey :: String + } + deriving (Show) + +cliParser :: Parser CliOptions +cliParser = + CliOptions + <$> ( strOption + ( long "bom-filepath" + <> short 'f' + <> metavar "FILENAME" + ) + ) + <*> ( strOption + ( long "project-name" + <> short 'p' + <> metavar "PROJECT_NAME" + <> value "wire-server-ci" + ) + ) + <*> ( strOption + ( long "project-version" + <> short 'v' + <> metavar "PROJECT_VERSION" + ) + ) + <*> ( switch + ( long "auto-create" + <> short 'c' + ) + ) + <*> ( strOption + ( long "api-key" + <> short 'k' + <> metavar "API_KEY" + ) + ) + +fullCliParser :: ParserInfo CliOptions +fullCliParser = + info + (cliParser <**> helper) + ( fullDesc + <> progDesc "Upload BOM files to deptrack" + ) + +main :: IO () main = do - (release, repo) <- options "Upload boms" do - (,) - <$> optText "release" 't' "Which release tag to upload the artifacts to" - <*> optText "repo" 'r' "Which repository to upload the artifacts to" - let bomName = "wire-server-bom-" <> release <> ".json" - ExitSuccess <- proc "nix" ["build", "-f", "nix", "wireServer.allLocalPackagesBom", "-o", bomName] mempty - printf ("uploading " % s % " to release " % s % "\n") bomName ("chart/" <> release) - proc "gh" ["-R", repo, "release", "upload", "chart/" <> release, bomName] mempty + options <- execParser fullCliParser + manager' <- HTTP.newManager HTTP.defaultManagerSettings + bom <- readFile $ opBomPath options + let payload = + Payload + { bom = bom, + projectName = opProjectName options, + projectVersion = opProjectVersion options, + autoCreate = opAutoCreate options + } + res <- + runClientM + (putBOM payload ((Just . opApiKey) options)) + (mkClientEnv manager' (BaseUrl Https "deptrack.wire.link" 443 "")) + case res of + Left err -> print $ "Error: " ++ show err + Right res -> print res From 3af02894f8672125e7968069e3a9c178868d45fe Mon Sep 17 00:00:00 2001 From: Sven Tennie Date: Tue, 16 Jan 2024 18:03:42 +0100 Subject: [PATCH 2/6] deptrack needs its bom base64 encoded --- hack/bin/bombon.hs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/hack/bin/bombon.hs b/hack/bin/bombon.hs index 7e1e991bdb..2a5da2ed7d 100755 --- a/hack/bin/bombon.hs +++ b/hack/bin/bombon.hs @@ -1,16 +1,21 @@ -#!/usr/bin/env -S nix -Lv run github:wireapp/ghc-flakr/a14de7ecd0c24192bc8d5cb534e8a0e21bbd91fa --extra-experimental-features flakes +#!/usr/bin/env -S nix -Lv run github:wireapp/ghc-flakr/99fe5a331fdd37d52043f14e5c565ac29a30bcb4 {-# LANGUAGE DataKinds #-} import Data.Aeson +import qualified Data.ByteString.Lazy.Char8 as BL +import qualified Data.ByteString.Base64.Lazy as Base64 import Data.Proxy import GHC.Generics import Network.HTTP.Client qualified as HTTP +import Network.HTTP.Client.TLS (tlsManagerSettings) import Options.Applicative import Servant.API import Servant.Client +import Data.Text.Lazy +import Data.Text.Lazy.Encoding data Payload = Payload - { bom :: String, + { bom :: Text, projectName :: String, projectVersion :: String, autoCreate :: Bool @@ -94,11 +99,11 @@ fullCliParser = main :: IO () main = do options <- execParser fullCliParser - manager' <- HTTP.newManager HTTP.defaultManagerSettings + manager' <- HTTP.newManager tlsManagerSettings bom <- readFile $ opBomPath options let payload = Payload - { bom = bom, + { bom = toBase64Text bom, projectName = opProjectName options, projectVersion = opProjectVersion options, autoCreate = opAutoCreate options @@ -110,3 +115,6 @@ main = do case res of Left err -> print $ "Error: " ++ show err Right res -> print res + +toBase64Text :: String -> Text +toBase64Text = decodeUtf8 . Base64.encode . BL.pack From d28e9e13f3f4ce72b43a276e0124efc4f9517820 Mon Sep 17 00:00:00 2001 From: Sven Tennie Date: Tue, 16 Jan 2024 18:17:56 +0100 Subject: [PATCH 3/6] Adjust `upload-bombon` Makefile target --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dbe1f612e5..6dd0ced4af 100644 --- a/Makefile +++ b/Makefile @@ -543,6 +543,12 @@ kind-restart-%: .local/kind-kubeconfig helm-template-%: clean-charts charts-integration ./hack/bin/helm-template.sh $(*) +# Ask the security team for the `DEPENDENCY_TRACK_API_KEY` (if you need it) .PHONY: upload-bombon upload-bombon: - ./hack/bin/bombon.hs -- "$@" + nix build -f nix wireServer.allLocalPackagesBom -o "bill-of-materials.$(HELM_SEMVER).json" + ./hack/bin/bombon.hs -- \ + --bom-filepath "./bill-of-materials.$(HELM_SEMVER).json" \ + --project-version $(HELM_SEMVER) \ + --api-key $(DEPENDENCY_TRACK_API_KEY) \ + --auto-create From 484a1e798bdc6957ddf8e91f1390654bfc065778 Mon Sep 17 00:00:00 2001 From: Sven Tennie Date: Tue, 16 Jan 2024 18:20:31 +0100 Subject: [PATCH 4/6] Remove bom file in `clean` Makefile target --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 6dd0ced4af..a5a06e2391 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,7 @@ full-clean: clean clean: cabal clean -rm -rf dist + -rm -f "bill-of-materials.$(HELM_SEMVER).json" .PHONY: clean-hint clean-hint: From 3ddb89aa3ee3c3e76625eb4349727f17eb41bb73 Mon Sep 17 00:00:00 2001 From: Sven Tennie Date: Wed, 17 Jan 2024 10:07:48 +0100 Subject: [PATCH 5/6] Add changelog entry. --- changelog.d/5-internal/upload-bom-to-deptrack | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog.d/5-internal/upload-bom-to-deptrack diff --git a/changelog.d/5-internal/upload-bom-to-deptrack b/changelog.d/5-internal/upload-bom-to-deptrack new file mode 100644 index 0000000000..abffca8b63 --- /dev/null +++ b/changelog.d/5-internal/upload-bom-to-deptrack @@ -0,0 +1,3 @@ +Upload bill-of-material (BOM) files directly to the Dependency Tracker via REST. +This eases the life of the security team and prevents cluttering our release +artifact page. From 9a7913606d789c278fd088153b1fd085ac89c1f5 Mon Sep 17 00:00:00 2001 From: Sven Tennie Date: Wed, 17 Jan 2024 10:16:30 +0100 Subject: [PATCH 6/6] Increase linter happieness "Found `qualified' in postpositive position." --- hack/bin/bombon.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hack/bin/bombon.hs b/hack/bin/bombon.hs index 2a5da2ed7d..0c01c4cf80 100755 --- a/hack/bin/bombon.hs +++ b/hack/bin/bombon.hs @@ -2,17 +2,17 @@ {-# LANGUAGE DataKinds #-} import Data.Aeson -import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.ByteString.Base64.Lazy as Base64 +import qualified Data.ByteString.Lazy.Char8 as BL import Data.Proxy +import Data.Text.Lazy +import Data.Text.Lazy.Encoding import GHC.Generics -import Network.HTTP.Client qualified as HTTP +import qualified Network.HTTP.Client as HTTP import Network.HTTP.Client.TLS (tlsManagerSettings) import Options.Applicative import Servant.API import Servant.Client -import Data.Text.Lazy -import Data.Text.Lazy.Encoding data Payload = Payload { bom :: Text,