From b6fbb5d86b38046225b1d1c0bb0ceba5a1622cbc Mon Sep 17 00:00:00 2001 From: ptrus Date: Wed, 17 Jun 2020 12:36:08 +0200 Subject: [PATCH] go/identity/cli: Add show TLS pubkey commands --- .changelog/3015.feature.md | 9 +++ go/oasis-node/cmd/identity/identity.go | 71 +++++++++++++++++++ .../scenario/e2e/identity_cli.go | 28 +++++++- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 .changelog/3015.feature.md diff --git a/.changelog/3015.feature.md b/.changelog/3015.feature.md new file mode 100644 index 00000000000..f5defbdf80c --- /dev/null +++ b/.changelog/3015.feature.md @@ -0,0 +1,9 @@ +go/identity/cli: Add show TLS pubkey commands + +Adds following CLI helpers for displaying TLS public keys: + +- `oasis-node identity show-tls-pubkey --datadir ` for displaying +the public key used in the external node gRPC endpoints. +- `oasis-node identity show-sentry-client-pubkey --datadir ` for +displaying the public key used by the upstream nodes when connecting to the +sentry control endpoint. diff --git a/go/oasis-node/cmd/identity/identity.go b/go/oasis-node/cmd/identity/identity.go index a7b5b2c3805..b7deb5078a2 100644 --- a/go/oasis-node/cmd/identity/identity.go +++ b/go/oasis-node/cmd/identity/identity.go @@ -2,6 +2,8 @@ package identity import ( + "crypto/ed25519" + "crypto/x509" "fmt" "os" @@ -28,6 +30,18 @@ var ( Run: doNodeInit, } + identityShowSentryPubkeyCmd = &cobra.Command{ + Use: "show-sentry-client-pubkey", + Short: "outputs node's sentry control client tls public key", + Run: doShowSentryTLSPubkey, + } + + identityShowTLSPubkeyCmd = &cobra.Command{ + Use: "show-tls-pubkey", + Short: "outputs node's endpoint tls public key", + Run: doShowTLSPubkey, + } + logger = logging.GetLogger("cmd/identity") ) @@ -60,12 +74,69 @@ func doNodeInit(cmd *cobra.Command, args []string) { fmt.Printf("Generated identity files in: %s\n", dataDir) } +func doShowPubkey(cmd *cobra.Command, args []string, sentry bool) { + if err := cmdCommon.Init(); err != nil { + cmdCommon.EarlyLogAndExit(err) + } + + dataDir := cmdCommon.DataDir() + if dataDir == "" { + logger.Error("data directory must be set") + os.Exit(1) + } + + nodeSignerFactory, err := fileSigner.NewFactory(dataDir, signature.SignerNode, signature.SignerP2P, signature.SignerConsensus) + if err != nil { + logger.Error("failed to create node identity signer factory", + "err", err, + ) + os.Exit(1) + } + identity, err := identity.Load(dataDir, nodeSignerFactory) + if err != nil { + cmdCommon.EarlyLogAndExit(err) + } + + var rawCertificate []byte + switch sentry { + case true: + rawCertificate = identity.TLSSentryClientCertificate.Certificate[0] + case false: + rawCertificate = identity.GetTLSCertificate().Certificate[0] + } + cert, err := x509.ParseCertificate(rawCertificate) + if err != nil { + cmdCommon.EarlyLogAndExit(fmt.Errorf("oasis: failed to parse sentry client certificate: %w", err)) + } + pk, ok := cert.PublicKey.(ed25519.PublicKey) + if !ok { + cmdCommon.EarlyLogAndExit(fmt.Errorf("oasis: bad sentry client public key type (expected: Ed25519 got: %T)", cert.PublicKey)) + } + var pubKey signature.PublicKey + if err := pubKey.UnmarshalBinary(pk[:]); err != nil { + cmdCommon.EarlyLogAndExit(fmt.Errorf("oasis: sentry client public key unmarshal failure: %w", err)) + } + key, _ := pubKey.MarshalText() + + fmt.Println(string(key)) +} + +func doShowTLSPubkey(cmd *cobra.Command, args []string) { + doShowPubkey(cmd, args, false) +} + +func doShowSentryTLSPubkey(cmd *cobra.Command, args []string) { + doShowPubkey(cmd, args, true) +} + // Register registers the client sub-command and all of it's children. func Register(parentCmd *cobra.Command) { tendermint.Register(identityCmd) identityInitCmd.Flags().AddFlagSet(cmdFlags.VerboseFlags) identityCmd.AddCommand(identityInitCmd) + identityCmd.AddCommand(identityShowSentryPubkeyCmd) + identityCmd.AddCommand(identityShowTLSPubkeyCmd) parentCmd.AddCommand(identityCmd) } diff --git a/go/oasis-test-runner/scenario/e2e/identity_cli.go b/go/oasis-test-runner/scenario/e2e/identity_cli.go index 3b309dcb893..a224a9a30b9 100644 --- a/go/oasis-test-runner/scenario/e2e/identity_cli.go +++ b/go/oasis-test-runner/scenario/e2e/identity_cli.go @@ -65,7 +65,12 @@ func (ident *identityCLIImpl) Run(childEnv *env.Env) error { if err := ident.loadIdentity(); err != nil { return fmt.Errorf("scenario/e2e/identity_cli: %w", err) } - + if err := ident.showTLSPubkey(childEnv, false); err != nil { + return fmt.Errorf("scenario/e2e/identity_cli: %w", err) + } + if err := ident.showTLSPubkey(childEnv, true); err != nil { + return fmt.Errorf("scenario/e2e/identity_cli: %w", err) + } if err := ident.tendermintShowAddress(childEnv, "node"); err != nil { return fmt.Errorf("scenario/e2e/identity_cli: %w", err) } @@ -89,6 +94,27 @@ func (ident *identityCLIImpl) loadIdentity() error { return nil } +func (ident *identityCLIImpl) showTLSPubkey(childEnv *env.Env, sentry bool) error { + var subCmd string + switch sentry { + case true: + subCmd = "show-sentry-client-pubkey" + case false: + subCmd = "show-tls-pubkey" + } + ident.logger.Info(fmt.Sprintf("running %s", subCmd)) + + args := []string{ + "identity", subCmd, + "--" + common.CfgDataDir, ident.dataDir, + } + nodeBinary, _ := ident.flags.GetString(cfgNodeBinary) + if out, err := cli.RunSubCommandWithOutput(childEnv, ident.logger, subCmd, nodeBinary, args); err != nil { + return fmt.Errorf("failed to run %s: error: %w output: %s", subCmd, err, out.String()) + } + return nil +} + func (ident *identityCLIImpl) tendermintShowAddress(childEnv *env.Env, addrName string) error { subCmd := fmt.Sprintf("show-%s-address", addrName) ident.logger.Info(fmt.Sprintf("running tendermint %s", subCmd))