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

ccl: debug encryption-active-key command to show active store key ID. #35234

Merged
merged 1 commit into from
Feb 27, 2019
Merged
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
89 changes: 84 additions & 5 deletions pkg/ccl/cliccl/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"time"

Expand All @@ -25,12 +27,20 @@ import (
"github.com/cockroachdb/cockroach/pkg/util/protoutil"
"github.com/cockroachdb/cockroach/pkg/util/stop"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

// Defines CCL-specific debug commands, adds the encryption flag to debug commands in
// `pkg/cli/debug.go`, and registers a callback to generate encryption options.

const (
// These constants are defined in libroach. They should NOT be changed.
plaintextKeyID = "plain"
keyRegistryFilename = "COCKROACHDB_DATA_KEYS"
fileRegistryFilename = "COCKROACHDB_REGISTRY"
)

var encryptionStatusOpts struct {
activeStoreIDOnly bool
}
Expand All @@ -51,11 +61,27 @@ and exits.
RunE: cli.MaybeDecorateGRPCError(runEncryptionStatus),
}

// Add it to the root debug command. We can't add it to the lists of commands (eg: DebugCmdsForRocksDB)
// as cli init() is called before us.
encryptionActiveKeyCmd := &cobra.Command{
Use: "encryption-active-key <directory>",
Short: "return ID of the active store key",
Long: `
Display the algorithm and key ID of the active store key for existing data directory 'directory'.
Does not require knowing the key.

Some sample outputs:
Plaintext: # encryption not enabled
AES128_CTR:be235... # AES-128 encryption with store key ID
`,
Args: cobra.ExactArgs(1),
RunE: cli.MaybeDecorateGRPCError(runEncryptionActiveKey),
}

// Add commands to the root debug command.
// We can't add them to the lists of commands (eg: DebugCmdsForRocksDB) as cli init() is called before us.
cli.DebugCmd.AddCommand(encryptionStatusCmd)
cli.DebugCmd.AddCommand(encryptionActiveKeyCmd)

// Add the encryption flag.
// Add the encryption flag to commands that need it.
f := encryptionStatusCmd.Flags()
cli.VarFlag(f, &storeEncryptionSpecs, cliflagsccl.EnterpriseEncryption)
// And other flags.
Expand Down Expand Up @@ -159,7 +185,7 @@ func runEncryptionStatus(cmd *cobra.Command, args []string) error {
fileKeyMap := make(map[string][]string)

for name, entry := range fileRegistry.Files {
keyID := "plain"
keyID := plaintextKeyID

if entry.EnvType != enginepb.EnvType_Plaintext && len(entry.EncryptionSettings) > 0 {
var setting enginepbccl.EncryptionSettings
Expand All @@ -178,7 +204,7 @@ func runEncryptionStatus(cmd *cobra.Command, args []string) error {

for _, dataKey := range keyRegistry.DataKeys {
info := dataKey.Info
parentKey := "plain"
parentKey := plaintextKeyID
if len(info.ParentKeyId) > 0 {
parentKey = info.ParentKeyId
}
Expand Down Expand Up @@ -249,3 +275,56 @@ func runEncryptionStatus(cmd *cobra.Command, args []string) error {

return nil
}

func runEncryptionActiveKey(cmd *cobra.Command, args []string) error {
keyType, keyID, err := getActiveEncryptionkey(args[0])
if err != nil {
return err
}

fmt.Printf("%s:%s\n", keyType, keyID)
return nil
}

// getActiveEncryptionkey opens the file registry directly, bypassing rocksdb.
// This allows looking up the active encryption key ID without knowing it.
func getActiveEncryptionkey(dir string) (string, string, error) {
registryFile := filepath.Join(dir, fileRegistryFilename)

// If the data directory does not exist, we return an error.
if _, err := os.Stat(dir); err != nil {
return "", "", errors.Wrapf(err, "data directory %s does not exist", dir)
}

// Open the file registry. Return plaintext if it does not exist.
contents, err := ioutil.ReadFile(registryFile)
if err != nil {
if os.IsNotExist(err) {
return enginepbccl.EncryptionType_Plaintext.String(), "", nil
}
return "", "", errors.Wrapf(err, "could not open registry file %s", registryFile)
}

var fileRegistry enginepb.FileRegistry
if err := protoutil.Unmarshal(contents, &fileRegistry); err != nil {
return "", "", err
}

// Find the entry for the key registry file.
entry, ok := fileRegistry.Files[keyRegistryFilename]
if !ok {
return "", "", fmt.Errorf("key registry file %s was not found in the file registry", keyRegistryFilename)
}

if entry.EnvType == enginepb.EnvType_Plaintext || len(entry.EncryptionSettings) == 0 {
// Plaintext: no encryption settings to unmarshal.
return enginepbccl.EncryptionType_Plaintext.String(), "", nil
}

var setting enginepbccl.EncryptionSettings
if err := protoutil.Unmarshal(entry.EncryptionSettings, &setting); err != nil {
return "", "", fmt.Errorf("could not unmarshal encryption settings for %s: %v", keyRegistryFilename, err)
}

return setting.EncryptionType.String(), setting.KeyId, nil
}