mirror of https://github.com/dapr/cli.git
mariner renew-certificate fix (#1139)
* mariner renew-certificate fix Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * added UT and E2E test Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * lint fix Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * Update cmd/renew_certificate.go Co-authored-by: Shubham Sharma <shubhash@microsoft.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * address review commnets Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * lint fix Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * trigger pr checks Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * Update utils/utils_test.go Co-authored-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * Update utils/utils_test.go Co-authored-by: Shubham Sharma <shubhash@microsoft.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * Update pkg/kubernetes/renew_certificate.go Co-authored-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * added inline comments Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * trigger pr checks Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * adding usage doc Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> Co-authored-by: Shubham Sharma <shubhash@microsoft.com> Co-authored-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com>
This commit is contained in:
parent
8a0936af9f
commit
63f14c36f9
|
|
@ -537,6 +537,10 @@ Use user provided ca.crt, issuer.crt and issuer.key
|
|||
```bash
|
||||
dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-key <issuer.key> --issuer-public-certificate <issuer.crt> --restart
|
||||
```
|
||||
#### To view the complete list of flags and their combination, run below command:
|
||||
```bash
|
||||
dapr mtls renew-certificate -h
|
||||
```
|
||||
|
||||
### List Components
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ var (
|
|||
|
||||
func RenewCertificateCmd() *cobra.Command {
|
||||
command := &cobra.Command{
|
||||
Use: "renew-certificate",
|
||||
Short: "Rotates Dapr root certificate of your kubernetes cluster",
|
||||
Use: "renew-certificate",
|
||||
Aliases: []string{"renew-cert", "rnc"},
|
||||
Short: "Rotates the Dapr root certificate on your Kubernetes cluster",
|
||||
|
||||
Example: `
|
||||
# Generates new root and issuer certificates for kubernetes cluster
|
||||
|
|
@ -50,6 +51,13 @@ dapr mtls renew-certificate -k --private-key myprivatekey.key --valid-until <no
|
|||
# Rotates certificate of your kubernetes cluster with provided ca.cert, issuer.crt and issuer.key file path
|
||||
dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private-key <issuer.key> --issuer-public-certificate <issuer.pem> --restart
|
||||
|
||||
# Generates new root and issuer certificates for kubernetes cluster with provided image variant
|
||||
dapr mtls renew-certificate -k --valid-until <no of days> --image-variant mariner --restart
|
||||
|
||||
# Use alias to renew certificate command
|
||||
dapr mtls rnc -k --valid-until <no of days> --restart
|
||||
dapr mtls renew-cert -k --valid-until <no of days> --restart
|
||||
|
||||
# See more at: https://docs.dapr.io/getting-started/
|
||||
`,
|
||||
|
||||
|
|
@ -62,6 +70,10 @@ dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private
|
|||
|
||||
if kubernetesMode {
|
||||
print.PendingStatusEvent(os.Stdout, "Starting certificate rotation")
|
||||
err = utils.ValidateImageVariant(imageVariant)
|
||||
if err != nil {
|
||||
logErrorAndExit(err)
|
||||
}
|
||||
if rootcertFlag || issuerKeyFlag || issuerCertFlag {
|
||||
flagArgsEmpty := checkReqFlagArgsEmpty(caRootCertificateFile, issuerPrivateKeyFile, issuerPublicCertificateFile)
|
||||
if flagArgsEmpty {
|
||||
|
|
@ -75,6 +87,7 @@ dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private
|
|||
IssuerCertificateFilePath: issuerPublicCertificateFile,
|
||||
IssuerPrivateKeyFilePath: issuerPrivateKeyFile,
|
||||
Timeout: timeout,
|
||||
ImageVariant: imageVariant,
|
||||
})
|
||||
if err != nil {
|
||||
logErrorAndExit(err)
|
||||
|
|
@ -90,6 +103,7 @@ dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private
|
|||
RootPrivateKeyFilePath: privateKey,
|
||||
ValidUntil: time.Hour * time.Duration(validUntil*24),
|
||||
Timeout: timeout,
|
||||
ImageVariant: imageVariant,
|
||||
})
|
||||
if err != nil {
|
||||
logErrorAndExit(err)
|
||||
|
|
@ -97,8 +111,9 @@ dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private
|
|||
} else {
|
||||
print.InfoStatusEvent(os.Stdout, "generating fresh certificates")
|
||||
err = kubernetes.RenewCertificate(kubernetes.RenewCertificateParams{
|
||||
ValidUntil: time.Hour * time.Duration(validUntil*24),
|
||||
Timeout: timeout,
|
||||
ValidUntil: time.Hour * time.Duration(validUntil*24),
|
||||
Timeout: timeout,
|
||||
ImageVariant: imageVariant,
|
||||
})
|
||||
if err != nil {
|
||||
logErrorAndExit(err)
|
||||
|
|
@ -132,6 +147,7 @@ dapr mtls renew-certificate -k --ca-root-certificate <root.pem> --issuer-private
|
|||
command.Flags().UintVarP(&validUntil, "valid-until", "", 365, "Max days before certificate expires")
|
||||
command.Flags().BoolVarP(&restartDaprServices, "restart", "", false, "Restart Dapr control plane services")
|
||||
command.Flags().UintVarP(&timeout, "timeout", "", 300, "The timeout for the certificate renewal")
|
||||
command.Flags().StringVarP(&imageVariant, "image-variant", "", "", "The image variant to use for the Dapr runtime, for example: mariner")
|
||||
command.MarkFlagRequired("kubernetes")
|
||||
return command
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"k8s.io/helm/pkg/strvals"
|
||||
|
||||
"github.com/dapr/cli/pkg/print"
|
||||
"github.com/dapr/cli/utils"
|
||||
"github.com/dapr/dapr/pkg/sentry/ca"
|
||||
"github.com/dapr/dapr/pkg/sentry/certs"
|
||||
)
|
||||
|
|
@ -37,6 +38,7 @@ type RenewCertificateParams struct {
|
|||
RootPrivateKeyFilePath string
|
||||
ValidUntil time.Duration
|
||||
Timeout uint
|
||||
ImageVariant string
|
||||
}
|
||||
|
||||
func RenewCertificate(conf RenewCertificateParams) error {
|
||||
|
|
@ -63,7 +65,7 @@ func RenewCertificate(conf RenewCertificateParams) error {
|
|||
}
|
||||
}
|
||||
print.InfoStatusEvent(os.Stdout, "Updating certifcates in your Kubernetes cluster")
|
||||
err = renewCertificate(rootCertBytes, issuerCertBytes, issuerKeyBytes, conf.Timeout)
|
||||
err = renewCertificate(rootCertBytes, issuerCertBytes, issuerKeyBytes, conf.Timeout, conf.ImageVariant)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -86,14 +88,25 @@ func parseCertificateFiles(rootCert, issuerCert, issuerKey string) ([]byte, []by
|
|||
return rootCertBytes, issuerCertBytes, issuerKeyBytes, nil
|
||||
}
|
||||
|
||||
func renewCertificate(rootCert, issuerCert, issuerKey []byte, timeout uint) error {
|
||||
func renewCertificate(rootCert, issuerCert, issuerKey []byte, timeout uint, imageVariant string) error {
|
||||
var daprVersion, daprImageVariant string
|
||||
status, err := GetDaprResourcesStatus()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
daprVersion := GetDaprVersion(status)
|
||||
daprVersion = GetDaprVersion(status)
|
||||
print.InfoStatusEvent(os.Stdout, "Dapr control plane version %s detected in namespace %s", daprVersion, status[0].Namespace)
|
||||
|
||||
// Get the control plane version from daprversion(1.x.x-mariner), if image variant is provided.
|
||||
// Here, imageVariant is used only to extract the actual control plane version,
|
||||
// and do some validation on top of that.
|
||||
if imageVariant != "" {
|
||||
daprVersion, daprImageVariant = utils.GetVersionAndImageVariant(daprVersion)
|
||||
if daprImageVariant != imageVariant {
|
||||
return fmt.Errorf("error in parsing dapr version. found image variant %q is not same as provided value %q", daprImageVariant, imageVariant)
|
||||
}
|
||||
}
|
||||
|
||||
helmConf, err := helmConfig(status[0].Namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -104,11 +117,14 @@ func renewCertificate(rootCert, issuerCert, issuerKey []byte, timeout uint) erro
|
|||
return err
|
||||
}
|
||||
upgradeClient := helm.NewUpgrade(helmConf)
|
||||
|
||||
// Reuse the existing helm configuration values i.e. tags, registry, etc.
|
||||
upgradeClient.ReuseValues = true
|
||||
upgradeClient.Wait = true
|
||||
upgradeClient.Timeout = time.Duration(timeout) * time.Second
|
||||
upgradeClient.Namespace = status[0].Namespace
|
||||
|
||||
// Override the helm configuration values with the new certificates.
|
||||
vals, err := createHelmParamsForNewCertificates(string(rootCert), string(issuerCert), string(issuerKey))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -437,7 +437,17 @@ func GenerateNewCertAndRenew(details VersionDetails, opts TestOptions) func(t *t
|
|||
err := exportCurrentCertificate(daprPath)
|
||||
require.NoError(t, err, "expected no error on certificate exporting")
|
||||
|
||||
output, err := spawn.Command(daprPath, "mtls", "renew-certificate", "-k", "--valid-until", "20", "--restart")
|
||||
args := []string{
|
||||
"mtls",
|
||||
"renew-certificate",
|
||||
"-k",
|
||||
"--valid-until", "20",
|
||||
"--restart",
|
||||
}
|
||||
if details.ImageVariant != "" {
|
||||
args = append(args, "--image-variant", details.ImageVariant)
|
||||
}
|
||||
output, err := spawn.Command(daprPath, args...)
|
||||
t.Log(output)
|
||||
require.NoError(t, err, "expected no error on certificate renewal")
|
||||
|
||||
|
|
|
|||
|
|
@ -381,7 +381,9 @@ func TestRenewCertWithIncorrectFlags(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestKubernetesInstallwithMarinerImages(t *testing.T) {
|
||||
// install dapr control plane with mariner docker images.
|
||||
// Renew the certificate of this control plane.
|
||||
func TestK8sInstallwithMarinerImagesAndRenewCertificate(t *testing.T) {
|
||||
// ensure clean env for test
|
||||
ensureCleanEnv(t)
|
||||
|
||||
|
|
@ -402,6 +404,15 @@ func TestKubernetesInstallwithMarinerImages(t *testing.T) {
|
|||
|
||||
tests = append(tests, common.GetTestsOnInstall(currentVersionDetails, installOpts)...)
|
||||
|
||||
// tests for certifcate renewal with newly generated certificates.
|
||||
tests = append(tests, []common.TestCase{
|
||||
{"Renew certificate which expires in less than 30 days", common.GenerateNewCertAndRenew(currentVersionDetails, installOpts)},
|
||||
}...)
|
||||
tests = append(tests, common.GetTestsPostCertificateRenewal(currentVersionDetails, installOpts)...)
|
||||
tests = append(tests, []common.TestCase{
|
||||
{"Cert Expiry warning message check " + currentVersionDetails.RuntimeVersion, common.CheckMTLSStatus(currentVersionDetails, installOpts, true)},
|
||||
}...)
|
||||
|
||||
// teardown everything
|
||||
tests = append(tests, common.GetTestsOnUninstall(currentVersionDetails, common.TestOptions{
|
||||
CheckResourceExists: map[common.Resource]bool{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ const (
|
|||
DOCKER ContainerRuntime = "docker"
|
||||
PODMAN ContainerRuntime = "podman"
|
||||
|
||||
marinerImageVariantName = "mariner"
|
||||
|
||||
socketFormat = "%s/dapr-%s-%s.socket"
|
||||
)
|
||||
|
||||
|
|
@ -72,8 +74,6 @@ func Contains[T comparable](vs []T, x T) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
const marinerImageVariantName = "mariner"
|
||||
|
||||
// PrintTable to print in the table format.
|
||||
func PrintTable(csvContent string) {
|
||||
WriteTable(os.Stdout, csvContent)
|
||||
|
|
@ -310,3 +310,14 @@ func GetVariantVersion(version, imageVariant string) string {
|
|||
}
|
||||
return fmt.Sprintf("%s-%s", version, imageVariant)
|
||||
}
|
||||
|
||||
// Returns image version and variant.
|
||||
// Expected imageTag format: <version>-<variant>, i.e. 1.0.0-mariner or 1.0.0-rc.1-mariner.
|
||||
func GetVersionAndImageVariant(imageTag string) (string, string) {
|
||||
imageVersionOffset := strings.LastIndex(imageTag, "-")
|
||||
imageVariant := imageTag[imageVersionOffset+1:]
|
||||
if imageVariant == marinerImageVariantName {
|
||||
return imageTag[:imageVersionOffset], imageVariant
|
||||
}
|
||||
return imageTag, ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@ limitations under the License.
|
|||
|
||||
package utils
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestContainerRuntimeUtils(t *testing.T) {
|
||||
testcases := []struct {
|
||||
|
|
@ -117,3 +121,45 @@ func TestContains(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetVersionAndImageVariant(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
input string
|
||||
expectedVersion string
|
||||
expectedImageVariant string
|
||||
}{
|
||||
{
|
||||
name: "image tag contains version and variant",
|
||||
input: "1.9.0-mariner",
|
||||
expectedVersion: "1.9.0",
|
||||
expectedImageVariant: "mariner",
|
||||
},
|
||||
{
|
||||
name: "image tag contains only version",
|
||||
input: "1.9.0",
|
||||
expectedVersion: "1.9.0",
|
||||
expectedImageVariant: "",
|
||||
},
|
||||
{
|
||||
name: "image tag contains only rc version and variant",
|
||||
input: "1.9.0-rc.1-mariner",
|
||||
expectedVersion: "1.9.0-rc.1",
|
||||
expectedImageVariant: "mariner",
|
||||
},
|
||||
{
|
||||
name: "image tag contains only rc version",
|
||||
input: "1.9.0-rc.1",
|
||||
expectedVersion: "1.9.0-rc.1",
|
||||
expectedImageVariant: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
version, imageVariant := GetVersionAndImageVariant(tc.input)
|
||||
assert.Equal(t, tc.expectedVersion, version)
|
||||
assert.Equal(t, tc.expectedImageVariant, imageVariant)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue