Skip to content

Commit

Permalink
Add encryption support to sysdump.
Browse files Browse the repository at this point in the history
Adds a '--encrypt' flag (defaulting to true) that encrypts the resulting
zip file with either the bundled public key or the public key specified
via '--encryption-key'.

Signed-off-by: Bruno Miguel Custódio <brunomcustodio@gmail.com>
  • Loading branch information
bmcustodio committed Jun 9, 2021
1 parent 94cba86 commit 4ce19f5
Show file tree
Hide file tree
Showing 37 changed files with 7,671 additions and 8 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/mholt/archiver/v3 v3.5.0
github.com/spf13/cobra v1.1.1
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
google.golang.org/grpc v1.34.0
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
k8s.io/api v0.19.11
Expand Down
6 changes: 6 additions & 0 deletions internal/cli/cmd/sysdump.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ func newCmdSysdump() *cobra.Command {
cmd.Flags().IntVar(&sysdumpOptions.WorkerCount,
"worker-count", sysdump.DefaultWorkerCount,
"The number of workers to use")
cmd.Flags().BoolVar(&sysdumpOptions.Encrypt,
"encrypt", sysdump.DefaultEncrypt,
"Whether to encrypt the resulting zip file")
cmd.Flags().StringVar(&sysdumpOptions.EncryptionKey,
"encryption-key", sysdump.DefaultEncryptionKey,
"The path to the OpenPGP-compliant public key to use for encrypting the resulting zip file. Defaults to an embeded OpenPGP-compliant public key")

return cmd
}
1 change: 1 addition & 0 deletions sysdump/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const (
kubernetesServicesFileName = "k8s-services-<ts>.yaml"
kubernetesVersionInfoFileName = "k8s-version-<ts>.txt"
timestampPlaceholderFileName = "<ts>"
outputZipFilename = "cilium-sysdump-<ts>.zip"
)

const (
Expand Down
2 changes: 2 additions & 0 deletions sysdump/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const (
DefaultCiliumOperatorLabelSelector = "io.cilium/app=operator"
DefaultCiliumOperatorNamespace = DefaultCiliumNamespace
DefaultDebug = false
DefaultEncrypt = true
DefaultEncryptionKey = ""
DefaultHubbleLabelSelector = labelPrefix + "hubble"
DefaultHubbleNamespace = DefaultCiliumNamespace
DefaultHubbleRelayLabelSelector = labelPrefix + "hubble-relay"
Expand Down
83 changes: 83 additions & 0 deletions sysdump/encryption.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2021 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sysdump

import (
"bytes"
_ "embed"
"io"
"os"
"path/filepath"
"time"

"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
)

//go:embed pubkey.gpg
var pubKey []byte

func createEncryptedZipFile(pathToZipFile string, pathToEncryptionKey string) (string, error) {
// Read the destination entity.
e, err := readDestinationEntity(pathToEncryptionKey)
if err != nil {
return "", err
}
// Create the destination file.
d := pathToZipFile + ".gpg"
o, err := os.Create(d)
if err != nil {
return "", err
}
// Encrypt the zip file.
h := &openpgp.FileHints{
FileName: filepath.Base(pathToZipFile),
IsBinary: true,
ModTime: time.Now(),
}
encOut, err := openpgp.Encrypt(o, []*openpgp.Entity{e}, nil, h, nil)
if err != nil {
return "", err
}
defer encOut.Close()
i, err := os.Open(pathToZipFile)
if err != nil {
return "", err
}
r, err := io.ReadAll(i)
if err != nil {
return "", err
}
if _, err = encOut.Write(r); err != nil {
return "", err
}
// Return the path to the encrypted file.
return d, nil
}

func readDestinationEntity(pathToEncryptionKey string) (*openpgp.Entity, error) {
var r io.Reader
switch pathToEncryptionKey {
case DefaultEncryptionKey:
r = bytes.NewReader(pubKey)
default:
k, err := os.Open(pathToEncryptionKey)
if err != nil {
return nil, err
}
r = k
}
return openpgp.ReadEntity(packet.NewReader(r))
}
Binary file added sysdump/pubkey.gpg
Binary file not shown.
40 changes: 33 additions & 7 deletions sysdump/sysdump.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ type Options struct {
CiliumOperatorNamespace string
// Whether to enable debug logging.
Debug bool
// Whether to encrypt the resulting zip file.
Encrypt bool
// The path to the OpenPGP-compliant public key to use for encrypting the resulting zip file.
EncryptionKey string
// The labels used to target Hubble pods.
HubbleLabelSelector string
// The namespace Hubble is running in.
Expand Down Expand Up @@ -668,14 +672,10 @@ func (c *Collector) Run() error {
}

// Create the zip file in the current directory.
c.log("🗳 Compiling sysdump")
p, err := os.Getwd()
c.log("🗳 Archiving sysdump")
f, err := c.createOutputFile(d, absoluteTempPath)
if err != nil {
return fmt.Errorf("failed to get current directory: %w", err)
}
f := filepath.Join(p, replaceTimestamp(c.options.OutputFileName)+".zip")
if err := archiver.Archive([]string{d}, f); err != nil {
return fmt.Errorf("failed to create zip file: %w", err)
return fmt.Errorf("failed to create output: %w", err)
}
c.log("✅ The sysdump has been saved to %s", f)

Expand All @@ -687,6 +687,32 @@ func (c *Collector) Run() error {
return nil
}

func (c *Collector) createOutputFile(d string, path func(string) string) (string, error) {
// Create the zip file.
f := path(outputZipFilename)
if err := archiver.Archive([]string{d}, f); err != nil {
return "", fmt.Errorf("failed to create zip file: %w", err)
}
// Encrypt it if asked to.
if c.options.Encrypt {
e, err := createEncryptedZipFile(f, c.options.EncryptionKey)
if err != nil {
return "", fmt.Errorf("failed to encrypt zip file: %w", err)
}
f = e
}
// Move the output file to the current directory.
p, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get current directory: %w", err)
}
r := filepath.Join(p, filepath.Base(f))
if err := os.Rename(f, r); err != nil {
return "", fmt.Errorf("failed to move zip file: %w", err)
}
return r, nil
}

func (c *Collector) log(msg string, args ...interface{}) {
fmt.Fprintf(c.options.Writer, msg+"\n", args...)
}
Expand Down
1 change: 0 additions & 1 deletion sysdump/tasks.go

This file was deleted.

Loading

0 comments on commit 4ce19f5

Please sign in to comment.