Skip to content

Commit 5ab29be

Browse files
ldesauwgbahezreinessebz
authored
Secret API v2 (#56)
* feat(secretv2): add secret v2 implementation * feat(secrets): add venom test * chore: add test on preprod * feat(secrets): add test config secrets v2 * feat(secret): factorize code for secrets version * feat(secret): add test list * fix(secret): add info in venom test * fix(secret): add Metadata Version * fix(test): read restriction on token * fix(secret): allow update without new data * fix: secret version parameter * chore: add use examples for secrets commands (#111) * feat: update OKMS 2.5 (#130) * feat(sdk): sdk v0.5.1 * fix: tests --------- Co-authored-by: Gabriel Bahezre <[email protected]> Co-authored-by: inessebz <[email protected]> Co-authored-by: gbahezre <[email protected]>
1 parent 3663bfe commit 5ab29be

File tree

33 files changed

+1293
-91
lines changed

33 files changed

+1293
-91
lines changed

.github/workflows/test.yaml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,57 @@ jobs:
5959
./tests/out/coverage.txt
6060
./tests/out/coverage.html
6161
retention-days: 5
62+
63+
test-preprod:
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@v4
67+
- uses: ./.github/actions/setup-build-env
68+
- name: Build CLI
69+
run: go build -cover ./cmd/okms
70+
- name: Setup Venom
71+
run: |
72+
wget https://github.com/ovh/venom/releases/download/v1.2.0/venom.linux-amd64
73+
mv venom.linux-amd64 venom
74+
chmod +x venom
75+
- name: Setup okms config file
76+
run: |
77+
echo "${{secrets.KMS_PREPROD_CERTIFICATE}}" > tls.crt
78+
echo "${{secrets.KMS_PREPROD_PRIVATEKEY}}" > tls.key
79+
cat > okms.yaml <<-EOF
80+
version: 1
81+
profile: default
82+
profiles:
83+
default: # default profile
84+
http:
85+
endpoint: ${{secrets.KMS_PREPROD_ENDPOINT}}
86+
auth:
87+
type: mtls
88+
cert: $(pwd)/tls.crt
89+
key: $(pwd)/tls.key
90+
kmip:
91+
endpoint: ${{secrets.KMS_PREPROD_KMIP_ENDPOINT}}
92+
auth:
93+
type: mtls
94+
cert: $(pwd)/tls.crt
95+
key: $(pwd)/tls.key
96+
EOF
97+
- name: Test connectivity to KMS dmain
98+
run: ./okms keys ls -d -c okms.yaml
99+
- name: Execute tests
100+
run: make -C tests
101+
- uses: actions/upload-artifact@v4
102+
with:
103+
name: test_results_preprod
104+
path: |
105+
./tests/out/test_results.html
106+
./tests/out/venom.log
107+
retention-days: 5
108+
if: always()
109+
- uses: actions/upload-artifact@v4
110+
with:
111+
name: coverage-preprod
112+
path: |
113+
./tests/out/coverage.txt
114+
./tests/out/coverage.html
115+
retention-days: 5

cmd/okms/common/client.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@ package common
33
import (
44
"os"
55

6+
"github.com/google/uuid"
67
"github.com/ovh/okms-cli/common/config"
78
"github.com/ovh/okms-cli/common/utils/exit"
89
"github.com/ovh/okms-sdk-go"
910
"github.com/spf13/cobra"
1011
)
1112

12-
var ccmRestClient *okms.Client
13+
var (
14+
okmsId uuid.UUID
15+
restClient *okms.Client
16+
)
1317

1418
func Client() *okms.Client {
15-
return ccmRestClient
19+
return restClient
20+
}
21+
22+
func GetOkmsId() uuid.UUID {
23+
return okmsId
1624
}
1725

1826
type CustomizeFunc func(c *cobra.Command) func(*okms.Client)
@@ -28,6 +36,7 @@ func SetupRestApiFlags(command *cobra.Command, cust CustomizeFunc) {
2836
}
2937

3038
config.SetupEndpointFlags(command, "http", func(command *cobra.Command, cfg config.EndpointConfig) {
39+
okmsId = cfg.Auth.GetOkmsId()
3140
clientCfg := okms.ClientConfig{
3241
Timeout: timeout,
3342
TlsCfg: cfg.TlsConfig(""),
@@ -38,7 +47,12 @@ func SetupRestApiFlags(command *cobra.Command, cust CustomizeFunc) {
3847
if *debug {
3948
clientCfg.Middleware = okms.DebugTransport(os.Stderr)
4049
}
41-
ccmRestClient = exit.OnErr2(okms.NewRestAPIClient(cfg.Endpoint, clientCfg))
42-
f(ccmRestClient)
50+
restClient = exit.OnErr2(okms.NewRestAPIClient(cfg.Endpoint, clientCfg))
51+
52+
if cfg.Auth.GetToken() != nil {
53+
restClient.SetCustomHeader("Authorization", "Bearer "+*cfg.Auth.GetToken())
54+
}
55+
56+
f(restClient)
4357
})
4458
}

cmd/okms/configure/root.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,19 @@ func Run(profile string) {
4545
choice := exit.OnErr2(pterm.DefaultInteractiveSelect.WithOptions([]string{"HTTP", "KMIP"}).Show("Select a protocol to configure"))
4646
switch choice {
4747
case "HTTP":
48-
config.ReadUserInput("CA file", "http.ca", profile, config.ValidateFileExists.AllowEmpty())
49-
config.ReadUserInput("Certificate file", "http.auth.cert", profile, config.ValidateFileExists)
50-
config.ReadUserInput("Private key file", "http.auth.key", profile, config.ValidateFileExists)
5148
config.ReadUserInput("Endpoint", "http.endpoint", profile, config.ValidateURL)
49+
config.ReadUserInput("CA file", "http.ca", profile, config.ValidateFileExists.AllowEmpty())
50+
authChoice := exit.OnErr2(pterm.DefaultInteractiveSelect.WithOptions([]string{"mtls", "token"}).Show("Select authentication to configure"))
51+
switch authChoice {
52+
case "mtls":
53+
config.SetConfigKey(profile, "http.auth.type", "mtls")
54+
config.ReadUserInput("Certificate file", "http.auth.cert", profile, config.ValidateFileExists)
55+
config.ReadUserInput("Private key file", "http.auth.key", profile, config.ValidateFileExists)
56+
case "token":
57+
config.SetConfigKey(profile, "http.auth.type", "token")
58+
config.ReadUserInput("Token", "http.auth.token", profile, config.ValidateNotEmpty)
59+
config.ReadUserInput("okmsId", "http.auth.okmsId", profile, config.ValidateUUID)
60+
}
5261
case "KMIP":
5362
config.ReadUserInput("CA file", "kmip.ca", profile, config.ValidateFileExists.AllowEmpty())
5463
config.ReadUserInput("Certificate file", "kmip.auth.cert", profile, config.ValidateFileExists)

cmd/okms/keys/datakeys.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func newGenerateDataKeyFromServiceKeyCmd() *cobra.Command {
3939
Args: cobra.ExactArgs(1),
4040
Run: func(cmd *cobra.Command, args []string) {
4141
keyId := exit.OnErr2(uuid.Parse(args[0]))
42-
plaintext, encrypted := exit.OnErr3(common.Client().GenerateDataKey(cmd.Context(), keyId, name, keySize))
42+
plaintext, encrypted := exit.OnErr3(common.Client().GenerateDataKey(cmd.Context(), common.GetOkmsId(), keyId, name, keySize))
4343
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
4444
output.JsonPrint(map[string]any{
4545
"plain": plaintext,
@@ -66,7 +66,7 @@ DATA-KEY can be either plain text, a '-' to read from stdin, or a filename prefi
6666
Args: cobra.ExactArgs(2),
6767
Run: func(cmd *cobra.Command, args []string) {
6868
keyId := exit.OnErr2(uuid.Parse(args[0]))
69-
plaintext := exit.OnErr2(common.Client().DecryptDataKey(cmd.Context(), keyId, flagsmgmt.StringFromArg(args[1], 8192)))
69+
plaintext := exit.OnErr2(common.Client().DecryptDataKey(cmd.Context(), common.GetOkmsId(), keyId, flagsmgmt.StringFromArg(args[1], 8192)))
7070
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
7171
output.JsonPrint(plaintext)
7272
} else {

cmd/okms/keys/decrypt.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ OUTPUT can be either a filepath, or a "-" for stdout. If not set, output is stdo
4949
}
5050

5151
text := flagsmgmt.BytesFromArg(args[1], 8192)
52-
resp := exit.OnErr2(common.Client().Decrypt(cmd.Context(), keyId, context, string(text)))
52+
resp := exit.OnErr2(common.Client().Decrypt(cmd.Context(), common.GetOkmsId(), keyId, context, string(text)))
5353
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
5454
output.JsonPrint(resp)
5555
} else {
@@ -84,7 +84,7 @@ func wrapDecrypt(ctx context.Context, input, output string, keyId uuid.UUID, key
8484
out := flagsmgmt.WriterFromArg(output)
8585
defer out.Close()
8686

87-
in, err := common.Client().DataKeys(keyId).DecryptStream(ctx, in, keyCtx)
87+
in, err := common.Client().DataKeys(common.GetOkmsId(), keyId).DecryptStream(ctx, in, keyCtx)
8888
if err != nil {
8989
return err
9090
}

cmd/okms/keys/encrypt.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ OUTPUT can be either a filepath, or a "-" for stdout. If not set, output is stdo
5050
return
5151
}
5252
data := flagsmgmt.BytesFromArg(args[1], 8192)
53-
resp := exit.OnErr2(common.Client().Encrypt(cmd.Context(), keyId, context, data))
53+
resp := exit.OnErr2(common.Client().Encrypt(cmd.Context(), common.GetOkmsId(), keyId, context, data))
5454
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
5555
output.JsonPrint(resp)
5656
} else {
@@ -83,7 +83,7 @@ func wrapEncrypt(ctx context.Context, input, output string, keyId uuid.UUID, key
8383
defer out.Close()
8484
}
8585

86-
out, err := common.Client().DataKeys(keyId).EncryptStream(ctx, out, keyCtx, okms.BlockSize4MB)
86+
out, err := common.Client().DataKeys(common.GetOkmsId(), keyId).EncryptStream(ctx, out, keyCtx, okms.BlockSize4MB)
8787
if err != nil {
8888
return err
8989
}

cmd/okms/keys/keys.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import (
2828

2929
func newListServiceKeysCmd() *cobra.Command {
3030
var (
31-
keysPageSize uint32
32-
listAll bool
31+
pageSize uint32
32+
listAll bool
3333
)
3434

3535
cmd := &cobra.Command{
@@ -47,7 +47,7 @@ func newListServiceKeysCmd() *cobra.Command {
4747
if listAll {
4848
stateFilter = types.KeyStatesAll
4949
}
50-
for key, err := range common.Client().ListAllServiceKeys(&keysPageSize, &stateFilter).Iter(cmd.Context()) {
50+
for key, err := range common.Client().ListAllServiceKeys(common.GetOkmsId(), &pageSize, &stateFilter).Iter(cmd.Context()) {
5151
exit.OnErr(err)
5252
keys.ObjectsList = append(keys.ObjectsList, *key)
5353
}
@@ -75,7 +75,7 @@ func newListServiceKeysCmd() *cobra.Command {
7575
},
7676
}
7777

78-
cmd.Flags().Uint32Var(&keysPageSize, "page-size", 100, "Number of keys to fetch per page (between 10 and 500)")
78+
cmd.Flags().Uint32Var(&pageSize, "page-size", 100, "Number of keys to fetch per page (between 10 and 500)")
7979
cmd.Flags().BoolVarP(&listAll, "all", "A", false, "List all keys (including deactivated and deleted ones)")
8080
return cmd
8181
}
@@ -115,7 +115,7 @@ func newAddServiceKeyCmd() *cobra.Command {
115115
body.Size = &keySizeEnum
116116
}
117117

118-
resp := exit.OnErr2(common.Client().CreateImportServiceKey(cmd.Context(), nil, body))
118+
resp := exit.OnErr2(common.Client().CreateImportServiceKey(cmd.Context(), common.GetOkmsId(), nil, body))
119119
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
120120
output.JsonPrint(resp)
121121
} else {
@@ -141,7 +141,7 @@ func newGetServiceKeyCmd() *cobra.Command {
141141
Args: cobra.ExactArgs(1),
142142
Run: func(cmd *cobra.Command, args []string) {
143143
keyId := exit.OnErr2(uuid.Parse(args[0]))
144-
resp := exit.OnErr2(common.Client().GetServiceKey(cmd.Context(), keyId, nil))
144+
resp := exit.OnErr2(common.Client().GetServiceKey(cmd.Context(), common.GetOkmsId(), keyId, nil))
145145
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
146146
output.JsonPrint(resp)
147147
} else {
@@ -159,7 +159,7 @@ func newExportPublicKeyCmd() *cobra.Command {
159159
Args: cobra.ExactArgs(1),
160160
Run: func(cmd *cobra.Command, args []string) {
161161
keyId := exit.OnErr2(uuid.Parse(args[0]))
162-
resp := exit.OnErr2(common.Client().GetServiceKey(cmd.Context(), keyId, utils.PtrTo(types.Jwk)))
162+
resp := exit.OnErr2(common.Client().GetServiceKey(cmd.Context(), common.GetOkmsId(), keyId, utils.PtrTo(types.Jwk)))
163163
if resp.Keys == nil || len(*resp.Keys) == 0 {
164164
exit.OnErr(errors.New("Server returned no key"))
165165
}
@@ -228,10 +228,10 @@ func newImportServiceKeyCmd() *cobra.Command {
228228
key := flagsmgmt.BytesFromArg(args[1], 8192)
229229
var resp *types.GetServiceKeyResponse
230230
if !symmetric {
231-
resp = exit.OnErr2(common.Client().ImportKeyPairPEM(cmd.Context(), key, args[0], keyContext, keyUsage.ToCryptographicUsage()...))
231+
resp = exit.OnErr2(common.Client().ImportKeyPairPEM(cmd.Context(), common.GetOkmsId(), key, args[0], keyContext, keyUsage.ToCryptographicUsage()...))
232232
} else {
233233
k := exit.OnErr2(base64.StdEncoding.DecodeString(string(key)))
234-
resp = exit.OnErr2(common.Client().ImportKey(cmd.Context(), k, args[0], keyContext, keyUsage.ToCryptographicUsage()...))
234+
resp = exit.OnErr2(common.Client().ImportKey(cmd.Context(), common.GetOkmsId(), k, args[0], keyContext, keyUsage.ToCryptographicUsage()...))
235235
}
236236

237237
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
@@ -310,12 +310,12 @@ func newDeleteKeyCmd() *cobra.Command {
310310
continue
311311
}
312312
if force {
313-
if err := common.Client().DeactivateServiceKey(cmd.Context(), keyId, types.Unspecified); err != nil {
313+
if err := common.Client().DeactivateServiceKey(cmd.Context(), common.GetOkmsId(), keyId, types.Unspecified); err != nil {
314314
errs = append(errs, fmt.Errorf("Failed to deactivate key %q: %w", id, err))
315315
continue
316316
}
317317
}
318-
if err := common.Client().DeleteServiceKey(cmd.Context(), keyId); err != nil {
318+
if err := common.Client().DeleteServiceKey(cmd.Context(), common.GetOkmsId(), keyId); err != nil {
319319
errs = append(errs, fmt.Errorf("Failed to delete key %q: %w", id, err))
320320
}
321321
}
@@ -342,7 +342,7 @@ func newDeactivateKeyCmd() *cobra.Command {
342342
errs = append(errs, fmt.Errorf("Invalid Key ID %q: %w", id, err))
343343
continue
344344
}
345-
if err := common.Client().DeactivateServiceKey(cmd.Context(), keyId, revocationReason.RestModel()); err != nil {
345+
if err := common.Client().DeactivateServiceKey(cmd.Context(), common.GetOkmsId(), keyId, revocationReason.RestModel()); err != nil {
346346
errs = append(errs, fmt.Errorf("Failed to deactivate key %q: %w", id, err))
347347
}
348348
}
@@ -366,7 +366,7 @@ func newActivateKeyCmd() *cobra.Command {
366366
errs = append(errs, fmt.Errorf("Invalid Key ID %q: %w", id, err))
367367
continue
368368
}
369-
if err := common.Client().ActivateServiceKey(cmd.Context(), keyId); err != nil {
369+
if err := common.Client().ActivateServiceKey(cmd.Context(), common.GetOkmsId(), keyId); err != nil {
370370
errs = append(errs, fmt.Errorf("Failed to activate key %q: %w", id, err))
371371
}
372372
}
@@ -388,7 +388,7 @@ func newUpdateKeyCmd() *cobra.Command {
388388
if name != "" {
389389
body.Name = name
390390
}
391-
resp := exit.OnErr2(common.Client().UpdateServiceKey(cmd.Context(), keyId, body))
391+
resp := exit.OnErr2(common.Client().UpdateServiceKey(cmd.Context(), common.GetOkmsId(), keyId, body))
392392
printServiceKey(resp)
393393
},
394394
}

cmd/okms/keys/sign.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ In both cases, DATA can be either plain text, a '-' to read from stdin, or a fil
4141
signCmd.Run = func(cmd *cobra.Command, args []string) {
4242
data := readDigest(params.signatureAlgorithm, args[1], "Signing", noProgress)
4343
keyId := exit.OnErr2(uuid.Parse(args[0]))
44-
signature := exit.OnErr2(common.Client().Sign(cmd.Context(), keyId, nil, params.signatureAlgorithm.Alg(), true, data))
44+
signature := exit.OnErr2(common.Client().Sign(cmd.Context(), common.GetOkmsId(), keyId, nil, params.signatureAlgorithm.Alg(), true, data))
4545
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
4646
output.JsonPrint(signature)
4747
} else {
@@ -81,7 +81,7 @@ SIGNATURE can also be passed from a file or stdin using '-' or '@'. Stdin can ho
8181
signature := flagsmgmt.StringFromArg(args[2], 8192)
8282
keyId := exit.OnErr2(uuid.Parse(args[0]))
8383
if !local {
84-
valid := exit.OnErr2(common.Client().Verify(cmd.Context(), keyId, params.signatureAlgorithm.Alg(), true, data, signature))
84+
valid := exit.OnErr2(common.Client().Verify(cmd.Context(), common.GetOkmsId(), keyId, params.signatureAlgorithm.Alg(), true, data, signature))
8585
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
8686
output.JsonPrint(valid)
8787
} else if valid {
@@ -91,7 +91,7 @@ SIGNATURE can also be passed from a file or stdin using '-' or '@'. Stdin can ho
9191
exit.OnErr(errors.New("Signature invalid"))
9292
}
9393
} else {
94-
resp := exit.OnErr2(common.Client().GetServiceKey(cmd.Context(), keyId, utils.PtrTo(types.Jwk)))
94+
resp := exit.OnErr2(common.Client().GetServiceKey(cmd.Context(), common.GetOkmsId(), keyId, utils.PtrTo(types.Jwk)))
9595
if len(*resp.Keys) == 0 {
9696
exit.OnErr(errors.New("The server returned no key"))
9797
}

cmd/okms/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/ovh/okms-cli/cmd/okms/configure"
99
"github.com/ovh/okms-cli/cmd/okms/keys"
1010
"github.com/ovh/okms-cli/cmd/okms/kmip"
11+
"github.com/ovh/okms-cli/cmd/okms/secrets"
12+
secretsv2 "github.com/ovh/okms-cli/cmd/okms/secretsV2"
1113

1214
"github.com/ovh/okms-cli/cmd/okms/x509"
1315
"github.com/ovh/okms-cli/common/commands"
@@ -36,7 +38,8 @@ func createRootCommand() *cobra.Command {
3638
command.AddCommand(
3739
// rnd.CreateCommand(nil),
3840
keys.CreateCommand(nil),
39-
// secrets.CreateCommand(nil),
41+
secrets.CreateCommand(nil),
42+
secretsv2.CreateCommand(nil),
4043
x509.CreateX509Command(nil),
4144
kmip.NewCommand(nil),
4245
configure.CreateCommand(),

cmd/okms/secrets/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func kvReadConfigCommand() *cobra.Command {
3333
Short: "Reads secret engine configuration",
3434
Args: cobra.NoArgs,
3535
Run: func(cmd *cobra.Command, args []string) {
36-
resp := exit.OnErr2(common.Client().GetSecretConfig(cmd.Context()))
36+
resp := exit.OnErr2(common.Client().GetSecretConfig(cmd.Context(), common.GetOkmsId()))
3737
if cmd.Flag("output").Value.String() == string(flagsmgmt.JSON_OUTPUT_FORMAT) {
3838
output.JsonPrint(resp)
3939
} else {
@@ -82,7 +82,7 @@ func kvWriteConfigCommand() *cobra.Command {
8282
MaxVersions: m,
8383
}
8484

85-
exit.OnErr(common.Client().PostSecretConfig(cmd.Context(), body))
85+
exit.OnErr(common.Client().PostSecretConfig(cmd.Context(), common.GetOkmsId(), body))
8686
},
8787
}
8888

0 commit comments

Comments
 (0)