2018-10-12 12:21:29 -06:00
|
|
|
/*
|
|
|
|
|
Copyright 2018 The Rook Authors. All rights reserved.
|
|
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
|
limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Package mgr for the Ceph manager.
|
|
|
|
|
package mgr
|
|
|
|
|
|
|
|
|
|
import (
|
2019-05-02 13:50:21 -07:00
|
|
|
"context"
|
2020-01-05 01:01:23 +05:30
|
|
|
"crypto/rand"
|
2021-06-08 22:46:58 -06:00
|
|
|
"fmt"
|
2021-04-08 09:58:38 +05:30
|
|
|
"os"
|
2019-01-08 14:34:11 -08:00
|
|
|
"strconv"
|
2018-10-12 12:21:29 -06:00
|
|
|
"syscall"
|
|
|
|
|
"time"
|
|
|
|
|
|
2019-10-08 12:51:36 +02:00
|
|
|
"github.com/pkg/errors"
|
2018-10-12 12:21:29 -06:00
|
|
|
"github.com/rook/rook/pkg/daemon/ceph/client"
|
2021-08-24 14:38:26 -06:00
|
|
|
"github.com/rook/rook/pkg/operator/ceph/config"
|
2018-10-12 12:21:29 -06:00
|
|
|
"github.com/rook/rook/pkg/operator/k8sutil"
|
2021-08-09 13:32:02 +05:30
|
|
|
"github.com/rook/rook/pkg/util"
|
2021-07-06 23:27:15 +02:00
|
|
|
"github.com/rook/rook/pkg/util/exec"
|
2019-08-14 18:43:23 +02:00
|
|
|
v1 "k8s.io/api/core/v1"
|
2019-10-08 12:51:36 +02:00
|
|
|
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
2018-10-12 12:21:29 -06:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
2020-01-07 19:24:56 +05:30
|
|
|
dashboardModuleName = "dashboard"
|
|
|
|
|
dashboardPortHTTPS = 8443
|
|
|
|
|
dashboardPortHTTP = 7000
|
|
|
|
|
dashboardUsername = "admin"
|
2022-04-04 19:55:41 +05:30
|
|
|
//nolint:gosec // because of the word `Password`
|
2018-10-12 12:21:29 -06:00
|
|
|
dashboardPasswordName = "rook-ceph-dashboard-password"
|
2020-01-05 01:01:23 +05:30
|
|
|
passwordLength = 20
|
2018-10-12 12:21:29 -06:00
|
|
|
passwordKeyName = "password"
|
|
|
|
|
certAlreadyConfiguredErrorCode = 5
|
2019-02-27 10:43:30 -05:00
|
|
|
invalidArgErrorCode = int(syscall.EINVAL)
|
2018-10-12 12:21:29 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
2024-01-22 13:21:25 +01:00
|
|
|
dashboardInitWaitTime = 5 * time.Second
|
|
|
|
|
removeMgrDaemonConfiguration = true
|
2018-10-12 12:21:29 -06:00
|
|
|
)
|
|
|
|
|
|
2023-03-03 18:17:46 +01:00
|
|
|
func (c *Cluster) configureDashboardService() error {
|
|
|
|
|
dashboardService, err := c.makeDashboardService(AppName)
|
2021-02-18 13:10:11 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2020-07-10 16:40:16 -06:00
|
|
|
if c.spec.Dashboard.Enabled {
|
2018-10-12 12:21:29 -06:00
|
|
|
// expose the dashboard service
|
2021-12-11 11:40:28 +09:00
|
|
|
if _, err := k8sutil.CreateOrUpdateService(c.clusterInfo.Context, c.context.Clientset, c.clusterInfo.Namespace, dashboardService); err != nil {
|
2021-02-11 17:31:55 -07:00
|
|
|
return errors.Wrap(err, "failed to configure dashboard svc")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// delete the dashboard service if it exists
|
2021-08-06 17:46:01 +02:00
|
|
|
err := c.context.Clientset.CoreV1().Services(c.clusterInfo.Namespace).Delete(c.clusterInfo.Context, dashboardService.Name, metav1.DeleteOptions{})
|
2019-10-08 12:51:36 +02:00
|
|
|
if err != nil && !kerrors.IsNotFound(err) {
|
2020-04-29 15:59:41 +05:30
|
|
|
return errors.Wrap(err, "failed to delete dashboard service")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-13 22:43:56 -06:00
|
|
|
// Ceph docs about the dashboard module: http://docs.ceph.com/docs/nautilus/mgr/dashboard/
|
2019-10-18 17:26:09 -06:00
|
|
|
func (c *Cluster) configureDashboardModules() error {
|
2020-07-10 16:40:16 -06:00
|
|
|
if c.spec.Dashboard.Enabled {
|
|
|
|
|
if err := client.MgrEnableModule(c.context, c.clusterInfo, dashboardModuleName, true); err != nil {
|
2021-04-09 16:52:28 +05:30
|
|
|
return errors.Wrap(err, "failed to enable mgr dashboard module")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
} else {
|
2020-07-10 16:40:16 -06:00
|
|
|
if err := client.MgrDisableModule(c.context, c.clusterInfo, dashboardModuleName); err != nil {
|
2019-12-16 12:23:34 +01:00
|
|
|
logger.Errorf("failed to disable mgr dashboard module. %v", err)
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
2019-10-18 17:26:09 -06:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-06 14:35:39 +08:00
|
|
|
err := c.initializeSecureDashboard()
|
2019-10-18 17:26:09 -06:00
|
|
|
if err != nil {
|
2020-04-29 15:59:41 +05:30
|
|
|
return errors.Wrap(err, "failed to initialize dashboard")
|
2019-10-18 17:26:09 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-22 13:21:25 +01:00
|
|
|
hasChanged, err := c.configureDashboardModuleSettings()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2019-10-18 17:26:09 -06:00
|
|
|
}
|
|
|
|
|
if hasChanged {
|
2021-04-09 16:52:28 +05:30
|
|
|
logger.Info("dashboard config has changed. restarting the dashboard module")
|
2023-03-26 12:04:05 -04:00
|
|
|
return c.restartMgrModule(dashboardModuleName)
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-24 13:01:35 +01:00
|
|
|
// Delete the manager per-daemon configuration. Returns true
|
|
|
|
|
// if all the configuration entries have been delete successfully.
|
|
|
|
|
func (c *Cluster) deleteManagerDaemonConfiguration() bool {
|
|
|
|
|
|
|
|
|
|
mgrKeysToDelete := []string{
|
|
|
|
|
"mgr/dashboard/url_prefix",
|
|
|
|
|
"mgr/dashboard/ssl",
|
|
|
|
|
"mgr/dashboard/PROMETHEUS_API_HOST",
|
|
|
|
|
"mgr/dashboard/PROMETHEUS_API_SSL_VERIFY",
|
|
|
|
|
"mgr/dashboard/server_port",
|
|
|
|
|
"mgr/dashboard/ssl_server_port",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
success := true
|
|
|
|
|
monStore := config.GetMonStore(c.context, c.clusterInfo)
|
|
|
|
|
for _, daemonID := range c.getDaemonIDs() {
|
|
|
|
|
mgrDaemonID := fmt.Sprintf("%s.%s", config.MgrType, daemonID)
|
|
|
|
|
for _, key := range mgrKeysToDelete {
|
|
|
|
|
err := monStore.Delete(mgrDaemonID, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("failed to delete configuration entry %q %q, err: %v", mgrDaemonID, key, err)
|
|
|
|
|
success = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if success {
|
|
|
|
|
logger.Info("All per-daemon mgr configuration has been deleted successfully.")
|
|
|
|
|
} else {
|
|
|
|
|
logger.Error("At least one delete operation failed while trying to delete per-daemon mgr configuration.")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return success
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-22 13:21:25 +01:00
|
|
|
func (c *Cluster) configureDashboardModuleSettings() (bool, error) {
|
|
|
|
|
|
2021-08-24 14:38:26 -06:00
|
|
|
monStore := config.GetMonStore(c.context, c.clusterInfo)
|
|
|
|
|
|
2019-01-08 16:29:57 -08:00
|
|
|
// url prefix
|
2024-01-22 13:21:25 +01:00
|
|
|
hasChanged, err := monStore.SetIfChanged(config.MgrType, "mgr/dashboard/url_prefix", c.spec.Dashboard.URLPrefix)
|
2018-07-20 00:12:58 +03:00
|
|
|
if err != nil {
|
2019-10-18 17:26:09 -06:00
|
|
|
return false, err
|
2018-07-20 00:12:58 +03:00
|
|
|
}
|
2019-01-08 16:29:57 -08:00
|
|
|
|
2019-08-14 18:43:23 +02:00
|
|
|
// ssl support
|
2020-07-10 16:40:16 -06:00
|
|
|
ssl := strconv.FormatBool(c.spec.Dashboard.SSL)
|
2024-01-22 13:21:25 +01:00
|
|
|
changed, err := monStore.SetIfChanged(config.MgrType, "mgr/dashboard/ssl", ssl)
|
2019-01-08 14:34:11 -08:00
|
|
|
if err != nil {
|
2019-10-18 17:26:09 -06:00
|
|
|
return false, err
|
2019-01-08 14:34:11 -08:00
|
|
|
}
|
|
|
|
|
hasChanged = hasChanged || changed
|
2019-01-08 16:29:57 -08:00
|
|
|
|
2023-09-19 15:26:40 +02:00
|
|
|
// Prometheus host end point
|
|
|
|
|
prometheusEndpoint := c.spec.Dashboard.PrometheusEndpoint
|
2024-01-22 13:21:25 +01:00
|
|
|
changed, err = monStore.SetIfChanged(config.MgrType, "mgr/dashboard/PROMETHEUS_API_HOST", prometheusEndpoint)
|
2023-09-19 15:26:40 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
|
|
|
|
hasChanged = hasChanged || changed
|
|
|
|
|
|
|
|
|
|
// Prometheus host end point ssl verify
|
|
|
|
|
prometheusEndpointSSLVerify := strconv.FormatBool(c.spec.Dashboard.PrometheusEndpointSSLVerify)
|
2024-01-22 13:21:25 +01:00
|
|
|
changed, err = monStore.SetIfChanged(config.MgrType, "mgr/dashboard/PROMETHEUS_API_SSL_VERIFY", prometheusEndpointSSLVerify)
|
2023-09-19 15:26:40 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
|
|
|
|
hasChanged = hasChanged || changed
|
|
|
|
|
|
2019-08-14 18:43:23 +02:00
|
|
|
// server port
|
2022-10-05 11:28:19 -06:00
|
|
|
port := strconv.Itoa(c.dashboardInternalPort())
|
2024-01-22 13:21:25 +01:00
|
|
|
changed, err = monStore.SetIfChanged(config.MgrType, "mgr/dashboard/server_port", port)
|
2019-01-08 16:29:57 -08:00
|
|
|
if err != nil {
|
2019-10-18 17:26:09 -06:00
|
|
|
return false, err
|
2019-01-08 16:29:57 -08:00
|
|
|
}
|
|
|
|
|
hasChanged = hasChanged || changed
|
|
|
|
|
|
2020-02-11 17:20:06 +01:00
|
|
|
// SSL enabled. Needed to set specifically the ssl port setting
|
2020-07-10 16:40:16 -06:00
|
|
|
if c.spec.Dashboard.SSL {
|
2024-01-22 13:21:25 +01:00
|
|
|
changed, err = monStore.SetIfChanged(config.MgrType, "mgr/dashboard/ssl_server_port", port)
|
2020-02-11 17:20:06 +01:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
2019-08-14 18:43:23 +02:00
|
|
|
}
|
2020-02-11 17:20:06 +01:00
|
|
|
hasChanged = hasChanged || changed
|
2019-08-14 18:43:23 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-22 13:21:25 +01:00
|
|
|
// Remove any existing per mgr-daemon configuration
|
|
|
|
|
if removeMgrDaemonConfiguration {
|
2024-01-24 13:01:35 +01:00
|
|
|
removeMgrDaemonConfiguration = !c.deleteManagerDaemonConfiguration()
|
2024-01-22 13:21:25 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-18 17:26:09 -06:00
|
|
|
return hasChanged, nil
|
2018-07-20 00:12:58 +03:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 14:35:39 +08:00
|
|
|
func (c *Cluster) initializeSecureDashboard() error {
|
2018-10-12 12:21:29 -06:00
|
|
|
// we need to wait a short period after enabling the module before we can call the `ceph dashboard` commands.
|
|
|
|
|
time.Sleep(dashboardInitWaitTime)
|
|
|
|
|
|
|
|
|
|
password, err := c.getOrGenerateDashboardPassword()
|
|
|
|
|
if err != nil {
|
2023-04-06 14:35:39 +08:00
|
|
|
return errors.Wrap(err, "failed to generate a password for the ceph dashboard")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
|
2020-07-10 16:40:16 -06:00
|
|
|
if c.spec.Dashboard.SSL {
|
2019-01-08 16:29:57 -08:00
|
|
|
alreadyCreated, err := c.createSelfSignedCert()
|
|
|
|
|
if err != nil {
|
2023-04-06 14:35:39 +08:00
|
|
|
return errors.Wrap(err, "failed to create a self signed cert for the ceph dashboard")
|
2019-01-08 16:29:57 -08:00
|
|
|
}
|
|
|
|
|
if alreadyCreated {
|
2023-04-06 14:35:39 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if err := c.restartMgrModule(dashboardModuleName); err != nil {
|
|
|
|
|
logger.Warningf("failed to restart dashboard after generating ssl cert. %v", err)
|
2019-01-08 16:29:57 -08:00
|
|
|
}
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := c.setLoginCredentials(password); err != nil {
|
2023-04-06 14:35:39 +08:00
|
|
|
return errors.Wrap(err, "failed to set login credentials for the ceph dashboard")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 14:35:39 +08:00
|
|
|
return nil
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Cluster) createSelfSignedCert() (bool, error) {
|
2021-07-28 14:00:35 -06:00
|
|
|
// create a self-signed cert for the https connections
|
2018-10-12 12:21:29 -06:00
|
|
|
args := []string{"dashboard", "create-self-signed-cert"}
|
2018-12-20 16:07:00 -07:00
|
|
|
|
|
|
|
|
// retry a few times in the case that the mgr module is not ready to accept commands
|
|
|
|
|
for i := 0; i < 5; i++ {
|
2021-02-22 10:19:21 +00:00
|
|
|
_, err := client.NewCephCommand(c.context, c.clusterInfo, args).RunWithTimeout(exec.CephCommandsTimeout)
|
2019-05-02 13:50:21 -07:00
|
|
|
if err == context.DeadlineExceeded {
|
2021-04-09 16:52:28 +05:30
|
|
|
logger.Warning("cert creation timed out. trying again")
|
2019-05-02 13:50:21 -07:00
|
|
|
continue
|
|
|
|
|
}
|
2018-12-20 16:07:00 -07:00
|
|
|
if err != nil {
|
|
|
|
|
exitCode, parsed := c.exitCode(err)
|
|
|
|
|
if parsed {
|
2018-10-12 12:21:29 -06:00
|
|
|
if exitCode == certAlreadyConfiguredErrorCode {
|
2021-04-09 16:52:28 +05:30
|
|
|
logger.Info("dashboard is already initialized with a cert")
|
2018-10-12 12:21:29 -06:00
|
|
|
return true, nil
|
|
|
|
|
}
|
2018-12-20 16:07:00 -07:00
|
|
|
if exitCode == invalidArgErrorCode {
|
2021-04-09 16:52:28 +05:30
|
|
|
logger.Info("dashboard module is not ready yet. trying again")
|
2018-12-20 16:07:00 -07:00
|
|
|
time.Sleep(dashboardInitWaitTime)
|
|
|
|
|
continue
|
|
|
|
|
}
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
2020-04-29 15:59:41 +05:30
|
|
|
return false, errors.Wrap(err, "failed to create self signed cert on mgr")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
2018-12-20 16:07:00 -07:00
|
|
|
break
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Cluster) setLoginCredentials(password string) error {
|
|
|
|
|
// Set the login credentials. Write the command/args to the debug log so we don't write the password by default to the log.
|
2020-03-17 15:57:53 -06:00
|
|
|
logger.Infof("setting ceph dashboard %q login creds", dashboardUsername)
|
|
|
|
|
|
2021-04-08 09:58:38 +05:30
|
|
|
var args []string
|
|
|
|
|
// for latest Ceph versions
|
2022-07-01 10:38:15 -06:00
|
|
|
// Generate a temp file
|
|
|
|
|
file, err := util.CreateTempFile(password)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(err, "failed to create a temporary dashboard password file")
|
2021-04-08 09:58:38 +05:30
|
|
|
}
|
2024-01-30 14:20:27 +01:00
|
|
|
|
2022-07-01 10:38:15 -06:00
|
|
|
defer func() {
|
|
|
|
|
if err := os.Remove(file.Name()); err != nil {
|
|
|
|
|
logger.Errorf("failed to clean up dashboard password file %q. %v", file.Name(), err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
2021-04-08 09:58:38 +05:30
|
|
|
|
2024-01-30 14:20:27 +01:00
|
|
|
// Create dashboard user
|
|
|
|
|
// > ceph dashboard ac-user-create <username> -i <path-to-password-file>
|
|
|
|
|
//
|
|
|
|
|
// Note: this command will succeed in case the user <dashboardUsername> already
|
|
|
|
|
// exists however it will not update the password. That why we need to explicitly
|
|
|
|
|
// call the ac-user-set-password command to ensure the password is updated correctly
|
|
|
|
|
args = []string{"dashboard", "ac-user-create", dashboardUsername, "-i", file.Name(), "administrator"}
|
2022-07-01 10:38:15 -06:00
|
|
|
_, err = client.ExecuteCephCommandWithRetry(func() (string, []byte, error) {
|
2021-02-22 10:19:21 +00:00
|
|
|
output, err := client.NewCephCommand(c.context, c.clusterInfo, args).RunWithTimeout(exec.CephCommandsTimeout)
|
2024-01-30 14:20:27 +01:00
|
|
|
return "create dashboard user", output, err
|
2023-04-28 17:35:32 +05:30
|
|
|
}, 5, dashboardInitWaitTime)
|
2018-10-12 12:21:29 -06:00
|
|
|
if err != nil {
|
2024-01-30 14:20:27 +01:00
|
|
|
return errors.Wrapf(err, "failed to create dashboard user %q", dashboardUsername)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set dashboard user password
|
|
|
|
|
// > ceph dashboard ac-user-set-password <username> -i <path-to-password-file>
|
|
|
|
|
args = []string{"dashboard", "ac-user-set-password", dashboardUsername, "-i", file.Name()}
|
|
|
|
|
_, err = client.ExecuteCephCommandWithRetry(func() (string, []byte, error) {
|
|
|
|
|
output, err := client.NewCephCommand(c.context, c.clusterInfo, args).RunWithTimeout(exec.CephCommandsTimeout)
|
|
|
|
|
return "set dashboard user password", output, err
|
|
|
|
|
}, 5, dashboardInitWaitTime)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrapf(err, "failed to set password for user %q", dashboardUsername)
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
2020-03-17 15:57:53 -06:00
|
|
|
|
2021-04-09 16:52:28 +05:30
|
|
|
logger.Info("successfully set ceph dashboard creds")
|
2018-10-12 12:21:29 -06:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Cluster) getOrGenerateDashboardPassword() (string, error) {
|
2021-08-06 17:46:01 +02:00
|
|
|
secret, err := c.context.Clientset.CoreV1().Secrets(c.clusterInfo.Namespace).Get(c.clusterInfo.Context, dashboardPasswordName, metav1.GetOptions{})
|
2018-10-12 12:21:29 -06:00
|
|
|
if err == nil {
|
2021-04-09 16:52:28 +05:30
|
|
|
logger.Info("the dashboard secret was already generated")
|
2018-10-12 12:21:29 -06:00
|
|
|
return decodeSecret(secret)
|
|
|
|
|
}
|
2019-10-08 12:51:36 +02:00
|
|
|
if !kerrors.IsNotFound(err) {
|
2020-04-29 15:59:41 +05:30
|
|
|
return "", errors.Wrap(err, "failed to get dashboard secret")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate a password
|
2020-06-30 02:24:00 -04:00
|
|
|
password, err := GeneratePassword(passwordLength)
|
2020-01-05 01:01:23 +05:30
|
|
|
if err != nil {
|
2020-04-29 15:59:41 +05:30
|
|
|
return "", errors.Wrap(err, "failed to generate password")
|
2020-01-05 01:01:23 +05:30
|
|
|
}
|
2018-10-12 12:21:29 -06:00
|
|
|
|
|
|
|
|
// Store the keyring in a secret
|
|
|
|
|
secrets := map[string][]byte{
|
|
|
|
|
passwordKeyName: []byte(password),
|
|
|
|
|
}
|
|
|
|
|
secret = &v1.Secret{
|
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
|
Name: dashboardPasswordName,
|
2020-07-10 16:40:16 -06:00
|
|
|
Namespace: c.clusterInfo.Namespace,
|
2018-10-12 12:21:29 -06:00
|
|
|
},
|
|
|
|
|
Data: secrets,
|
|
|
|
|
Type: k8sutil.RookType,
|
|
|
|
|
}
|
2021-02-18 13:10:11 +00:00
|
|
|
err = c.clusterInfo.OwnerInfo.SetControllerReference(secret)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", errors.Wrapf(err, "failed to set owner reference to dashboard secret %q", secret.Name)
|
|
|
|
|
}
|
2018-10-12 12:21:29 -06:00
|
|
|
|
2021-08-06 17:46:01 +02:00
|
|
|
_, err = c.context.Clientset.CoreV1().Secrets(c.clusterInfo.Namespace).Create(c.clusterInfo.Context, secret, metav1.CreateOptions{})
|
2018-10-12 12:21:29 -06:00
|
|
|
if err != nil {
|
2020-04-29 15:59:41 +05:30
|
|
|
return "", errors.Wrap(err, "failed to save dashboard secret")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
return password, nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-30 02:24:00 -04:00
|
|
|
func GeneratePassword(length int) (string, error) {
|
2022-04-04 19:55:41 +05:30
|
|
|
//nolint:gosec // because of the word password
|
2020-01-05 01:01:23 +05:30
|
|
|
const passwordChars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
2020-07-27 19:55:24 +02:00
|
|
|
passwd, err := GenerateRandomBytes(length)
|
2020-01-05 01:01:23 +05:30
|
|
|
if err != nil {
|
2020-04-29 15:59:41 +05:30
|
|
|
return "", errors.Wrap(err, "failed to generate password")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
2020-01-05 01:01:23 +05:30
|
|
|
for i, pass := range passwd {
|
|
|
|
|
passwd[i] = passwordChars[pass%byte(len(passwordChars))]
|
|
|
|
|
}
|
|
|
|
|
return string(passwd), nil
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
|
2020-07-27 19:55:24 +02:00
|
|
|
// GenerateRandomBytes returns securely generated random bytes.
|
|
|
|
|
func GenerateRandomBytes(length int) ([]byte, error) {
|
2020-01-05 01:01:23 +05:30
|
|
|
bytes := make([]byte, length)
|
|
|
|
|
if _, err := rand.Read(bytes); err != nil {
|
2020-04-29 15:59:41 +05:30
|
|
|
return nil, errors.Wrap(err, "failed to generate random bytes")
|
2020-01-05 01:01:23 +05:30
|
|
|
}
|
|
|
|
|
return bytes, nil
|
|
|
|
|
}
|
2020-07-27 19:55:24 +02:00
|
|
|
|
2018-10-12 12:21:29 -06:00
|
|
|
func decodeSecret(secret *v1.Secret) (string, error) {
|
|
|
|
|
password, ok := secret.Data[passwordKeyName]
|
|
|
|
|
if !ok {
|
2019-10-08 12:51:36 +02:00
|
|
|
return "", errors.New("password not found in secret")
|
2018-10-12 12:21:29 -06:00
|
|
|
}
|
|
|
|
|
return string(password), nil
|
|
|
|
|
}
|