Skip to content

Commit 1331e29

Browse files
Do not allow mixing of flags in renew cert (#947)
* Do not allow mixing of flags in renew cert Signed-off-by: Pravin Pushkar <[email protected]> * Review comments fixes Signed-off-by: Pravin Pushkar <[email protected]> * check cert loaded in mtls expiry Signed-off-by: Pravin Pushkar <[email protected]>
1 parent 615c25c commit 1331e29

File tree

4 files changed

+118
-8
lines changed

4 files changed

+118
-8
lines changed

cmd/renew_certificate.go

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package cmd
1616
import (
1717
"fmt"
1818
"os"
19+
"strings"
1920
"time"
2021

2122
"github.com/spf13/cobra"
@@ -47,17 +48,29 @@ dapr mtls renew-certificate -k --valid-until <no of days> --restart
4748
dapr mtls renew-certificate -k --private-key myprivatekey.key --valid-until <no of days>
4849
4950
# Rotates certificate of your kubernetes cluster with provided ca.cert, issuer.crt and issuer.key file path
50-
dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-key <issuer.key> --issuer-public-certificate <issuer.crt> --restart
51+
dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private-key <issuer.key> --issuer-public-certificate <issuer.pem> --restart
5152
5253
# See more at: https://docs.dapr.io/getting-started/
5354
`,
5455

5556
Run: func(cmd *cobra.Command, args []string) {
57+
var err error
58+
pkFlag := cmd.Flags().Lookup("private-key").Changed
59+
rootcertFlag := cmd.Flags().Lookup("ca-root-certificate").Changed
60+
issuerKeyFlag := cmd.Flags().Lookup("issuer-private-key").Changed
61+
issuerCertFlag := cmd.Flags().Lookup("issuer-public-certificate").Changed
62+
5663
if kubernetesMode {
5764
print.PendingStatusEvent(os.Stdout, "Starting certificate rotation")
58-
if caRootCertificateFile != "" && issuerPrivateKeyFile != "" && issuerPublicCertificateFile != "" {
65+
if rootcertFlag || issuerKeyFlag || issuerCertFlag {
66+
flagArgsEmpty := checkReqFlagArgsEmpty(caRootCertificateFile, issuerPrivateKeyFile, issuerPublicCertificateFile)
67+
if flagArgsEmpty {
68+
err = fmt.Errorf("all required flags for this certificate rotation path, %q, %q and %q are not present",
69+
"ca-root-certificate", "issuer-private-key", "issuer-public-certificate")
70+
logErrorAndExit(err)
71+
}
5972
print.InfoStatusEvent(os.Stdout, "Using provided certificates")
60-
err := kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
73+
err = kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
6174
RootCertificateFilePath: caRootCertificateFile,
6275
IssuerCertificateFilePath: issuerPublicCertificateFile,
6376
IssuerPrivateKeyFilePath: issuerPrivateKeyFile,
@@ -66,9 +79,14 @@ dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-k
6679
if err != nil {
6780
logErrorAndExit(err)
6881
}
69-
} else if privateKey != "" {
82+
} else if pkFlag {
83+
flagArgsEmpty := checkReqFlagArgsEmpty(privateKey)
84+
if flagArgsEmpty {
85+
err = fmt.Errorf("%q flag has incorrect value", "privateKey")
86+
logErrorAndExit(err)
87+
}
7088
print.InfoStatusEvent(os.Stdout, "Using password file to generate root certificate")
71-
err := kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
89+
err = kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
7290
RootPrivateKeyFilePath: privateKey,
7391
ValidUntil: time.Hour * time.Duration(validUntil*24),
7492
Timeout: timeout,
@@ -78,7 +96,7 @@ dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-k
7896
}
7997
} else {
8098
print.InfoStatusEvent(os.Stdout, "generating fresh certificates")
81-
err := kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
99+
err = kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
82100
ValidUntil: time.Hour * time.Duration(validUntil*24),
83101
Timeout: timeout,
84102
})
@@ -118,8 +136,17 @@ dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-k
118136
return command
119137
}
120138

139+
func checkReqFlagArgsEmpty(params ...string) bool {
140+
for _, val := range params {
141+
if len(strings.TrimSpace(val)) == 0 {
142+
return true
143+
}
144+
}
145+
return false
146+
}
147+
121148
func logErrorAndExit(err error) {
122-
err = fmt.Errorf("certificate rotation failed %w", err)
149+
err = fmt.Errorf("certificate rotation failed: %w", err)
123150
print.FailureStatusEvent(os.Stderr, err.Error())
124151
os.Exit(1)
125152
}

pkg/kubernetes/mtls.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,10 @@ func Expiry() (*time.Time, error) {
165165
return nil, err
166166
}
167167

168-
caCrt := secret.Data["ca.crt"]
168+
caCrt, ok := secret.Data["ca.crt"]
169+
if !ok {
170+
return nil, errors.New("root certificate not loaded yet, please try again in few minutes")
171+
}
169172
block, _ := pem.Decode(caCrt)
170173
cert, err := x509.ParseCertificate(block.Bytes)
171174
if err != nil {

tests/e2e/common/common.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,50 @@ func UseProvidedNewCertAndRenew(details VersionDetails, opts TestOptions) func(t
486486
}
487487
}
488488

489+
func NegativeScenarioForCertRenew() func(t *testing.T) {
490+
return func(t *testing.T) {
491+
daprPath := getDaprPath()
492+
args := []string{
493+
"mtls", "renew-certificate", "-k",
494+
"--ca-root-certificate", "invalid_cert_file.pem",
495+
}
496+
output, err := spawn.Command(daprPath, args...)
497+
t.Log(output)
498+
require.Error(t, err, "expected error on certificate renewal")
499+
assert.Contains(t, output, "certificate rotation failed: all required flags for this certificate rotation path")
500+
501+
args = []string{
502+
"mtls", "renew-certificate", "-k",
503+
"--ca-root-certificate", "invalid_cert_file.pem",
504+
"--issuer-private-key", "invalid_cert_key.pem",
505+
"--issuer-public-certificate", "invalid_cert_file.pem",
506+
}
507+
output, err = spawn.Command(daprPath, args...)
508+
t.Log(output)
509+
require.Error(t, err, "expected error on certificate renewal")
510+
assert.Contains(t, output, "certificate rotation failed: open invalid_cert_file.pem: no such file or directory")
511+
512+
args = []string{
513+
"mtls", "renew-certificate", "-k",
514+
"--ca-root-certificate", "invalid_cert_file.pem",
515+
"--private-key", "invalid_root_key.pem",
516+
}
517+
output, err = spawn.Command(daprPath, args...)
518+
t.Log(output)
519+
require.Error(t, err, "expected error on certificate renewal")
520+
assert.Contains(t, output, "certificate rotation failed: all required flags for this certificate rotation path")
521+
522+
args = []string{
523+
"mtls", "renew-certificate", "-k",
524+
"--private-key", "invalid_root_key.pem",
525+
}
526+
output, err = spawn.Command(daprPath, args...)
527+
t.Log(output)
528+
require.Error(t, err, "expected error on certificate renewal")
529+
assert.Contains(t, output, "certificate rotation failed: open invalid_root_key.pem: no such file or directory")
530+
}
531+
}
532+
489533
func CheckMTLSStatus(details VersionDetails, opts TestOptions, shouldWarningExist bool) func(t *testing.T) {
490534
return func(t *testing.T) {
491535
daprPath := getDaprPath()

tests/e2e/kubernetes/kubernetes_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,3 +306,39 @@ func TestRenewCertWithPrivateKey(t *testing.T) {
306306
t.Run(tc.Name, tc.Callable)
307307
}
308308
}
309+
310+
func TestRenewCertWithIncorrectFlags(t *testing.T) {
311+
common.EnsureUninstall(true)
312+
313+
tests := []common.TestCase{}
314+
var installOpts = common.TestOptions{
315+
HAEnabled: false,
316+
MTLSEnabled: true,
317+
ApplyComponentChanges: true,
318+
CheckResourceExists: map[common.Resource]bool{
319+
common.CustomResourceDefs: true,
320+
common.ClusterRoles: true,
321+
common.ClusterRoleBindings: true,
322+
},
323+
}
324+
325+
tests = append(tests, common.GetTestsOnInstall(currentVersionDetails, installOpts)...)
326+
327+
// tests for certifcate renewal with incorrect set of flags provided.
328+
tests = append(tests, []common.TestCase{
329+
{"Renew certificate with incorrect flags", common.NegativeScenarioForCertRenew()},
330+
}...)
331+
332+
// teardown everything
333+
tests = append(tests, common.GetTestsOnUninstall(currentVersionDetails, common.TestOptions{
334+
CheckResourceExists: map[common.Resource]bool{
335+
common.CustomResourceDefs: true,
336+
common.ClusterRoles: false,
337+
common.ClusterRoleBindings: false,
338+
},
339+
})...)
340+
341+
for _, tc := range tests {
342+
t.Run(tc.Name, tc.Callable)
343+
}
344+
}

0 commit comments

Comments
 (0)