From bec2bbeff86474ec43c1524f1a44a5741835ed36 Mon Sep 17 00:00:00 2001 From: Atul Krishna Date: Tue, 15 Nov 2022 19:02:48 +0530 Subject: [PATCH] temp err revert back err Signed-off-by: Atul Krishna --- .../cmd/chef-automate/certRotate.go | 89 +++++++++++++++---- .../automate-cli/cmd/chef-automate/config.go | 13 +++ 2 files changed, 83 insertions(+), 19 deletions(-) diff --git a/components/automate-cli/cmd/chef-automate/certRotate.go b/components/automate-cli/cmd/chef-automate/certRotate.go index 6a59c7135ed..c6ff5d81fd6 100644 --- a/components/automate-cli/cmd/chef-automate/certRotate.go +++ b/components/automate-cli/cmd/chef-automate/certRotate.go @@ -4,7 +4,10 @@ import ( "fmt" "io/ioutil" "log" + "net" "os" + "path/filepath" + "regexp" "strings" "time" @@ -123,21 +126,23 @@ const ( sudo systemctl stop hab-sup.service echo "y" | sudo cp /tmp/%s /hab/user/automate-ha-%s/config/user.toml sudo systemctl start hab-sup.service` + + IP_V4_REGEX = `(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}` ) // This function will rotate the certificates of Automate, Chef Infra Server, Postgres and Opensearch. func certRotate(cmd *cobra.Command, args []string) error { - rootCA, publicCert, privateCert, adminCert, adminKey, err := getCerts() - if err != nil { - log.Fatal(err) - } - if isA2HARBFileExist() { infra, err := getAutomateHAInfraDetails() if err != nil { return err } + rootCA, publicCert, privateCert, adminCert, adminKey, err := getCerts(infra) + if err != nil { + log.Fatal(err) + } + if rootCA != "" && nodeFlag.node != "" { writer.Warn("root-ca flag will be ignored when node flag is provided") } @@ -393,35 +398,38 @@ func getIps(remoteService string, infra *AutomteHAInfraDetails) []string { } // This function will read the certificate paths, and then return the required certificates. -func getCerts() (string, string, string, string, string, error) { +func getCerts(infra *AutomteHAInfraDetails) (string, string, string, string, string, error) { privateCertPath := certFlags.privateCert publicCertPath := certFlags.publicCert rootCaPath := certFlags.rootCA adminCertPath := certFlags.adminCert adminKeyPath := certFlags.adminKey + var rootCABytes, adminCert, adminKey []byte var rootCA string var err error + const fileAccessErrorMsg string = "failed reading data from the given source, %s" + if privateCertPath == "" || publicCertPath == "" { return "", "", "", "", "", errors.New("Please provide public and private cert paths") } - privateCert, err := ioutil.ReadFile(privateCertPath) // nosemgrep + privateCert, err := getCertFromFile(privateCertPath, infra) if err != nil { return "", "", "", "", "", status.Wrap( err, status.FileAccessError, - fmt.Sprintf("failed reading data from file: %s", err.Error()), + fmt.Sprintf(fileAccessErrorMsg, err.Error()), ) } - publicCert, err := ioutil.ReadFile(publicCertPath) // nosemgrep + publicCert, err := getCertFromFile(publicCertPath, infra) if err != nil { return "", "", "", "", "", status.Wrap( err, status.FileAccessError, - fmt.Sprintf("failed reading data from file: %s", err.Error()), + fmt.Sprintf(fileAccessErrorMsg, err.Error()), ) } @@ -431,13 +439,13 @@ func getCerts() (string, string, string, string, string, error) { return "", "", "", "", "", errors.New("Please provide rootCA path") } if rootCaPath != "" { - rootCABytes, err = ioutil.ReadFile(rootCaPath) // nosemgrep + rootCABytes, err = getCertFromFile(rootCaPath, infra) rootCA = string(rootCABytes) if err != nil { return "", "", "", "", "", status.Wrap( err, status.FileAccessError, - fmt.Sprintf("failed reading data from file: %s", err.Error()), + fmt.Sprintf(fileAccessErrorMsg, err.Error()), ) } } @@ -448,34 +456,77 @@ func getCerts() (string, string, string, string, string, error) { if adminCertPath == "" || adminKeyPath == "" { return "", "", "", "", "", errors.New("Please provide Admin cert and Admin key paths") } - adminCert, err = ioutil.ReadFile(adminCertPath) // nosemgrep + adminCert, err = getCertFromFile(adminCertPath, infra) if err != nil { return "", "", "", "", "", status.Wrap( err, status.FileAccessError, - fmt.Sprintf("failed reading data from file: %s", err.Error()), + fmt.Sprintf(fileAccessErrorMsg, err.Error()), ) } - adminKey, err = ioutil.ReadFile(adminKeyPath) // nosemgrep + adminKey, err = getCertFromFile(adminKeyPath, infra) if err != nil { return "", "", "", "", "", status.Wrap( err, status.FileAccessError, - fmt.Sprintf("failed reading data from file: %s", err.Error()), + fmt.Sprintf(fileAccessErrorMsg, err.Error()), ) } } - return rootCA, string(publicCert), string(privateCert), string(adminCert), string(adminKey), nil } -/* If we are working on backend service, then first we have to get the applied configurations +// This function will read the certificate from the given path (local or remote). +func getCertFromFile(certPath string, infra *AutomteHAInfraDetails) ([]byte, error) { + // Checking if the given path is remote or local. + if isRemotePath(certPath) { + // Get Host IP from the given path and validate it. + hostIP := getIPV4(certPath) + if net.ParseIP(hostIP).To4() == nil { + return nil, errors.New(fmt.Sprintf("%v is not a valid IPv4 address", hostIP)) + } + + // Get the file path from the given remote address. + certPaths := strings.Split(certPath, ":") + if len(certPaths) != 2 { + return nil, errors.New(fmt.Sprintf("Invalid remote path: %v", certPath)) + } + remoteFilePath := strings.TrimSpace(certPaths[1]) + fileName := filepath.Base(remoteFilePath) + if remoteFilePath == "" || fileName == "" { + return nil, errors.New(fmt.Sprintf("Invalid remote path: %v", certPath)) + } + + // Download certificate from remote host. + sshUser, sskKeyFile, _ := getSshDetails(infra) + filePath, err := copyFileFromRemote(sskKeyFile, remoteFilePath, sshUser, hostIP, fileName) + if err != nil { + return nil, errors.New(fmt.Sprintf("Unable to copy file from remote path: %v", certPath)) + } + return ioutil.ReadFile(filePath) // nosemgrep + } + return ioutil.ReadFile(certPath) // nosemgrep +} + +func isRemotePath(path string) bool { + pattern := regexp.MustCompile(IP_V4_REGEX) + return pattern.MatchString(path) +} + +func getIPV4(path string) string { + pattern := regexp.MustCompile(IP_V4_REGEX) + return pattern.FindString(path) +} + +/* +If we are working on backend service, then first we have to get the applied configurations and then merge it with new configurations, then apply that configuration. Because if we directly apply the new configurations, then the old applied configurations will be gone. So, we have to retain the old configurations also. -This function will create the new toml file which includes old and new configurations.*/ +This function will create the new toml file which includes old and new configurations. +*/ func getMerger(fileName string, timestamp string, remoteType string, config string, sshUser string, sshPort string, sskKeyFile string, remoteIP string) (string, error) { tomlFile := fileName + timestamp scriptCommands := fmt.Sprintf(config, remoteType) diff --git a/components/automate-cli/cmd/chef-automate/config.go b/components/automate-cli/cmd/chef-automate/config.go index f3dde9cee07..117dbe7bcc6 100644 --- a/components/automate-cli/cmd/chef-automate/config.go +++ b/components/automate-cli/cmd/chef-automate/config.go @@ -367,6 +367,19 @@ func copyFileToRemote(sshKeyFile string, tomlFilePath string, sshUser string, ho return nil } +// This function will copy file from remote to local and return new local file path +func copyFileFromRemote(sshKeyFile string, remoteFilePath string, sshUser string, hostIP string, outputFileName string) (string, error) { + cmd := "scp" + ts := time.Now().Format("20060102150405") + destFileName := "/tmp/" + ts + "_" + outputFileName + execArgs := []string{"-o StrictHostKeyChecking=no", "-i", sshKeyFile, "-r", sshUser + "@" + hostIP + ":" + remoteFilePath, destFileName} + if err := exec.Command(cmd, execArgs...).Run(); err != nil { + writer.Print("Failed to copy file from remote\n") + return "", err + } + return destFileName, nil +} + func createKnownHosts() { f, fErr := os.OpenFile(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"), os.O_CREATE, 0600) if fErr != nil {