Skip to content

Commit 0bbb39e

Browse files
authored
Merge pull request #293 from smallstep/mariano/search
Implement search command
2 parents ffc9393 + 85a3560 commit 0bbb39e

10 files changed

Lines changed: 153 additions & 5 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ test:
9999
#########################################
100100

101101
fmt:
102-
$Q goimports --local github.com/smallstep/step-kms-plugin -l -w $(SRC)
102+
$Q goimports --local github.com/smallstep/step-kms-plugin --local go.step.sm/crypto -l -w $(SRC)
103103

104104
lint: golint govulncheck
105105

cmd/attest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131

3232
"github.com/fxamacker/cbor/v2"
3333
"github.com/spf13/cobra"
34+
3435
"go.step.sm/crypto/kms/apiv1"
3536
"go.step.sm/crypto/pemutil"
3637

cmd/certificate.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"strings"
2121

2222
"github.com/spf13/cobra"
23+
2324
"go.step.sm/crypto/kms"
2425
"go.step.sm/crypto/kms/apiv1"
2526
"go.step.sm/crypto/kms/uri"

cmd/create.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"strings"
2424

2525
"github.com/spf13/cobra"
26+
2627
"go.step.sm/crypto/kms/apiv1"
2728
"go.step.sm/crypto/kms/softkms"
2829
"go.step.sm/crypto/kms/tpmkms"

cmd/decrypt.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"os"
2626

2727
"github.com/spf13/cobra"
28+
2829
"go.step.sm/crypto/kms/apiv1"
2930

3031
"github.com/smallstep/step-kms-plugin/internal/flagutil"

cmd/encrypt.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"os"
2525

2626
"github.com/spf13/cobra"
27+
2728
"go.step.sm/crypto/kms/apiv1"
2829

2930
"github.com/smallstep/step-kms-plugin/internal/flagutil"

cmd/key.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"io/fs"
1919

2020
"github.com/spf13/cobra"
21+
2122
"go.step.sm/crypto/kms"
2223

2324
"github.com/smallstep/step-kms-plugin/internal/flagutil"

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"github.com/smallstep/cli-utils/step"
2828
"github.com/spf13/cobra"
29+
2930
"go.step.sm/crypto/kms"
3031
"go.step.sm/crypto/kms/apiv1"
3132
"go.step.sm/crypto/kms/uri"

cmd/search.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package cmd
2+
3+
import (
4+
"encoding/json"
5+
"encoding/pem"
6+
"fmt"
7+
8+
"github.com/spf13/cobra"
9+
10+
"go.step.sm/crypto/kms/apiv1"
11+
"go.step.sm/crypto/pemutil"
12+
13+
"github.com/smallstep/step-kms-plugin/internal/flagutil"
14+
)
15+
16+
var searchCmd = &cobra.Command{
17+
Use: "search <kms-uri>",
18+
Short: "search for keys stored in a KMS and list their names or details",
19+
Long: `Search for one or more keys stored in a Key Management System (KMS).
20+
21+
OUTPUT FORMATS:
22+
By default, this command prints a simple list of key names (URIs), one per line.
23+
Use the --json flag to output detailed information in JSON format, including
24+
each key's name and corresponding public key in PEM format.
25+
26+
SUPPORTED KMS TYPES:
27+
- mackms: macOS Keychain and Secure Enclave (Secure Enclave requires signed binaries)
28+
- tpmkms: Trusted Platform Module (TPM) 2.0
29+
30+
URI SYNTAX:
31+
The <kms-uri> format is: <kms-type>:[query-params]
32+
33+
Query parameters are optional and allow you to filter search results.
34+
Multiple parameters can be combined using standard URI query syntax.
35+
36+
QUERY PARAMETERS:
37+
38+
TPM (tpmkms:)
39+
- ak=true Search only attestation keys (AKs)
40+
- ak=false Search only application keys (non-AKs)
41+
- name=<name> Search for a key with the specified name
42+
- (no param) Search all keys (both AKs and application keys)
43+
44+
macOS Keychain and Secure Enclave (mackms:)
45+
- label=<name> Search keys with the specified label/name
46+
- hash=<hex> Search keys with the given hash (hexadecimal format)
47+
- tag=<tag> Search keys with the given tag (default: com.smallstep.crypto)
48+
- se=true Search only keys on the Secure Enclave (requires signed binary)
49+
- (no param) Search all keys on both Keychain and Secure Enclave`,
50+
Example: ` # Search all keys on macOS Keychain/Secure Enclave:
51+
step-kms-plugin search mackms:
52+
53+
# Search all keys with a custom tag:
54+
step-kms-plugin search mackms:tag=com.example.crypto
55+
56+
# Search all keys (application and attestation keys) on a TPM:
57+
step-kms-plugin search tpmkms:
58+
59+
# Search all keys on a TPM with a custom storage directory:
60+
step-kms-plugin search tpmkms:storage-directory=/tmp/tpmobjects
61+
62+
# Search only attestation keys (AKs) on a TPM:
63+
step-kms-plugin search tpmkms:ak=true
64+
65+
# Search only application keys (non-AKs) on a TPM:
66+
step-kms-plugin search tpmkms:ak=false
67+
68+
# Search TPM keys and output details in JSON format with public keys:
69+
step-kms-plugin search --json tpmkms:ak=false`,
70+
RunE: func(cmd *cobra.Command, args []string) error {
71+
if len(args) != 1 {
72+
return showErrUsage(cmd)
73+
}
74+
75+
flags := cmd.Flags()
76+
77+
kuri, name, err := getURIAndNameForFS(flagutil.MustString(flags, "kms"), args[0])
78+
if err != nil {
79+
return err
80+
}
81+
82+
km, err := openKMS(cmd.Context(), kuri)
83+
if err != nil {
84+
return fmt.Errorf("failed to load key manager: %w", err)
85+
}
86+
defer km.Close()
87+
88+
searchKMS, ok := km.(interface {
89+
SearchKeys(*apiv1.SearchKeysRequest) (*apiv1.SearchKeysResponse, error)
90+
})
91+
if !ok {
92+
return fmt.Errorf("the KMS does not implement the SearchKeys method")
93+
}
94+
95+
results, err := searchKMS.SearchKeys(&apiv1.SearchKeysRequest{
96+
Query: name,
97+
})
98+
if err != nil {
99+
return err
100+
}
101+
102+
if flagutil.MustBool(flags, "json") {
103+
keys := []map[string]any{}
104+
for _, r := range results.Results {
105+
block, err := pemutil.Serialize(r.PublicKey)
106+
if err != nil {
107+
return fmt.Errorf("failed to serialize the public key: %w", err)
108+
}
109+
110+
keys = append(keys, map[string]any{
111+
"name": r.Name,
112+
"publicKey": string(pem.EncodeToMemory(block)),
113+
})
114+
}
115+
116+
b, err := json.MarshalIndent(map[string]any{
117+
"keys": keys,
118+
}, "", " ")
119+
if err != nil {
120+
return fmt.Errorf("failed to marshal: %w", err)
121+
}
122+
fmt.Println(string(b))
123+
} else {
124+
for _, r := range results.Results {
125+
fmt.Println(r.Name)
126+
}
127+
}
128+
129+
return nil
130+
},
131+
}
132+
133+
func init() {
134+
rootCmd.AddCommand(searchCmd)
135+
searchCmd.SilenceUsage = true
136+
137+
flags := searchCmd.Flags()
138+
flags.SortFlags = false
139+
flags.Bool("json", false, "Show the output using JSON")
140+
}

cmd/sign.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ import (
3131
"strings"
3232

3333
"github.com/spf13/cobra"
34-
"go.step.sm/crypto/kms"
35-
"go.step.sm/crypto/kms/apiv1"
36-
"go.step.sm/crypto/kms/pkcs11"
37-
"go.step.sm/crypto/sshutil"
3834
"golang.org/x/crypto/cryptobyte"
3935
"golang.org/x/crypto/cryptobyte/asn1"
4036
"golang.org/x/crypto/ssh"
4137
"golang.org/x/crypto/ssh/agent"
4238

39+
"go.step.sm/crypto/kms"
40+
"go.step.sm/crypto/kms/apiv1"
41+
"go.step.sm/crypto/kms/pkcs11"
42+
"go.step.sm/crypto/sshutil"
43+
4344
"github.com/smallstep/step-kms-plugin/internal/flagutil"
4445
)
4546

0 commit comments

Comments
 (0)