Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: blob policy command messages with docs #1175

Merged
merged 13 commits into from
Feb 21, 2025
4 changes: 2 additions & 2 deletions cmd/notation/blob/policy/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
func Cmd() *cobra.Command {
command := &cobra.Command{
Use: "policy [command]",
Short: "Manage trust policy configuration for signed blobs",
Long: "Manage trust policy configuration for arbitrary blob signature verification.",
Short: "Manage blob trust policy configuration for arbitrary blob signature verification",
Long: "Manage blob trust policy configuration for arbitrary blob signature verification.",
}

command.AddCommand(
Expand Down
22 changes: 11 additions & 11 deletions cmd/notation/blob/policy/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@
Short: "Import blob trust policy configuration from a JSON file",
Long: `Import blob trust policy configuration from a JSON file.

Example - Import blob trust policy configuration from a file:
Example - Import blob trust policy configuration from a JSON file and store as "trustpolicy.blob.json":
notation blob policy import my_policy.json

Example - Import blob trust policy and override existing configuration without prompt:
notation blob policy import --force my_policy.json
`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return fmt.Errorf("requires 1 argument but received %d.\nUsage: notation blob policy import <path-to-policy.json>\nPlease specify a trust policy file location as the argument", len(args))
return fmt.Errorf("requires 1 argument but received %d.\nUsage: notation blob policy import <path-to-policy.json>\nPlease specify a trust policy configuration location as the argument", len(args))
}
return nil
},
Expand All @@ -70,33 +70,33 @@
return fmt.Errorf("failed to parse blob trust policy configuration: %w", err)
}
if err = doc.Validate(); err != nil {
return fmt.Errorf("failed to validate blob trust policy: %w", err)
return fmt.Errorf("failed to validate blob trust policy configuration: %w", err)
}

// optional confirmation
if !opts.force {
if _, err = trustpolicy.LoadBlobDocument(); err == nil {
confirmed, err := cmdutil.AskForConfirmation(os.Stdin, "The blob trust policy file already exists, do you want to overwrite it?", opts.force)
if _, err = trustpolicy.LoadBlobDocument(); err == nil {
if !opts.force {
confirmed, err := cmdutil.AskForConfirmation(os.Stdin, "The blob trust policy configuration already exists, do you want to overwrite it?", opts.force)
if err != nil {
return err
}
if !confirmed {
return nil
}
} else {
fmt.Fprintln(os.Stderr, "Warning: existing blob trust policy configuration will be overwritten")
}
} else {
fmt.Fprintln(os.Stderr, "Warning: existing blob trust policy file will be overwritten")
}

// write
policyPath, err := dir.ConfigFS().SysPath(dir.PathBlobTrustPolicy)
if err != nil {
return fmt.Errorf("failed to obtain path of blob trust policy file: %w", err)
return fmt.Errorf("failed to obtain path of blob trust policy configuration: %w", err)

Check warning on line 94 in cmd/notation/blob/policy/import.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/blob/policy/import.go#L94

Added line #L94 was not covered by tests
}
if err = osutil.WriteFile(policyPath, policyJSON); err != nil {
return fmt.Errorf("failed to write blob trust policy file: %w", err)
return fmt.Errorf("failed to write blob trust policy configuration: %w", err)
}

_, err = fmt.Fprintln(os.Stdout, "Successfully imported blob trust policy file.")
_, err = fmt.Fprintf(os.Stdout, "Successfully imported blob trust policy configuration to %s.\n", policyPath)
return err
}
18 changes: 3 additions & 15 deletions cmd/notation/blob/policy/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"os"

Expand Down Expand Up @@ -47,10 +46,10 @@ Example - Save current blob trust policy configuration to a file:
}

func runShow() error {
policyJSON, err := loadBlobTrustPolicy()
policyJSON, err := fs.ReadFile(dir.ConfigFS(), dir.PathBlobTrustPolicy)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("failed to show blob trust policy as the trust policy file does not exist.\nYou can import one using `notation blob policy import <path-to-policy.json>`")
return fmt.Errorf("failed to show blob trust policy as the configuration does not exist.\nYou can import one using `notation blob policy import <path-to-policy.json>`")
}
return fmt.Errorf("failed to show trust policy: %w", err)
}
Expand All @@ -59,7 +58,7 @@ func runShow() error {
err = doc.Validate()
}
if err != nil {
fmt.Fprintf(os.Stderr, "Existing blob trust policy file is invalid, you may update or create a new one via `notation blob policy import <path-to-policy.json>`. See https://github.com/notaryproject/specifications/blob/8cf800c60b7315a43f0adbcae463d848a353b412/specs/trust-store-trust-policy.md#trust-policy-for-blobs for a blob trust policy example.\n")
fmt.Fprintf(os.Stderr, "Existing blob trust policy configuration is invalid, you may update or create a new one via `notation blob policy import <path-to-policy.json>`. See https://github.com/notaryproject/specifications/blob/8cf800c60b7315a43f0adbcae463d848a353b412/specs/trust-store-trust-policy.md#trust-policy-for-blobs for a blob trust policy example.\n")
os.Stdout.Write(policyJSON)
return err
}
Expand All @@ -68,14 +67,3 @@ func runShow() error {
_, err = os.Stdout.Write(policyJSON)
return err
}

// loadBlobTrustPolicy loads the blob trust policy from notation configuration
// directory.
func loadBlobTrustPolicy() ([]byte, error) {
f, err := dir.ConfigFS().Open(dir.PathBlobTrustPolicy)
if err != nil {
return nil, err
}
defer f.Close()
return io.ReadAll(f)
}
40 changes: 20 additions & 20 deletions specs/commandline/blob.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

Use `notation blob` command to sign, verify, and inspect signatures associated with arbitrary blobs. Notation can sign and verify any arbitrary bag of bits like zip files, documents, executables, etc. When a user signs a blob, `notation` produces a detached signature, which the user can transport/distribute using any medium that the user prefers along with the original blob. On the verification side, Notation can verify the blob's signature and assert that the blob has not been tampered with during its transmission.

The `notation blob policy` command provides a user-friendly way to manage trust policies for signed blobs. It allows users to show blob trust policy configuration, import/export a blob trust policy configuration file from/to a JSON file. For more details, see [blob trust policy specification and examples](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#blob-trust-policy).
The `notation blob policy` command provides a user-friendly way to manage trust policies for signed blobs. It allows users to show blob trust policy configuration, import/export a blob trust policy configuration from/to a JSON file. For more details, see [blob trust policy specification and examples](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#blob-trust-policy).

The sample trust policy file (`trustpolicy.blob.json`) for verifying signed blobs is shown below. This sample trust policy file, contains three different statements for different use cases:
The sample blob trust policy configuration (`trustpolicy.blob.json`) for verifying signed blobs is shown below. This sample configuration contains three different statements for different use cases:

- The policy named "wabbit-networks-policy" is for verifying blob artifacts signed by Wabbit Networks.
- The policy named "skip-verification-policy" is for skipping verification on blob artifacts.
Expand Down Expand Up @@ -59,7 +59,7 @@ Usage:

Available Commands:
inspect Inspect a signature associated with a blob
policy Manage trust policy configuration for signed blobs
policy Manage blob trust policy configuration for arbitrary blob signature verification
sign Produce a detached signature for a given blob
verify Verify a signature associated with a blob

Expand Down Expand Up @@ -113,14 +113,14 @@ Flags:
### notation blob policy

```text
Manage trust policy configuration for arbitrary blob signature verification.
Manage blob trust policy configuration for arbitrary blob signature verification.

Usage:
notation blob policy [command]

Available Commands:
import import trust policy configuration from a JSON file
show show trust policy configuration
import import blob trust policy configuration from a JSON file
show show blob trust policy configuration

Flags:
-h, --help help for policy
Expand All @@ -135,7 +135,7 @@ Usage:
notation blob policy import [flags] <file_path>

Flags:
--force override the existing trust policy configuration, never prompt
--force override the existing blob trust policy configuration without prompt
-h, --help help for import
```

Expand Down Expand Up @@ -334,29 +334,29 @@ An example output:
notation blob inspect -o json /tmp/my-blob.bin.jws.sig
```

## Import/Export trust policy configuration files
## Import/Export blob trust policy configuration

### Import blob trust policy configuration from a JSON file

An example of import trust policy configuration from a JSON file:
An example of importing trust policy configuration from a JSON file:

```shell
notation blob policy import ./my_policy.json
```

The trust policy configuration in the JSON file should be validated according to [trust policy properties](https://github.com/notaryproject/notaryproject/specs/trust-store-trust-policy.md#blob-trust-policy). A successful message should be printed out if trust policy configuration are imported successfully. Error logs including the reason should be printed out if the importing fails.
The blob trust policy configuration in the JSON file should be validated according to [blob trust policy properties](https://github.com/notaryproject/notaryproject/specs/trust-store-trust-policy.md#blob-trust-policy). A successful message should be printed out if blob trust policy configuration is imported successfully. Error logs including the reason should be printed out if the importing fails.

If there is an existing trust policy configuration, prompt for users to confirm whether discarding existing configuration or not. Users can use `--force` flag to discard existing trust policy configuration without prompt.
If there is an existing blob trust policy configuration, prompt for users to confirm whether discarding existing configuration or not. Users can use `--force` flag to discard existing blob trust policy configuration without prompt.

### Show blob trust policies

Use the following command to show trust policy configuration:
Use the following command to show blob trust policy configuration:

```shell
notation blob policy show
```

Upon successful execution, the trust policy configuration is printed out to standard output. If trust policy is not configured or is malformed, users should receive an error message via standard error output, and a tip to import trust policy configuration from a JSON file.
Upon successful execution, the blob trust policy configuration is printed out to standard output. If blob trust policy is not configured or is malformed, users should receive an error message via standard error output, and a tip to import blob trust policy configuration from a JSON file.

### Export blob trust policy configuration into a JSON file

Expand All @@ -366,25 +366,25 @@ Users can redirect the output of command `notation blob policy show` to a JSON f
notation blob policy show > ./blob_trust_policy.json
```

### Update trust policy configuration
### Update blob trust policy configuration

The steps to update blob trust policy configuration:

1. Export trust policy configuration into a JSON file.
1. Export blob trust policy configuration into a JSON file.

```shell
notation blob policy show > ./blob_trust_policy.json
```

2. Edit the exported JSON file "blob_trust_policy.json", update trust policy configuration and save the file.
3. Import trust policy configuration from the file.
2. Edit the exported JSON file "blob_trust_policy.json", update blob trust policy configuration and save the file.
3. Import blob trust policy configuration from the JSON file.

```shell
notation blob policy import ./blob_trust_policy.json
```

## Verify blob signatures
The `notation blob verify` command can be used to verify blob signatures. In order to verify signatures, user will need to setup a trust policy file `trustpolicy.blob.json` with policies for blobs. Below are two examples of how a policy configuration file can be setup for verifying blob signatures.
The `notation blob verify` command can be used to verify blob signatures. In order to verify signatures, user will need to setup a blob trust policy configuration `trustpolicy.blob.json` with policies for blobs. Below are two examples of how a policy configuration can be setup for verifying blob signatures.

- The policy named "wabbit-networks-policy" is for verifying blob artifacts signed by Wabbit Networks.
- The policy named "global-verification-policy" is for auditing verification results when user does not set the `--policy-name` flag in `notation blob verify` command.
Expand Down Expand Up @@ -420,15 +420,15 @@ The `notation blob verify` command can be used to verify blob signatures. In ord

### Verify the signature of a blob

Configure trust store and trust policy properly before using `notation blob verify` command.
Configure trust store and blob trust policy configuration properly before using `notation blob verify` command.

```shell

# Prerequisites: Blob and its associated signature is present on the filesystem.
# Configure trust store by adding a certificate file into trust store named "wabbit-network" of type "ca"
notation certificate add --type ca --store wabbit-networks wabbit-networks.crt

# Setup the trust policy in a JSON file named "trustpolicy.blob.json" under directory "{NOTATION_CONFIG}".
# Setup the blob trust policy in a JSON file named "trustpolicy.blob.json" under directory "{NOTATION_CONFIG}".

# Verify the blob signature
notation blob verify --signature /tmp/my-blob.bin.jws.sig /tmp/my-blob.bin
Expand Down
10 changes: 5 additions & 5 deletions test/e2e/suite/command/blob/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ var _ = Describe("blob trust policy maintainer", func() {
Expect(err).NotTo(HaveOccurred())
Host(Opts(AddBlobTrustPolicyOption(policyName)), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("blob", "policy", "show").
MatchErrKeyWords("existing blob trust policy file is invalid").
MatchErrKeyWords("existing blob trust policy configuration is invalid").
MatchContent(string(content))
})
})
Expand Down Expand Up @@ -123,7 +123,7 @@ var _ = Describe("blob trust policy maintainer", func() {

notation.ExpectFailure().
Exec("blob", "policy", "import", filepath.Join(NotationE2ETrustPolicyDir, validBlobTrustPolicyName), "--force").
MatchErrKeyWords("failed to write blob trust policy file")
MatchErrKeyWords("failed to write blob trust policy configuration")
})
})

Expand Down Expand Up @@ -190,7 +190,7 @@ var _ = Describe("blob trust policy maintainer", func() {
Host(Opts(AddBlobTrustPolicyOption("invalid_format_trustpolicy.json")), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
policyFileName := "skip_trustpolicy.json"
notation.Exec("blob", "policy", "import", filepath.Join(NotationE2ETrustPolicyDir, policyFileName)).MatchKeyWords().
MatchKeyWords("Successfully imported blob trust policy file.")
MatchKeyWords("Successfully imported blob trust policy configuration to")
// validate
content, err := os.ReadFile(filepath.Join(NotationE2ETrustPolicyDir, policyFileName))
Expect(err).NotTo(HaveOccurred())
Expand All @@ -202,7 +202,7 @@ var _ = Describe("blob trust policy maintainer", func() {
Host(opts, func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
policyFileName := "skip_trustpolicy.json"
notation.WithInput(strings.NewReader("Y\n")).Exec("blob", "policy", "import", filepath.Join(NotationE2ETrustPolicyDir, policyFileName)).
MatchKeyWords("Successfully imported blob trust policy file.")
MatchKeyWords("Successfully imported blob trust policy configuration to")
// validate
content, err := os.ReadFile(filepath.Join(NotationE2ETrustPolicyDir, policyFileName))
Expect(err).NotTo(HaveOccurred())
Expand All @@ -214,7 +214,7 @@ var _ = Describe("blob trust policy maintainer", func() {
Host(opts, func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
policyFileName := "skip_trustpolicy.json"
notation.Exec("blob", "policy", "import", filepath.Join(NotationE2ETrustPolicyDir, policyFileName), "--force").
MatchKeyWords("Successfully imported blob trust policy file.")
MatchKeyWords("Successfully imported blob trust policy configuration to")
// validate
content, err := os.ReadFile(filepath.Join(NotationE2ETrustPolicyDir, policyFileName))
Expect(err).NotTo(HaveOccurred())
Expand Down
Loading