diff --git a/docs/pipelines/validateSignedPipelines/help.go b/docs/pipelines/validateSignedPipelines/help.go new file mode 100644 index 000000000..589a70022 --- /dev/null +++ b/docs/pipelines/validateSignedPipelines/help.go @@ -0,0 +1,7 @@ +package validatesignedpipelines + +var Usage = []string{"pl validate-signed-pipelines"} + +func GetDescription() string { + return "Performs validation of signed pipelines for different artifact types." +} diff --git a/go.mod b/go.mod index c85f3507a..78d691128 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.1 // indirect github.com/gookit/color v1.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -131,8 +131,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20231019085746-e1b192457664 -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20231019090648-a85aaa5fe352 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/bhanurp/jfrog-cli-core/v2 v2.24.4-0.20230904193216-07be942c9e9e // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev +replace github.com/jfrog/jfrog-client-go => github.com/bhanurp/jfrog-client-go v0.0.0-20230904192757-e76adff9e71b diff --git a/go.sum b/go.sum index aae59c1f9..f127d47c6 100644 --- a/go.sum +++ b/go.sum @@ -69,7 +69,10 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkE github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bhanurp/jfrog-cli-core/v2 v2.24.4-0.20230904193216-07be942c9e9e h1:1Y0DRhb5q2pjnQrgTnBqx9UIwQTHfp4zvEHaf/YuJ3E= +github.com/bhanurp/jfrog-cli-core/v2 v2.24.4-0.20230904193216-07be942c9e9e/go.mod h1:Cg3ofbmAc+Ectl3v1NanVfjr5ja7/D87ZQDahaohFjk= +github.com/bhanurp/jfrog-client-go v0.0.0-20230904192757-e76adff9e71b h1:tRC1vjvgb6EFMzU8aTHxYN0D3R84a/HHV1LgC1j5rDI= +github.com/bhanurp/jfrog-client-go v0.0.0-20230904192757-e76adff9e71b/go.mod h1:uUnMrqHX7Xi+OCaZEE4b3BtsmGeOSCB7XqaEWVXEH/E= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= @@ -199,8 +202,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -245,18 +249,12 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jedib0t/go-pretty/v6 v6.4.8 h1:HiNzyMSEpsBaduKhmK+CwcpulEeBrTmxutz4oX/oWkg= -github.com/jedib0t/go-pretty/v6 v6.4.8/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= -github.com/jfrog/build-info-go v1.9.14 h1:xVezJ16Vpm/boRBn3lI1THCQmkylm+6R4zYWxOQ0NSM= -github.com/jfrog/build-info-go v1.9.14/go.mod h1:ujJ8XQZMdT2tMkLSMJNyDd1pCY+duwHdjV+9or9FLIg= -github.com/jfrog/gofrog v1.3.1 h1:QqAwQXCVReT724uga1AYqG/ZyrNQ6f+iTxmzkb+YFQk= -github.com/jfrog/gofrog v1.3.1/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= -github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-core/v2 v2.45.4 h1:IHwL2RQ0VwibUCPLFtCm53tMrO1ZOmSkf6Kt2o3iD3U= -github.com/jfrog/jfrog-cli-core/v2 v2.45.4/go.mod h1:5rTYHinkg5k2ALHYROR3AnE2mMQ22SFZF5dwew1sgco= -github.com/jfrog/jfrog-client-go v1.34.3 h1:kDfw3FUQQvOsTKFqonIgLlziez6CSX80xCYZIH9YYcg= -github.com/jfrog/jfrog-client-go v1.34.3/go.mod h1:fuxhYzWEkA16+ZV5cP/BJUGjA3SXVKbBoDmb8ZS6J4g= +github.com/jedib0t/go-pretty/v6 v6.4.7 h1:lwiTJr1DEkAgzljsUsORmWsVn5MQjt1BPJdPCtJ6KXE= +github.com/jedib0t/go-pretty/v6 v6.4.7/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= +github.com/jfrog/build-info-go v1.9.9 h1:YMA9okHawBNL8SrCWzqULSf5M4W+YnWyUhmkWSjoXEE= +github.com/jfrog/build-info-go v1.9.9/go.mod h1:t31QRpH5xUJKw8XkQlAA+Aq7aanyS1rrzpcK8xSNVts= +github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= +github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/pipelines/cli.go b/pipelines/cli.go index a053b9f98..d8678512e 100644 --- a/pipelines/cli.go +++ b/pipelines/cli.go @@ -1,7 +1,9 @@ package pipelines import ( + "errors" "fmt" + "github.com/jfrog/jfrog-cli-core/v2/common/commands" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" pipelines "github.com/jfrog/jfrog-cli-core/v2/pipelines/commands" @@ -12,6 +14,7 @@ import ( "github.com/jfrog/jfrog-cli/docs/pipelines/sync" "github.com/jfrog/jfrog-cli/docs/pipelines/syncstatus" "github.com/jfrog/jfrog-cli/docs/pipelines/trigger" + "github.com/jfrog/jfrog-cli/docs/pipelines/validatesignedpipelines" "github.com/jfrog/jfrog-cli/docs/pipelines/version" "github.com/jfrog/jfrog-cli/utils/cliutils" @@ -72,6 +75,16 @@ func GetCommands() []cli.Command { BashComplete: corecommon.CreateBashCompletionFunc(), Action: getSyncPipelineResourcesStatus, }, + { + Name: "validate-signed-pipelines", + Flags: cliutils.GetCommandFlags(cliutils.ValidateSignedPipelines), + Aliases: []string{"vsp"}, + Usage: validatesignedpipelines.GetDescription(), + HelpName: corecommon.CreateUsage("pl validate-signed-pipelines", validatesignedpipelines.GetDescription(), validatesignedpipelines.Usage), + ArgsUsage: common.CreateEnvVars(), + BashComplete: corecommon.CreateBashCompletionFunc(), + Action: performSignedPipelinesValidation, + }, }) } @@ -195,3 +208,82 @@ func triggerNewRun(c *cli.Context) error { SetMultiBranch(multiBranch) return commands.Exec(triggerCommand) } + +func performSignedPipelinesValidation(c *cli.Context) error { + artifactType := c.Args().Get(0) + coreutils.PrintTitle("Preparing signed pipelines validation") + // Get service config details + serviceDetails, err := createPipelinesDetailsByFlags(c) + if err != nil { + return err + } + validateSignedPipelinesCommand := pipelines.NewValidateSignedPipelinesCommand() + switch artifactType { + case "buildInfo": + buildName, buildNumber, projectKey, err := getBuildInfoArtifactTypeParams(c) + if err != nil { + return err + } + validateSignedPipelinesCommand.SetArtifactType(artifactType). + SetBuildName(buildName). + SetBuildNumber(buildNumber). + SetProjectKey(projectKey). + SetServerDetails(serviceDetails) + case "artifact": + artifactPath, err := getArtifactArtifactTypeParams(c) + if err != nil { + return err + } + validateSignedPipelinesCommand.SetArtifactType(artifactType). + SetArtifactPath(artifactPath). + SetServerDetails(serviceDetails) + case "releaseBundle": + releaseBundleName, releaseBundleVersion, err := getReleaseBundleArtifactTypeParams(c) + if err != nil { + return nil + } + validateSignedPipelinesCommand.SetArtifactType(artifactType). + SetReleaseBundleName(releaseBundleName). + SetReleaseBundleVersion(releaseBundleVersion). + SetServerDetails(serviceDetails) + default: + return errors.New("Allowed artifactType is buildInfo, artifact, releaseBundle") + } + return commands.Exec(validateSignedPipelinesCommand) +} + +func getBuildInfoArtifactTypeParams(c *cli.Context) (string, string, string, error) { + buildName := c.String("build-name") + if buildName == "" { + return "", "", "", cliutils.PrintHelpAndReturnError("The --build-name option is mandatory.", c) + } + buildNumber := c.String("build-number") + if buildNumber == "" { + return "", "", "", cliutils.PrintHelpAndReturnError("The --build-number option is mandatory.", c) + } + projectKey := c.String("project-key") + if projectKey == "" { + return "", "", "", cliutils.PrintHelpAndReturnError("The --project-key option is mandatory.", c) + } + return buildName, buildNumber, projectKey, nil +} + +func getArtifactArtifactTypeParams(c *cli.Context) (string, error) { + artifactPath := c.String("artifact-path") + if artifactPath == "" { + return "", cliutils.PrintHelpAndReturnError("The --artifact-path option is mandatory.", c) + } + return artifactPath, nil +} + +func getReleaseBundleArtifactTypeParams(c *cli.Context) (string, string, error) { + releaseBundleName := c.String("release-bundle-name") + if releaseBundleName == "" { + return "", "", cliutils.PrintHelpAndReturnError("The --release-bundle-name option is mandatory.", c) + } + releaseBundleVersion := c.String("release-bundle-version") + if releaseBundleVersion == "" { + return "", "", cliutils.PrintHelpAndReturnError("The --release-bundle-version option is mandatory.", c) + } + return releaseBundleName, releaseBundleVersion, nil +} diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index ef823ad63..d87766773 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -555,17 +555,22 @@ const ( // *** JFrog Pipelines Commands' flags *** // Base flags - branch = "branch" - Trigger = "trigger" - pipelineName = "pipeline-name" - name = "name" - Validate = "validate" - Resources = "resources" - monitor = "monitor" - repository = "repository" - singleBranch = "single-branch" - Sync = "sync" - SyncStatus = "sync-status" + branch = "branch" + Trigger = "trigger" + pipelineName = "pipeline-name" + name = "name" + Validate = "validate" + Resources = "resources" + monitor = "monitor" + repository = "repository" + singleBranch = "single-branch" + Sync = "sync" + SyncStatus = "sync-status" + ValidateSignedPipelines = "validate-signed-pipelines" + projectKey = "project-key" + artifactPath = "artifact-path" + releaseBundleName = "release-bundle-name" + releaseBundleVersion = "release-bundle-version" // *** TransferInstall Commands' flags *** installPluginPrefix = "install-" @@ -1667,6 +1672,22 @@ var flagsMap = map[string]cli.Flag{ Name: dryRun, Usage: "[Default: false] Set to true to only simulate the distribution of the release bundle.` `", }, + projectKey: cli.StringFlag{ + Name: projectKey, + Usage: "[Optional] Specify project name as projectKey", + }, + artifactPath: cli.StringFlag{ + Name: artifactPath, + Usage: "[Optional] Mention path of the artifact in repository", + }, + releaseBundleName: cli.StringFlag{ + Name: releaseBundleName, + Usage: "[Optional] Provide release bundle name to perform validation of signed pipelines", + }, + releaseBundleVersion: cli.StringFlag{ + Name: releaseBundleVersion, + Usage: "[Optional] Provide release bundle version to perform validation of signed pipelines", + }, ThirdPartyContextualAnalysis: cli.BoolFlag{ Name: ThirdPartyContextualAnalysis, Usage: "Default: false] [npm] when set, the Contextual Analysis scan also uses the code of the project dependencies to determine the applicability of the vulnerability.", @@ -2098,6 +2119,9 @@ var commandFlags = map[string][]string{ SyncStatus: { branch, repository, serverId, }, + ValidateSignedPipelines: { + buildName, buildNumber, projectKey, artifactPath, releaseBundleName, releaseBundleVersion, serverId, + }, } func GetCommandFlags(cmd string) []cli.Flag {