From eee8a85b2a242352b25c86722fdc072cd895aee1 Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Mon, 15 Jan 2024 20:39:51 +0100 Subject: [PATCH] add HMAC API test This commit adds tests for the HMAC server API. It also removes enclave code that is no longer used nor supported. --- api_test.go | 49 ++++++++++++++++++++++++++++++++++++++++ cmd/kes/identity.go | 54 +-------------------------------------------- cmd/kes/key.go | 11 +++------ cmd/kes/main.go | 8 ------- cmd/kes/policy.go | 54 +-------------------------------------------- server.go | 4 ++-- 6 files changed, 56 insertions(+), 124 deletions(-) diff --git a/api_test.go b/api_test.go index 676a1140..59946fe7 100644 --- a/api_test.go +++ b/api_test.go @@ -6,6 +6,7 @@ package kes import ( "bytes" + "crypto/hmac" "errors" "net/http" "runtime" @@ -54,6 +55,7 @@ func TestAPI(t *testing.T) { t.Run("v1/key/import", testImportKey) t.Run("v1/key/describe", testDescribeKey) t.Run("v1/key/generate", testGenerateKey) + t.Run("v1/key/hmac", testHMAC) t.Run("v1/key/encrypt", testEncryptDecryptKey) // also tests decryption t.Run("v1/key/list", testListKeys) t.Run("v1/identity/describe", testDescribeIdentity) @@ -335,6 +337,53 @@ func testGenerateKey(t *testing.T) { } } +func testHMAC(t *testing.T) { + t.Parallel() + + ctx := testContext(t) + srv, url := startServer(ctx, nil) + defer srv.Close() + + message1 := []byte("Hello World") + message2 := []byte("Hello World!") + + client := defaultClient(url) + for i, test := range validNameTests { + err := client.CreateKey(ctx, test.Name) + if err == nil && test.ShouldFail { + t.Errorf("Test %d: setup: creating key '%s' should have failed", i, test.Name) + } + if err != nil && !test.ShouldFail { + t.Errorf("Test %d: setup: failed to create key '%s': %v", i, test.Name, err) + } + + if test.ShouldFail { + continue + } + + sum1, err := client.HMAC(ctx, test.Name, message1) + if err != nil { + t.Errorf("Test %d: failed to compute HMAC with key '%s': %v", i, test.Name, err) + } + sum2, err := client.HMAC(ctx, test.Name, message2) + if err != nil { + t.Errorf("Test %d: failed to compute HMAC with key '%s': %v", i, test.Name, err) + } + if hmac.Equal(sum1, sum2) { + t.Errorf("Test %d: HMACs of different messages are equal: got '%x' and '%x'", i, sum1, sum2) + } + + verifySum, err := client.HMAC(ctx, test.Name, message1) + if err != nil { + t.Errorf("Test %d: failed to compute HMAC with key '%s': %v", i, test.Name, err) + } + + if !hmac.Equal(sum1, verifySum) { + t.Errorf("Test %d: HMACs of equal messages are not equal: got '%x' and '%x'", i, sum1, verifySum) + } + } +} + func testEncryptDecryptKey(t *testing.T) { t.Parallel() diff --git a/cmd/kes/identity.go b/cmd/kes/identity.go index 8171f5d9..72d1297c 100644 --- a/cmd/kes/identity.go +++ b/cmd/kes/identity.go @@ -39,7 +39,6 @@ Commands: of Compute a KES identity from a certificate. info Get information about a KES identity. ls List KES identities. - rm Remove a KES identity. Options: -h, --help Print command line options. @@ -54,7 +53,6 @@ func identityCmd(args []string) { "of": ofIdentityCmd, "info": infoIdentityCmd, "ls": lsIdentityCmd, - "rm": rmIdentityCmd, } if len(args) < 2 { @@ -480,7 +478,6 @@ Options: is detected - colors are automatically disabled if the output goes to a pipe. Possible values: *auto*, never, always. - -e, --enclave Operate within the specified enclave. -h, --help Print command line options. @@ -497,12 +494,10 @@ func lsIdentityCmd(args []string) { jsonFlag bool colorFlag colorOption insecureSkipVerify bool - enclaveName string ) cmd.BoolVar(&jsonFlag, "json", false, "Print identities in JSON format") cmd.Var(&colorFlag, "color", "Specify when to use colored output") cmd.BoolVarP(&insecureSkipVerify, "insecure", "k", false, "Skip TLS certificate validation") - cmd.StringVarP(&enclaveName, "enclave", "e", "", "Operate within the specified enclave") if err := cmd.Parse(args[1:]); err != nil { if errors.Is(err, flag.ErrHelp) { os.Exit(2) @@ -522,7 +517,7 @@ func lsIdentityCmd(args []string) { ctx, cancelCtx := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) defer cancelCtx() - enclave := newEnclave(enclaveName, insecureSkipVerify) + enclave := newClient(insecureSkipVerify) iter := &kes.ListIter[kes.Identity]{ NextFunc: enclave.ListIdentities, } @@ -556,50 +551,3 @@ func lsIdentityCmd(args []string) { } fmt.Print(buf) } - -const rmIdentityCmdUsage = `Usage: - kes identity rm ... - -Options: - -k, --insecure Skip TLS certificate validation. - -e, --enclave Operate within the specified enclave. - - -h, --help Print command line options. - -Examples: - $ kes identity rm 736bf58626441e3e134a2daf2e6a8441b40e1abc0eac510878168c8aac9f2b0b -` - -func rmIdentityCmd(args []string) { - cmd := flag.NewFlagSet(args[0], flag.ContinueOnError) - cmd.Usage = func() { fmt.Fprint(os.Stderr, rmIdentityCmdUsage) } - - var ( - insecureSkipVerify bool - enclaveName string - ) - cmd.BoolVarP(&insecureSkipVerify, "insecure", "k", false, "Skip TLS certificate validation") - cmd.StringVarP(&enclaveName, "enclave", "e", "", "Operate within the specified enclave") - if err := cmd.Parse(args[1:]); err != nil { - if errors.Is(err, flag.ErrHelp) { - os.Exit(2) - } - cli.Fatalf("%v. See 'kes identity rm --help'", err) - } - if cmd.NArg() == 0 { - cli.Fatal("no identity specified. See 'kes identity rm --help'") - } - - client := newClient(insecureSkipVerify) - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) - defer cancel() - - for _, identity := range cmd.Args() { - if err := client.DeleteIdentity(ctx, kes.Identity(identity)); err != nil { - if errors.Is(err, context.Canceled) { - os.Exit(1) - } - cli.Fatalf("failed to remove identity %q: %v", identity, err) - } - } -} diff --git a/cmd/kes/key.go b/cmd/kes/key.go index caf04c50..3e341c1d 100644 --- a/cmd/kes/key.go +++ b/cmd/kes/key.go @@ -132,7 +132,6 @@ const importKeyCmdUsage = `Usage: Options: -k, --insecure Skip TLS certificate validation. - -e, --enclave Operate within the specified enclave. -h, --help Print command line options. @@ -144,12 +143,8 @@ func importKeyCmd(args []string) { cmd := flag.NewFlagSet(args[0], flag.ContinueOnError) cmd.Usage = func() { fmt.Fprint(os.Stderr, importKeyCmdUsage) } - var ( - insecureSkipVerify bool - enclaveName string - ) + var insecureSkipVerify bool cmd.BoolVarP(&insecureSkipVerify, "insecure", "k", false, "Skip TLS certificate validation") - cmd.StringVarP(&enclaveName, "enclave", "e", "", "Operate within the specified enclave") if err := cmd.Parse(args[1:]); err != nil { if errors.Is(err, flag.ErrHelp) { os.Exit(2) @@ -174,7 +169,7 @@ func importKeyCmd(args []string) { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) defer cancel() - enclave := newEnclave(enclaveName, insecureSkipVerify) + enclave := newClient(insecureSkipVerify) if err = enclave.ImportKey(ctx, name, &kes.ImportKeyRequest{Key: key}); err != nil { if errors.Is(err, context.Canceled) { os.Exit(1) @@ -313,7 +308,7 @@ func lsKeyCmd(args []string) { ctx, cancelCtx := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) defer cancelCtx() - enclave := newEnclave(enclaveName, insecureSkipVerify) + enclave := newClient(insecureSkipVerify) iter := &kes.ListIter[string]{ NextFunc: enclave.ListKeys, } diff --git a/cmd/kes/main.go b/cmd/kes/main.go index cda5ac1c..ef38fd5b 100644 --- a/cmd/kes/main.go +++ b/cmd/kes/main.go @@ -227,14 +227,6 @@ func newClient(insecureSkipVerify bool) *kes.Client { }) } -func newEnclave(name string, insecureSkipVerify bool) *kes.Enclave { - client := newClient(insecureSkipVerify) - if name == "" { - name = os.Getenv("KES_ENCLAVE") - } - return client.Enclave(name) -} - func isTerm(f *os.File) bool { return term.IsTerminal(int(f.Fd())) } func decodePrivateKey(pemBlock []byte) (*pem.Block, error) { diff --git a/cmd/kes/policy.go b/cmd/kes/policy.go index 49784a2c..ffa3f6b8 100644 --- a/cmd/kes/policy.go +++ b/cmd/kes/policy.go @@ -41,7 +41,6 @@ func policyCmd(args []string) { subCmds := commands{ "info": infoPolicyCmd, "ls": lsPolicyCmd, - "rm": rmPolicyCmd, "show": showPolicyCmd, } if len(args) < 2 { @@ -76,7 +75,6 @@ Options: is detected - colors are automatically disabled if the output goes to a pipe. Possible values: *auto*, never, always. - -e, --enclave Operate within the specified enclave. -h, --help Print command line options. @@ -93,12 +91,10 @@ func lsPolicyCmd(args []string) { jsonFlag bool colorFlag colorOption insecureSkipVerify bool - enclaveName string ) cmd.BoolVar(&jsonFlag, "json", false, "Print identities in JSON format") cmd.Var(&colorFlag, "color", "Specify when to use colored output") cmd.BoolVarP(&insecureSkipVerify, "insecure", "k", false, "Skip TLS certificate validation") - cmd.StringVarP(&enclaveName, "enclave", "e", "", "Operate within the specified enclave") if err := cmd.Parse(args[1:]); err != nil { if errors.Is(err, flag.ErrHelp) { os.Exit(2) @@ -118,7 +114,7 @@ func lsPolicyCmd(args []string) { ctx, cancelCtx := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) defer cancelCtx() - enclave := newEnclave(enclaveName, insecureSkipVerify) + enclave := newClient(insecureSkipVerify) iter := &kes.ListIter[string]{ NextFunc: enclave.ListPolicies, } @@ -152,54 +148,6 @@ func lsPolicyCmd(args []string) { fmt.Print(buf) } -const rmPolicyCmdUsage = `Usage: - kes policy rm [options] ... - -Options: - -k, --insecure Skip TLS certificate validation. - -e, --enclave Operate within the specified enclave. - - -h, --help Print command line options. - -Examples: - $ kes policy delete my-policy - $ kes policy delete my-policy1, my-policy2 -` - -func rmPolicyCmd(args []string) { - cmd := flag.NewFlagSet(args[0], flag.ContinueOnError) - cmd.Usage = func() { fmt.Fprint(os.Stderr, rmPolicyCmdUsage) } - - var ( - insecureSkipVerify bool - enclaveName string - ) - cmd.BoolVarP(&insecureSkipVerify, "insecure", "k", false, "Skip TLS certificate validation") - cmd.StringVarP(&enclaveName, "enclave", "e", "", "Operate within the specified enclave") - if err := cmd.Parse(args[1:]); err != nil { - if errors.Is(err, flag.ErrHelp) { - os.Exit(2) - } - cli.Fatalf("%v. See 'kes policy rm --help'", err) - } - if cmd.NArg() == 0 { - cli.Fatal("no policy name specified. See 'kes policy rm --help'") - } - - ctx, cancelCtx := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) - defer cancelCtx() - - client := newClient(insecureSkipVerify) - for _, name := range cmd.Args() { - if err := client.DeletePolicy(ctx, name); err != nil { - if errors.Is(err, context.Canceled) { - os.Exit(1) - } - cli.Fatalf("failed to delete policy %q: %v", name, err) - } - } -} - const infoPolicyCmdUsage = `Usage: kes policy info [options] diff --git a/server.go b/server.go index fe2b7d4a..86c4bf89 100644 --- a/server.go +++ b/server.go @@ -924,8 +924,8 @@ func (s *Server) hmacKey(resp *api.Response, req *api.Request) { return } - api.ReplyWith(resp, http.StatusOK, api.DecryptKeyResponse{ - Plaintext: key.HMACKey.Sum(body.Message), + api.ReplyWith(resp, http.StatusOK, api.HMACResponse{ + Sum: key.HMACKey.Sum(body.Message), }) }