Skip to content

Commit

Permalink
feat(redactors): Run redactors on an existing support bundle (#887)
Browse files Browse the repository at this point in the history
* feat(redactors): Run redactors on an existing support bundle

Add redact subcommand to support-bundle to allow running redactors on an
existing bundle to creating a new redacted bundle.

The command will be launched like so

support-bundle redact <redactor urls> --bundle support-bundle.tar.gz

Fixes: #705
  • Loading branch information
banjoh authored Jan 3, 2023
1 parent d73d5c6 commit a523551
Show file tree
Hide file tree
Showing 33 changed files with 502 additions and 154 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ sbom/

# Ignore generated support bundles
*.tar.gz
!testdata/supportbundle/*.tar.gz
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ endef

BUILDFLAGS = -tags "netgo containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" -installsuffix netgo

all: test support-bundle preflight collect
all: test support-bundle preflight collect analyze

.PHONY: ffi
ffi: fmt vet
Expand Down Expand Up @@ -202,8 +202,8 @@ scan:

.PHONY: lint
lint:
golangci-lint run -c .golangci.yaml
golangci-lint run --new -c .golangci.yaml pkg/... cmd/...

.PHONY: lint-and-fix
lint-and-fix:
golangci-lint run --fix -c .golangci.yaml
golangci-lint run --new --fix -c .golangci.yaml pkg/... cmd/...
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ To run a sample preflight check from a sample application, install the preflight
```
curl https://krew.sh/preflight | bash
```
and run, where https://preflight.replicated.com provides an **example** preflight spec:
and run, where https://preflight.replicated.com provides an **example** preflight spec:

```
kubectl preflight https://preflight.replicated.com
```

**NOTE** this is an example. Do **not** use to validate real scenarios.
**NOTE** this is an example. Do **not** use to validate real scenarios.

For more details on creating the custom resource files that drive preflight checks, visit [creating preflight checks](https://troubleshoot.sh/docs/preflight/introduction/).

Expand All @@ -31,13 +31,13 @@ To collect a sample support bundle, install the troubleshoot kubectl plugin:
```
curl https://krew.sh/support-bundle | bash
```
and run, where https://support-bundle.replicated.com provides an **example** support bundle spec:
and run, where https://support-bundle.replicated.com provides an **example** support bundle spec:

```
kubectl support-bundle https://support-bundle.replicated.com
```

**NOTE** this is an example. Do **not** use to validate real scenarios.
**NOTE** this is an example. Do **not** use to validate real scenarios.

For more details on creating the custom resource files that drive support-bundle collection, visit [creating collectors](https://troubleshoot.sh/docs/collect/) and [creating analyzers](https://troubleshoot.sh/docs/analyze/).

Expand All @@ -47,9 +47,9 @@ And see our other tool [sbctl](https://github.com/replicatedhq/sbctl) that makes

For questions about using Troubleshoot, there's a [Replicated Community](https://help.replicated.com/community) forum, and a [#app-troubleshoot channel in Kubernetes Slack](https://kubernetes.slack.com/channels/app-troubleshoot).

# Software Bill of Materials
A signed SBOM that includes Troubleshoot dependencies is included in each release.
- **troubleshoot-sbom.tgz** contains a software bill of materials for Troubleshoot.
# Software Bill of Materials
A signed SBOM that includes Troubleshoot dependencies is included in each release.
- **troubleshoot-sbom.tgz** contains a software bill of materials for Troubleshoot.
- **troubleshoot-sbom.tgz.sig** is the digital signature for troubleshoot-sbom.tgz
- **key.pub** is the public key from the key pair used to sign troubleshoot-sbom.tgz

Expand Down
17 changes: 8 additions & 9 deletions cmd/collect/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,15 @@ func runCollect(v *viper.Viper, arg string) error {
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode

additionalRedactors := &troubleshootv1beta2.Redactor{}
for idx, redactor := range v.GetStringSlice("redactors") {
redactorObj, err := supportbundle.GetRedactorFromURI(redactor)
if err != nil {
return errors.Wrapf(err, "failed to get redactor spec %s, #%d", redactor, idx)
}
redactors, err := supportbundle.GetRedactorsFromURIs(v.GetStringSlice("redactors"))
if err != nil {
return errors.Wrap(err, "failed to get redactors")
}

if redactorObj != nil {
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactorObj.Spec.Redactors...)
}
additionalRedactors := &troubleshootv1beta2.Redactor{
Spec: troubleshootv1beta2.RedactorSpec{
Redactors: redactors,
},
}

for i, additionalDoc := range multidocs {
Expand Down
85 changes: 85 additions & 0 deletions cmd/troubleshoot/cli/redact.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package cli

import (
"fmt"
"os"
"time"

"github.com/pkg/errors"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/replicatedhq/troubleshoot/pkg/supportbundle"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func Redact() *cobra.Command {
cmd := &cobra.Command{
Use: "redact [urls...]",
Args: cobra.MinimumNArgs(1), // TODO
Short: "Redact information from a generated support bundle archive",
Long: `Redaction is the process of masking sensitive information from collected data in a support bundle.
This is done using rules defined in the list of redactor manifests provided in the [urls...] command line
argument. Default built in redactors will also be run, but these would have been run when the support
bundle was generated. After redaction, the support bundle is archived once more. The resulting file will
be stored in the current directory in the path provided by the --output flag.
The [urls...] argument is a list of either oci://.., http://.., https://.. or local paths to yaml files.
For more information on redactors visit https://troubleshoot.sh/docs/redact/
`,
PreRunE: func(cmd *cobra.Command, args []string) error {
return viper.BindPFlags(cmd.Flags())
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()

logger.SetQuiet(v.GetBool("quiet"))

// 1. Decode redactors from provided URLs
redactors, err := supportbundle.GetRedactorsFromURIs(args)
if err != nil {
return err
}

// 2. Download the bundle and extract it
tmpDir, bundleDir, err := analyzer.DownloadAndExtractSupportBundle(v.GetString("bundle"))
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)

// 3. Represent bundle as a CollectorResult
collectorResult, err := collect.CollectorResultFromBundle(bundleDir)
if err != nil {
return err
}

// 4. Perform redaction on the bundle
err = collect.RedactResult(bundleDir, collectorResult, redactors)
if err != nil {
return errors.Wrap(err, "failed to redact support bundle")
}

// 5. Compress the bundle once more after redacting
output := v.GetString("output")
if output == "" {
output = fmt.Sprintf("redacted-support-bundle-%s.tar.gz", time.Now().Format("2006-01-02T15_04_05"))
}
err = collectorResult.ArchiveSupportBundle(bundleDir, output)
if err != nil {
return errors.Wrap(err, "failed to create support bundle archive")
}
fmt.Println("Redacted support bundle:", output)
return nil
},
}

cmd.Flags().String("bundle", "", "file path of the support bundle archive to redact")
cmd.MarkFlagRequired("bundle")
cmd.Flags().BoolP("quiet", "q", false, "enable/disable error messaging and only show parseable output")
cmd.Flags().StringP("output", "o", "", "file path of where to save the redacted support bundle archive (default \"redacted-support-bundle-YYYY-MM-DDTHH_MM_SS.tar.gz\")")

return cmd
}
3 changes: 2 additions & 1 deletion cmd/troubleshoot/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "support-bundle [url]",
Use: "support-bundle [urls...]",
Args: cobra.MinimumNArgs(0),
Short: "Generate a support bundle",
Long: `A support bundle is an archive of files, output, metrics and state
Expand All @@ -40,6 +40,7 @@ from a server that can be used to assist when troubleshooting a Kubernetes clust
cobra.OnInitialize(initConfig)

cmd.AddCommand(Analyze())
cmd.AddCommand(Redact())
cmd.AddCommand(VersionCmd())

cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
Expand Down
13 changes: 4 additions & 9 deletions cmd/troubleshoot/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,11 @@ func runTroubleshoot(v *viper.Viper, arg []string) error {
return errors.New("no collectors specified in support bundle")
}

for idx, redactor := range v.GetStringSlice("redactors") {
redactorObj, err := supportbundle.GetRedactorFromURI(redactor)
if err != nil {
return errors.Wrapf(err, "failed to get redactor spec %s, #%d", redactor, idx)
}

if redactorObj != nil {
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactorObj.Spec.Redactors...)
}
redactors, err := supportbundle.GetRedactorsFromURIs(v.GetStringSlice("redactors"))
if err != nil {
return errors.Wrap(err, "failed to get redactors")
}
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactors...)

var collectorCB func(chan interface{}, string)
progressChan := make(chan interface{}) // non-zero buffer can result in missed messages
Expand Down
5 changes: 2 additions & 3 deletions cmd/troubleshoot/cli/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path/filepath"

troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/constants"
"github.com/replicatedhq/troubleshoot/pkg/version"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
Expand All @@ -26,8 +27,6 @@ func VersionCmd() *cobra.Command {
return cmd
}

const VersionFilename = "version.yaml"

func writeVersionFile(path string) error {
version := troubleshootv1beta2.SupportBundleVersion{
ApiVersion: "troubleshoot.sh/v1beta2",
Expand All @@ -41,7 +40,7 @@ func writeVersionFile(path string) error {
return err
}

filename := filepath.Join(path, VersionFilename)
filename := filepath.Join(path, constants.VersionFilename)
err = ioutil.WriteFile(filename, b, 0644)
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions docs/preflight.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ preflight [url] [flags]
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "/Users/xavpaice/.kube/cache")
--cache-dir string Default cache directory (default "$HOME/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
Expand Down Expand Up @@ -48,4 +48,4 @@ preflight [url] [flags]

* [preflight version](preflight_version.md) - Print the current version and exit

###### Auto generated by spf13/cobra on 21-Nov-2022
###### Auto generated by spf13/cobra on 22-Dec-2022
2 changes: 1 addition & 1 deletion docs/preflight_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ preflight version [flags]

* [preflight](preflight.md) - Run and retrieve preflight checks in a cluster

###### Auto generated by spf13/cobra on 21-Nov-2022
###### Auto generated by spf13/cobra on 22-Dec-2022
11 changes: 6 additions & 5 deletions docs/support-bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ A support bundle is an archive of files, output, metrics and state
from a server that can be used to assist when troubleshooting a Kubernetes cluster.

```
support-bundle [url] [flags]
support-bundle [urls...] [flags]
```

### Options
Expand All @@ -17,7 +17,7 @@ support-bundle [url] [flags]
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "/Users/xavpaice/.kube/cache")
--cache-dir string Default cache directory (default "$HOME/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
Expand Down Expand Up @@ -47,7 +47,8 @@ support-bundle [url] [flags]

### SEE ALSO

* [support-bundle analyze](support-bundle_analyze.md) - analyze a support bundle
* [support-bundle version](support-bundle_version.md) - Print the current version and exit
* [support-bundle analyze](support-bundle_analyze.md) - analyze a support bundle
* [support-bundle redact](support-bundle_redact.md) - Redact information from a generated support bundle archive
* [support-bundle version](support-bundle_version.md) - Print the current version and exit

###### Auto generated by spf13/cobra on 21-Nov-2022
###### Auto generated by spf13/cobra on 22-Dec-2022
2 changes: 1 addition & 1 deletion docs/support-bundle_analyze.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ support-bundle analyze [url] [flags]

* [support-bundle](support-bundle.md) - Generate a support bundle

###### Auto generated by spf13/cobra on 21-Nov-2022
###### Auto generated by spf13/cobra on 22-Dec-2022
35 changes: 35 additions & 0 deletions docs/support-bundle_redact.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## support-bundle redact

Redact information from a generated support bundle archive

### Synopsis

Redaction is the process of masking sensitive information from collected data in a support bundle.
This is done using rules defined in the list of redactor manifests provided in the [urls...] command line
argument. Default built in redactors will also be run, but these would have been run when the support
bundle was generated. After redaction, the support bundle is archived once more. The resulting file will
be stored in the current directory in the path provided by the --output flag.

The [urls...] argument is a list of either oci://.., http://.., https://.. or local paths to yaml files.

For more information on redactors visit https://troubleshoot.sh/docs/redact/


```
support-bundle redact [urls...] [flags]
```

### Options

```
--bundle string file path of the support bundle archive to redact
-h, --help help for redact
-o, --output string file path of where to save the redacted support bundle archive (default "redacted-support-bundle-YYYY-MM-DDTHH_MM_SS.tar.gz")
-q, --quiet enable/disable error messaging and only show parseable output
```

### SEE ALSO

* [support-bundle](support-bundle.md) - Generate a support bundle

###### Auto generated by spf13/cobra on 22-Dec-2022
2 changes: 1 addition & 1 deletion docs/support-bundle_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ support-bundle version [flags]

* [support-bundle](support-bundle.md) - Generate a support bundle

###### Auto generated by spf13/cobra on 21-Nov-2022
###### Auto generated by spf13/cobra on 22-Dec-2022
10 changes: 10 additions & 0 deletions examples/redact/e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: troubleshoot.sh/v1beta2
kind: Redactor
metadata:
name: e2e-redactor
spec:
redactors:
- name: redact-static-text
removals:
values:
- static
24 changes: 24 additions & 0 deletions internal/testutils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package testutils

import (
"os"
"path/filepath"
"runtime"
"testing"

"github.com/stretchr/testify/require"
)

func GetTestFixture(t *testing.T, path string) string {
t.Helper()
p := filepath.Join("../../testdata", path)
b, err := os.ReadFile(p)
require.NoError(t, err)
return string(b)
}

// FileDir returns the directory of the current source file.
func FileDir() string {
_, filename, _, _ := runtime.Caller(0)
return filepath.Dir(filename)
}
Loading

0 comments on commit a523551

Please sign in to comment.