Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions evidence/cli/command/command_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,33 +57,37 @@ func GetCommands() []components.Command {
Aliases: []string{"create"},
Flags: flags.GetCommandFlags(flags.CreateEvidence),
Description: create.GetDescription(),
AIDescription: create.GetAIDescription(),
Arguments: create.GetArguments(),
Action: createEvidence,
SupportedFormats: []format.OutputFormat{format.Json, format.Table},
},
{
Name: "get-evidence",
Aliases: []string{"get"},
Flags: flags.GetCommandFlags(flags.GetEvidence),
Description: get.GetDescription(),
Arguments: get.GetArguments(),
Action: getEvidence,
Name: "get-evidence",
Aliases: []string{"get"},
Flags: flags.GetCommandFlags(flags.GetEvidence),
Description: get.GetDescription(),
AIDescription: get.GetAIDescription(),
Arguments: get.GetArguments(),
Action: getEvidence,
},
{
Name: "verify-evidence",
Aliases: []string{"verify"},
Flags: flags.GetCommandFlags(flags.VerifyEvidence),
Description: verify.GetDescription(),
Arguments: verify.GetArguments(),
Action: verifyEvidence,
Name: "verify-evidence",
Aliases: []string{"verify"},
Flags: flags.GetCommandFlags(flags.VerifyEvidence),
Description: verify.GetDescription(),
AIDescription: verify.GetAIDescription(),
Arguments: verify.GetArguments(),
Action: verifyEvidence,
},
{
Name: "generate-key-pair",
Aliases: []string{"gen-keys"},
Flags: flags.GetCommandFlags(flags.GenerateKeyPair),
Description: generate.GetDescription(),
Arguments: generate.GetArguments(),
Action: generateKeyPair,
Name: "generate-key-pair",
Aliases: []string{"gen-keys"},
Flags: flags.GetCommandFlags(flags.GenerateKeyPair),
Description: generate.GetDescription(),
AIDescription: generate.GetAIDescription(),
Arguments: generate.GetArguments(),
Action: generateKeyPair,
},
}
}
Expand Down
34 changes: 34 additions & 0 deletions evidence/cli/docs/create/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,40 @@ func GetDescription() string {
return " Create a custom evidence and save it to a repository. Add a predicate, predicate-type, repo-path, key, key-name and attachments."
}

func GetAIDescription() string {
return `Sign a predicate and upload it as an in-toto DSSE evidence attached to a subject in Artifactory. Use this when an agent or CI step needs to record a verifiable attestation (SLSA provenance, SBOM, test results, scanner reports, custom claims) tied to a specific artifact, build, package, application or release bundle.

When to use:
- Attach signed provenance or scan results to an artifact, build, package, application or release bundle.
- Re-upload a pre-signed Sigstore bundle via --sigstore-bundle.
- Generate a predicate automatically from a SonarQube scan via --integration sonar.

Prerequisites:
- A configured JFrog Platform server (jf c add or jf login). Basic auth is rejected; use --access-token or a configured server-id.
- A private signing key supplied via --key (path or PEM body) or the JFROG_CLI_SIGNING_KEY env variable. Supported: ecdsa, rsa, ed25519.
- Exactly one subject: --subject-repo-path, --build-name/--build-number (or JFROG_CLI_BUILD_NAME/_NUMBER), --package-name/--package-version/--package-repo-name, --release-bundle/--release-bundle-version, or --application-key/--application-version.
- For attachments: --attach-artifactory-temp-path (or EVIDENCE_ATTACHMENT_ARTIFACTORY_TEMP_PATH config) when using --attach-local.
- For sonar integration: SONAR_TOKEN or SONARQUBE_TOKEN env var plus a report-task.txt from a completed scan.

Common patterns:
$ jf evd create --subject-repo-path generic-local/app.tgz --predicate ./provenance.json --predicate-type https://slsa.dev/provenance/v1 --key ./evidence.key --key-alias my-signer
$ jf evd create --build-name my-build --build-number 42 --predicate ./sbom.json --predicate-type https://cyclonedx.org/bom --key-alias my-signer
$ jf evd create --package-name my-npm-pkg --package-version 1.2.3 --package-repo-name npm-local --predicate ./scan.json --predicate-type https://example.com/scan/v1
$ jf evd create --release-bundle my-rb --release-bundle-version 1.0.0 --predicate ./attest.json --predicate-type https://example.com/attest/v1
$ jf evd create --subject-repo-path generic-local/app.tgz --sigstore-bundle ./app.sigstore.json
$ jf evd create --build-name my-build --build-number 42 --integration sonar

Gotchas:
- --sigstore-bundle is mutually exclusive with --key, --key-alias, --predicate, --predicate-type, --subject-sha256 and all --attach-* flags (values are extracted from the bundle).
- Specifying multiple subjects in one invocation is an error, except the documented --type + --build-name (gh-committer) combination.
- --attach-local uploads the file to --attach-artifactory-temp-path first; once set, the temp path is persisted in the evidence config for subsequent runs.
- Evidence services reject basic authentication; only access tokens work.
- When --integration sonar is used, --predicate and --predicate-type must be omitted; the predicate is generated from the SonarQube report.
- Output formatting (--format json|table) only renders after a successful create call.

Related: jf evd verify, jf evd get, jf evd gen-keys`
}

func GetArguments() []components.Argument {
return []components.Argument{}
}
27 changes: 27 additions & 0 deletions evidence/cli/docs/generate/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ func GetDescription() string {
return "Generate an ECDSA P-256 key pair for evidence signing. Creates evidence.key (private) and evidence.pub (public) files in the specified output directory (current directory by default). Private keys are stored unencrypted with secure file permissions. Optionally uploads the public key to JFrog platform trusted keys."
}

func GetAIDescription() string {
return `Generate an ECDSA P-256 key pair used to sign evidence and, by default, upload the public key to the JFrog Platform trusted-keys store under a chosen alias. Use this when bootstrapping a signer identity for jf evd create / jf evd verify in a project or pipeline.

When to use:
- Bootstrap a new signing identity for a project, environment or CI step.
- Rotate keys by generating a new pair with a fresh --key-alias.
- Produce local-only key files for self-hosted verification by setting --upload-public-key=false.

Prerequisites:
- A configured JFrog Platform server (jf c add or jf login) with permission to write trusted keys (when uploading).
- Write access to the output directory (--key-file-path).

Common patterns:
$ jf evd gen-keys --key-alias my-signer
$ jf evd gen-keys --key-alias my-signer --key-file-path ./keys --key-file-name release-signer
$ jf evd gen-keys --upload-public-key=false --key-file-path ./local-keys

Gotchas:
- --upload-public-key defaults to true; passing no flag will contact the configured platform and upload the public key.
- The private key is written unencrypted (mode 0600); store it outside of source control and pipeline logs.
- Default file names are evidence.key and evidence.pub; existing files in the target directory will be overwritten without prompting.
- --key-file-path creates the directory if it does not exist, but only one level deep.
- Generated keys are ECDSA P-256 only; if you need RSA or ed25519 keys, produce them with your own tooling and skip this command.

Related: jf evd create, jf evd verify`
}

func GetArguments() []components.Argument {
return []components.Argument{}
}
29 changes: 29 additions & 0 deletions evidence/cli/docs/get/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,35 @@ func GetDescription() string {
Supports JSON and JSONL formats.`
}

func GetAIDescription() string {
return `Retrieve evidence (DSSE envelopes and metadata) attached to a subject from Artifactory. Use this when an agent needs to inspect or ingest existing evidence for an artifact or release bundle, optionally including the predicate payload.

When to use:
- List all evidence attached to a single artifact (--subject-repo-path).
- Enumerate evidence across every build and artifact of a release bundle (--release-bundle / --release-bundle-version).
- Pipe machine-readable output into downstream tooling via --format json or --format jsonl.

Prerequisites:
- A configured JFrog Platform server (jf c add or jf login) with access-token auth; basic auth is rejected.
- Read permissions on the subject path and the evidence repository.
- Exactly one of --subject-repo-path or --release-bundle (with --release-bundle-version). Other subject types are not supported by get.

Common patterns:
$ jf evd get --subject-repo-path generic-local/app.tgz
$ jf evd get --subject-repo-path generic-local/app.tgz --include-predicate --format json
$ jf evd get --release-bundle my-rb --release-bundle-version 1.0.0 --format jsonl --output ./rb-evidence.jsonl
$ jf evd get --release-bundle my-rb --release-bundle-version 1.0.0 --artifacts-limit 5000

Gotchas:
- --include-predicate is off by default; without it the predicate body is omitted from results.
- --artifacts-limit defaults to 1000 for release bundles; larger bundles need an explicit higher value.
- Only --subject-repo-path and --release-bundle subjects are accepted; passing --build-name, --package-name or --application-key returns "unsupported subject".
- --output writes to a file; without it results go to stdout.
- jsonl is only useful with --format; the default human format ignores --output formatting for streaming.

Related: jf evd create, jf evd verify`
}

func GetArguments() []components.Argument {
return []components.Argument{}
}
32 changes: 32 additions & 0 deletions evidence/cli/docs/verify/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,38 @@ func GetDescription() string {
Keys can be supplied using the --keys flag, the JFROG_CLI_SIGNING_KEY environment variable, or retrieved from Artifactory using the --use-artifactory-keys option.`
}

func GetAIDescription() string {
return `Verify every DSSE evidence attached to a subject by checking signatures against supplied or Artifactory-stored public keys, plus any attachment integrity. Use this when an agent needs to confirm that evidence on an artifact, build, package or release bundle is signed by a trusted key before continuing a pipeline.

When to use:
- Gate a release on signed provenance/SBOM/scan evidence being present and valid.
- Re-verify evidence after a key rotation by re-running with the new --public-keys.
- Validate evidence with trust roots managed in Artifactory via --use-artifactory-keys.

Prerequisites:
- A configured JFrog Platform server (jf c add or jf login) using access-token auth.
- One or more public keys provided via --public-keys (semicolon-separated paths or PEM bodies), JFROG_CLI_SIGNING_KEY, or --use-artifactory-keys.
- Exactly one subject: --subject-repo-path, --build-name/--build-number, --package-name/--package-version/--package-repo-name, or --release-bundle/--release-bundle-version.
- Supported key algorithms: ecdsa, rsa, ed25519.

Common patterns:
$ jf evd verify --subject-repo-path generic-local/app.tgz --public-keys ./evidence.pub
$ jf evd verify --subject-repo-path generic-local/app.tgz --use-artifactory-keys --format json
$ jf evd verify --build-name my-build --build-number 42 --public-keys ./key1.pub;./key2.pub
$ jf evd verify --release-bundle my-rb --release-bundle-version 1.0.0 --public-keys ./evidence.pub
$ jf evd verify --package-name my-npm-pkg --package-version 1.2.3 --package-repo-name npm-local --use-artifactory-keys

Gotchas:
- JFROG_CLI_SIGNING_KEY is appended to whatever is passed via --public-keys; ensure the env var is unset if you only want explicit keys.
- --public-keys uses ";" as the separator, not "," or whitespace.
- --application-key subjects are not supported by verify (only create/get cover them).
- Failures from the verifier are wrapped as "evidence verification failed: ..."; check the wrapped cause for the specific signature, key or attachment mismatch.
- --use-artifactory-keys still requires platform credentials with read access to the trusted-keys store.
- Attachments referenced by evidence are also verified; mismatched or missing attachment files cause the whole verify to fail.

Related: jf evd create, jf evd get, jf evd gen-keys`
}

func GetArguments() []components.Argument {
return []components.Argument{}
}
34 changes: 17 additions & 17 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ go 1.25.7

require (
github.com/distribution/reference v0.6.0
github.com/gookit/color v1.6.0
github.com/jedib0t/go-pretty/v6 v6.7.8
github.com/gookit/color v1.6.1
github.com/jedib0t/go-pretty/v6 v6.7.10
github.com/jfrog/build-info-go v1.13.1-0.20260429070557-93b98034d295
github.com/jfrog/froggit-go v1.21.1
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-artifactory v0.8.0
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260504054219-ba16d20c7b0f
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260601130310-8d52a530da18
github.com/jfrog/jfrog-client-go v1.55.1-0.20260319105834-2953fed40f60
github.com/pkg/errors v0.9.1
github.com/secure-systems-lab/go-securesystemslib v0.10.0
Expand All @@ -27,15 +27,15 @@ require (
require (
dario.cat/mergo v1.0.2 // indirect
github.com/BurntSushi/toml v1.6.0 // indirect
github.com/CycloneDX/cyclonedx-go v0.10.0 // indirect
github.com/CycloneDX/cyclonedx-go v0.11.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.4.1 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/brotli v1.2.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/buger/jsonparser v1.1.2 // indirect
github.com/buger/jsonparser v1.2.0 // indirect
github.com/c-bata/go-prompt v0.2.6 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
Expand All @@ -51,7 +51,7 @@ require (
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/forPelevin/gomoji v1.4.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fsnotify/fsnotify v1.10.1 // indirect
github.com/gfleury/go-bitbucket-v1 v0.0.0-20240917142304-df385efaac68 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.9.0 // indirect
Expand Down Expand Up @@ -80,7 +80,7 @@ require (
github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
github.com/go-openapi/validate v0.25.2 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 // indirect
github.com/gocarina/gocsv v0.0.0-20260523204920-c264028e67ea // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/snappy v1.0.0 // indirect
Expand All @@ -99,22 +99,22 @@ require (
github.com/jedisct1/go-minisign v0.0.0-20241212093149-d2f9f49435c7 // indirect
github.com/jfrog/archiver/v3 v3.6.3 // indirect
github.com/kevinburke/ssh_config v1.6.0 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/klauspost/compress v1.18.6 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/ktrysmt/go-bitbucket v0.9.88 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.21 // indirect
github.com/mattn/go-tty v0.0.7 // indirect
github.com/mattn/go-isatty v0.0.22 // indirect
github.com/mattn/go-runewidth v0.0.23 // indirect
github.com/mattn/go-tty v0.0.8 // indirect
github.com/microsoft/azure-devops-go-api/azuredevops/v7 v7.1.0 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/nwaples/rardecode/v2 v2.2.2 // indirect
github.com/nwaples/rardecode/v2 v2.2.3 // indirect
github.com/oklog/ulid/v2 v2.1.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.3.0 // indirect
github.com/pelletier/go-toml/v2 v2.3.1 // indirect
github.com/pierrec/lz4/v4 v4.1.26 // indirect
github.com/pjbgf/sha1cd v0.6.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
Expand All @@ -139,7 +139,7 @@ require (
github.com/transparency-dev/formats v0.1.0 // indirect
github.com/transparency-dev/merkle v0.0.2 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/vbauerster/mpb/v8 v8.12.0 // indirect
github.com/vbauerster/mpb/v8 v8.12.1 // indirect
github.com/xanzy/go-gitlab v0.115.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
Expand All @@ -151,8 +151,8 @@ require (
go.opentelemetry.io/otel/metric v1.42.0 // indirect
go.opentelemetry.io/otel/trace v1.42.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/mod v0.35.0 // indirect
golang.org/x/exp v0.0.0-20260527015227-08cc5374adb3 // indirect
golang.org/x/mod v0.36.0 // indirect
golang.org/x/net v0.55.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.20.0 // indirect
Expand Down
Loading
Loading