Repository: chef/automate
Pull request #8111 (2023-08-09 06:33:30)

Service Now doc changes
### :nut_and_bolt: Description: What code changed, and why?

<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

The service now docs have inconsistent API paths. Some places the API paths were incorrect also. Few images needed improvement. As part of this pr we have updated them

### :chains: Related Resources

https://chefio.atlassian.net/browse/CHEF-5541

### :+1: Definition of Done

### :athletic_shoe: How to Build and Test the Change

### :white_check_mark: Checklist

**All PRs** must tick these:

- [ ] I have read the [CONTRIBUTING document](https://github.com/chef/automate/blob/master/CONTRIBUTING.md).
- [ ] All commits signed-off for the [Developer Certification of Origin](https://github.com/chef/chef/blob/master/CONTRIBUTING.md#developer-certification-of-origin-dco).

With occasional exceptions, all PRs **from Progress employees** must tick these:

- [ ] Is the code clear? *(complicated code or lots of comments--subdivide and use well-named methods, meaningful variable names, etc.)*
- [ ] Consistency checked? *(user notifications, user prompts, visual patterns, code patterns, variable names)*
- [ ] Repeated code blocks eliminated? *(adapt and reuse existing components, blocks, functions, etc.)*
- [ ] Spelling, grammar, typos checked? *(at a minimum use `make spell` in any component directory)*
- [ ] Code well-formatted? *(indents, line breaks, etc. improve rather than hinder readability)*

All PRs **from Progress employees** should tick these if appropriate:

- [ ] Tests added/updated? (all new code needs new tests)
- [ ] Docs added/updated? (all customer-facing changes)

*Please add a note next to any checkbox above if you are NOT ticking it.*

### :camera: Screenshots, if applicable


netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *chef-automate* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | ed68480c273b732ef256994f3bf56ed73c074c88 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/chef-automate/deploys/64d3333c4c48a90008dfd5bb |
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&metric=coverage&view=list) No Coverage information  
[![No Duplication information](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8111&metric=duplicated_lines_density&view=list) No Duplication information



Patch:
diff --git a/VERSION b/VERSION
index 4e3b0de78..361e4695c 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.9.16
\ No newline at end of file
+4.9.32
\ No newline at end of file
diff --git a/components/automate-cli/cmd/chef-automate/applications.go b/components/automate-cli/cmd/chef-automate/applications.go
index bc64374c6..3a80d19e3 100644
--- a/components/automate-cli/cmd/chef-automate/applications.go
+++ b/components/automate-cli/cmd/chef-automate/applications.go
@@ -5,6 +5,8 @@ import (
 	"fmt"
 	"io"
 	"os"
+	"os/exec"
+	"strings"
 	"time"
 
 	"github.com/pkg/errors"
@@ -13,8 +15,20 @@ import (
 	"github.com/chef/automate/api/external/applications"
 	"github.com/chef/automate/components/automate-cli/pkg/client/apiclient"
 	"github.com/chef/automate/components/automate-cli/pkg/docs"
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
 )
 
+const (
+	SHOW_COMMAND = "chef-automate applications show-svcs"
+)
+
+type IExecutor interface {
+	execCommand(string) (string, error)
+	runCommandOnSingleAutomateNode(cmd *cobra.Command, args []string) (string, error)
+}
+
+type Executor struct{}
+
 func init() {
 	appsSubcmd := newApplicationsRootSubcmd()
 
@@ -29,7 +43,7 @@ func newApplicationsRootSubcmd() *cobra.Command {
 		Use:   "applications COMMAND",
 		Short: "Manage applications observability features",
 		Annotations: map[string]string{
-			docs.Tag: docs.Automate,
+			docs.Tag: docs.BastionHost,
 		},
 	}
 }
@@ -159,7 +173,7 @@ Display a list of the habitat services stored in the applications database.
 `,
 		RunE: runApplicationsShowSvcsCmd,
 		Annotations: map[string]string{
-			docs.Tag: docs.Automate,
+			docs.Tag: docs.BastionHost,
 		},
 	}
 
@@ -189,7 +203,7 @@ services database.
 `,
 		RunE: runApplicationsRemoveSvcsCmd,
 		Annotations: map[string]string{
-			docs.Tag: docs.Automate,
+			docs.Tag: docs.BastionHost,
 		},
 	}
 
@@ -262,7 +276,16 @@ func makeServicesReqWithFilters() *applications.ServicesReq {
 	return req
 }
 
-func runApplicationsShowSvcsCmd(cmd *cobra.Command, args []string) error {
+func showApplicationsHA(cmd *cobra.Command, args []string, e IExecutor) error {
+	output, err := e.runCommandOnSingleAutomateNode(cmd, args)
+	if err != nil {
+		return err
+	}
+	writer.Print(output)
+	return nil
+}
+
+func showApplicationsStandalone() error {
 	s := &serviceSet{
 		applicationsServiceFilters: applicationsServiceFiltersFlags,
 	}
@@ -281,11 +304,79 @@ func runApplicationsShowSvcsCmd(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func runApplicationsRemoveSvcsCmd(cmd *cobra.Command, args []string) error {
-	if !applicationsServiceFiltersFlags.FilterApplied() && !removeSvcsFlags.all {
-		return errors.New("You must filter the services to be deleted or pass the --all flag to delete all services")
+func runApplicationsShowSvcsCmd(cmd *cobra.Command, args []string) error {
+	if isA2HARBFileExist() {
+		if err := showApplicationsHA(cmd, args, Executor{}); err != nil {
+			return err
+		}
+	} else {
+		if err := showApplicationsStandalone(); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func showAndPrompt(cmd *cobra.Command, e IExecutor, w *cli.Writer) ([]string, bool, error) {
+	var splittedString []string
+	flags := GetEnabledFlags(cmd, map[string]int{"all": 1})
+	showCmd := SHOW_COMMAND + flags
+	output, err := e.execCommand(showCmd)
+	if err != nil {
+		return splittedString, false, err
+	}
+	splittedString = strings.Split(output, "\n")
+	// splittedString always contains 2 lines no matter services matches the criteria or not
+	// first line is table header and last line is empty line.
+	// >2 means it's containing the services which matches the criteria.
+	if len(splittedString) > 2 {
+		for i := 0; i < len(splittedString); i++ {
+			fmt.Println(splittedString[i])
+		}
+		prompt := fmt.Sprintf("The above %d services will be deleted. Do you wish to continue?", len(splittedString)-2)
+		proceed, err := w.Confirm(prompt)
+		if err != nil {
+			return splittedString, false, err
+		}
+		if !proceed {
+			return splittedString, false, nil
+		}
+	}
+	return splittedString, true, nil
+}
+
+func removeApplicationsHA(cmd *cobra.Command, args []string, e IExecutor, w *cli.Writer) error {
+	var splittedString []string
+	// If user is not passing -y flag, then first we need to show the list with given conditions and then
+	// give confirmation prompt
+	if !removeSvcsFlags.yes {
+		var proceed bool
+		var err error
+		splittedString, proceed, err = showAndPrompt(cmd, e, w)
+		if err != nil {
+			return err
+		}
+		if !proceed {
+			return nil
+		}
 	}
+	args = append(args, "-y")
+	output, err := e.runCommandOnSingleAutomateNode(cmd, args)
+	if err != nil {
+		return err
+	}
+	// len(splittedString) == 2 means list is empty it's just containing table header and empty line which means we haven't
+	// got any services to remove
+	if removeSvcsFlags.yes || len(splittedString) == 2 {
+		writer.Println(output)
+	} else {
+		writer.Println(fmt.Sprintf("Removed %d services", len(splittedString)-2))
+	}
+
+	return nil
+}
 
+func removeApplicationsStandalone() error {
 	s := &serviceSet{
 		applicationsServiceFilters: applicationsServiceFiltersFlags,
 	}
@@ -324,6 +415,22 @@ func runApplicationsRemoveSvcsCmd(cmd *cobra.Command, args []string) error {
 	if err != nil {
 		return err
 	}
+	return nil
+}
+
+func runApplicationsRemoveSvcsCmd(cmd *cobra.Command, args []string) error {
+	if !applicationsServiceFiltersFlags.FilterApplied() && !removeSvcsFlags.all {
+		return errors.New("You must filter the services to be deleted or pass the --all flag to delete all services")
+	}
+	if isA2HARBFileExist() {
+		if err := removeApplicationsHA(cmd, args, Executor{}, writer); err != nil {
+			return err
+		}
+	} else {
+		if err := removeApplicationsStandalone(); err != nil {
+			return err
+		}
+	}
 
 	return nil
 }
@@ -335,6 +442,18 @@ type serviceSet struct {
 	ctx        context.Context
 }
 
+func (e Executor) execCommand(cmd string) (string, error) {
+	output, err := exec.Command("/bin/sh", "-c", cmd).Output()
+	if err != nil {
+		return "", err
+	}
+	return string(output), nil
+}
+
+func (e Executor) runCommandOnSingleAutomateNode(cmd *cobra.Command, args []string) (string, error) {
+	return RunCmdOnSingleAutomateNode(cmd, args)
+}
+
 func (s *serviceSet) Connect() error {
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
 	defer cancel()
@@ -395,7 +514,7 @@ func (s *serviceSet) PrintTSV() error {
 		len(s.statusLabelFor(svc)),
 	)
 
-	fmt.Fprintf(os.Stderr, fmtString, "id", "svc.group", "release", "FQDN", "app:env", "status")
+	fmt.Printf(fmtString, "id", "svc.group", "release", "FQDN", "app:env", "status")
 	for _, svc := range s.services {
 		fmt.Printf("%s\t%s\t%s\t%s\t%s:%s\t%s\n",
 			svc.Id,
diff --git a/components/automate-cli/cmd/chef-automate/ca.go b/components/automate-cli/cmd/chef-automate/ca.go
index 550b15c6f..f45127378 100644
--- a/components/automate-cli/cmd/chef-automate/ca.go
+++ b/components/automate-cli/cmd/chef-automate/ca.go
@@ -1,10 +1,12 @@
 package main
 
 import (
+	"container/list"
 	"context"
 	"fmt"
 	"time"
 
+	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
 	api "github.com/chef/automate/api/interservice/deployment"
@@ -14,56 +16,118 @@ import (
 	"github.com/chef/automate/components/automate-deployment/pkg/client"
 )
 
+var caCmdFlags = struct {
+	automate    bool
+	chef_server bool
+	node        string
+}{}
+
+var caCmd = &cobra.Command{
+	Use:   "internal-ca COMMAND",
+	Short: "Manage Chef Automate's internal certificate authority",
+	Long:  "Manage Chef Automate's internal certificate authority. Used for inter-service encryption and authentication.",
+	Annotations: map[string]string{
+		docs.Tag: docs.BastionHost,
+	},
+}
+
+var caInfo = &cobra.Command{
+	Use:   "info",
+	Short: "Print information of the root certificate for the internal certificate authority",
+	RunE:  runCAInfoCmd,
+	Args:  cobra.MaximumNArgs(0),
+	Annotations: map[string]string{
+		docs.Tag: docs.BastionHost,
+	},
+}
+
+var regen = &cobra.Command{
+	Use:   "regenerate",
+	Short: "Commands to regenerate certificates issued by the internal certificate authority",
+	Annotations: map[string]string{
+		docs.Tag: docs.BastionHost,
+	},
+}
+
+var regenRoot = &cobra.Command{
+	Use:   "root",
+	Short: "Regenerate the root certificate for the internal certificate authority",
+	RunE:  runRegenRootCmd,
+	Args:  cobra.MaximumNArgs(0),
+	Annotations: map[string]string{
+		docs.Tag: docs.BastionHost,
+	},
+}
+
 func init() {
-	RootCmd.AddCommand(caCmd())
+	regen.AddCommand(regenRoot)
+	caCmd.AddCommand(caInfo)
+	caCmd.AddCommand(regen)
+
+	caInfo.PersistentFlags().BoolVarP(&caCmdFlags.automate, "automate", "a", false, "Print information of the root certificate of automate nodes")
+	caInfo.PersistentFlags().SetAnnotation("automate", docs.Compatibility, []string{docs.CompatiblewithHA})
+	caInfo.PersistentFlags().BoolVar(&caCmdFlags.automate, "a2", false, "Print information of the root certificate of automate nodes")
+	caInfo.PersistentFlags().SetAnnotation("a2", docs.Compatibility, []string{docs.CompatiblewithHA})
+	caInfo.PersistentFlags().BoolVarP(&caCmdFlags.chef_server, "chef_server", "c", false, "Print information of the root certificate of chef_server nodes")
+	caInfo.PersistentFlags().SetAnnotation("chef_server", docs.Compatibility, []string{docs.CompatiblewithHA})
+	caInfo.PersistentFlags().BoolVar(&caCmdFlags.chef_server, "cs", false, "Print information of the root certificate of chef_server nodes")
+	caInfo.PersistentFlags().SetAnnotation("cs", docs.Compatibility, []string{docs.CompatiblewithHA})
+	caInfo.PersistentFlags().StringVar(&caCmdFlags.node, "node", "", "Node Ip address")
+	caInfo.PersistentFlags().SetAnnotation("node", docs.Compatibility, []string{docs.CompatiblewithHA})
+
+	regenRoot.PersistentFlags().BoolVarP(&caCmdFlags.automate, "automate", "a", false, "Regenerate the root certificate for automate nodes")
+	regenRoot.PersistentFlags().SetAnnotation("automate", docs.Compatibility, []string{docs.CompatiblewithHA})
+	regenRoot.PersistentFlags().BoolVar(&caCmdFlags.automate, "a2", false, "Regenerate the root certificate for automate nodes")
+	regenRoot.PersistentFlags().SetAnnotation("a2", docs.Compatibility, []string{docs.CompatiblewithHA})
+	regenRoot.PersistentFlags().BoolVarP(&caCmdFlags.chef_server, "chef_server", "c", false, "Regenerate the root certificate for chef_server nodes")
+	regenRoot.PersistentFlags().SetAnnotation("chef_server", docs.Compatibility, []string{docs.CompatiblewithHA})
+	regenRoot.PersistentFlags().BoolVar(&caCmdFlags.chef_server, "cs", false, "Regenerate the root certificate for chef_server nodes")
+	regenRoot.PersistentFlags().SetAnnotation("cs", docs.Compatibility, []string{docs.CompatiblewithHA})
+	regenRoot.PersistentFlags().StringVar(&caCmdFlags.node, "node", "", "Node Ip address")
+	regenRoot.PersistentFlags().SetAnnotation("node", docs.Compatibility, []string{docs.CompatiblewithHA})
+
+	RootCmd.AddCommand(caCmd)
 }
 
-func caCmd() *cobra.Command {
-	cmd := &cobra.Command{
-		Use:   "internal-ca COMMAND",
-		Short: "Manage Chef Automate's internal certificate authority",
-		Long:  "Manage Chef Automate's internal certificate authority. Used for inter-service encryption and authentication.",
-		Annotations: map[string]string{
-			docs.Tag: docs.FrontEnd,
-		},
-	}
+func runCAInfoCmd(cmd *cobra.Command, args []string) error {
+	if isA2HARBFileExist() {
+		infra, err := getAutomateHAInfraDetails()
+		if err != nil {
+			return err
+		}
 
-	caInfo := &cobra.Command{
-		Use:   "info",
-		Short: "Print information the root certificate for the internal certificate authority",
-		RunE:  runCAInfoCmd,
-		Args:  cobra.MaximumNArgs(0),
-		Annotations: map[string]string{
-			docs.Tag: docs.FrontEnd,
-		},
-	}
+		if err = runInternalCaHA(infra, cmd); err != nil {
+			return err
+		}
 
-	regen := &cobra.Command{
-		Use:   "regenerate",
-		Short: "Commands to regenerate certificates issued by the internal certificate authority",
-		Annotations: map[string]string{
-			docs.Tag: docs.FrontEnd,
-		},
+	} else {
+		if err := runInternalCaInfoStandalone(); err != nil {
+			return err
+		}
 	}
+	return nil
+}
 
-	regenRoot := &cobra.Command{
-		Use:   "root",
-		Short: "Regenerate the root certificate for the internal certificate authority",
-		RunE:  runRegenRootCmd,
-		Args:  cobra.MaximumNArgs(0),
-		Annotations: map[string]string{
-			docs.Tag: docs.FrontEnd,
-		},
-	}
+func runRegenRootCmd(cmd *cobra.Command, args []string) error {
+	if isA2HARBFileExist() {
+		infra, err := getAutomateHAInfraDetails()
+		if err != nil {
+			return err
+		}
 
-	regen.AddCommand(regenRoot)
+		if err = runInternalCaHA(infra, cmd); err != nil {
+			return err
+		}
 
-	cmd.AddCommand(regen)
-	cmd.AddCommand(caInfo)
-	return cmd
+	} else {
+		if err := runGenerateRootStandalone(); err != nil {
+			return err
+		}
+	}
+	return nil
 }
 
-func runCAInfoCmd(*cobra.Command, []string) error {
+func runInternalCaInfoStandalone() error {
 	connection, err := client.Connection(client.DefaultClientTimeout)
 	if err != nil {
 		return status.Wrap(
@@ -96,15 +160,7 @@ func runCAInfoCmd(*cobra.Command, []string) error {
 	return nil
 }
 
-func prettyDuration(d time.Duration) string {
-	if d > 24*time.Hour {
-		return fmt.Sprintf("%dd", int(d.Hours()/24))
-	}
-
-	return d.String()
-}
-
-func runRegenRootCmd(*cobra.Command, []string) error {
+func runGenerateRootStandalone() error {
 	connection, err := client.Connection(client.DefaultClientTimeout)
 	if err != nil {
 		return status.Wrap(
@@ -126,3 +182,135 @@ func runRegenRootCmd(*cobra.Command, []string) error {
 	writer.Title("Certificate authority regenerated.")
 	return nil
 }
+
+func runInternalCaHA(infra *AutomateHAInfraDetails, cmd *cobra.Command) error {
+	scriptCommands := "sudo " + cmd.CommandPath()
+	if err := flagsValidation(cmd); err != nil {
+		return err
+	}
+
+	sshConfig := getSshDetails(infra)
+	ips, remoteService, err := getHANodes(infra)
+	if err != nil {
+		return err
+	}
+	if len(ips) == 0 {
+		return errors.New(fmt.Sprintf("No %s IPs are found", remoteService))
+	}
+
+	err = triggerInternalCaHA(*sshConfig, ips, remoteService, scriptCommands)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func getHANodes(infra *AutomateHAInfraDetails) ([]string, string, error) {
+	var ips []string
+	var remoteService string
+	if caCmdFlags.automate {
+		remoteService = AUTOMATE
+		automateIps, err := getParticularServiceNodes(infra, remoteService)
+		if err != nil {
+			return []string{}, remoteService, err
+		}
+		ips = append(ips, automateIps...)
+	}
+	if caCmdFlags.chef_server {
+		remoteService = CHEF_SERVER
+		chefserverIps, err := getParticularServiceNodes(infra, remoteService)
+		if err != nil {
+			return []string{}, remoteService, err
+		}
+		ips = append(ips, chefserverIps...)
+	}
+
+	if caCmdFlags.automate && caCmdFlags.chef_server {
+		remoteService = FRONTEND
+	}
+
+	return ips, remoteService, nil
+}
+
+func getParticularServiceNodes(infra *AutomateHAInfraDetails, remoteService string) ([]string, error) {
+	var ips []string
+	if caCmdFlags.node != "" {
+		isValid := validateEachIp(remoteService, infra, caCmdFlags.node)
+		if !isValid {
+			return []string{}, errors.New(fmt.Sprintf("Please Enter Valid %s IP", remoteService))
+		}
+		ips = append(ips, caCmdFlags.node)
+	} else {
+		ips = append(ips, getIps(remoteService, infra)...)
+	}
+
+	return ips, nil
+}
+
+func triggerInternalCaHA(sshConfig SSHConfig, ips []string, remoteService, scriptCommands string) error {
+	sshUtilMap := getMapSSHUtils(ips, &sshConfig)
+	errorList := list.New()
+
+	resultChan := make(chan Result, len(ips))
+	for _, hostIP := range ips {
+		sshUtil := sshUtilMap[hostIP]
+		go commandExecuteFrontEnd(scriptCommands, sshUtil, resultChan)
+	}
+	printMessageForInternalCAResultChan(resultChan, ips, remoteService, errorList)
+	if errorList != nil && errorList.Len() > 0 {
+		return status.Wrapf(getSingleErrorFromList(errorList), status.ServiceUnloadError, "Not able to generate root or fetch root info")
+	}
+	return nil
+}
+
+func printMessageForInternalCAResultChan(resultChan chan Result, ips []string, remoteService string, errorList *list.List) {
+	for i := 0; i < len(ips); i++ {
+		result := <-resultChan
+		printInternalCAConnectionMessage(remoteService, result.HostIP)
+		if result.Error != nil {
+			printInternalCAErrorMessage(remoteService, result.HostIP, result.Error)
+			errorList.PushBack(result.Error.Error())
+		} else {
+			writer.Printf("Output for Host IP %s : %s", result.HostIP, result.Output+"\n")
+			printInternalCASuccessMessage(remoteService, result.HostIP)
+		}
+	}
+}
+
+func printInternalCAConnectionMessage(remoteService string, hostIP string) {
+	writer.Println("Connecting to the " + remoteService + NODE + hostIP)
+	writer.BufferWriter().Flush()
+}
+
+func printInternalCAErrorMessage(remoteService string, hostIP string, err error) {
+	writer.Failf("Command failed on "+remoteService+NODE+hostIP+" with error:\n%v \n", err)
+	writer.BufferWriter().Flush()
+}
+
+func printInternalCASuccessMessage(remoteService string, hostIP string) {
+	writer.Success("Command is completed on " + remoteService + NODE + hostIP + "\n")
+	writer.BufferWriter().Flush()
+}
+
+func flagsValidation(cmd *cobra.Command) error {
+	if !caCmdFlags.automate && !caCmdFlags.chef_server {
+		if caCmdFlags.node != "" {
+			writer.Println("Please Provide service flag")
+			return errors.New("Please provide service flag")
+		}
+		writer.Println(cmd.UsageString())
+		return errors.New("No flag is enabled. Please provide any flag")
+	}
+	if caCmdFlags.automate && caCmdFlags.chef_server && caCmdFlags.node != "" {
+		return errors.New("Please remove node flag if you have given multiple service flags.")
+	}
+	return nil
+}
+
+func prettyDuration(d time.Duration) string {
+	if d > 24*time.Hour {
+		return fmt.Sprintf("%dd", int(d.Hours()/24))
+	}
+
+	return d.String()
+}
diff --git a/components/automate-cli/cmd/chef-automate/cliUtils.go b/components/automate-cli/cmd/chef-automate/cliUtils.go
index d38ac2052..98ad07741 100644
--- a/components/automate-cli/cmd/chef-automate/cliUtils.go
+++ b/components/automate-cli/cmd/chef-automate/cliUtils.go
@@ -25,17 +25,16 @@ func GenerateOriginalAutomateCLICommand(cmd *cobra.Command, args []string) strin
 }
 
 // RunCmdOnSingleAutomateNode runs the command on a single automate node
-func RunCmdOnSingleAutomateNode(cmd *cobra.Command, args []string) error {
+func RunCmdOnSingleAutomateNode(cmd *cobra.Command, args []string) (string, error) {
 	script := GenerateOriginalAutomateCLICommand(cmd, args)
-
 	infra, err := getAutomateHAInfraDetails()
 	if err != nil {
-		return err
+		return "", err
 	}
 
 	ips := infra.Outputs.AutomatePrivateIps.Value
 	if len(ips) == 0 {
-		return errors.New("No automate IPs are found")
+		return "", errors.New("No automate IPs are found")
 	}
 
 	sshConfig := &SSHConfig{
@@ -52,10 +51,9 @@ func RunCmdOnSingleAutomateNode(cmd *cobra.Command, args []string) error {
 		if len(strings.TrimSpace(output)) != 0 {
 			printErrorMessage("Automate", ips[0], writer, output)
 		}
-		return err
+		return "", err
 	}
-	writer.Print(output)
-	return nil
+	return output, nil
 }
 
 // RunCmdOnSingleAutomateNode runs the command on a single automate node
@@ -93,3 +91,20 @@ func RunCmdOnSingleAutomateNodeNCopyReport(cmd *cobra.Command, args []string, fi
 
 	return nil
 }
+
+func GetEnabledFlags(cmd *cobra.Command, flagsToIgnore map[string]int) string {
+	flags := ""
+	cmd.Flags().VisitAll(func(flag *pflag.Flag) {
+		if flagsToIgnore[flag.Name] != 0 {
+			return
+		}
+		if flag.Changed {
+			if flag.Value.Type() != "bool" {
+				flags += " --" + flag.Name + " " + flag.Value.String()
+			} else {
+				flags += " --" + flag.Name
+			}
+		}
+	})
+	return flags
+}
diff --git a/components/automate-cli/cmd/chef-automate/iam.go b/components/automate-cli/cmd/chef-automate/iam.go
index 7f2765237..ac8589d6f 100644
--- a/components/automate-cli/cmd/chef-automate/iam.go
+++ b/components/automate-cli/cmd/chef-automate/iam.go
@@ -292,12 +292,13 @@ func preIAMCmd(cmd *cobra.Command, args []string) error {
 		return status.Wrap(err, status.CommandExecutionError, "unable to set command parent settings")
 	}
 	if isA2HARBFileExist() {
-		err = RunCmdOnSingleAutomateNode(cmd, args)
+		output, err := RunCmdOnSingleAutomateNode(cmd, args)
 		if err != nil {
 			return err
 		}
+		writer.Print(output)
 		// NOTE: used os.exit as need to stop next lifecycle method to execute
-		os.Exit(1)
+		os.Exit(0)
 	}
 	return nil
 }
diff --git a/components/automate-cli/cmd/chef-automate/infrastructure.go b/components/automate-cli/cmd/chef-automate/infrastructure.go
index 225571b0c..406548e98 100644
--- a/components/automate-cli/cmd/chef-automate/infrastructure.go
+++ b/components/automate-cli/cmd/chef-automate/infrastructure.go
@@ -65,10 +65,12 @@ func preInfrastructureCmd(cmd *cobra.Command, args []string) error {
 		return status.Wrap(err, status.CommandExecutionError, "unable to set command parent settings")
 	}
 	if isA2HARBFileExist() {
-		if err = RunCmdOnSingleAutomateNode(cmd, args); err != nil {
+		output, err := RunCmdOnSingleAutomateNode(cmd, args)
+		if err != nil {
 			return err
 		}
-		os.Exit(1)
+		writer.Print(output)
+		os.Exit(0)
 	}
 	return nil
 }
diff --git a/components/automate-cli/cmd/chef-automate/license.go b/components/automate-cli/cmd/chef-automate/license.go
index e2aa242a0..d28eb061c 100644
--- a/components/automate-cli/cmd/chef-automate/license.go
+++ b/components/automate-cli/cmd/chef-automate/license.go
@@ -460,12 +460,13 @@ func preLicenseCmd(cmd *cobra.Command, args []string) error {
 		return status.Wrap(err, status.CommandExecutionError, "unable to set command parent settings")
 	}
 	if isA2HARBFileExist() {
-		err = RunCmdOnSingleAutomateNode(cmd, args)
+		output, err := RunCmdOnSingleAutomateNode(cmd, args)
 		if err != nil {
 			return err
 		}
+		writer.Print(output)
 		// NOTE: used os.exit as need to stop next lifecycle method to execute
-		os.Exit(1)
+		os.Exit(0)
 	}
 	return nil
 }
@@ -495,7 +496,7 @@ func getPreLicenseReportCmd(fileNamePrefix string) func(*cobra.Command, []string
 				return err
 			}
 			// NOTE: used os.exit as need to stop next lifecycle method to execute
-			os.Exit(1)
+			os.Exit(0)
 		}
 		return nil
 	}
diff --git a/components/automate-cli/cmd/chef-automate/service_versions.go b/components/automate-cli/cmd/chef-automate/service_versions.go
index f9061e959..02c3310c0 100644
--- a/components/automate-cli/cmd/chef-automate/service_versions.go
+++ b/components/automate-cli/cmd/chef-automate/service_versions.go
@@ -4,26 +4,291 @@ package main
 
 import (
 	"context"
+	"os"
+	"strings"
 
 	"github.com/spf13/cobra"
 
 	api "github.com/chef/automate/api/interservice/deployment"
 	"github.com/chef/automate/components/automate-cli/pkg/docs"
 	"github.com/chef/automate/components/automate-cli/pkg/status"
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
 	"github.com/chef/automate/components/automate-deployment/pkg/client"
 )
 
-var serviceVersionsCmd = &cobra.Command{
-	Use:   "service-versions",
-	Short: "Retrieve the versions of the individual Chef Automate services",
-	Long:  "Retrieve the versions of the individual Chef Automate services",
-	RunE:  runServiceVersionsCmd,
-	Annotations: map[string]string{
-		docs.Tag: docs.FrontEnd,
-	},
+const (
+	SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED = "Showing the service-versions for externally configured %s is not supported."
+	BACKEND_SERVICE_VERSIONS_CMD           = `sudo HAB_LICENSE=accept-no-persist hab svc status | awk 'NR>1 {split($1,a,"/"); printf "%s/%s %s %s\n", a[1], a[2], a[3], a[4]}'`
+	FRONTEND_SERVICE_VERSIONS_CMD          = "sudo chef-automate service-versions"
+)
+
+type ServiceVersionsCmdFlags struct {
+	automate   bool
+	chefServer bool
+	postgresql bool
+	opensearch bool
+	node       string
+}
+
+var serviceVersionsCmdFlag = ServiceVersionsCmdFlags{}
+
+type ServiceVersionsCmdResult struct {
+	cmdResult map[string][]*CmdResult
+	writer    *cli.Writer
+	nodeType  string
+	err       error
+}
+
+func init() {
+	var serviceVersionsCmd = &cobra.Command{
+		Use:   "service-versions",
+		Short: "Retrieve the versions of the individual Chef Automate services",
+		Long:  "Retrieve the versions of the individual Chef Automate services",
+		RunE:  runServiceVersionsCmd,
+		Annotations: map[string]string{
+			docs.Tag: docs.BastionHost,
+		},
+	}
+	serviceVersionsCmd.PersistentFlags().BoolVarP(&serviceVersionsCmdFlag.automate, "automate", "a", false, "Shows service-versions for Automate nodes")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("automate", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVarP(&serviceVersionsCmdFlag.chefServer, "chef_server", "c", false, "Shows service-versions for Chef-server nodes")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("chef_server", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVarP(&serviceVersionsCmdFlag.postgresql, "postgresql", "p", false, "Shows service-versions for PostgresQL nodes")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("postgresql", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVarP(&serviceVersionsCmdFlag.opensearch, "opensearch", "o", false, "Shows service-versions for OpenSearch nodes")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("opensearch", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVar(&serviceVersionsCmdFlag.automate, "a2", false, "Shows service-versions for Automate nodes[DUPLICATE]")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("a2", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVar(&serviceVersionsCmdFlag.chefServer, "cs", false, "Shows service-versions for Chef-server nodes[DUPLICATE]")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("cs", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVar(&serviceVersionsCmdFlag.postgresql, "pg", false, "Shows service-versions for PostgresQL nodes[DUPLICATE]")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("pg", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().BoolVar(&serviceVersionsCmdFlag.opensearch, "os", false, "Shows service-versions for OpenSearch nodes[DUPLICATE]")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("os", docs.Compatibility, []string{docs.CompatiblewithHA})
+	serviceVersionsCmd.PersistentFlags().StringVar(&serviceVersionsCmdFlag.node, "node", "", "Pass this flag to check service-versions of particular node in the cluster")
+	serviceVersionsCmd.PersistentFlags().SetAnnotation("node", docs.Compatibility, []string{docs.CompatiblewithHA})
+	RootCmd.AddCommand(serviceVersionsCmd)
 }
 
 func runServiceVersionsCmd(cmd *cobra.Command, args []string) error {
+	if isA2HARBFileExist() {
+		nodeOpUtils := &NodeUtilsImpl{}
+		remoteExecutor := NewRemoteCmdExecutorWithoutNodeMap(&SSHUtilImpl{}, cli.NewWriter(os.Stdout, os.Stderr, os.Stdin))
+		if err := isServiceVersionsFlagSet(cmd, &serviceVersionsCmdFlag, nodeOpUtils); err != nil {
+			return err
+		}
+		return runServiceVersionsFromBastion(&serviceVersionsCmdFlag, nodeOpUtils, remoteExecutor, printServiceVersionsOutput)
+	}
+	if err := runServiceVersionsOnStandalone(); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func runServiceVersionsFromBastion(flags *ServiceVersionsCmdFlags, nodeOpUtils NodeOpUtils, remoteExe RemoteCmdExecutor, printServiceVersionsOutput func(map[string][]*CmdResult, string, *cli.Writer)) error {
+
+	infra, _, err := nodeOpUtils.getHaInfraDetails()
+	if err != nil {
+		return err
+	}
+	serviceVersionsCmdResults := make(chan ServiceVersionsCmdResult, 4)
+
+	runServiceVersionsCmdForFrontEnd(flags, infra, serviceVersionsCmdResults, remoteExe)
+
+	if nodeOpUtils.isManagedServicesOn() {
+		serviceVersionsCmdResults <- ServiceVersionsCmdResult{}
+		serviceVersionsCmdResults <- ServiceVersionsCmdResult{}
+		err = getValueFromResultChannel(serviceVersionsCmdResults, printServiceVersionsOutput)
+		if err != nil {
+			return err
+		}
+		return handleManagedServiceErrorForServiceVersionsCmd(flags)
+	}
+
+	runServiceVersionsCmdForBackend(flags, infra, serviceVersionsCmdResults, remoteExe)
+
+	return getValueFromResultChannel(serviceVersionsCmdResults, printServiceVersionsOutput)
+}
+
+func runServiceVersionsCmdForFrontEnd(flags *ServiceVersionsCmdFlags, infra *AutomateHAInfraDetails, serviceVersionsCmdResults chan ServiceVersionsCmdResult, remoteExe RemoteCmdExecutor) {
+
+	if flags.automate {
+		go nodeServiceVersions(*flags, AUTOMATE, infra, serviceVersionsCmdResults, remoteExe)
+	} else {
+		serviceVersionsCmdResults <- ServiceVersionsCmdResult{}
+	}
+	if flags.chefServer {
+		flags.automate = false
+		go nodeServiceVersions(*flags, CHEF_SERVER, infra, serviceVersionsCmdResults, remoteExe)
+	} else {
+		serviceVersionsCmdResults <- ServiceVersionsCmdResult{}
+	}
+}
+func getValueFromResultChannel(serviceVersionsCmdResults chan ServiceVersionsCmdResult, printServiceVersionsOutput func(map[string][]*CmdResult, string, *cli.Writer)) error {
+	for i := 0; i < 4; i++ {
+		cmdResult := <-serviceVersionsCmdResults
+		if cmdResult.err != nil {
+			return cmdResult.err
+		} else {
+			if cmdResult.writer != nil {
+				printServiceVersionsOutput(cmdResult.cmdResult, cmdResult.nodeType, cmdResult.writer)
+			}
+		}
+	}
+	return nil
+}
+
+func handleManagedServiceErrorForServiceVersionsCmd(flags *ServiceVersionsCmdFlags) error {
+
+	if flags.postgresql && flags.opensearch {
+		return status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, POSTGRESQL+" and "+OPENSEARCH)
+	}
+
+	if flags.postgresql {
+		return status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, POSTGRESQL)
+	}
+
+	if flags.opensearch {
+		return status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, OPENSEARCH)
+	}
+
+	return nil
+}
+func runServiceVersionsCmdForBackend(flags *ServiceVersionsCmdFlags, infra *AutomateHAInfraDetails, serviceVersionsCmdResults chan ServiceVersionsCmdResult, remoteExe RemoteCmdExecutor) {
+
+	if flags.postgresql {
+		flags.automate = false
+		flags.chefServer = false
+		go nodeServiceVersions(*flags, POSTGRESQL, infra, serviceVersionsCmdResults, remoteExe)
+	} else {
+		serviceVersionsCmdResults <- ServiceVersionsCmdResult{}
+	}
+
+	if flags.opensearch {
+		flags.automate = false
+		flags.chefServer = false
+		flags.postgresql = false
+		go nodeServiceVersions(*flags, OPENSEARCH, infra, serviceVersionsCmdResults, remoteExe)
+	} else {
+		serviceVersionsCmdResults <- ServiceVersionsCmdResult{}
+	}
+
+}
+
+func nodeServiceVersions(flags ServiceVersionsCmdFlags, nodeType string, infra *AutomateHAInfraDetails, serviceVersionsCmdResults chan ServiceVersionsCmdResult, remoteExe RemoteCmdExecutor) {
+	writer := cli.NewWriter(os.Stdout, os.Stderr, os.Stdin)
+	remoteExe.SetWriter(writer)
+	nodeMap := constructNodeMapForServiceVersions(infra, &flags)
+	cmdResult, err := remoteExe.ExecuteWithNodeMap(nodeMap)
+	serviceVersionsCmdResults <- ServiceVersionsCmdResult{
+		cmdResult: cmdResult,
+		writer:    writer,
+		nodeType:  nodeType,
+		err:       err,
+	}
+}
+
+func constructNodeMapForServiceVersions(infra *AutomateHAInfraDetails, flags *ServiceVersionsCmdFlags) *NodeTypeAndCmd {
+	nodeMap := &NodeTypeAndCmd{
+		Frontend: &Cmd{
+			CmdInputs: &CmdInputs{
+				Cmd:                      FRONTEND_SERVICE_VERSIONS_CMD,
+				SkipPrintOutput:          true,
+				HideSSHConnectionMessage: true,
+			},
+		},
+		Automate: &Cmd{
+			CmdInputs: &CmdInputs{
+				Cmd:                      FRONTEND_SERVICE_VERSIONS_CMD,
+				ErrorCheckEnableInOutput: true,
+				NodeIps:                  []string{flags.node},
+				NodeType:                 flags.automate,
+				SkipPrintOutput:          true,
+				HideSSHConnectionMessage: true,
+			},
+		},
+		ChefServer: &Cmd{
+			CmdInputs: &CmdInputs{
+				Cmd:                      FRONTEND_SERVICE_VERSIONS_CMD,
+				ErrorCheckEnableInOutput: true,
+				NodeIps:                  []string{flags.node},
+				NodeType:                 flags.chefServer,
+				SkipPrintOutput:          true,
+				HideSSHConnectionMessage: true,
+			},
+		},
+		Postgresql: &Cmd{
+			CmdInputs: &CmdInputs{
+				Cmd:                      BACKEND_SERVICE_VERSIONS_CMD,
+				NodeIps:                  []string{flags.node},
+				ErrorCheckEnableInOutput: true,
+				NodeType:                 flags.postgresql,
+				SkipPrintOutput:          true,
+				HideSSHConnectionMessage: true,
+			},
+		},
+		Opensearch: &Cmd{
+			CmdInputs: &CmdInputs{
+				Cmd:                      BACKEND_SERVICE_VERSIONS_CMD,
+				NodeIps:                  []string{flags.node},
+				ErrorCheckEnableInOutput: true,
+				NodeType:                 flags.opensearch,
+				SkipPrintOutput:          true,
+				HideSSHConnectionMessage: true,
+			},
+		},
+		Infra: infra,
+	}
+	return nodeMap
+}
+
+func printServiceVersionsOutput(cmdResult map[string][]*CmdResult, remoteService string, writer *cli.Writer) {
+	writer.Printf("\n=====================================================%s =======================================================\n", " Service-Versions on "+remoteService)
+
+	for _, value := range cmdResult {
+		for _, cmdResult := range value {
+			if cmdResult.Error != nil {
+				printServiceVersionsErrorOutput(cmdResult, remoteService, writer)
+			} else {
+				writer.Printf("Output for Host IP %s : \n%s", cmdResult.HostIP, cmdResult.Output+"\n")
+				writer.Success("Command is executed on " + remoteService + " node : " + cmdResult.HostIP + "\n")
+			}
+			writer.BufferWriter().Flush()
+		}
+	}
+}
+
+func printServiceVersionsErrorOutput(cmdResult *CmdResult, remoteService string, writer *cli.Writer) {
+	isOutputError := false
+
+	if strings.Contains(cmdResult.Output, "DeploymentServiceUnreachableError") {
+		isOutputError = true
+		writer.Failf(CMD_FAIL_MSG, remoteService, cmdResult.HostIP, cmdResult.Output)
+	}
+
+	if !isOutputError {
+		writer.Failf(CMD_FAIL_MSG, remoteService, cmdResult.HostIP, cmdResult.Error.Error())
+	}
+}
+
+func isServiceVersionsFlagSet(cmd *cobra.Command, flags *ServiceVersionsCmdFlags, nodeOpUtils NodeOpUtils) error {
+	if !flags.automate && !flags.chefServer && !flags.opensearch && !flags.postgresql {
+		if len(flags.node) != 0 {
+			return status.Errorf(status.InvalidCommandArgsError, "Please provide service flag")
+		}
+		flags.automate = true
+		flags.chefServer = true
+
+		if !nodeOpUtils.isManagedServicesOn() {
+			flags.opensearch = true
+			flags.postgresql = true
+		}
+	}
+	return nil
+}
+
+func runServiceVersionsOnStandalone() error {
 	connection, err := client.Connection(client.DefaultClientTimeout)
 	if err != nil {
 		return err
@@ -40,10 +305,5 @@ func runServiceVersionsCmd(cmd *cobra.Command, args []string) error {
 	for _, s := range response.Services {
 		writer.Printf("%s/%s %s %s\n", s.Origin, s.Name, s.Version, s.Release)
 	}
-
 	return nil
 }
-
-func init() {
-	RootCmd.AddCommand(serviceVersionsCmd)
-}
diff --git a/components/automate-gateway/gateway/middleware/authz/authz.go b/components/automate-gateway/gateway/middleware/authz/authz.go
index 3215e9bd8..2ab727768 100644
--- a/components/automate-gateway/gateway/middleware/authz/authz.go
+++ b/components/automate-gateway/gateway/middleware/authz/authz.go
@@ -33,14 +33,14 @@ func (c *client) Handle(ctx context.Context, subjects []string, projectsToFilter
 
 	polInfo := policy.InfoForMethod(method, req)
 	if polInfo == nil {
-		log.Warnf("no policy annotation for method %s", method)
+		log.Errorf("no policy annotation for method %s", method)
 		return nil, status.Errorf(codes.Internal,
 			"missing policy info for method %q", method)
 	}
 
 	action, resource := polInfo.Action, polInfo.Resource
 	if action == "" || resource == "" {
-		log.Warnf("no policy annotation for method %s", method)
+		log.Errorf("no policy annotation for method %s", method)
 		return nil, status.Errorf(codes.Internal,
 			"missing policy info for method %q", method)
 	}
@@ -67,13 +67,13 @@ func (c *client) Handle(ctx context.Context, subjects []string, projectsToFilter
 		}
 		log.WithError(err).Error("error authorizing request")
 		return nil, status.Errorf(codes.PermissionDenied,
-			"error authorizing action %q on resource %q filtered by projects %q for members %q: %s",
-			action, resource, projectsToFilter, subjects, err.Error())
+			"Permission Denied")
 	}
 	if len(filteredResp.Projects) == 0 {
-		return nil, status.Errorf(codes.PermissionDenied,
-			"unauthorized: members %q cannot perform action %q on resource %q filtered by projects %q",
+		log.Errorf("unauthorized: members %q cannot perform action %q on resource %q filtered by projects %q",
 			subjects, action, resource, projectsToFilter)
+		return nil, status.Errorf(codes.PermissionDenied,
+			"Permission Denied")
 	}
 	projects := filteredResp.Projects
 
@@ -112,20 +112,21 @@ func (c *client) IsAuthorized(ctx context.Context, subjects []string, resource,
 // FilterAuthorizedPairs drives authz introspection
 // Q: There's no projects here! This can't be right!
 // A(msorens): The short answer to that is introspection is not yet project-aware.
-//    It is on the list of things to do... maybe.
-//    For the current uses of introspection we have been able to get by without projects.
-//    Should the user see this button? ... this page? .. this item in the nav bar?
-//    Where introspection-plus-projects would be needed is, for example, on the Delete
-//    button on individual rows on projects list, tokens list, teams list, etc. We had
-//    actually wired that up using introspection-sans-projects and immediately ran into
-//    performance issues: it is unacceptable to do a separate introspection network call
-//    for each row in a table. So we took that out again for the time being.
-//    You have probably already observed that for non-parameterized introspection it is
-//    now highly optimized, doing a single IntrospectAll call once the front-end cache
-//    is stale enough (I think it invalidates in 60 seconds or so).
-//    The most likely strategy for introducing parameterized introspection back in the
-//    mix is doing a single IntrospectSome passing all the ids on a given list at one
-//    time. And then we need to figure out projects, too.
+//
+//	It is on the list of things to do... maybe.
+//	For the current uses of introspection we have been able to get by without projects.
+//	Should the user see this button? ... this page? .. this item in the nav bar?
+//	Where introspection-plus-projects would be needed is, for example, on the Delete
+//	button on individual rows on projects list, tokens list, teams list, etc. We had
+//	actually wired that up using introspection-sans-projects and immediately ran into
+//	performance issues: it is unacceptable to do a separate introspection network call
+//	for each row in a table. So we took that out again for the time being.
+//	You have probably already observed that for non-parameterized introspection it is
+//	now highly optimized, doing a single IntrospectAll call once the front-end cache
+//	is stale enough (I think it invalidates in 60 seconds or so).
+//	The most likely strategy for introducing parameterized introspection back in the
+//	mix is doing a single IntrospectSome passing all the ids on a given list at one
+//	time. And then we need to figure out projects, too.
 func (c *client) FilterAuthorizedPairs(ctx context.Context, subjects []string, inputPairs []*pairs.Pair,
 ) ([]*pairs.Pair, error) {
 	pairsV2 := make([]*authz.Pair, len(inputPairs))
diff --git a/components/automate-gateway/gateway/services.go b/components/automate-gateway/gateway/services.go
index 0ce8f7f54..949e169b6 100644
--- a/components/automate-gateway/gateway/services.go
+++ b/components/automate-gateway/gateway/services.go
@@ -465,7 +465,8 @@ func (s *Server) ProfileCreateHandler(w http.ResponseWriter, r *http.Request) {
 		var t ProfileRequest
 		err := decoder.Decode(&t)
 		if err != nil {
-			http.Error(w, err.Error(), http.StatusBadRequest)
+			log.Errorf("Received error while decoding request : %s", err.Error())
+			http.Error(w, "Error decoding request", http.StatusBadRequest)
 			return
 		}
 		profileName = t.Name
@@ -475,14 +476,15 @@ func (s *Server) ProfileCreateHandler(w http.ResponseWriter, r *http.Request) {
 		file, _, err := r.FormFile("file")
 		if err != nil {
 			log.Errorf("Received error while getting file from request : %s", err.Error())
-			http.Error(w, err.Error(), http.StatusBadRequest)
+			http.Error(w, "Error getting file", http.StatusBadRequest)
 			return
 		}
 		defer file.Close() // nolint: errcheck
 
 		_, err = io.Copy(&content, file)
 		if err != nil {
-			http.Error(w, err.Error(), http.StatusBadRequest)
+			log.Errorf("Received error while copying content : %s", err.Error())
+			http.Error(w, "Error copying content", http.StatusBadRequest)
 			return
 		}
 
@@ -501,7 +503,8 @@ func (s *Server) ProfileCreateHandler(w http.ResponseWriter, r *http.Request) {
 	resource := fmt.Sprintf("compliance:profiles:%s", owner)
 	ctx, err := s.authRequest(r, resource, action)
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusForbidden)
+		log.Errorf("Forbidden request : %s", err.Error())
+		http.Error(w, "Forbidden request", http.StatusForbidden)
 		return
 	}
 
@@ -515,7 +518,8 @@ func (s *Server) ProfileCreateHandler(w http.ResponseWriter, r *http.Request) {
 
 	stream, err := profilesClient.Create(ctx)
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		log.Errorf("Error in profile create : %s", err.Error())
+		http.Error(w, "Error creating profile", http.StatusInternalServerError)
 		return
 	}
 
@@ -532,19 +536,22 @@ func (s *Server) ProfileCreateHandler(w http.ResponseWriter, r *http.Request) {
 	}
 	err = stream.Send(&request)
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusBadRequest)
+		log.Errorf("Error in profile service : %s", err.Error())
+		http.Error(w, "Error profile service", http.StatusBadRequest)
 		return
 	}
 	log.Info("Request successfully sent to backend service")
 
 	reply, err := stream.CloseAndRecv()
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusBadRequest)
+		log.Errorf("Error in profile service : %s", err.Error())
+		http.Error(w, "Error profile service", http.StatusBadRequest)
 		return
 	}
 	data, err := json.Marshal(reply)
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		log.Errorf("Error in marshal : %s", err.Error())
+		http.Error(w, "Error in marshal", http.StatusInternalServerError)
 		return
 	}
 
diff --git a/components/automate-gateway/handler/notifications.go b/components/automate-gateway/handler/notifications.go
index de089c662..92884560c 100644
--- a/components/automate-gateway/handler/notifications.go
+++ b/components/automate-gateway/handler/notifications.go
@@ -2,6 +2,7 @@ package handler
 
 import (
 	"context"
+	"errors"
 	"reflect"
 	"strings"
 
@@ -148,7 +149,7 @@ func (s *notificationsServer) ValidateWebhook(ctx context.Context,
 
 	resp, err := s.notificationsClient.ValidateWebhook(ctx, &transformUVR)
 	if err != nil {
-		return nil, err
+		return nil, errors.New("unable to connect: check URL, username and password.")
 	}
 
 	switch resp.GetCode() {
diff --git a/components/automate-openjdk/habitat/plan.sh b/components/automate-openjdk/habitat/plan.sh
index 918632a06..bec8d401c 100644
--- a/components/automate-openjdk/habitat/plan.sh
+++ b/components/automate-openjdk/habitat/plan.sh
@@ -9,10 +9,10 @@ pkg_origin=chef
 pkg_maintainer="Chef Software Inc. <support@chef.io>"
 pkg_name=automate-openjdk
 # Release archive https://jdk.java.net/archive/
-pkg_version=11.0.17+8
-pkg_source=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.17%2B8/OpenJDK11U-jdk_x64_linux_hotspot_11.0.17_8.tar.gz
-pkg_shasum=b8d46ed08ef4859476fe6421a7690d899ed83dce63f13fd894f994043177ef3c
-pkg_filename=OpenJDK11U-jdk_x64_linux_hotspot_11.0.17_8.tar.gz
+pkg_version=11.0.18+10
+pkg_source=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz
+pkg_shasum=4a29efda1d702b8ff38e554cf932051f40ec70006caed5c4857a8cbc7a0b7db7
+pkg_filename=OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz
 pkg_dirname="jdk-${pkg_version}"
 pkg_license=("GPL-2.0-with-classpath-exception")
 pkg_description=('Eclipse Temurin is the open source Java SE build based upon OpenJDK.')
diff --git a/components/compliance-service/dao/pgdb/jobs.go b/components/compliance-service/dao/pgdb/jobs.go
index 7d08dce64..19fa614e7 100644
--- a/components/compliance-service/dao/pgdb/jobs.go
+++ b/components/compliance-service/dao/pgdb/jobs.go
@@ -748,7 +748,8 @@ func (db *DB) GetJob(id string) (*jobs.Job, error) {
 func (db *DB) DeleteJob(id string) error {
 	_, err := db.Exec(softDeleteJobById, id)
 	if err != nil {
-		return errors.Wrap(err, "DeleteJob unable to delete job")
+		logrus.Errorf("DeleteJob unable to delete job : %s", err.Error())
+		return errors.New("unable to delete job")
 	}
 
 	return nil
@@ -756,33 +757,39 @@ func (db *DB) DeleteJob(id string) error {
 
 func (db *DB) UpdateJob(inJob *jobs.Job) error {
 	if err := validateJob(inJob); err != nil {
-		return errorutils.ProcessInvalid(err, "UpdateJob error validating job")
+		logrus.Errorf("UpdateJob error validating job : %s", err.Error())
+		return errors.New("error validating job")
 	}
 
 	job, err := toDBJob(inJob)
 	if err != nil {
-		return errors.Wrap(err, "Update Job unable to translate job to db struct")
+		logrus.Errorf("Update Job unable to translate job to db struct : %s", err.Error())
+		return errors.New("unable to translate job")
 	}
 
 	err = Transact(db, func(tx *DBTrans) error {
 		err = tx.processJobsTagsUpdate(inJob)
 		if err != nil {
-			return errors.Wrap(err, "Update Job unable to process jobs tags update")
+			logrus.Errorf("Update Job unable to process jobs tags update : %s", err.Error())
+			return errors.New("unable to process jobs")
 		}
 
 		err = tx.processJobsNodesUpdate(inJob)
 		if err != nil {
-			return errors.Wrap(err, "Update Job unable to process jobs nodes update")
+			logrus.Errorf("Update Job unable to process jobs nodes update : %s", err.Error())
+			return errors.New("unable to process jobs")
 		}
 
 		err = tx.processJobsProfilesUpdate(inJob)
 		if err != nil {
-			return errors.Wrap(err, "Update Job unable to process jobs profiles update")
+			logrus.Errorf("Update Job unable to process jobs profiles update : %s", err.Error())
+			return errors.New("unable to process jobs")
 		}
 
 		_, err = tx.Update(&job)
 		if err != nil {
-			return errors.Wrap(err, "Update Job unable to update job")
+			logrus.Errorf("Update Job unable to update job : %s", err.Error())
+			return errors.New("unable to update job")
 		}
 
 		return nil
diff --git a/components/compliance-service/reporting/relaxting/reports.go b/components/compliance-service/reporting/relaxting/reports.go
index be79a126d..bb3c3147d 100644
--- a/components/compliance-service/reporting/relaxting/reports.go
+++ b/components/compliance-service/reporting/relaxting/reports.go
@@ -1226,7 +1226,7 @@ func (backend *ES2Backend) getControlItem(controlBucket *elastic.AggregationBuck
 
 }
 
-//getProfileMinForControlItem is parsing the  control title form the result of control list from comp-7-r-*
+// getProfileMinForControlItem is parsing the  control title form the result of control list from comp-7-r-*
 func getTitleForControlItem(controlBucket *elastic.AggregationBucketKeyItem) string {
 	var title string
 	var ok bool
@@ -1243,7 +1243,7 @@ func getTitleForControlItem(controlBucket *elastic.AggregationBucketKeyItem) str
 
 }
 
-//getEndTimeForControlItem is parsing the end time form the result of control list from comp-7-r-*
+// getEndTimeForControlItem is parsing the end time form the result of control list from comp-7-r-*
 func getEndTimeForControlItem(controlBucket *elastic.AggregationBucketKeyItem) (*timestamppb.Timestamp, error) {
 	var timestamp *timestamppb.Timestamp
 
@@ -1264,7 +1264,7 @@ func getEndTimeForControlItem(controlBucket *elastic.AggregationBucketKeyItem) (
 	return timestamp, nil
 }
 
-//getProfileMinForControlItem is parsing the profile id,title and version form the result of control list from comp-7-r-*
+// getProfileMinForControlItem is parsing the profile id,title and version form the result of control list from comp-7-r-*
 func getProfileMinForControlItem(controlBucket *elastic.AggregationBucketKeyItem, profileMin *reportingapi.ProfileMin) {
 	if profileResult, found := controlBucket.Aggregations.ReverseNested("profile"); found {
 		if result, found := profileResult.Terms("sha"); found && len(result.Buckets) > 0 {
@@ -1337,10 +1337,11 @@ func (backend *ES2Backend) getWaiverData(waiverDataBuckets *elastic.AggregationB
 	return waiverDataCollection, nil
 }
 
-//getFiltersQuery - builds up an elasticsearch query filter based on the filters map that is passed in
-//  arguments: filters - is a map of filters that serve as the source for generated es query filters
-//             latestOnly - specifies whether or not we are only interested in retrieving only the latest report
-//  return *elastic.BoolQuery
+// getFiltersQuery - builds up an elasticsearch query filter based on the filters map that is passed in
+//
+//	arguments: filters - is a map of filters that serve as the source for generated es query filters
+//	           latestOnly - specifies whether or not we are only interested in retrieving only the latest report
+//	return *elastic.BoolQuery
 func (backend ES2Backend) getFiltersQuery(filters map[string][]string, latestOnly bool) *elastic.BoolQuery {
 	utils.DeDupFilters(filters)
 	logrus.Debugf("????? Called getFiltersQuery with filters=%+v, latestOnly=%t", filters, latestOnly)
@@ -1604,14 +1605,14 @@ func containsWildcardChar(value string) bool {
 	return false
 }
 
-//  getFiltersQueryForDeepReport - builds up an elasticsearch query filter based on the reportId filters map passed in.
-//   This func ignores all but the profile_id and control filter.  If a single profile_id or a single profile_id and a
-//   child control from the single profile_id is passed in, then we are in deep filtering mode and the
-//   fetchSourceContexts will be adjusted accordingly
-//    arguments:
-//			reportId - the id of the report we are querying for.
-//			filters - is a map of filters that serve as the source for generated es query filters
-//    return *elastic.BoolQuery
+//	 getFiltersQueryForDeepReport - builds up an elasticsearch query filter based on the reportId filters map passed in.
+//	  This func ignores all but the profile_id and control filter.  If a single profile_id or a single profile_id and a
+//	  child control from the single profile_id is passed in, then we are in deep filtering mode and the
+//	  fetchSourceContexts will be adjusted accordingly
+//	   arguments:
+//				reportId - the id of the report we are querying for.
+//				filters - is a map of filters that serve as the source for generated es query filters
+//	   return *elastic.BoolQuery
 func getFiltersQueryForDeepReport(reportId string,
 	filters map[string][]string) *elastic.BoolQuery {
 
@@ -2196,7 +2197,7 @@ func getControlSummaryFilters(controlId []string, filters map[string][]string) *
 
 }
 
-//getMultiControlString takes the list of strings and returns the query string used in search.
+// getMultiControlString takes the list of strings and returns the query string used in search.
 func getMultiControlString(list []string) string {
 	controlList := []string{}
 	for _, control := range list {
@@ -2205,7 +2206,7 @@ func getMultiControlString(list []string) string {
 	return strings.Join(controlList, " ")
 }
 
-//handleSpecialChar takes the string, and add additional char in front of the reserved chars.
+// handleSpecialChar takes the string, and add additional char in front of the reserved chars.
 func handleSpecialChar(term string) string {
 	//maintain `\` always first in the list to stop encoding the characters we are appending.
 	reservedChar := []string{`\`, `/`, `+`, `-`, `=`, `&&`, `||`, `>`, `<`, `!`, `(`, `)`, `{`, `}`, `[`, `]`, `^`, `"`, `~`, `*`, `?`, `:`}
@@ -2215,6 +2216,7 @@ func handleSpecialChar(term string) string {
 	return fmt.Sprintf("(%s)", term)
 }
 
+//filterQueryChange Will return day latest only for last 24 hours
 func filterQueryChange(endTime string, startTime string) ([]string, error) {
 	if len(endTime) == 0 && len(startTime) == 0 {
 		return []string{"day_latest", "daily_latest"}, nil
@@ -2222,16 +2224,7 @@ func filterQueryChange(endTime string, startTime string) ([]string, error) {
 	if len(startTime) == 0 {
 		return []string{"daily_latest"}, nil
 	}
-	eTime, err := time.Parse(layout, endTime)
-	sTime, err := time.Parse(layout, startTime)
-	diff := int(eTime.Sub(sTime).Hours() / 24)
-	if err != nil {
-		return nil, errors.Errorf("cannot parse the time")
-	}
-	if diff == 0 {
-		return []string{"daily_latest"}, nil
-	}
-	return []string{"day_latest", "daily_latest"}, nil
+	return []string{"daily_latest"}, nil
 
 }
 
diff --git a/components/docs-chef-io/content/automate/notifications.md b/components/docs-chef-io/content/automate/notifications.md
index 5ebf5d321..95b91b139 100644
--- a/components/docs-chef-io/content/automate/notifications.md
+++ b/components/docs-chef-io/content/automate/notifications.md
@@ -45,8 +45,8 @@ To add a servicenow notification for Chef Automate, follow the steps given below
 1. Enter a unique notification **name**.
 1. Select the **failure type** to be notified on from the drop-down menu. Current options are Chef Infra Client run or InSpec scan. According to the failure type selected, enter the **Webhook URL** as shown below:
 
-    - For Chef Infra Client Run: https://devxxxxx.service-now.com/api/x_chef_incident/v1/client_run
-    - For Inspec Scan: https://devxxxxx.service-now.com/api/x_chef_incident/v1/inspec_scan
+    - For Chef Infra Client Run: https://devxxxxx.service-now.com/api/x_chef_incident/client_run
+    - For Inspec Scan: https://devxxxxx.service-now.com/api/x_chef_incident/inspec_scan
 
 1. Enter the **ServiceNow Username**.
 1. Enter the **ServiceNow Password**.
diff --git a/components/docs-chef-io/content/automate/servicenow_event_creation.md b/components/docs-chef-io/content/automate/servicenow_event_creation.md
index 7a09cc909..e9d4cf632 100644
--- a/components/docs-chef-io/content/automate/servicenow_event_creation.md
+++ b/components/docs-chef-io/content/automate/servicenow_event_creation.md
@@ -20,7 +20,7 @@ The Event Creation App exposes the REST API endpoint for communication between C
 ## User Requirements
 
 - Your unique ServiceNow URL. It has the format: `https://ven12345.service-now.com`.
-- Setting up the Event Creation App requires the `x_chef_automate.api` role in configuring it. Your ServiceNow administrator can enable this for you.
+- Setting up the Event Creation App requires the `x_chef_event.api` role in configuring it. Your ServiceNow administrator can enable this for you.
 
 ## Required ServiceNow Plugins
 
diff --git a/components/docs-chef-io/content/automate/servicenow_incident_creation.md b/components/docs-chef-io/content/automate/servicenow_incident_creation.md
index 746c763b2..267d9e528 100644
--- a/components/docs-chef-io/content/automate/servicenow_incident_creation.md
+++ b/components/docs-chef-io/content/automate/servicenow_incident_creation.md
@@ -30,7 +30,7 @@ The Incident App generates a data stream of compliance events that you can lever
 ## User Requirements
 
 * Your unique ServiceNow URL. It has the format: `https://ven12345.service-now.com`.
-* Setting up the Incident App requires the `x_chef_automate.api` role to configure it. Your ServiceNow administrator can enable this for you.
+* Setting up the Incident App requires the `x_chef_incident.api` role to configure it. Your ServiceNow administrator can enable this for you.
 
 ### System Requirements
 
@@ -55,14 +55,14 @@ You can setup automatic incident creation for:
 
 To set up automatic incident reporting for failed Chef Infra Client runs from Chef Automate:
 
-1. Confirm that you have the `x_chef_automate.api` role.
+1. Confirm that you have the `x_chef_incident.api` role.
 1. Navigate to **Settings** > **Notifications**
 1. Select **Create Notification**
 1. Enter or select:
    * **Name**: A unique name for this notification.
    * **Webhook Type**: The product or proccess receiving the notification. Options: **Slack**, **Webhook**, and **ServiceNow**.
    * **Failure Type**: The Chef process for the notification. Select **Infra Client Run failures**.
-   * **Webhook URL**: The API address that the notification uses. It has the format: `https://ven12345.service-now.com/api/x_chef_automate/client_run`.
+   * **Webhook URL**: The API address that the notification uses. It has the format: `https://ven12345.service-now.com/api/x_chef_incident/client_run`.
    * **ServiceNow Username**: The name you use to sign in to ServiceNow.
    * **ServiceNow Password**: The password you use to sign in to ServiceNow.
 1. Select **Test Connectivity**. A successful test displays **Notification test connected successfully**. An unsuccessful test displays a message with information about any connection or credential problems to help you fix the error.
@@ -80,7 +80,7 @@ Follow these steps to report failed Chef InSpec scans from Chef Automate:
    * **Name**: A unique name for this notification.
    * **Webhook Type**: The product or proccess receiving the notification. Select the **ServiceNow** option.
    * **Failure Type**: The Chef process for the notification. Select the **Inspec compliance scan failures** option.
-   * **Webhook URL**: The API address that the notification uses. It has the format:`https://ven12345.service-now.com/api/x_chef_automate/inspec_scan`
+   * **Webhook URL**: The API address that the notification uses. It has the format:`https://ven12345.service-now.com/api/x_chef_incident/inspec_scan`
    * **ServiceNow Username**: The name you use to sign in to ServiceNow.
    * **ServiceNow Password**: The password you use to sign in to ServiceNow.
 1. Select **Test Connectivity**. A successful test displays **Notification test connected successfully**. An unsuccessful test displays a message with information about any connection or credential problems to help you fix the error.
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications.yaml
index eb1d9c17d..af9e8ebea 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications.yaml
@@ -20,4 +20,4 @@ see_also:
 - chef-automate - Chef Automate CLI
 - remove-svcs - Remove services from the applications database
 - show-svcs - Show services in the applications database
-supported_on: Automate
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_remove-svcs.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_remove-svcs.yaml
index 8ad6278c1..fcdb02587 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_remove-svcs.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_remove-svcs.yaml
@@ -75,4 +75,4 @@ inherited_options:
   usage: Write command result as JSON to PATH
 see_also:
 - chef-automate applications - Manage applications observability features
-supported_on: Automate
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_show-svcs.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_show-svcs.yaml
index f41280505..3fe667c4c 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_show-svcs.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_applications_show-svcs.yaml
@@ -61,4 +61,4 @@ inherited_options:
   usage: Write command result as JSON to PATH
 see_also:
 - chef-automate applications - Manage applications observability features
-supported_on: Automate
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca.yaml
index 161943e4b..aeb2b977c 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca.yaml
@@ -20,7 +20,7 @@ inherited_options:
   usage: Write command result as JSON to PATH
 see_also:
 - chef-automate - Chef Automate CLI
-- info - Print information the root certificate for the internal certificate authority
+- info - Print information of the root certificate for the internal certificate authority
 - regenerate - Commands to regenerate certificates issued by the internal certificate
   authority
-supported_on: FrontEnd
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_info.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_info.yaml
index 1a5c86a07..f36325ffc 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_info.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_info.yaml
@@ -1,12 +1,35 @@
 name: chef-automate internal-ca info
 synopsis: |
-  Print information the root certificate for the internal certificate authority
+  Print information of the root certificate for the internal certificate authority
 usage: chef-automate internal-ca info [flags]
 options:
+- name: a2
+  default_value: "false"
+  usage: Print information of the root certificate of automate nodes
+  compatible_with_options: AutomateHA
+- name: automate
+  shorthand: a
+  default_value: "false"
+  usage: Print information of the root certificate of automate nodes
+  compatible_with_options: AutomateHA
+- name: chef_server
+  shorthand: c
+  default_value: "false"
+  usage: |
+    Print information of the root certificate of chef_server nodes
+  compatible_with_options: AutomateHA
+- name: cs
+  default_value: "false"
+  usage: |
+    Print information of the root certificate of chef_server nodes
+  compatible_with_options: AutomateHA
 - name: help
   shorthand: h
   default_value: "false"
   usage: help for info
+- name: node
+  usage: Node Ip address
+  compatible_with_options: AutomateHA
 inherited_options:
 - name: debug
   shorthand: d
@@ -19,4 +42,4 @@ inherited_options:
   usage: Write command result as JSON to PATH
 see_also:
 - chef-automate internal-ca - Manage Chef Automate's internal certificate authority
-supported_on: FrontEnd
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate.yaml
index c6df0947a..6c484250f 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate.yaml
@@ -20,4 +20,4 @@ inherited_options:
 see_also:
 - chef-automate internal-ca - Manage Chef Automate's internal certificate authority
 - root - Regenerate the root certificate for the internal certificate authority
-supported_on: FrontEnd
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate_root.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate_root.yaml
index c3f4686e6..54cb04b9f 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate_root.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_internal-ca_regenerate_root.yaml
@@ -3,10 +3,31 @@ synopsis: |
   Regenerate the root certificate for the internal certificate authority
 usage: chef-automate internal-ca regenerate root [flags]
 options:
+- name: a2
+  default_value: "false"
+  usage: Regenerate the root certificate for automate nodes
+  compatible_with_options: AutomateHA
+- name: automate
+  shorthand: a
+  default_value: "false"
+  usage: Regenerate the root certificate for automate nodes
+  compatible_with_options: AutomateHA
+- name: chef_server
+  shorthand: c
+  default_value: "false"
+  usage: Regenerate the root certificate for chef_server nodes
+  compatible_with_options: AutomateHA
+- name: cs
+  default_value: "false"
+  usage: Regenerate the root certificate for chef_server nodes
+  compatible_with_options: AutomateHA
 - name: help
   shorthand: h
   default_value: "false"
   usage: help for root
+- name: node
+  usage: Node Ip address
+  compatible_with_options: AutomateHA
 inherited_options:
 - name: debug
   shorthand: d
@@ -20,4 +41,4 @@ inherited_options:
 see_also:
 - chef-automate internal-ca regenerate - Commands to regenerate certificates issued
   by the internal certificate authority
-supported_on: FrontEnd
+supported_on: Bastion
diff --git a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_service-versions.yaml b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_service-versions.yaml
index e16697cc5..f5c1b7417 100644
--- a/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_service-versions.yaml
+++ b/components/docs-chef-io/data/automate/cli_chef_automate/commands/chef-automate_service-versions.yaml
@@ -5,10 +5,50 @@ usage: chef-automate service-versions [flags]
 description: |
   Retrieve the versions of the individual Chef Automate services
 options:
+- name: a2
+  default_value: "false"
+  usage: Shows service-versions for Automate nodes[DUPLICATE]
+  compatible_with_options: AutomateHA
+- name: automate
+  shorthand: a
+  default_value: "false"
+  usage: Shows service-versions for Automate nodes
+  compatible_with_options: AutomateHA
+- name: chef_server
+  shorthand: c
+  default_value: "false"
+  usage: Shows service-versions for Chef-server nodes
+  compatible_with_options: AutomateHA
+- name: cs
+  default_value: "false"
+  usage: Shows service-versions for Chef-server nodes[DUPLICATE]
+  compatible_with_options: AutomateHA
 - name: help
   shorthand: h
   default_value: "false"
   usage: help for service-versions
+- name: node
+  usage: |
+    Pass this flag to check service-versions of particular node in the cluster
+  compatible_with_options: AutomateHA
+- name: opensearch
+  shorthand: o
+  default_value: "false"
+  usage: Shows service-versions for OpenSearch nodes
+  compatible_with_options: AutomateHA
+- name: os
+  default_value: "false"
+  usage: Shows service-versions for OpenSearch nodes[DUPLICATE]
+  compatible_with_options: AutomateHA
+- name: pg
+  default_value: "false"
+  usage: Shows service-versions for PostgresQL nodes[DUPLICATE]
+  compatible_with_options: AutomateHA
+- name: postgresql
+  shorthand: p
+  default_value: "false"
+  usage: Shows service-versions for PostgresQL nodes
+  compatible_with_options: AutomateHA
 inherited_options:
 - name: debug
   shorthand: d
@@ -21,4 +61,4 @@ inherited_options:
   usage: Write command result as JSON to PATH
 see_also:
 - chef-automate - Chef Automate CLI
-supported_on: FrontEnd
+supported_on: Bastion


Test patch:
diff --git a/components/automate-cli/cmd/chef-automate/applications_test.go b/components/automate-cli/cmd/chef-automate/applications_test.go
new file mode 100644
index 000000000..66d45bfc9
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/applications_test.go
@@ -0,0 +1,316 @@
+package main
+
+import (
+	"errors"
+	"testing"
+
+	"github.com/chef/automate/api/external/applications"
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
+	"github.com/chef/automate/lib/majorupgrade_utils"
+	"github.com/spf13/cobra"
+	"github.com/stretchr/testify/assert"
+)
+
+type MockExecutor struct{}
+
+func (me MockExecutor) execCommand(cmd string) (string, error) {
+	return `id   	svc.group    	release                         	FQDN                                       	app:env            	status
+37035	redis.default	core/redis/4.0.14/20220311173537	ip-172-31-41-174.eu-west-3.compute.internal	DummyApp:acceptance	OK
+37033	nginx.default	core/nginx/1.21.4/20220311143833	ip-172-31-41-174.eu-west-3.compute.internal	DummyApp:acceptance	OK
+37034	postgresql94.default	core/postgresql94/9.4.26/20220311203133	ip-172-31-41-174.eu-west-3.compute.internal	DummyApp:acceptance	OK
+`, nil
+}
+
+func (me MockExecutor) runCommandOnSingleAutomateNode(cmd *cobra.Command, args []string) (string, error) {
+	return "", nil
+}
+
+func TestExecCommand(t *testing.T) {
+	e := Executor{}
+	tests := []struct {
+		TestName       string
+		Input          string
+		ExpectedOutput string
+		ExpectedError  error
+	}{
+		{"Valid Command", "echo Hello", "Hello\n", nil},
+		{"Invalid Command", "ech Hello", "", errors.New("")},
+	}
+	for _, tt := range tests {
+		t.Run(tt.TestName, func(t *testing.T) {
+			output, err := e.execCommand(tt.Input)
+			if tt.ExpectedError != nil {
+				assert.Error(t, err)
+			} else {
+				assert.NoError(t, err)
+				assert.Equal(t, tt.ExpectedOutput, output)
+			}
+		})
+	}
+}
+
+func TestRemoveApplicationsHA(t *testing.T) {
+	mockExec := MockExecutor{}
+	actualExec := Executor{}
+	cmd := &cobra.Command{}
+	args := []string{}
+	YesMockWriter := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	NoMockWriter := majorupgrade_utils.NewCustomWriterWithInputs("n")
+	tests := []struct {
+		TestName               string
+		Executor               IExecutor
+		CliWriter              *cli.Writer
+		AutoApproveFlagEnabled bool
+		ExpectedError          error
+	}{
+		{
+			TestName:               "used -y flag while running the command and everything works fine",
+			Executor:               mockExec,
+			CliWriter:              YesMockWriter.CliWriter,
+			AutoApproveFlagEnabled: true,
+			ExpectedError:          nil,
+		},
+		{
+			TestName:               "not used -y flag and mocked show command returned list of services and user entered 'y' for confirmation prompt to remove",
+			Executor:               mockExec,
+			CliWriter:              YesMockWriter.CliWriter,
+			AutoApproveFlagEnabled: false,
+			ExpectedError:          nil,
+		},
+		{
+			TestName:               "not used -y flag and but show command failed to run",
+			Executor:               actualExec,
+			CliWriter:              YesMockWriter.CliWriter,
+			AutoApproveFlagEnabled: false,
+			ExpectedError:          errors.New(""),
+		},
+		{
+			TestName:               "not used -y flag, mocked show command returned list of services but user entered 'n' for confirmation prompt to remove",
+			Executor:               mockExec,
+			CliWriter:              NoMockWriter.CliWriter,
+			AutoApproveFlagEnabled: false,
+			ExpectedError:          nil,
+		},
+		{
+			TestName:               "not used -y flag, mocked show command returned list of services but writer gave some error",
+			Executor:               mockExec,
+			CliWriter:              writer,
+			AutoApproveFlagEnabled: false,
+			ExpectedError:          errors.New("failed to read user input in confirmation: EOF"),
+		},
+		{
+			TestName:               "used -y flag while running the command but Command running on automate node not successfully ended",
+			Executor:               actualExec,
+			CliWriter:              YesMockWriter.CliWriter,
+			AutoApproveFlagEnabled: true,
+			ExpectedError:          errors.New("Automate Ha infra confile file not exist"),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.TestName, func(t *testing.T) {
+			removeSvcsFlags.yes = tt.AutoApproveFlagEnabled
+			err := removeApplicationsHA(cmd, args, tt.Executor, tt.CliWriter)
+			if tt.ExpectedError != nil {
+				assert.Error(t, err)
+				assert.ErrorContains(t, err, tt.ExpectedError.Error())
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+	// Resetting the Global variable to its default value
+	removeSvcsFlags.yes = false
+}
+
+func TestRunApplicationsRemoveSvcsCmd(t *testing.T) {
+	cmd := &cobra.Command{}
+	args := []string{}
+
+	tests := []struct {
+		TestName       string
+		FilterApplied  bool
+		AllFlagEnabled bool
+		ExpectedError  error
+	}{
+		{
+			TestName:       "Didn't used all or any filter flag",
+			FilterApplied:  false,
+			AllFlagEnabled: false,
+			ExpectedError:  errors.New("You must filter the services to be deleted or pass the --all flag to delete all services"),
+		},
+		{
+			TestName:       "used all flag",
+			FilterApplied:  false,
+			AllFlagEnabled: true,
+			ExpectedError:  errors.New(""),
+		},
+		{
+			TestName:       "used some filter flag",
+			FilterApplied:  true,
+			AllFlagEnabled: false,
+			ExpectedError:  errors.New(""),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.TestName, func(t *testing.T) {
+			removeSvcsFlags.all = tt.AllFlagEnabled
+			if tt.FilterApplied {
+				applicationsServiceFiltersFlags.serviceName = "anything"
+			} else {
+				applicationsServiceFiltersFlags.serviceName = ""
+			}
+			err := runApplicationsRemoveSvcsCmd(cmd, args)
+			if tt.ExpectedError != nil {
+				assert.Error(t, err)
+				assert.ErrorContains(t, err, tt.ExpectedError.Error())
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+
+	// Resetting the Global variable to its default value
+	removeSvcsFlags.all = false
+	applicationsServiceFiltersFlags.serviceName = ""
+}
+
+func TestShowApplicationsHA(t *testing.T) {
+	mockExec := MockExecutor{}
+	actualExec := Executor{}
+	cmd := &cobra.Command{}
+	args := []string{}
+
+	tests := []struct {
+		TestName      string
+		Executor      IExecutor
+		ExpectedError error
+	}{
+		{
+			TestName:      "Command Ran Successfully",
+			Executor:      mockExec,
+			ExpectedError: nil,
+		},
+		{
+			TestName:      "Command Gave Error ",
+			Executor:      actualExec,
+			ExpectedError: errors.New(""),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.TestName, func(t *testing.T) {
+			err := showApplicationsHA(cmd, args, tt.Executor)
+			if tt.ExpectedError != nil {
+				assert.Error(t, err)
+				assert.ErrorContains(t, err, tt.ExpectedError.Error())
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestRunApplicationsShowSvcsCmd(t *testing.T) {
+	cmd := &cobra.Command{}
+	args := []string{}
+
+	tests := []struct {
+		TestName      string
+		ExpectedError error
+	}{
+		{
+			TestName:      "Standalone System",
+			ExpectedError: errors.New(""),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.TestName, func(t *testing.T) {
+			err := runApplicationsShowSvcsCmd(cmd, args)
+			if tt.ExpectedError != nil {
+				assert.Error(t, err)
+				assert.ErrorContains(t, err, tt.ExpectedError.Error())
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestMakeServicesReqWithFilters(t *testing.T) {
+	applicationsServiceFiltersFlags.origin = "origin_value"
+	applicationsServiceFiltersFlags.serviceName = "servicename_value"
+	applicationsServiceFiltersFlags.version = "version_value"
+	applicationsServiceFiltersFlags.channel = "channel_value"
+	applicationsServiceFiltersFlags.application = "app_value"
+	applicationsServiceFiltersFlags.environment = "environment_value"
+	applicationsServiceFiltersFlags.site = "site_value"
+	applicationsServiceFiltersFlags.buildTimestamp = "timestamp_value"
+	applicationsServiceFiltersFlags.groupName = "group_value"
+	res := makeServicesReqWithFilters()
+	ExpectedResp := &applications.ServicesReq{
+		Filter: []string{
+			"origin:origin_value",
+			"service:servicename_value",
+			"version:version_value",
+			"channel:channel_value",
+			"application:app_value",
+			"environment:environment_value",
+			"site:site_value",
+			"buildstamp:timestamp_value",
+			"group:group_value",
+		},
+	}
+	assert.Equal(t, ExpectedResp, res)
+
+	// Setting Disconnected Flag
+	applicationsServiceFiltersFlags.disconnected = true
+	res = makeServicesReqWithFilters()
+	ExpectedResp = &applications.ServicesReq{
+		Filter: []string{
+			"status:disconnected",
+			"origin:origin_value",
+			"service:servicename_value",
+			"version:version_value",
+			"channel:channel_value",
+			"application:app_value",
+			"environment:environment_value",
+			"site:site_value",
+			"buildstamp:timestamp_value",
+			"group:group_value",
+		},
+	}
+	assert.Equal(t, ExpectedResp, res)
+
+	// Resetting the Global variable to its default value
+	applicationsServiceFiltersFlags = applicationsServiceFilters{}
+}
+
+func TestPrintTSV(t *testing.T) {
+	s := serviceSet{
+		services: []*applications.Service{
+			{
+				Id:           "37035",
+				Group:        "redis.default",
+				Release:      "core/redis/4.0.14/20220311173537",
+				Fqdn:         "ip-172-31-41-174.eu-west-3.compute.internal",
+				Application:  "DummyApp",
+				Environment:  "acceptance",
+				Disconnected: true,
+			},
+			{
+				Id:           "37035",
+				Group:        "redis.default",
+				Release:      "core/redis/4.0.14/20220311173537",
+				Fqdn:         "ip-172-31-41-174.eu-west-3.compute.internal",
+				Application:  "DummyApp",
+				Environment:  "acceptance",
+				Disconnected: false,
+			},
+		},
+	}
+	err := s.PrintTSV()
+	assert.NoError(t, err)
+}
diff --git a/components/automate-cli/cmd/chef-automate/ca_test.go b/components/automate-cli/cmd/chef-automate/ca_test.go
new file mode 100644
index 000000000..c87847eb2
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/ca_test.go
@@ -0,0 +1,195 @@
+package main
+
+import (
+	"testing"
+
+	"github.com/spf13/cobra"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestInternalCaHA(t *testing.T) {
+	tests := []struct {
+		name            string
+		isForAutomate   bool
+		isForChefServer bool
+		isInfraEmpty    bool
+		node            string
+		isErrorExpected bool
+		errorMessage    string
+	}{
+		{
+			name:            "test_Automate",
+			isForAutomate:   true,
+			isForChefServer: false,
+			node:            "",
+			isErrorExpected: true,
+			errorMessage:    "Not able to generate root or fetch root info: \nopen : no such file or directory",
+		},
+		{
+			name:            "test_ChefServer",
+			isForAutomate:   false,
+			isForChefServer: true,
+			node:            "",
+			isErrorExpected: true,
+			errorMessage:    "Not able to generate root or fetch root info: \nopen : no such file or directory",
+		},
+		{
+			name:            "test_node_with_MultipleServiceFlags",
+			isForAutomate:   true,
+			isForChefServer: true,
+			node:            "1.2.3.4",
+			isErrorExpected: true,
+			errorMessage:    "Please remove node flag if you have given multiple service flags.",
+		},
+		{
+			name:            "test_valid_node_with_Automate",
+			isForAutomate:   true,
+			isForChefServer: false,
+			node:            "127.0.0.0",
+			isErrorExpected: true,
+			errorMessage:    "Not able to generate root or fetch root info: \nopen : no such file or directory",
+		},
+		{
+			name:            "test_invalid_node_with_Automate",
+			isForAutomate:   true,
+			isForChefServer: false,
+			node:            "127.0.0.5",
+			isErrorExpected: true,
+			errorMessage:    "Please Enter Valid automate IP",
+		},
+		{
+			name:            "test_valid_node_with_ChefServer",
+			isForAutomate:   false,
+			isForChefServer: true,
+			node:            "127.0.0.1",
+			isErrorExpected: true,
+			errorMessage:    "Not able to generate root or fetch root info: \nopen : no such file or directory",
+		},
+		{
+			name:            "test_invalid_node_with_ChefServer",
+			isForAutomate:   false,
+			isForChefServer: true,
+			node:            "127.0.0.5",
+			isErrorExpected: true,
+			errorMessage:    "Please Enter Valid chef_server IP",
+		},
+		{
+			name:            "test_empty_infra",
+			isForAutomate:   true,
+			isForChefServer: false,
+			isInfraEmpty:    true,
+			node:            "",
+			isErrorExpected: true,
+			errorMessage:    "No automate IPs are found",
+		},
+		{
+			name:            "test_multiple_service_flags",
+			isForAutomate:   true,
+			isForChefServer: true,
+			node:            "",
+			isErrorExpected: true,
+			errorMessage:    "Not able to generate root or fetch root info: \nopen : no such file or directory\nopen : no such file or directory",
+		},
+		{
+			name:            "test_empty_service_and_node_flag",
+			isForAutomate:   false,
+			isForChefServer: false,
+			node:            "",
+			isErrorExpected: true,
+			errorMessage:    "No flag is enabled. Please provide any flag",
+		},
+		{
+			name:            "test_empty_service_but_given_node_flag",
+			isForAutomate:   false,
+			isForChefServer: false,
+			node:            "1.2.3.4",
+			isErrorExpected: true,
+			errorMessage:    "Please provide service flag",
+		},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			var infra *AutomateHAInfraDetails
+			caCmdFlags.automate = tc.isForAutomate
+			caCmdFlags.chef_server = tc.isForChefServer
+			caCmdFlags.node = tc.node
+			if tc.isInfraEmpty {
+				infra = &AutomateHAInfraDetails{}
+			} else {
+				infra = getMockInfra()
+			}
+			err := runInternalCaHA(infra, &cobra.Command{})
+			if tc.isErrorExpected {
+				assert.Error(t, err)
+				assert.EqualError(t, err, tc.errorMessage)
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+	// Resetting the global variables to its default values.
+	caCmdFlags.automate = false
+	caCmdFlags.chef_server = false
+	caCmdFlags.node = ""
+}
+
+func TestCAInfo(t *testing.T) {
+	tests := []struct {
+		testName        string
+		isStandalone    bool
+		isErrorExpected bool
+		errorMessage    string
+	}{
+		{
+			testName:        "Standalone_Mode",
+			isStandalone:    true,
+			isErrorExpected: true,
+			errorMessage:    "Connecting to deployment-service failed: Failed to read deployment-service TLS certificates: Could not read the service cert: open /hab/svc/deployment-service/data/deployment-service.crt: no such file or directory",
+		},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.testName, func(t *testing.T) {
+			err := runCAInfoCmd(&cobra.Command{}, []string{})
+			if tc.isErrorExpected {
+				assert.Error(t, err)
+				assert.EqualError(t, err, tc.errorMessage)
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+	// Resetting the global variables to its default values.
+	caCmdFlags.automate = false
+}
+
+func TestRegenRoot(t *testing.T) {
+	tests := []struct {
+		testName        string
+		isStandalone    bool
+		isErrorExpected bool
+		errorMessage    string
+	}{
+		{
+			testName:        "Standalone_Mode",
+			isStandalone:    true,
+			isErrorExpected: true,
+			errorMessage:    "Connecting to deployment-service failed: Failed to read deployment-service TLS certificates: Could not read the service cert: open /hab/svc/deployment-service/data/deployment-service.crt: no such file or directory",
+		},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.testName, func(t *testing.T) {
+			err := runRegenRootCmd(&cobra.Command{}, []string{})
+			if tc.isErrorExpected {
+				assert.Error(t, err)
+				assert.ErrorContains(t, err, tc.errorMessage)
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+	// Resetting the global variables to its default values.
+	caCmdFlags.automate = false
+}
diff --git a/components/automate-cli/cmd/chef-automate/cliUtils_test.go b/components/automate-cli/cmd/chef-automate/cliUtils_test.go
index 224a85e34..0e4750475 100644
--- a/components/automate-cli/cmd/chef-automate/cliUtils_test.go
+++ b/components/automate-cli/cmd/chef-automate/cliUtils_test.go
@@ -50,3 +50,45 @@ func basicCmd() *cobra.Command {
 func runExampleForTestCmd(cmd *cobra.Command, _ []string) error {
 	return nil
 }
+
+func TestGetEnabledFlags(t *testing.T) {
+	// Define a Cobra command for testing purposes
+	cmd := &cobra.Command{
+		Use:   "my-command",
+		Short: "A description of my command",
+		Run: func(cmd *cobra.Command, args []string) {
+			// Not used in this test
+		},
+	}
+
+	// Define some flags for the Cobra command
+	cmd.Flags().String("string-flag", "", "A description of the string flag")
+	cmd.Flags().Int("int-flag", 0, "A description of the int flag")
+	cmd.Flags().Bool("bool-flag", false, "A description of the bool flag")
+
+	// Set the values of the string and int flags
+	cmd.Flags().Set("string-flag", "string-value")
+	cmd.Flags().Set("int-flag", "42")
+
+	tests := []struct {
+		TestName       string
+		flagsToIgnore  map[string]int
+		EnableBoolFlag bool
+		ExpectedOutput string
+	}{
+		{"Not Ignoring any flag", map[string]int{}, false, " --int-flag 42 --string-flag string-value"},
+		{"Ignoring some flag", map[string]int{"string-flag": 1}, false, " --int-flag 42"},
+		{"Bool flag enabled", map[string]int{}, true, " --bool-flag --int-flag 42 --string-flag string-value"},
+	}
+
+	for _, e := range tests {
+		t.Run(e.TestName, func(t *testing.T) {
+			cmd.Flag("bool-flag").Changed = false
+			if e.EnableBoolFlag {
+				cmd.Flag("bool-flag").Changed = true
+			}
+			flags := GetEnabledFlags(cmd, e.flagsToIgnore)
+			assert.Equal(t, e.ExpectedOutput, flags)
+		})
+	}
+}
diff --git a/components/automate-cli/cmd/chef-automate/service_versions_test.go b/components/automate-cli/cmd/chef-automate/service_versions_test.go
new file mode 100644
index 000000000..2791fcef6
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/service_versions_test.go
@@ -0,0 +1,390 @@
+package main
+
+import (
+	"testing"
+
+	"github.com/chef/automate/components/automate-cli/pkg/status"
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
+	"github.com/pkg/errors"
+	"github.com/spf13/cobra"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestRunServiceVersionsFromBastion(t *testing.T) {
+	type testCase struct {
+		description       string
+		flags             *ServiceVersionsCmdFlags
+		mockNodeOpUtils   *MockNodeUtilsImpl
+		mockRemoteCmdExec *MockRemoteCmdExecutor
+		errorWant         error
+	}
+
+	printServiceVersionsOutput := func(m map[string][]*CmdResult, s string, w *cli.Writer) {}
+	testCases := []testCase{
+
+		{
+			description: "Error while reading infra details",
+			flags:       &ServiceVersionsCmdFlags{},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return nil, nil, errors.New("Error occured while reading infra details")
+				},
+			},
+			errorWant: errors.New("Error occured while reading infra details"),
+		},
+		{
+			description: "Want service-versions of all services",
+			flags: &ServiceVersionsCmdFlags{
+				automate:   true,
+				chefServer: true,
+				opensearch: true,
+				postgresql: true,
+			},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return false
+				},
+			},
+			mockRemoteCmdExec: &MockRemoteCmdExecutor{
+				ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+					return map[string][]*CmdResult{}, nil
+				},
+				SetWriterFunc: func(cli *cli.Writer) {},
+			},
+			errorWant: nil,
+		},
+		{
+			description: "Want service_versions of backend services",
+			flags: &ServiceVersionsCmdFlags{
+				automate:   false,
+				chefServer: false,
+				opensearch: true,
+				postgresql: true,
+			},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return false
+				},
+			},
+			mockRemoteCmdExec: &MockRemoteCmdExecutor{
+				ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+					return map[string][]*CmdResult{}, nil
+				},
+				SetWriterFunc: func(cli *cli.Writer) {},
+			},
+			errorWant: nil,
+		},
+		{
+			description: "Want service_versions of frontend services",
+			flags: &ServiceVersionsCmdFlags{
+				automate:   true,
+				chefServer: true,
+				opensearch: false,
+				postgresql: false,
+			},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return false
+				},
+			},
+			mockRemoteCmdExec: &MockRemoteCmdExecutor{
+				ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+					return map[string][]*CmdResult{}, nil
+				},
+				SetWriterFunc: func(cli *cli.Writer) {},
+			},
+			errorWant: nil,
+		},
+		{
+			description: "Want service-versions of all services but error occured while remote execution",
+			flags: &ServiceVersionsCmdFlags{
+				automate:   true,
+				chefServer: true,
+				opensearch: true,
+				postgresql: true,
+			},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return false
+				},
+			},
+			mockRemoteCmdExec: &MockRemoteCmdExecutor{
+				ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+					return map[string][]*CmdResult{}, errors.New("Some error occured while remote execution")
+				},
+				SetWriterFunc: func(cli *cli.Writer) {},
+			},
+			errorWant: errors.New("Some error occured while remote execution"),
+		},
+		{
+			description: "Managed services and pg flag provided",
+
+			flags: &ServiceVersionsCmdFlags{
+				postgresql: true,
+			},
+
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return true
+				},
+			},
+			mockRemoteCmdExec: &MockRemoteCmdExecutor{
+				ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+					return map[string][]*CmdResult{}, nil
+				},
+				SetWriterFunc: func(cli *cli.Writer) {},
+			},
+			errorWant: status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, POSTGRESQL),
+		},
+		{
+			description: "Want service-versions of all services but error occured while remote execution",
+			flags: &ServiceVersionsCmdFlags{
+				automate: true,
+			},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return true
+				},
+			},
+			mockRemoteCmdExec: &MockRemoteCmdExecutor{
+				ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+					cmdResultWithError := &CmdResult{
+						ScriptName: "script_1",
+						HostIP:     "192.168.1.1",
+						Error:      errors.New("Error occurred"),
+					}
+					return map[string][]*CmdResult{
+						"1": {cmdResultWithError},
+					}, errors.New("Some error occured while remote execution")
+				},
+				SetWriterFunc: func(cli *cli.Writer) {},
+			},
+			errorWant: errors.New("Some error occured while remote execution"),
+		},
+	}
+
+	for _, testCase := range testCases {
+		t.Run(testCase.description, func(t *testing.T) {
+			err := runServiceVersionsFromBastion(testCase.flags, testCase.mockNodeOpUtils, testCase.mockRemoteCmdExec, printServiceVersionsOutput)
+			if err != nil {
+				assert.EqualError(t, testCase.errorWant, err.Error())
+			} else {
+				assert.Nil(t, err)
+			}
+		})
+	}
+}
+
+func TestHandleManagedServiceForServiceVersionCmd(t *testing.T) {
+
+	testCases := []struct {
+		flags          *ServiceVersionsCmdFlags
+		errorExepected error
+	}{
+		{
+			flags: &ServiceVersionsCmdFlags{
+
+				postgresql: true,
+			},
+			errorExepected: status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, POSTGRESQL),
+		},
+		{
+			flags: &ServiceVersionsCmdFlags{
+
+				opensearch: true,
+			},
+			errorExepected: status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, OPENSEARCH),
+		},
+		{
+			flags: &ServiceVersionsCmdFlags{},
+
+			errorExepected: nil,
+		},
+		{
+			flags: &ServiceVersionsCmdFlags{
+				opensearch: true,
+				postgresql: true,
+			},
+			errorExepected: status.Errorf(status.InvalidCommandArgsError, SERVICE_VERSIONS_ERROR_ON_SELF_MANAGED, POSTGRESQL+" and "+OPENSEARCH),
+		},
+	}
+
+	for _, testCase := range testCases {
+		err := handleManagedServiceErrorForServiceVersionsCmd(testCase.flags)
+
+		if testCase.errorExepected != nil {
+			assert.EqualError(t, err, testCase.errorExepected.Error())
+		} else {
+			assert.Nil(t, err)
+		}
+	}
+}
+
+func TestConstructNodeMapForServiceVersions(t *testing.T) {
+	type testCase struct {
+		flags           *ServiceVersionsCmdFlags
+		nodeMapExpected *NodeTypeAndCmd
+	}
+	infra := &AutomateHAInfraDetails{}
+
+	testCases := []testCase{
+		{
+			flags: &ServiceVersionsCmdFlags{
+				automate:   true,
+				chefServer: true,
+			},
+			nodeMapExpected: &NodeTypeAndCmd{
+				Frontend: &Cmd{
+					CmdInputs: &CmdInputs{
+						Cmd:                      FRONTEND_SERVICE_VERSIONS_CMD,
+						SkipPrintOutput:          true,
+						HideSSHConnectionMessage: true,
+					},
+				},
+				Automate: &Cmd{
+					CmdInputs: &CmdInputs{
+						Cmd:                      FRONTEND_SERVICE_VERSIONS_CMD,
+						ErrorCheckEnableInOutput: true,
+						NodeIps:                  []string{""},
+						NodeType:                 true,
+						SkipPrintOutput:          true,
+						HideSSHConnectionMessage: true,
+					},
+				},
+				ChefServer: &Cmd{
+					CmdInputs: &CmdInputs{
+						Cmd:                      FRONTEND_SERVICE_VERSIONS_CMD,
+						ErrorCheckEnableInOutput: true,
+						NodeIps:                  []string{""},
+						NodeType:                 true,
+						SkipPrintOutput:          true,
+						HideSSHConnectionMessage: true,
+					},
+				},
+				Postgresql: &Cmd{
+					CmdInputs: &CmdInputs{
+						Cmd:                      BACKEND_SERVICE_VERSIONS_CMD,
+						NodeIps:                  []string{""},
+						ErrorCheckEnableInOutput: true,
+						NodeType:                 false,
+						SkipPrintOutput:          true,
+						HideSSHConnectionMessage: true,
+					},
+				},
+				Opensearch: &Cmd{
+					CmdInputs: &CmdInputs{
+						Cmd:                      BACKEND_SERVICE_VERSIONS_CMD,
+						NodeIps:                  []string{""},
+						ErrorCheckEnableInOutput: true,
+						NodeType:                 false,
+						SkipPrintOutput:          true,
+						HideSSHConnectionMessage: true,
+					},
+				},
+				Infra: infra,
+			},
+		},
+	}
+
+	for _, testCase := range testCases {
+		nodeMapGet := constructNodeMapForServiceVersions(infra, testCase.flags)
+		assert.Equal(t, testCase.nodeMapExpected, nodeMapGet)
+	}
+}
+
+func TestRunServiceVersionsCmd(t *testing.T) {
+	tests := []struct {
+		testName        string
+		isHA            bool
+		isDevMode       bool
+		isStandalone    bool
+		isExpectedError bool
+		errorMessage    string
+		mockNodeOpUtils *MockNodeUtilsImpl
+	}{
+		{
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				isA2HARBFileExistFunc: func() bool {
+					return true
+				},
+			},
+			isExpectedError: true,
+			errorMessage:    "Failed to read deployment-service TLS certificates: Could not read the service cert: open /hab/svc/deployment-service/data/deployment-service.crt: no such file or directory",
+		},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.testName, func(t *testing.T) {
+			err := runServiceVersionsCmd(&cobra.Command{}, []string{})
+			if tc.isExpectedError {
+				assert.Error(t, err)
+			} else {
+				assert.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestIsFalgSet(t *testing.T) {
+
+	testCases := []struct {
+		flags           *ServiceVersionsCmdFlags
+		mockNodeOpUtils *MockNodeUtilsImpl
+		errorExepected  error
+	}{
+		{
+			flags: &ServiceVersionsCmdFlags{},
+			mockNodeOpUtils: &MockNodeUtilsImpl{
+				getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+					return &AutomateHAInfraDetails{}, &SSHConfig{}, nil
+				},
+				isManagedServicesOnFunc: func() bool {
+					return false
+				},
+			},
+			errorExepected: nil,
+		},
+		{
+			flags: &ServiceVersionsCmdFlags{
+				node: "12",
+			},
+			errorExepected: status.Errorf(status.InvalidCommandArgsError, "Please provide service flag"),
+		},
+		{
+
+			flags: &ServiceVersionsCmdFlags{
+				node:     "12",
+				automate: true,
+			},
+			errorExepected: nil,
+		},
+	}
+
+	for _, testCases := range testCases {
+		err := isServiceVersionsFlagSet(&cobra.Command{}, testCases.flags, testCases.mockNodeOpUtils)
+
+		if testCases.errorExepected != nil {
+			assert.EqualError(t, err, testCases.errorExepected.Error())
+		} else {
+			assert.Nil(t, err)
+		}
+	}
+}
diff --git a/components/compliance-service/reporting/relaxting/filters_test.go b/components/compliance-service/reporting/relaxting/filters_test.go
index 31cb2d09d..ec2d4a631 100644
--- a/components/compliance-service/reporting/relaxting/filters_test.go
+++ b/components/compliance-service/reporting/relaxting/filters_test.go
@@ -2,8 +2,9 @@ package relaxting
 
 import (
 	"encoding/json"
-	"github.com/stretchr/testify/assert"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 var esr = ES2Backend{
@@ -159,7 +160,7 @@ func TestFiltersForControlIndex(t *testing.T) {
 			name:          "Test for Day Latest and Daily Latest Flags",
 			filtersKey:    "organization",
 			filtersValue:  []string{"ORG"},
-			expectedQuery: `{"bool":{"must":[{"nested":{"path":"nodes","query":{"bool":{"must":{"bool":{"should":{"terms":{"nodes.organization_name.lower":["ORG"]}}}}}}}},{"range":{"end_time":{"from":"2022-07-17T00:00:00Z","include_lower":true,"include_upper":true,"to":"2022-07-18T23:59:59Z"}}},{"terms":{"day_latest":[true]}},{"terms":{"daily_latest":[true]}}]}}`,
+			expectedQuery: `{"bool":{"must":[{"nested":{"path":"nodes","query":{"bool":{"must":{"bool":{"should":{"terms":{"nodes.organization_name.lower":["ORG"]}}}}}}}},{"range":{"end_time":{"from":"2022-07-17T00:00:00Z","include_lower":true,"include_upper":true,"to":"2022-07-18T23:59:59Z"}}},{"terms":{"daily_latest":[true]}}]}}`,
 			esr:           esr,
 			startTime:     startTime,
 			endTime:       endTime,
diff --git a/components/compliance-service/reporting/relaxting/reports_test.go b/components/compliance-service/reporting/relaxting/reports_test.go
index 476404687..3cd43870c 100644
--- a/components/compliance-service/reporting/relaxting/reports_test.go
+++ b/components/compliance-service/reporting/relaxting/reports_test.go
@@ -410,16 +410,16 @@ func TestGetNodeInfoFromReportID_Success(t *testing.T) {
 		ChefDeliveryToken: "",
 	}
 	filters := map[string][]string{
-		"control":               []string{"ssh-10"},
-		"end_time":              []string{"2021-09-30T23:59:59Z"},
-		"environment":           []string{"DevSec Dev Delta"},
-		"inspec_version":        []string{"2.2.20"},
-		"node_id":               []string{"5d84476e-362a-3c65-8acd-dc8b38f3a272"},
-		"platform_with_version": []string{"ubuntu 18.04"},
-		"profile_id":            []string{"f42d2f48c9acd48f52324d52ec575ca9028e405eb303f69cb34d79eb0e588b5c"},
-		"recipe":                []string{"tomcat"},
-		"role":                  []string{"base_windows"},
-		"start_time":            []string{"2021-09-29T00:00:00Z"},
+		"control":               {"ssh-10"},
+		"end_time":              {"2021-09-30T23:59:59Z"},
+		"environment":           {"DevSec Dev Delta"},
+		"inspec_version":        {"2.2.20"},
+		"node_id":               {"5d84476e-362a-3c65-8acd-dc8b38f3a272"},
+		"platform_with_version": {"ubuntu 18.04"},
+		"profile_id":            {"f42d2f48c9acd48f52324d52ec575ca9028e405eb303f69cb34d79eb0e588b5c"},
+		"recipe":                {"tomcat"},
+		"role":                  {"base_windows"},
+		"start_time":            {"2021-09-29T00:00:00Z"},
 	}
 
 	nodeHeaderInfo, err := esr.GetNodeInfoFromReportID("0d67b0ab-2709-49c7-81e4-efcc5700c5cf", filters)
@@ -459,9 +459,9 @@ func TestGetNodeInfoFromReportID_Failed(t *testing.T) {
 		ChefDeliveryToken: "",
 	}
 	filters := map[string][]string{
-		"end_time":   []string{"2021-09-29T23:59:59Z"},
-		"node_id":    []string{"5d84476e-362a-3c65-8acd-dc8b38f3a272"},
-		"start_time": []string{"2021-09-29T00:00:00Z"},
+		"end_time":   {"2021-09-29T23:59:59Z"},
+		"node_id":    {"5d84476e-362a-3c65-8acd-dc8b38f3a272"},
+		"start_time": {"2021-09-29T00:00:00Z"},
 	}
 	_, err := esr.GetNodeInfoFromReportID("0d67b0ab-2709-49c7-81e4-efcc5700c5cf", filters)
 	assert.Error(t, err)
@@ -479,14 +479,7 @@ func TestFilterQueryChangeForDifferentDates(t *testing.T) {
 	endTime1 := "2022-06-23T00:00:00Z"
 	startTime1 := "2022-06-21T00:00:00Z"
 	setFlag, _ := filterQueryChange(endTime1, startTime1)
-	assert.Equal(t, "day_latest", setFlag[0])
-}
-
-func TestFilterQueryChangeForError(t *testing.T) {
-	endTime2 := "2022-06-26T00:00:00Z"
-	startTime2 := startTimeErr
-	_, err := filterQueryChange(endTime2, startTime2)
-	assert.EqualErrorf(t, err, errCannotParse, "")
+	assert.Equal(t, "daily_latest", setFlag[0])
 }
 
 func TestFilterQueryChangeForErrorWithBlankStartTimeAndEndTime(t *testing.T) {
@@ -498,7 +491,7 @@ func TestFilterQueryChangeForEndTime(t *testing.T) {
 	endTime2 := ""
 	startTime2 := "2022-06-22T00:00:00Z"
 	setFlag, _ := filterQueryChange(endTime2, startTime2)
-	assert.Equal(t, "day_latest", setFlag[0])
+	assert.Equal(t, "daily_latest", setFlag[0])
 }
 func TestValidateFiltersTimeRangeForError(t *testing.T) {
 	endTime2 := "2022-06-23T00:00:00Z"