Repository: chef/automate
Pull request #7981 (2023-06-21 12:30:42)

Resolving minor issues
### :nut_and_bolt: Description: What code changed, and why?

Correcting verify-server issues found at integration testing.

<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

### :chains: Related Resources

https://chefio.atlassian.net/browse/CHEF-3731

### :+1: Definition of Done

Below is the list of issues:-

- Only consider 9638 for udp only for opensearch and postgres firewall check
- Consider only port 22 from bastion for all the nodes and 7234/9200 for postgrsql/opensearch
- Construct correct response from firewall api trigger for batch check service. Which will make slice with unique node type and ip.
- For firewall, make insecure connection for https api
- For s3 config check, make base path as default "automate" if no base path is present in config
- Increase timeout for the APIs as 35 sec, as some api gives response in 30 sec
- Added skip for certificates if not present for chef server and automate nodes
- Resolving error for certificate in config parser and mock server
- External Open-search taking ORN as a paramater, this is not required
- Corrected the request for external opensearch


### :athletic_shoe: How to Build and Test the Change

chef-automate verify-server --config config.toml

### :white_check_mark: Checklist

**All PRs** must tick these:

- [X] I have read the [CONTRIBUTING document](https://github.com/chef/automate/blob/master/CONTRIBUTING.md).
- [X] 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:

- [X] Is the code clear? *(complicated code or lots of comments--subdivide and use well-named methods, meaningful variable names, etc.)*
- [X] Consistency checked? *(user notifications, user prompts, visual patterns, code patterns, variable names)*
- [X] Repeated code blocks eliminated? *(adapt and reuse existing components, blocks, functions, etc.)*
- [X] Spelling, grammar, typos checked? *(at a minimum use `make spell` in any component directory)*
- [X] Code well-formatted? *(indents, line breaks, etc. improve rather than hinder readability)*

All PRs **from Progress employees** should tick these if appropriate:

- [X] Tests added/updated? (all new code needs new tests)
- [X] 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 | 85d520f74e78c9978e094e8c13c25d13151c9475 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/chef-automate/deploys/6492ed7477f607000863799a |
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=7981)

[![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=7981&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=7981&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&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=7981&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=7981&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&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=7981) [![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=7981) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981)  
[![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=7981&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=7981&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&resolved=false&types=CODE_SMELL)

[![93.5%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/90-16px.png '93.5%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_coverage&view=list) [93.5% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_duplicated_lines_density&view=list)


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=7981)

[![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=7981&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=7981&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&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=7981&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=7981&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&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=7981) [![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=7981) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981)  
[![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=7981&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=7981&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&resolved=false&types=CODE_SMELL)

[![95.1%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/90-16px.png '95.1%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_coverage&view=list) [95.1% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_duplicated_lines_density&view=list)


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=7981)

[![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=7981&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=7981&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&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=7981&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=7981&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&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=7981) [![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=7981) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981)  
[![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=7981&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=7981&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&resolved=false&types=CODE_SMELL)

[![93.8%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/90-16px.png '93.8%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_coverage&view=list) [93.8% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7981&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/VERSION b/VERSION
index 9660e8580..1d7130a8a 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.7.92
\ No newline at end of file
+4.7.101
\ No newline at end of file
diff --git a/components/automate-backend-deployment/habitat/plan.sh b/components/automate-backend-deployment/habitat/plan.sh
index 4d3ae1a88..ac1dbf5e0 100644
--- a/components/automate-backend-deployment/habitat/plan.sh
+++ b/components/automate-backend-deployment/habitat/plan.sh
@@ -110,7 +110,6 @@ do_install() {
   rm -f $pkg_prefix/workspace/backups
 }
 
-
 do_strip() {
   return 0
 }
\ No newline at end of file
diff --git a/components/automate-cli/cmd/chef-automate/verify.go b/components/automate-cli/cmd/chef-automate/verify.go
index fd9be1bad..769f5adf9 100644
--- a/components/automate-cli/cmd/chef-automate/verify.go
+++ b/components/automate-cli/cmd/chef-automate/verify.go
@@ -34,12 +34,16 @@ const (
 	SYSTEMD_PATH              = "/etc/systemd/system"
 	REMOTE_NODES              = "remote nodes"
 	BASTION                   = "bastion"
+	LOCALHOST                 = "localhost"
 	SLEEP_DURATION            = 2 * time.Second
 )
 
 var (
-	statusAPIEndpoint     = fmt.Sprintf("http://localhost:%s/status", getPort())
-	batchCheckAPIEndpoint = fmt.Sprintf("http://localhost:%s/api/v1/checks/batch-checks", getPort())
+	statusAPIRoute     = "/status"
+	batchCheckAPIRoute = "/api/v1/checks/batch-checks"
+	getAPIEndpoint     = func(hostIp string, port string, route string) string {
+		return fmt.Sprintf("http://%s:%s%s", hostIp, port, route)
+	}
 )
 
 type verifyCmdFlags struct {
@@ -80,6 +84,12 @@ type verifyServeCmdFlow struct{}
 
 type verifySystemdCreateFlow struct{}
 
+type StatusResponse struct {
+	HostIp       string
+	ResponseBody []byte
+	Error        error
+}
+
 func init() {
 	flagsObj := verifyCmdFlags{}
 
@@ -323,6 +333,7 @@ func (v *verifyCmdFlow) runVerifyServiceForBastion(batchCheckConfig models.Confi
 	v.Writer.Println("Checking automate-verify service on bastion")
 
 	//Call status API to check if automate-verify service is running on bastion
+	statusAPIEndpoint := getAPIEndpoint(LOCALHOST, getPort(), statusAPIRoute)
 	_, responseBody, err := v.Client.MakeRequest(http.MethodGet, statusAPIEndpoint, nil)
 	if err != nil {
 		v.Writer.Printf("error while checking automate-verify service on bastion: %v\n", err)
@@ -389,16 +400,24 @@ func (v *verifyCmdFlow) runVerifyServiceForRemote(batchCheckConfig models.Config
 
 	destFileName := "chef-automate"
 
-	// Copying CLI binary to remote nodes
-	err := v.copyCLIOnRemoteNodes(destFileName, sshConfig, hostIPs)
+	hostIPsToCopyLatestCLI, err := v.getHostIPsWithNoLatestCLI(hostIPs)
 	if err != nil {
 		return nil, err
 	}
 
-	// Starting automate-verify service on remote nodes
-	err = v.startServiceOnRemoteNodes(destFileName, sshConfig, hostIPs)
-	if err != nil {
-		return nil, err
+	if len(hostIPsToCopyLatestCLI) > 0 {
+		v.Writer.Printf("Copying CLI to the follwoing IPs: %v", hostIPsToCopyLatestCLI)
+		// Copying Latest CLI binary to remote nodes
+		err = v.copyCLIOnRemoteNodes(destFileName, sshConfig, hostIPsToCopyLatestCLI)
+		if err != nil {
+			return nil, err
+		}
+
+		// Starting automate-verify service on remote nodes
+		err = v.startServiceOnRemoteNodes(destFileName, sshConfig, hostIPs)
+		if err != nil {
+			return nil, err
+		}
 	}
 
 	//TODO: Need to handle the case for AWS
@@ -412,6 +431,54 @@ func (v *verifyCmdFlow) runVerifyServiceForRemote(batchCheckConfig models.Config
 	return v.makeBatchCheckAPICall(batchCheckRemoteReq, REMOTE_NODES)
 }
 
+// Get Host IPs without chef-automate binary or without latest version chef-automate binary
+func (v *verifyCmdFlow) getHostIPsWithNoLatestCLI(hostIPs []string) ([]string, error) {
+
+	responseChan := make(chan StatusResponse, len(hostIPs))
+	for _, hostIP := range hostIPs {
+		statusAPIEndpoint := getAPIEndpoint(hostIP, getPort(), statusAPIRoute)
+
+		go func(hostIP string) {
+			rc := StatusResponse{hostIP, nil, nil}
+			_, responseBody, err := v.Client.MakeRequest(http.MethodGet, statusAPIEndpoint, nil)
+			if err != nil {
+				rc.Error = err
+				responseChan <- rc
+				return
+			}
+			rc.ResponseBody = responseBody
+			responseChan <- rc
+
+		}(hostIP)
+	}
+
+	hostIPsWithoutLatestCLI := []string{}
+	for i := 0; i < len(hostIPs); i++ {
+		response := <-responseChan
+
+		// Incase of unreachable error (connection refused) , appending IP to the array
+		if response.Error != nil {
+			hostIPsWithoutLatestCLI = append(hostIPsWithoutLatestCLI, response.HostIp)
+			continue
+		}
+
+		resultBytes, err := v.getResultFromResponseBody(response.ResponseBody)
+		if err != nil {
+			return nil, err
+		}
+
+		var result models.StatusDetails
+		if err := json.Unmarshal(resultBytes, &result); err != nil {
+			return nil, fmt.Errorf("failed to unmarshal Result field: %v", err)
+		}
+
+		if result.CliVersion < version.BuildTime {
+			hostIPsWithoutLatestCLI = append(hostIPsWithoutLatestCLI, response.HostIp)
+		}
+	}
+	return hostIPsWithoutLatestCLI, nil
+}
+
 // Creates systemd service with current CLI binary
 func (v *verifyCmdFlow) createSystemdOnBastion() error {
 	err := v.CreateSystemdService.Create()
@@ -426,6 +493,7 @@ func (v *verifyCmdFlow) createSystemdOnBastion() error {
 // Makes batch-check API call
 func (v *verifyCmdFlow) makeBatchCheckAPICall(requestBody models.BatchCheckRequest, nodeType string) ([]byte, error) {
 	v.Writer.Printf("Doing batch-check API call for %s\n", nodeType)
+	batchCheckAPIEndpoint := getAPIEndpoint(LOCALHOST, getPort(), batchCheckAPIRoute)
 	_, responseBody, err := v.Client.MakeRequest(http.MethodPost, batchCheckAPIEndpoint, requestBody)
 	if err != nil {
 		if responseBody != nil {
diff --git a/components/automate-cli/pkg/verifyserver/models/batchcheck.go b/components/automate-cli/pkg/verifyserver/models/batchcheck.go
index 68195ba39..46101dac9 100644
--- a/components/automate-cli/pkg/verifyserver/models/batchcheck.go
+++ b/components/automate-cli/pkg/verifyserver/models/batchcheck.go
@@ -94,6 +94,7 @@ type Config struct {
 func appendCertsByIpToNodeCerts(certsByIP *[]config.CertByIP, ipList []string, privateKey, publicKey, adminKey, adminCert, nodeRootCa string) []*NodeCert {
 	nodeCertsList := make([]*NodeCert, 0)
 	certByIpMap := createMapforCertByIp(certsByIP)
+	
 	for _, ip := range ipList {
 		certByIP, ok := certByIpMap[ip]
 		var nodeCert *NodeCert
@@ -127,7 +128,8 @@ func createMapforCertByIp(certsByIP *[]config.CertByIP) map[string]*config.CertB
 	certByIPMap := make(map[string]*config.CertByIP)
 	if certsByIP != nil {
 		for _, cert := range *certsByIP {
-			certByIPMap[cert.IP] = &cert
+			certificateIp := cert
+			certByIPMap[cert.IP] = &certificateIp
 		}
 
 	}
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/firewall.go b/components/automate-cli/pkg/verifyserver/server/api/v1/firewall.go
index bcdf1fc14..4410cd09f 100644
--- a/components/automate-cli/pkg/verifyserver/server/api/v1/firewall.go
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/firewall.go
@@ -44,12 +44,6 @@ func (h *Handler) FirewallCheck(c *fiber.Ctx) error {
 		return fiber.NewError(http.StatusBadRequest, "source_node_ip and destination_node_ip cannot be same")
 	}
 
-	// For https protocol root_ca is mandatory
-	if strings.TrimSpace(reqBody.DestinationServiceProtocol) == constants.HTTPS &&
-		strings.TrimSpace(reqBody.RootCert) == "" {
-		return fiber.NewError(http.StatusBadRequest, "root_cert value is mandatory for protocol https")
-	}
-
 	// Supported protocol check
 	if strings.TrimSpace(reqBody.DestinationServiceProtocol) != constants.TCP &&
 		strings.TrimSpace(reqBody.DestinationServiceProtocol) != constants.UDP &&
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable.go b/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable.go
index 16036eaf2..aaa69a159 100644
--- a/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable.go
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable.go
@@ -27,9 +27,6 @@ func (h *Handler) PortReachable(c *fiber.Ctx) error {
 		return fiber.NewError(http.StatusBadRequest, "Invalid port number")
 	}
 
-	if reqBody.DestinationNodeServiceProtocol == constants.HTTPS && reqBody.RootCA == "" {
-		return fiber.NewError(http.StatusBadRequest, "RootCA value is mandatory for protocol HTTPS")
-	}
 	if reqBody.DestinationNodeServiceProtocol != constants.TCP && reqBody.DestinationNodeServiceProtocol != constants.UDP && reqBody.DestinationNodeServiceProtocol != constants.HTTPS {
 		return fiber.NewError(http.StatusBadRequest, "Please Give Valid Protocol i.e tcp, udp or https")
 	}
diff --git a/components/automate-cli/pkg/verifyserver/server/server.go b/components/automate-cli/pkg/verifyserver/server/server.go
index ec16aa7e3..7e8584bf0 100644
--- a/components/automate-cli/pkg/verifyserver/server/server.go
+++ b/components/automate-cli/pkg/verifyserver/server/server.go
@@ -96,7 +96,7 @@ func NewVerifyServer(port string, debug bool) (*VerifyServer, error) {
 		AddBatchCheckService(
 			batchcheckservice.NewBatchCheckService(trigger.NewCheckTrigger(
 				hardwareresourcechecktrigger.NewHardwareResourceCountCheck(l, port),
-				sshuseraccesschecktrigger.NewSshUserAccessCheck(l, port),
+				sshuseraccesschecktrigger.NewSshUserAccessCheck(l, fileutils.NewFileSystemUtils(), port),
 				certificatechecktrigger.NewCertificateCheck(l, port),
 				externalopensearchchecktrigger.NewExternalOpensearchCheck(l, port),
 				externalpostgresqlchecktrigger.NewExternalPostgresCheck(l, port),
@@ -117,7 +117,7 @@ func NewVerifyServer(port string, debug bool) (*VerifyServer, error) {
 		AddS3ConfigService(s3configservice.NewS3ConfigService(l, awsutils.NewAwsUtils())).
 		AddOSS3BackupService(opensearchbackupservice.NewOSS3BackupService(l)).
 		AddPortReachableService(portreachableservice.NewPortReachableService(l, constants.TIMEOUT)).
-		AddExternalPostgresqlService(externalpostgresqlservice.NewExternalPostgresqlService(db.NewDBImpl(),  fileutils.NewFileSystemUtils(),  l)).
+		AddExternalPostgresqlService(externalpostgresqlservice.NewExternalPostgresqlService(db.NewDBImpl(), fileutils.NewFileSystemUtils(), l)).
 		AddSystemUserService(systemuserservice.NewSystemUserService(l, executil.NewExecCmdServiceImp(), userutils.NewUserUtilImp())).
 		AddExternalOpensearchService(externalopensearchservice.NewExternalOpensearchService(l, constants.TIMEOUT)).
 		AddFqdnService(fqdnservice.NewFqdnService(l, constants.TIMEOUT)).
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice.go
index 23c8ddc61..9b317f9a7 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice.go
@@ -52,10 +52,12 @@ func (ss *BatchCheckService) BatchCheck(checks []string, config *models.Config)
 		checkTriggerRespMap = getBastionCheckResp(ss, bastionChecks, config)
 	}
 
-	config.DeploymentState, err = ss.getDeploymentState(config)
-	if err != nil {
-		ss.log.Error("Failed to get the Deployment state:", err)
-		return models.BatchCheckResponse{}, err
+	if len(remoteChecks) > 0 {
+		config.DeploymentState, err = ss.getDeploymentState(config)
+		if err != nil {
+			ss.log.Error("Failed to get the Deployment state:", err)
+			return models.BatchCheckResponse{}, err
+		}
 	}
 
 	successfullyStartedMockServers, notStartedMockServers := ss.startMockServerIfNeeded(remoteChecks, config)
@@ -258,7 +260,7 @@ func (ss *BatchCheckService) generateRootCaAndPrivateKeyForHost(host, nodeType s
 
 	certificateNodes, ok := certMap[nodeType]
 	if ok && len(certificateNodes.Nodes) > 0 {
-		nodes := config.Certificate[0].Nodes
+		nodes := certificateNodes.Nodes
 		for _, nodeData := range nodes {
 			if host == nodeData.IP {
 				startMockServerRequestBody.Cert = nodeData.Cert
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger.go
index f8d4728d2..6ee5522a8 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger.go
@@ -7,6 +7,7 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/constants"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/configutils"
 	"github.com/chef/automate/lib/logger"
 )
 
@@ -42,8 +43,14 @@ func (ss *CertificateCheck) Run(config *models.Config) []models.CheckTriggerResp
 	//This map will hold the Response against each IP
 	var finalResult []models.CheckTriggerResponse
 
+	hardwareMap := configutils.GetNodeTypeMap(config.Hardware)
+
 	url := fmt.Sprintf("%s:%s%s", ss.host, ss.port, constants.CERTIFICATE_CHECK_API_PATH)
 	for _, certificate := range config.Certificate {
+		if len(certificate.Nodes) == 0 {
+			finalResult = append(finalResult, skipCertificateForAutomateAndChefServerNodes(certificate.NodeType, hardwareMap)...)
+			continue
+		}
 		for _, node := range certificate.Nodes {
 			//construct the request for Certificate Check API
 			requestBody := models.CertificateCheckRequest{
@@ -81,3 +88,18 @@ func isCertificateEmpty(certificate []*models.Certificate) bool {
 func isCertificateNil(certificate []*models.Certificate) bool {
 	return certificate == nil
 }
+
+func skipCertificateForAutomateAndChefServerNodes(nodeType string, hardwareMap map[string][]string) []models.CheckTriggerResponse {
+	var result []models.CheckTriggerResponse
+
+	for ip, nodeTypes := range hardwareMap {
+		for _, nodeTypeMap := range nodeTypes {
+			if nodeTypeMap == nodeType {
+				result = append(result, trigger.SkippedTriggerCheckResp(ip, constants.CERTIFICATE, nodeTypeMap))
+			}
+		}
+	}
+
+	return result
+
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchcheck.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchcheck.go
index d13a4713c..6e869c335 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchcheck.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchcheck.go
@@ -74,8 +74,8 @@ func runCheckForOpensearch(config *models.Config, port string, log logger.Logger
 
 }
 
-func getOpensearchRequest(details *models.ExternalOS) models.ExternalOS {
-	return models.ExternalOS{
+func getOpensearchRequest(details *models.ExternalOS) models.ExternalOSRequest {
+	return models.ExternalOSRequest{
 		OSDomainName:   details.OSDomainName,
 		OSDomainURL:    details.OSDomainURL,
 		OSUsername:     details.OSUsername,
@@ -104,8 +104,7 @@ func isEmptyExternalOS(externalOS *models.ExternalOS) bool {
 		externalOS.OSDomainURL == "" ||
 		externalOS.OSUsername == "" ||
 		externalOS.OSUserPassword == "" ||
-		externalOS.OSCert == "" ||
-		externalOS.OSRoleArn == ""
+		externalOS.OSCert == ""
 }
 
 func externalOSEmptyResp(config *models.Config, checkType string) []models.CheckTriggerResponse {
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger.go
index 8256d03a2..fbbe91149 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger.go
@@ -7,7 +7,6 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/constants"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger"
-	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/configutils"
 	"github.com/chef/automate/lib/logger"
 )
 
@@ -39,27 +38,24 @@ func (fc *FirewallCheck) Run(config *models.Config) []models.CheckTriggerRespons
 
 	response := triggerMultipleRequests(config, fc.log, endPoint, http.MethodPost, requestMap)
 
-	return response
+	return constructResponseFromOutput(response)
 }
 
 func (fc *FirewallCheck) GetPortsForMockServer() map[string]map[string][]int {
 	nodeTypePortMap := map[string]map[string][]int{
 		constants.AUTOMATE: {
-			constants.TCP:   []int{9631, 9638},
-			constants.HTTPS: []int{443},
-			constants.HTTP:  []int{80},
+			constants.HTTP: []int{80},
 		},
 		constants.CHEF_INFRA_SERVER: {
-			constants.TCP:   []int{9631, 9638},
-			constants.HTTP:  []int{80},
-			constants.HTTPS: []int{443},
+			constants.HTTP: []int{80},
 		},
 		constants.POSTGRESQL: {
-			constants.TCP: []int{7432, 9631, 5432, 6432, 9638},
+			constants.TCP: []int{7432, 9631, 5432, 6432},
 			constants.UDP: []int{9638},
 		},
 		constants.OPENSEARCH: {
-			constants.TCP: []int{9200, 9300, 9631, 9638},
+			constants.TCP: []int{9200, 9300, 9631},
+			constants.UDP: []int{9638},
 		},
 	}
 	return nodeTypePortMap
@@ -105,38 +101,11 @@ func getRequestsForAutomateAsSource(config *models.Config) []models.FirewallRequ
 
 }
 
-func getRootCertForNodeWithNodeTypeAndIP(certMap map[string]*models.Certificate, nodeType string, nodeIp string) string {
-
-	nodesCert, found := certMap[nodeType]
-	if found {
-		for _, cert := range nodesCert.Nodes {
-			if cert.IP == nodeIp {
-				return cert.RootCert
-			}
-		}
-	}
-
-	return ""
-}
-
 // getRequestsForChefServerAsSource gives the requests for all the ports where chefserver is the source
 func getRequestsForChefServerAsSource(config *models.Config) []models.FirewallRequest {
 
 	var reqBodies []models.FirewallRequest
-	certMap := configutils.GetCertificateMap(config.Certificate)
 	for _, sourceNodeIP := range config.Hardware.ChefInfraServerNodeIps {
-		//Dest Automate
-		for _, destNodeIP := range config.Hardware.AutomateNodeIps {
-			reqBody := models.FirewallRequest{
-				SourceNodeIP:               sourceNodeIP,
-				DestinationNodeIP:          destNodeIP,
-				DestinationServicePort:     "443",
-				DestinationServiceProtocol: "https",
-				RootCert:                   getRootCertForNodeWithNodeTypeAndIP(certMap, constants.AUTOMATE, destNodeIP),
-			}
-			reqBodies = append(reqBodies, reqBody)
-		}
-
 		// Dest postgres
 		for _, destNodeIP := range config.Hardware.PostgresqlNodeIps {
 			reqBody := models.FirewallRequest{
@@ -314,3 +283,36 @@ func triggerMultipleRequests(config *models.Config, log logger.Logger, endPoint,
 	close(outputCh)
 	return result
 }
+
+// constructResponseFromOutput constructing the final output from result in the format excepted by Batch Check service
+func constructResponseFromOutput(result []models.CheckTriggerResponse) []models.CheckTriggerResponse {
+
+	var response []models.CheckTriggerResponse
+	resultMap := make(map[string]models.CheckTriggerResponse)
+
+	for _, checkResponse := range result {
+		key := checkResponse.Host + "_" + checkResponse.NodeType
+		value, ok := resultMap[key]
+		if ok {
+			//Adding checks for the results
+			newChecks := value.Result.Checks
+			newChecks = append(newChecks, checkResponse.Result.Checks...)
+			//Adding the new checks to the result
+			value.Result.Checks = newChecks
+			if checkResponse.Result.Error != nil {
+				value.Result.Error = checkResponse.Result.Error
+			}
+			resultMap[key] = value
+		} else {
+			resultMap[key] = checkResponse
+		}
+
+	}
+
+	//Creating the check trigger response
+	for _, checkResponses := range resultMap {
+		response = append(response, checkResponses)
+	}
+
+	return response
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/vars.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/vars.go
index e43fcd56d..3ede9d020 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/vars.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/vars.go
@@ -1,9 +1,9 @@
 package firewallchecktrigger
 
 var (
-	postgresqlTCPPorts   = [5]string{"9631", "7432", "5432", "6432", "9638"}
-	opensearchTCPPorts   = [4]string{"9631", "9200", "9300", "9638"}
-	a2CsTCPPorts         = [3]string{"22", "9631", "9638"}
-	postgresBastionPorts = [4]string{"22", "9631", "9638", "7432"}
-	ossBastionPorts      = [4]string{"22", "9631", "9638", "9200"}
+	postgresqlTCPPorts   = [4]string{"9631", "7432", "5432", "6432"}
+	opensearchTCPPorts   = [3]string{"9631", "9200", "9300"}
+	a2CsTCPPorts         = [1]string{"22"}
+	postgresBastionPorts = [2]string{"22", "7432"}
+	ossBastionPorts      = [2]string{"22", "9200"}
 )
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/opensearchs3bucketaccesschecktrigger/opensearchs3bucketaccesscheck.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/opensearchs3bucketaccesschecktrigger/opensearchs3bucketaccesscheck.go
index ea3acb49d..904000ae7 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/opensearchs3bucketaccesschecktrigger/opensearchs3bucketaccesscheck.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/opensearchs3bucketaccesschecktrigger/opensearchs3bucketaccesscheck.go
@@ -37,6 +37,11 @@ func (osb *OpensearchS3BucketAccessCheck) Run(config *models.Config) []models.Ch
 		}
 	}
 
+	//Passing a default value if s3 bucket path not provided
+	if config.Backup.ObjectStorage.BasePath == "" {
+		config.Backup.ObjectStorage.BasePath = "automate"
+	}
+
 	s3OpensearchBackupRequest := models.S3BackupDetails{
 		Endpoint:   config.ExternalOS.OSDomainURL,
 		Username:   config.ExternalOS.OSUsername,
@@ -97,7 +102,6 @@ func isEmptyExternalOS(externalOS *models.ExternalOS) bool {
 
 func isObjectStorage(backup *models.Backup) bool {
 	return backup.ObjectStorage.BucketName == "" ||
-		backup.ObjectStorage.BasePath == "" ||
 		backup.ObjectStorage.AccessKey == "" ||
 		backup.ObjectStorage.SecretKey == "" ||
 		backup.ObjectStorage.AWSRegion == ""
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go
index 5ee597741..0fb9db9c8 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go
@@ -70,6 +70,10 @@ func getResultFromOutputChan(reqList int, outputCh chan models.CheckTriggerRespo
 }
 
 func getS3CheckRequest(object *models.ObjectStorage) models.S3ConfigRequest {
+	//passing a default value if s3 bucket path not provided
+	if object.BasePath == "" {
+		object.BasePath = "automate"
+	}
 	return models.S3ConfigRequest{
 		Endpoint:   object.Endpoint,
 		BucketName: object.BucketName,
@@ -82,7 +86,6 @@ func getS3CheckRequest(object *models.ObjectStorage) models.S3ConfigRequest {
 
 func isObjectStorage(backup *models.Backup) bool {
 	return backup.ObjectStorage.BucketName == "" ||
-		backup.ObjectStorage.BasePath == "" ||
 		backup.ObjectStorage.AccessKey == "" ||
 		backup.ObjectStorage.SecretKey == "" ||
 		backup.ObjectStorage.AWSRegion == ""
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger.go
index 6d85a6610..83e676cb4 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger.go
@@ -8,20 +8,25 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/configutils"
+	"github.com/chef/automate/lib/io/fileutils"
 	"github.com/chef/automate/lib/logger"
+	"github.com/gofiber/fiber/v2"
+	"github.com/pkg/errors"
 )
 
 type SshUserAccessCheck struct {
-	host string
-	port string
-	log  logger.Logger
+	host      string
+	port      string
+	log       logger.Logger
+	fileUtils fileutils.FileUtils
 }
 
-func NewSshUserAccessCheck(log logger.Logger, port string) *SshUserAccessCheck {
+func NewSshUserAccessCheck(log logger.Logger, fileutils fileutils.FileUtils, port string) *SshUserAccessCheck {
 	return &SshUserAccessCheck{
-		log:  log,
-		host: constants.LOCAL_HOST_URL,
-		port: port,
+		log:       log,
+		host:      constants.LOCAL_HOST_URL,
+		port:      port,
+		fileUtils: fileutils,
 	}
 }
 
@@ -39,17 +44,30 @@ func (ss *SshUserAccessCheck) Run(config *models.Config) []models.CheckTriggerRe
 		return trigger.ConstructEmptyResp(config, constants.SSH_USER, "SSH credentials is missing")
 	}
 
-	count := config.Hardware.AutomateNodeCount + config.Hardware.ChefInfraServerNodeCount +
-		config.Hardware.PostgresqlNodeCount + config.Hardware.OpenSearchNodeCount
+	count := 0
 
-	outputCh := make(chan models.CheckTriggerResponse, count)
+	outputCh := make(chan models.CheckTriggerResponse)
 	url := fmt.Sprintf("%s:%s%s", ss.host, ss.port, constants.SSH_USER_CHECK_API_PATH)
-
 	var finalResult []models.CheckTriggerResponse
 	hostMap := configutils.GetNodeTypeMap(config.Hardware)
 	for ip, types := range hostMap {
 		for i := 0; i < len(types); i++ {
-			requestBody := getSShUserAPIRquest(ip, config.SSHUser)
+			requestBody, err := ss.getSShUserAPIRequest(ip, config.SSHUser)
+			if err != nil {
+				finalResult = append(finalResult, models.CheckTriggerResponse{
+					Host:     ip,
+					NodeType: types[i],
+					Result: models.ApiResult{
+						Passed: false,
+						Error: &fiber.Error{
+							Code:    http.StatusBadRequest,
+							Message: err.Error(),
+						},
+					},
+				})
+				continue
+			}
+			count = count + 1
 			go trigger.TriggerCheckAPI(url, ip, types[i], http.MethodPost, outputCh, requestBody)
 		}
 	}
@@ -58,19 +76,30 @@ func (ss *SshUserAccessCheck) Run(config *models.Config) []models.CheckTriggerRe
 		finalResult = append(finalResult, resp)
 	}
 	close(outputCh)
-
 	return finalResult
 }
 
-func getSShUserAPIRquest(ip string, sshUser *models.SSHUser) models.SShUserRequest {
-
+func (ss *SshUserAccessCheck) getSShUserAPIRequest(ip string, sshUser *models.SSHUser) (models.SShUserRequest, error) {
+	permisssion, err := ss.fileUtils.GetFilePermission(sshUser.PrivateKey)
+	if err != nil {
+		return models.SShUserRequest{}, err
+	}
+	if permisssion > 400 {
+		return models.SShUserRequest{}, errors.New("Permissions on the ssh key file do not satisfy the requirement")
+	}
+	ct, err := ss.fileUtils.ReadFile(sshUser.PrivateKey)
+	if err != nil {
+		ss.log.Errorf("Error while opening the private file path %s: %v\n", sshUser.PrivateKey, err)
+		return models.SShUserRequest{}, err
+	}
+	keyContents := string(ct)
 	return models.SShUserRequest{
 		IP:           ip,
 		Username:     sshUser.Username,
 		Port:         sshUser.Port,
 		SudoPassword: sshUser.SudoPassword,
-		PrivateKey:   sshUser.PrivateKey,
-	}
+		PrivateKey:   keyContents,
+	}, nil
 }
 
 func (ss *SshUserAccessCheck) GetPortsForMockServer() map[string]map[string][]int {
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/triggerapi.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/triggerapi.go
index db8a21346..fe922db79 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/triggerapi.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/triggerapi.go
@@ -115,7 +115,7 @@ func TriggerCheckAPI(endPoint, host, nodeType, method string, output chan<- mode
 	}
 
 	client := http.Client{
-		Timeout: 5 * time.Second,
+		Timeout: 35 * time.Second,
 	}
 	resp, err := client.Do(req)
 	if err != nil {
diff --git a/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable.go b/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable.go
index ed8ef6ec2..054c170cb 100644
--- a/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable.go
+++ b/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable.go
@@ -86,20 +86,36 @@ func (pr *PortReachableService) udpClient(protocolType, host, port string) error
 
 func (pr *PortReachableService) httpsClient(host, cert string, port int) error {
 	pr.log.Debug(fmt.Sprintf("Trying to connect https server on %s:%d", host, port))
-	caCertPool := x509.NewCertPool()
-	ok := caCertPool.AppendCertsFromPEM([]byte(cert))
-	if !ok {
-		return errors.New("certificate error: root_ca is not of correct format")
-	}
-	client := &http.Client{
-		Transport: &http.Transport{
-			TLSClientConfig: &tls.Config{
-				RootCAs:    caCertPool,
-				MinVersion: tls.VersionTLS12,
+	//Checking for insecure connection as root ca will not be available for https port
+	var client *http.Client
+	if cert != "" {
+		caCertPool := x509.NewCertPool()
+		ok := caCertPool.AppendCertsFromPEM([]byte(cert))
+		if !ok {
+			return errors.New("certificate error: root_ca is not of correct format")
+		}
+
+		client = &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: &tls.Config{
+					RootCAs:    caCertPool,
+					MinVersion: tls.VersionTLS12,
+				},
 			},
-		},
-		Timeout: time.Second * pr.timeout,
+			Timeout: time.Second * pr.timeout,
+		}
+	} else {
+		client = &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: &tls.Config{
+					InsecureSkipVerify: true,
+					MinVersion:         tls.VersionTLS12,
+				},
+			},
+			Timeout: time.Second * pr.timeout,
+		}
 	}
+
 	url := fmt.Sprintf("https://%s:%d", host, port)
 	pr.log.Debug("URL: ", url)
 	resp, err := client.Get(url)
diff --git a/components/automate-cli/pkg/verifysystemdcreate/mocksystemdcreateutils.go b/components/automate-cli/pkg/verifysystemdcreate/mocksystemdcreateutils.go
index 549a80de6..6a97abbf9 100644
--- a/components/automate-cli/pkg/verifysystemdcreate/mocksystemdcreateutils.go
+++ b/components/automate-cli/pkg/verifysystemdcreate/mocksystemdcreateutils.go
@@ -5,6 +5,7 @@ type MockSystemdCreateUtils struct {
 	SystemdRunningFunc           func() error
 	CreateDestinationAndCopyFunc func(binarySrcPath, binaryDestPath string) error
 	ExecuteShellCommandFunc      func(name string, arg []string) error
+	GetEnvFunc                   func() string
 }
 
 func (msc *MockSystemdCreateUtils) GetBinaryPath() (string, error) {
@@ -19,3 +20,6 @@ func (msc *MockSystemdCreateUtils) CreateDestinationAndCopy(binarySrcPath, binar
 func (msc *MockSystemdCreateUtils) ExecuteShellCommand(name string, arg []string) error {
 	return msc.ExecuteShellCommandFunc(name, arg)
 }
+func (msc *MockSystemdCreateUtils) GetEnv() string {
+	return msc.GetEnvFunc()
+}
diff --git a/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc.go b/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc.go
index b629a7860..16a833b78 100644
--- a/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc.go
+++ b/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc.go
@@ -28,7 +28,7 @@ ExecStart={{.ServiceCommand}}
 Restart=always
 StandardOutput=journal
 StandardError=journal
-
+Environment="HOME={{.HomeEnv}}"
 [Install]
 WantedBy=multi-user.target
 `
@@ -38,6 +38,7 @@ type systemdInput struct {
 	ServiceName        string
 	ServiceDescription string
 	ServiceCommand     string
+	HomeEnv            string  
 }
 
 type CreateSystemdServiceImpl struct {
@@ -102,12 +103,13 @@ func (css *CreateSystemdServiceImpl) createSystemdServiceFile() error {
 	if err != nil {
 		return errors.Wrap(err, "Error parsing template")
 	}
-
+	envVariable := css.SystemdCreateUtils.GetEnv()
 	// Prepare the template data.
 	data := systemdInput{
 		ServiceName:        SERVICE_NAME,
 		ServiceDescription: SERVICE_DESCRIPTION,
 		ServiceCommand:     css.BinaryDestinationFolder + "/" + SERVICE_COMMAND,
+		HomeEnv:            envVariable,
 	}
 
 	css.Logger.Debugf(
diff --git a/components/automate-cli/pkg/verifysystemdcreate/systemdcreateutils.go b/components/automate-cli/pkg/verifysystemdcreate/systemdcreateutils.go
index ae7695f47..2e2cdaf7f 100644
--- a/components/automate-cli/pkg/verifysystemdcreate/systemdcreateutils.go
+++ b/components/automate-cli/pkg/verifysystemdcreate/systemdcreateutils.go
@@ -15,6 +15,7 @@ type SystemdCreateUtils interface {
 	SystemdRunning() error
 	CreateDestinationAndCopy(binarySrcPath, binaryDestPath string) error
 	ExecuteShellCommand(name string, arg []string) error
+	GetEnv() string
 }
 
 type SystemdCreateUtilsImpl struct{}
@@ -52,3 +53,7 @@ func (scu *SystemdCreateUtilsImpl) CreateDestinationAndCopy(binarySrcPath, binar
 func (scu *SystemdCreateUtilsImpl) ExecuteShellCommand(name string, arg []string) error {
 	return exec.Command(name, arg...).Run()
 }
+
+func (scu *SystemdCreateUtilsImpl) GetEnv() string {
+	return os.Getenv("HOME")
+}
diff --git a/components/docs-chef-io/content/automate/ha_backup_restore_file_system.md b/components/docs-chef-io/content/automate/ha_backup_restore_file_system.md
index 238c36870..7f2b50fbf 100644
--- a/components/docs-chef-io/content/automate/ha_backup_restore_file_system.md
+++ b/components/docs-chef-io/content/automate/ha_backup_restore_file_system.md
@@ -31,15 +31,11 @@ A shared file system is always required to create **OpenSearch** snapshots. To r
 
 #### Configuration in OpenSearch Node
 
-- Mount the shared file system on **all** OpenSearch and Frontend servers :
-
-    ```sh
-    mount /mnt/automate_backups
-    ```
+- Mount the shared file system to the base mount path which is mentioned in `backup_mount` on **all** OpenSearch and Frontend servers. 
 
 {{< note >}}
 
-- `/mnt/automate_backups` is the default value for the backup path, we can change it to any other value.
+- `/mnt/automate_backups` is the default value for the `backup_mount`, which is also used in this document page as reference backup path.
 
 {{< /note >}}
 
diff --git a/components/docs-chef-io/content/automate/ha_config.md b/components/docs-chef-io/content/automate/ha_config.md
index 5718041ea..0730cf2a8 100644
--- a/components/docs-chef-io/content/automate/ha_config.md
+++ b/components/docs-chef-io/content/automate/ha_config.md
@@ -22,7 +22,7 @@ gh_repo = "automate"
 
 {{< warning >}}
 
-- For certificate rotation, don't use `config patch`. Instead, the `cert-rotate` command can be used. To know more about certificate rotation, click [here](/automate/ha_cert_rotaion)
+- For certificate rotation, don't use `config patch`. Instead, the `cert-rotate` command can be used. To know more about certificate rotation, click [here](/automate/ha_cert_rotation)
 - While patching the same from **the provision host**, structures such as TLS from the OpenSearch configuration .toml file and SSL from the PostgreSQL configuration toml file will be ignored.
 
 {{< /warning >}}
diff --git a/components/docs-chef-io/content/automate/ha_existing_a2ha_to_automate_ha.md b/components/docs-chef-io/content/automate/ha_existing_a2ha_to_automate_ha.md
index f73649e76..67d982753 100644
--- a/components/docs-chef-io/content/automate/ha_existing_a2ha_to_automate_ha.md
+++ b/components/docs-chef-io/content/automate/ha_existing_a2ha_to_automate_ha.md
@@ -35,24 +35,23 @@ In order to verify the migration is completed successfully we'll need to capture
 
 Create `capture_infra_counts.sh` and run it using `./capture_infra_counts.sh > pre_migration_infra_counts.log`
 
-    ```bash
-    #!/usr/bin/bash
-
-    for i in `chef-server-ctl org-list`; do
-        org=https://localhost/organizations/$i
-        echo "Orgination: ${i}"
-        echo -n "node count: "
-        knife node list -s $org | wc -l
-        echo -n "client count: "
-        knife client list -s $org | wc -l
-        echo -n "cookbook count: "
-        knife cookbook list -s $org | wc -l
-        echo -n "total objects: "
-        knife list / -R -s $org | wc -l
-        echo "----------------"
-    done
-    ```
-
+```bash
+#!/usr/bin/bash
+
+for i in `chef-server-ctl org-list`; do
+    org=https://localhost/organizations/$i
+    echo "Orgination: ${i}"
+    echo -n "node count: "
+    knife node list -s $org | wc -l
+    echo -n "client count: "
+    knife client list -s $org | wc -l
+    echo -n "cookbook count: "
+    knife cookbook list -s $org | wc -l
+    echo -n "total objects: "
+    knife list / -R -s $org | wc -l
+    echo "----------------"
+done
+```
 
 ## Migration
 
@@ -78,7 +77,7 @@ Create `capture_infra_counts.sh` and run it using `./capture_infra_counts.sh > p
 
 1. Detach the File system from the old A2HA cluster.
 
-1. Configure the backup at Automate HA cluster. If you have not configured it, please refer to this [Doc: Pre Backup Configuration for File System Backup](/automate/ha_backup_restore_prerequisites/#pre-backup-configuration-for-file-system-backup)
+1. Configure the backup at Automate HA cluster. If you have not configured it, please refer to this [Doc: Pre Backup Configuration for File System Backup](/automate/ha_backup_restore_file_system/#setting-up-the-backup-configuration)
 
 1. From Step 3, you will get the backup mount path.
 
diff --git a/components/docs-chef-io/content/automate/ha_on_premises_deployment_prerequisites.md b/components/docs-chef-io/content/automate/ha_on_premises_deployment_prerequisites.md
index a89fdfbba..e7ba61560 100644
--- a/components/docs-chef-io/content/automate/ha_on_premises_deployment_prerequisites.md
+++ b/components/docs-chef-io/content/automate/ha_on_premises_deployment_prerequisites.md
@@ -192,7 +192,7 @@ The on-premises deployment specific pre-requisites are as follows:
 ### Cluster Setup
 
 - LoadBalancers should be set up according to [Chef Automate HA Architecture](/automate/ha/#chef-automate-ha-architecture/).
-- Network ports should be opened as per [Chef Automate HA Architecture](/automate/ha/#chef-automate-ha-architecture/) needs as explained in [Security and Firewall page](/automate/ha_security_firewall/).
+- Network ports should be opened as per [Chef Automate HA Architecture](/automate/ha/#chef-automate-ha-architecture/) needs as explained in [Security and Firewall page](/automate/ha_on_premises_deployment_prerequisites/#firewall-checks).
 - DNS is configured to redirect `chefautomate.example.com` to the Primary Load Balancer.
 - DNS is configured to redirect `chefinfraserver.example.com` to the Primary Load Balancer.
 - Domain Certificates should be created and added for `chefautomate.example.com`, and `chefinfraserver.example.com` in the Load Balancers.
diff --git a/lib/config/helper.go b/lib/config/helper.go
index 119417f98..47b193343 100644
--- a/lib/config/helper.go
+++ b/lib/config/helper.go
@@ -305,10 +305,13 @@ func validateCertsByIP(certsByIpList *[]CertByIP, nodeType string) error {
 		if checkIPAddress(element.IP) != nil {
 			errorList.PushBack(nodeType + " " + element.IP + " for certs is not valid")
 		}
-		errorList.PushBack(checkCertValid([]keydetails{
+		err := checkCertValid([]keydetails{
 			{key: element.PrivateKey, certtype: PRIVATE_KEY, svc: nodeType},
 			{key: element.PublicKey, certtype: PUBLIC_KEY, svc: nodeType},
-		}))
+		})
+		if err != nil {
+			errorList.PushBack(err)
+		}
 	}
 	return getSingleErrorFromList(errorList)
 }
diff --git a/lib/io/fileutils/fileutils.go b/lib/io/fileutils/fileutils.go
index 40dd21763..1e4a7660e 100644
--- a/lib/io/fileutils/fileutils.go
+++ b/lib/io/fileutils/fileutils.go
@@ -2,11 +2,13 @@ package fileutils
 
 import (
 	"bufio"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
+	"strconv"
 	"strings"
 
 	"github.com/pkg/errors"
@@ -35,6 +37,7 @@ type FileUtils interface {
 	DeleteFile(fileName string) error
 	Move(sourceFile string, destinationFile string) error
 	RemoveFirstLine(filePath string) error
+	GetFilePermission(filePath string) (int64, error)
 }
 
 type FileSystemUtils struct{}
@@ -84,6 +87,10 @@ func (fsu *FileSystemUtils) RemoveFirstLine(filePath string) error {
 	return RemoveFirstLine(filePath)
 }
 
+func (fsu *FileSystemUtils) GetFilePermission(filePath string) (int64, error) {
+	return GetFilePermission(filePath)
+}
+
 // LogCLose closes the given io.Closer, logging any error.
 func LogClose(c io.Closer, log logrus.FieldLogger, msg string) {
 	if err := c.Close(); err != nil {
@@ -280,3 +287,17 @@ func CreateTomlFileFromConfig(config interface{}, tomlFile string) (string, erro
 
 	return tomlFile, nil
 }
+
+func GetFilePermission(filePath string) (int64, error) {
+	info, err := os.Stat(filePath)
+	if err != nil {
+		return 0, errors.New("Unable to get the file on the path provided")
+	}
+	permissions := info.Mode().Perm()
+	perms := fmt.Sprintf("%04o", permissions)
+	testint, err := strconv.ParseInt(perms, 10, 32)
+	if err != nil {
+		return 0, errors.New("Error while parsing the file permission")
+	}
+	return testint, nil
+}
diff --git a/lib/io/fileutils/mockFileUtils.go b/lib/io/fileutils/mockFileUtils.go
index 45e47355c..1a512bc4c 100644
--- a/lib/io/fileutils/mockFileUtils.go
+++ b/lib/io/fileutils/mockFileUtils.go
@@ -18,6 +18,7 @@ type MockFileSystemUtils struct {
 	DeleteTempFileFunc         func(tempFile string) error
 	MoveFunc                   func(sourceFile string, destinationFile string) error
 	RemoveFirstLineFunc        func(filePath string) error
+	GetFilePermissionFunc      func(filePath string) (int64, error)
 }
 
 func (fsu *MockFileSystemUtils) PathExists(path string) (bool, error) {
@@ -59,3 +60,6 @@ func (fsu *MockFileSystemUtils) Move(sourceFile string, destinationFile string)
 func (fsu *MockFileSystemUtils) RemoveFirstLine(filePath string) error {
 	return fsu.RemoveFirstLineFunc(filePath)
 }
+func (fsu *MockFileSystemUtils) GetFilePermission(filePath string) (int64, error) {
+	return fsu.GetFilePermissionFunc(filePath)
+}
diff --git a/terraform/a2ha-terraform/destroy/aws/main.tf b/terraform/a2ha-terraform/destroy/aws/main.tf
index a5f6fa72a..1c798d826 100644
--- a/terraform/a2ha-terraform/destroy/aws/main.tf
+++ b/terraform/a2ha-terraform/destroy/aws/main.tf
@@ -1,17 +1,12 @@
-data "http" "getEc2PrivateIP" {
-  url = "http://169.254.169.254/latest/meta-data/local-ipv4"
-}
-
-locals {
-  json_data = "${join(".", [for i, s in split(".",data.http.getEc2PrivateIP.response_body) : (
-    i == 3 ? 0: s
-  )])}/26"
-}
 provider "aws" {
   region  = var.aws_region
   profile = var.aws_profile
 }
 
+module "aws_metadata" {
+  source     = "../../modules/aws_metadata"
+}
+
 module "aws" {
   ami_filter_name                 = var.ami_filter_name
   ami_filter_owner                = var.ami_filter_owner
@@ -58,7 +53,9 @@ module "aws" {
   lb_access_logs                  = var.lb_access_logs
   tags                            = var.aws_tags
   aws_instance_profile_name       = var.backup_config_s3 == "true" ? module.s3[0].instance_profile_name : null
-  json_data                          = local.json_data
+  json_data                       = module.aws_metadata.json_data
+
+  depends_on = [module.aws_metadata]
 }
 
 module "efs" {
diff --git a/terraform/a2ha-terraform/modules/automate/files/config.toml.erb b/terraform/a2ha-terraform/modules/automate/files/config.toml.erb
index bf89d3530..801d3db39 100644
--- a/terraform/a2ha-terraform/modules/automate/files/config.toml.erb
+++ b/terraform/a2ha-terraform/modules/automate/files/config.toml.erb
@@ -134,7 +134,7 @@
     [cs_nginx.v1.sys.ngx.http]
       ssl_verify_depth = 6
     [global.v1.external.automate.ssl]
-      server_name = "https://<%= overrides[:automate_fqdn] %>"
+      server_name = "<%= overrides[:automate_fqdn] %>"
       root_cert = """<%= overrides[:automate_root_ca] %>"""
   <% end %>
 <% else %>
diff --git a/terraform/a2ha-terraform/modules/aws/main.tf b/terraform/a2ha-terraform/modules/aws/main.tf
index b9530e482..36fe1a141 100644
--- a/terraform/a2ha-terraform/modules/aws/main.tf
+++ b/terraform/a2ha-terraform/modules/aws/main.tf
@@ -212,6 +212,11 @@ resource "aws_instance" "chef_automate_postgresql" {
       root_block_device
     ]
   }
+  metadata_options {
+    http_endpoint          = "enabled"
+    http_tokens            = "required"
+    instance_metadata_tags = "enabled"
+  }
   depends_on = [aws_route_table.route1,aws_route_table.route2,aws_route_table.route3]
 
 }
@@ -247,6 +252,11 @@ resource "aws_instance" "chef_automate_opensearch" {
       tags_all,
       root_block_device    ]
   }
+  metadata_options {
+    http_endpoint          = "enabled"
+    http_tokens            = "required"
+    instance_metadata_tags = "enabled"
+  }
   depends_on = [aws_route_table.route1,aws_route_table.route2,aws_route_table.route3]
 
 }
@@ -285,7 +295,11 @@ resource "aws_instance" "chef_automate" {
       root_block_device
     ]
   }
-
+  metadata_options {
+    http_endpoint          = "enabled"
+    http_tokens            = "required"
+    instance_metadata_tags = "enabled"
+  }
   depends_on = [aws_route_table.route1,aws_route_table.route2,aws_route_table.route3]
   
 }
@@ -325,7 +339,11 @@ resource "aws_instance" "chef_server" {
       root_block_device
     ]
   }
-  
+  metadata_options {
+    http_endpoint          = "enabled"
+    http_tokens            = "required"
+    instance_metadata_tags = "enabled"
+  }
   depends_on = [aws_route_table.route1,aws_route_table.route2,aws_route_table.route3]
 
 }
diff --git a/terraform/a2ha-terraform/modules/aws_metadata/main.tf b/terraform/a2ha-terraform/modules/aws_metadata/main.tf
new file mode 100644
index 000000000..411d5a67b
--- /dev/null
+++ b/terraform/a2ha-terraform/modules/aws_metadata/main.tf
@@ -0,0 +1,17 @@
+resource "null_resource" "generateMetadataToken" {
+  provisioner "local-exec" {
+    command = "echo `curl -X PUT http://169.254.169.254/latest/api/token -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'` > ${path.module}/metadata_token.txt"
+  }
+}
+
+data "local_file" "readToken" {
+  filename   = "${path.module}/metadata_token.txt"
+  depends_on = [null_resource.generateMetadataToken]
+}
+
+data "http" "getEc2PrivateIP" {
+  url = "http://169.254.169.254/latest/meta-data/local-ipv4"
+  request_headers = {
+    X-aws-ec2-metadata-token = chomp(data.local_file.readToken.content)
+  }
+}
diff --git a/terraform/a2ha-terraform/modules/aws_metadata/output.tf b/terraform/a2ha-terraform/modules/aws_metadata/output.tf
new file mode 100644
index 000000000..4209b78bb
--- /dev/null
+++ b/terraform/a2ha-terraform/modules/aws_metadata/output.tf
@@ -0,0 +1,3 @@
+output "json_data" {
+  value = "${data.http.getEc2PrivateIP.response_body}/32"
+}
diff --git a/terraform/a2ha-terraform/reference_architectures/aws/main.tf b/terraform/a2ha-terraform/reference_architectures/aws/main.tf
index 8dc89bb7b..b8ce743e1 100644
--- a/terraform/a2ha-terraform/reference_architectures/aws/main.tf
+++ b/terraform/a2ha-terraform/reference_architectures/aws/main.tf
@@ -1,15 +1,12 @@
-data "http" "getEc2PrivateIP" {
-  url = "http://169.254.169.254/latest/meta-data/local-ipv4"
-}
-
-locals {
-  json_data = "${data.http.getEc2PrivateIP.response_body}/32"
-}
 provider "aws" {
   region  = var.aws_region
   profile = var.aws_profile
 }
 
+module "aws_metadata" {
+  source = "./modules/aws_metadata"
+}
+
 module "aws" {
   ami_filter_name                    = var.ami_filter_name
   ami_filter_owner                   = var.ami_filter_owner
@@ -62,7 +59,9 @@ module "aws" {
   lb_access_logs                     = var.lb_access_logs
   tags                               = var.aws_tags
   aws_instance_profile_name          = var.backup_config_s3 == "true" ? module.s3[0].instance_profile_name : null
-  json_data                          = local.json_data
+  json_data                          = module.aws_metadata.json_data
+
+  depends_on = [module.aws_metadata]
 }
 
 module "efs" {


Test patch:
diff --git a/components/automate-cli/cmd/chef-automate/verify_test.go b/components/automate-cli/cmd/chef-automate/verify_test.go
index 8d077d1a6..5111625bf 100644
--- a/components/automate-cli/cmd/chef-automate/verify_test.go
+++ b/components/automate-cli/cmd/chef-automate/verify_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/chef/automate/lib/httputils"
 	"github.com/chef/automate/lib/majorupgrade_utils"
 	"github.com/chef/automate/lib/sshutils"
+	"github.com/chef/automate/lib/version"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -154,6 +155,121 @@ func TestRunVerifyCmd(t *testing.T) {
 
 }
 
+func TestGetHostIPsWithNoLatestCLI(t *testing.T) {
+	tests := []struct {
+		description           string
+		mockHttputils         *httputils.MockHTTPClient
+		mockHostIPs           []string
+		expectedIpsListLength int
+		BuildVersion          string
+		wantErr               error
+	}{
+
+		{
+			description: "remote with existing automate-verify - success",
+			mockHttputils: &httputils.MockHTTPClient{
+				MakeRequestFunc: func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
+					return &http.Response{
+							StatusCode: http.StatusOK,
+							Body:       nil,
+						}, []byte(`{
+							"status": "SUCCESS",
+							"result": {
+									"status": "OK",
+									"services": [],
+									"cli_version": "2023",
+									"error": "error getting services from hab svc status"
+							}
+					}`), nil
+				},
+			},
+			mockHostIPs:           []string{"10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4", "10.0.0.5"},
+			expectedIpsListLength: 0,
+			BuildVersion:          "2023",
+			wantErr:               nil,
+		},
+		{
+			description: "remote with some unreachable IP",
+			mockHttputils: &httputils.MockHTTPClient{
+				MakeRequestFunc: func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
+					if strings.Contains(url, "10.0.0.2") {
+						return nil, nil, errors.New("failed to make HTTP request")
+					}
+					return &http.Response{
+							StatusCode: http.StatusOK,
+							Body:       nil,
+						}, []byte(`{
+							"status": "SUCCESS",
+							"result": {
+									"status": "OK",
+									"services": [],
+									"cli_version": "2023",
+									"error": "error getting services from hab svc status"
+							}
+					}`), nil
+				},
+			},
+			mockHostIPs:           []string{"10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4", "10.0.0.5"},
+			expectedIpsListLength: 1,
+			BuildVersion:          "2023",
+			wantErr:               nil,
+		},
+		{
+			description: "remote with some of the machines have old cli version",
+			mockHttputils: &httputils.MockHTTPClient{
+				MakeRequestFunc: func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
+					if strings.Contains(url, "10.0.0.2") {
+						return &http.Response{
+								StatusCode: http.StatusOK,
+							}, []byte(`{
+							"status": "SUCCESS",
+							"result": {
+									"status": "OK",
+									"services": [],
+									"cli_version": "2022",
+									"error": "error getting services from hab svc status"
+							}
+					}`), nil
+					}
+					return &http.Response{
+							StatusCode: http.StatusOK,
+						}, []byte(`{
+							"status": "SUCCESS",
+							"result": {
+									"status": "OK",
+									"services": [],
+									"cli_version": "2023",
+									"error": "error getting services from hab svc status"
+							}
+					}`), nil
+				},
+			},
+			mockHostIPs:           []string{"10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4", "10.0.0.5"},
+			expectedIpsListLength: 1,
+			BuildVersion:          "2023",
+			wantErr:               nil,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			version.BuildTime = tt.BuildVersion
+			cw := majorupgrade_utils.NewCustomWriter()
+
+			vc := newMockVerifyCmdFlow(tt.mockHttputils, cw)
+
+			hostIpsList, err := vc.getHostIPsWithNoLatestCLI(tt.mockHostIPs)
+			if tt.wantErr != nil {
+				assert.Error(t, err)
+				assert.ErrorContains(t, err, tt.wantErr.Error())
+			} else {
+				assert.NoError(t, err)
+				assert.Equal(t, tt.expectedIpsListLength, len(hostIpsList))
+			}
+		})
+	}
+}
+
 func TestVerifyCmdFunc(t *testing.T) {
 	flagsObj := &verifyCmdFlags{
 		config: CONFIG_TOML_PATH + CONFIG_FILE,
@@ -167,3 +283,43 @@ func TestVerifyCmdFunc(t *testing.T) {
 	assert.Error(t, err)
 	assert.ErrorContains(t, err, "Cannot create automate-verify service since systemd is not present on this machine")
 }
+
+func newMockVerifyCmdFlow(mockHttputils *httputils.MockHTTPClient, cw *majorupgrade_utils.CustomWriter) *verifyCmdFlow {
+
+	mockCreateSystemdService := &verifysystemdcreate.MockCreateSystemdService{
+		CreateFun: func() error {
+			return nil
+		},
+	}
+	mockSystemdCreateUtils := &verifysystemdcreate.MockSystemdCreateUtils{
+		GetBinaryPathFunc: func() (string, error) {
+			return "", nil
+		},
+	}
+	mockSSHUtil := &sshutils.MockSSHUtilsImpl{
+		ExecuteConcurrentlyFunc: func(sshConfig sshutils.SSHConfig, cmd string, hostIPs []string) []sshutils.Result {
+			return []sshutils.Result{
+				{
+					HostIP: "",
+					Error:  nil,
+					Output: "",
+				},
+			}
+		},
+		CopyFileToRemoteConcurrentlyFunc: func(sshConfig sshutils.SSHConfig, srcFilePath string, destFileName string, removeFile bool, hostIPs []string) []sshutils.Result {
+			return []sshutils.Result{
+				{
+					HostIP: "",
+					Error:  nil,
+					Output: "",
+				},
+			}
+		},
+	}
+	return NewVerifyCmdFlow(mockHttputils,
+		mockCreateSystemdService,
+		mockSystemdCreateUtils,
+		config.NewHaDeployConfig(),
+		mockSSHUtil,
+		cw.CliWriter)
+}
diff --git a/components/automate-cli/pkg/verifyserver/models/batchcheck_test.go b/components/automate-cli/pkg/verifyserver/models/batchcheck_test.go
index 72b3652ce..cfdd053dd 100644
--- a/components/automate-cli/pkg/verifyserver/models/batchcheck_test.go
+++ b/components/automate-cli/pkg/verifyserver/models/batchcheck_test.go
@@ -173,7 +173,7 @@ var (
 )
 
 func TestAppendCertsByIpToNodeCerts(t *testing.T) {
-	// // Test case 1: certsByIP is nil, ipList is not empty
+	// Test case 1: certsByIP is nil, ipList is not empty
 	ipList := []string{"192.168.0.3", "192.168.0.4"}
 	privateKey := "private_key"
 	publicKey := "public_key"
@@ -271,6 +271,54 @@ func TestAppendCertsByIpToNodeCerts(t *testing.T) {
 			t.Errorf("Test case 2 failed: Expected node %+v not found in the result.", expectedNode)
 		}
 	}
+
+	//Test case 3: certsByIP is not nil, ipList is not nil
+	certByIps = []config.CertByIP{
+		{
+			IP:         "1.1.1.1",
+			PrivateKey: "private1",
+			PublicKey:  "public1",
+		},
+		{
+			IP:         "1.1.1.2",
+			PrivateKey: "private1",
+			PublicKey:  "public1",
+		},
+	}
+	ipList = []string{"1.1.1.1", "1.1.1.2"}
+	privateKey = "private_key"
+	publicKey = "public_key"
+	adminKey = "admin_key"
+	adminCert = "admin_cert"
+
+	actual = appendCertsByIpToNodeCerts(&certByIps, ipList, privateKey, publicKey, adminKey, adminCert, "")
+
+	expected = []*NodeCert{
+		{
+			IP:        "1.1.1.1",
+			Key:       "private1",
+			Cert:      "public1",
+			AdminKey:  "admin_key",
+			AdminCert: "admin_cert",
+			RootCert:  "",
+		},
+		{
+			IP:        "1.1.1.2",
+			Key:       "private1",
+			Cert:      "public1",
+			AdminKey:  "admin_key",
+			AdminCert: "admin_cert",
+			RootCert:  "",
+		},
+	}
+
+	//Check if each expected element exists in the actual result
+	for _, expectedNode := range expected {
+		found := containsElement(actual, expectedNode)
+		if !found {
+			t.Errorf("Test case 4 failed: Expected node %+v not found in the result.", expectedNode)
+		}
+	}
 }
 
 func containsElement(nodes []*NodeCert, targetNode *NodeCert) bool {
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/firewall_test.go b/components/automate-cli/pkg/verifyserver/server/api/v1/firewall_test.go
index 718257ffc..206c399c6 100644
--- a/components/automate-cli/pkg/verifyserver/server/api/v1/firewall_test.go
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/firewall_test.go
@@ -193,24 +193,6 @@ func TestFirewallCheck(t *testing.T) {
 				}
 			}`,
 		},
-		{
-			TestName: "Using HTTPS protocol but not giving root_ca",
-			RequestBody: `{
-				"source_node_ip": "15.237.128.20",
-				"destination_node_ip": "13.39.148.115",
-				"destination_service_port": "7432",
-				"destination_service_protocol": "https"
-			  }`,
-			ExpectedCode: 400,
-			ExpectedBody: `{
-				"status": "FAILED",
-				"result": null,
-				"error": {
-					"code": 400,
-					"message": "root_cert value is mandatory for protocol https"
-				}
-			}`,
-		},
 		{
 			TestName: "Giving Invalid Protocol",
 			RequestBody: `{
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable_test.go b/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable_test.go
index 8c53c9429..d8e8dfc62 100644
--- a/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable_test.go
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/portreachable_test.go
@@ -111,23 +111,6 @@ func TestPortReachable(t *testing.T) {
 				"destination_node_service_protocol": "udp"
 			  }`,
 		},
-		{
-			TestName:     "Not Given the rootCA while using HTTPS Protocol",
-			ExpectedCode: 400,
-			ExpectedBody: `{
-				"status": "FAILED",
-				"result": null,
-				"error": {
-					"code": 400,
-					"message": "RootCA value is mandatory for protocol HTTPS"
-				}
-			}`,
-			RequestBody: `{
-				"destination_node_ip": "13.37.23.16",
-				"destination_node_port": 443,
-				"destination_node_service_protocol": "https"
-			  }`,
-		},
 		{
 			TestName:     "Giving Invalid Protocol Type",
 			ExpectedCode: 400,
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice_test.go
index 824cb24b1..93887e355 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/batchcheckservice_test.go
@@ -1143,3 +1143,50 @@ func TestConstructResult(t *testing.T) {
 	assert.Empty(t, result[0].Tests)
 	assert.Len(t, result, 1)
 }
+
+func TestBastionBatchChecks(t *testing.T) {
+	ss := NewBatchCheckService(trigger.NewCheckTrigger(SetupMockHardwareResourceCountCheck([]models.CheckTriggerResponse{
+		{
+			Status:   "Passed",
+			Host:     "1.2.3.4",
+			NodeType: "automate",
+			Result: models.ApiResult{
+				Passed: false,
+				Checks: []models.Checks{
+					{
+						Title: "hardware-resource-count-check-1",
+					},
+					{
+						Title: "hardware-resource-count-check-2",
+					},
+				},
+			},
+		},
+	}),
+		SetupMockSshUserAccessCheck(nil),
+		SetupMockCertificateCheck(),
+		SetupMockExternalOpenSearchCheck(nil),
+		SetupMockExternalPostgresCheck(nil),
+		SetupMockFirewallCheck(),
+		SetupMockFqdnCheck(),
+		SetupMockNfsBackupConfigCheck(),
+		SetupMockOpenSearchS3BucketAccessCheck(),
+		SetupMockS3BackupConfigCheck(),
+		SetupMockSoftwareVersionCheck(),
+		SetupMockSystemResourceCheck(),
+		SetupMockSystemUserCheck(),
+	), logger.NewTestLogger(), "1234")
+
+	checksToExecute := []string{
+		constants.HARDWARE_RESOURCE_COUNT,
+	}
+	resp, err := ss.BatchCheck(checksToExecute, &models.Config{
+		Hardware: &models.Hardware{
+			AutomateNodeCount:        1,
+			AutomateNodeIps:          []string{"1.2.3.4"},
+		},
+	})
+	assert.Equal(t, nil, err)
+	assert.Equal(t, false, resp.Passed)
+	assert.Equal(t, "{\"node_type\":\"automate\",\"ip\":\"1.2.3.4\",\"tests\":[{\"passed\":false,\"msg\":\"Hardware Resource Count Check\",\"check\":\"hardware-resource-count\",\"checks\":[{\"title\":\"hardware-resource-count-check-1\",\"passed\":false,\"success_msg\":\"\",\"error_msg\":\"\",\"resolution_msg\":\"\",\"skipped\":false},{\"title\":\"hardware-resource-count-check-2\",\"passed\":false,\"success_msg\":\"\",\"error_msg\":\"\",\"resolution_msg\":\"\",\"skipped\":false}],\"skipped\":false}]}", getResponseForIp(resp.NodeResult, "1.2.3.4", "automate"))
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger_test.go
index fd2935fab..8c6ba9f50 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/certificatechecktrigger/certificatechecktrigger_test.go
@@ -602,6 +602,41 @@ func TestCertificateCheck_Run(t *testing.T) {
 
 	})
 
+	t.Run("Nodes Empty", func(t *testing.T) {
+		config := &models.Config{
+			Hardware: &models.Hardware{
+				AutomateNodeCount:        1,
+				AutomateNodeIps:          []string{"12.12.1.2"},
+				ChefInfraServerNodeCount: 1,
+				ChefInfraServerNodeIps:   []string{"12.12.1.3"},
+				PostgresqlNodeCount:      1,
+				PostgresqlNodeIps:        []string{"12.12.1.4"},
+				OpenSearchNodeCount:      1,
+				OpenSearchNodeIps:        []string{"12.12.1.5"},
+			},
+			Certificate: []*models.Certificate{
+				{
+					Fqdn:         "example.com",
+					FqdnRootCert: "root_ca",
+					NodeType:     constants.AUTOMATE,
+					Nodes:        []*models.NodeCert{},
+				},
+			},
+		}
+
+		suc := NewCertificateCheck(logger.NewLogrusStandardLogger(), "8080")
+		ctr := suc.Run(config)
+
+		require.Len(t, ctr, 1)
+
+		for _, v := range ctr {
+			require.Equal(t, constants.CERTIFICATE, v.Result.Check)
+			assert.NotEmpty(t, v.Host)
+			require.True(t, v.Result.Skipped)
+		}
+
+	})
+
 }
 
 func TestGetPortsForMockServer(t *testing.T) {
@@ -610,3 +645,56 @@ func TestGetPortsForMockServer(t *testing.T) {
 
 	assert.Equal(t, 0, len(resp))
 }
+
+func Test_skipCertificateForAutomateAndChefServerNodes(t *testing.T) {
+	type args struct {
+		nodeType    string
+		hardwareMap map[string][]string
+	}
+	tests := []struct {
+		name string
+		args args
+		want []models.CheckTriggerResponse
+	}{{
+		name: "Check response for automate nodes",
+		args: args{
+			nodeType: constants.AUTOMATE,
+			hardwareMap: map[string][]string{
+				"test_ip":  {constants.AUTOMATE},
+				"test_ip2": {constants.AUTOMATE},
+			},
+		},
+		want: []models.CheckTriggerResponse{
+			{
+				Host:      "test_ip",
+				NodeType:  constants.AUTOMATE,
+				CheckType: constants.CERTIFICATE,
+				Result: models.ApiResult{
+					Skipped: true,
+					Passed:  false,
+					Check:   constants.CERTIFICATE,
+				},
+			}, {
+				Host:      "test_ip2",
+				NodeType:  constants.AUTOMATE,
+				CheckType: constants.CERTIFICATE,
+				Result: models.ApiResult{
+					Skipped: true,
+					Passed:  false,
+					Check:   constants.CERTIFICATE,
+				},
+			},
+		},
+	},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := skipCertificateForAutomateAndChefServerNodes(tt.args.nodeType, tt.args.hardwareMap)
+			assert.Equal(t, len(tt.want), len(got))
+			for _, w := range tt.want {
+				assert.Contains(t, got, w)
+			}
+
+		})
+	}
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchchecktrigger_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchchecktrigger_test.go
index 5caabc878..99fbea889 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchchecktrigger_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/externalopensearchchecktrigger/externalopensearchchecktrigger_test.go
@@ -216,14 +216,13 @@ const (
 	oSRoleArn      = "arn:aws:iam::123456789012:role/MyRole"
 )
 
-func getRequest() models.ExternalOS {
-	return models.ExternalOS{
+func getRequest() models.ExternalOSRequest {
+	return models.ExternalOSRequest{
 		OSDomainName:   osDomainName,
 		OSDomainURL:    osDomainURL,
 		OSUsername:     osUsername,
 		OSUserPassword: osUserPassword,
 		OSCert:         osCert,
-		OSRoleArn:      "",
 	}
 
 }
@@ -351,8 +350,7 @@ func TestOpensearchCheck_Run(t *testing.T) {
 						OSDomainURL:    osDomainURL,
 						OSUsername:     osUsername,
 						OSUserPassword: osUserPassword,
-						OSCert:         osCert,
-						OSRoleArn:      "",
+						OSCert:         "",
 					},
 				},
 			},
@@ -526,7 +524,7 @@ func TestForChefserverOpensearch(t *testing.T) {
 func createDummyServer(t *testing.T, requiredStatusCode int, isPassed bool) (*httptest.Server, string, string) {
 	if requiredStatusCode == http.StatusOK {
 		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			var got models.ExternalOS
+			var got models.ExternalOSRequest
 			req := r.Body
 			reader, _ := io.ReadAll(req)
 			json.Unmarshal(reader, &got)
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger_test.go
index 93173750a..f5b06fa8a 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/firewallchecktrigger/firewallchecktrigger_test.go
@@ -103,86 +103,13 @@ const (
 						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
 						"error_msg": "",
 						"resolution_msg": ""
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": true,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port from the source node",
-						"passed": true,
-						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
-						"error_msg": "",
-						"resolution_msg": ""
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": true,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port from the source node",
-						"passed": true,
-						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
-						"error_msg": "",
-						"resolution_msg": ""
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": true,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port from the source node",
-						"passed": true,
-						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
-						"error_msg": "",
-						"resolution_msg": ""
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": true,
-				"checks": [
-					{
+					},{
 						"title": "Check for reachability of service at destination port from the source node",
 						"passed": true,
 						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
 						"error_msg": "",
 						"resolution_msg": ""
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": true,
-				"checks": [
-					{
+					},{
 						"title": "Check for reachability of service at destination port from the source node",
 						"passed": true,
 						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
@@ -191,24 +118,7 @@ const (
 					}
 				]
 			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": true,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port from the source node",
-						"passed": true,
-						"success_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is reachable fro <source_node_ip>",
-						"error_msg": "",
-						"resolution_msg": ""
-					}
-				]
-			}
-		}
+		}		
 	]
 	 `
 
@@ -243,103 +153,13 @@ const (
 						"success_msg": "",
 						"error_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is not reachable from <source_ip>",
 						"resolution_msg": "Check your firewall settings to provide access to <destination_node_port> port at <destination_node_ip> from <source_node_ip>"
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": false,
-				"checks": [
-					{
+					},{
 						"title": "Check for reachability of service at destination port",
 						"passed": false,
 						"success_msg": "",
 						"error_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is not reachable from <source_ip>",
 						"resolution_msg": "Check your firewall settings to provide access to <destination_node_port> port at <destination_node_ip> from <source_node_ip>"
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": false,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port",
-						"passed": false,
-						"success_msg": "",
-						"error_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is not reachable from <source_ip>",
-						"resolution_msg": "Check your firewall settings to provide access to <destination_node_port> port at <destination_node_ip> from <source_node_ip>"
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": false,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port",
-						"passed": false,
-						"success_msg": "",
-						"error_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is not reachable from <source_ip>",
-						"resolution_msg": "Check your firewall settings to provide access to <destination_node_port> port at <destination_node_ip> from <source_node_ip>"
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": false,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port",
-						"passed": false,
-						"success_msg": "",
-						"error_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is not reachable from <source_ip>",
-						"resolution_msg": "Check your firewall settings to provide access to <destination_node_port> port at <destination_node_ip> from <source_node_ip>"
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": false,
-				"checks": [
-					{
-						"title": "Check for reachability of service at destination port",
-						"passed": false,
-						"success_msg": "",
-						"error_msg": "The <protocol> service running at <destination_node_ip>:<destination_node_port> is not reachable from <source_ip>",
-						"resolution_msg": "Check your firewall settings to provide access to <destination_node_port> port at <destination_node_ip> from <source_node_ip>"
-					}
-				]
-			}
-		},
-		{
-			"status": "SUCCESS",
-			"host": "127.0.0.1",
-			"node_type": "bastion",
-			"result": {
-				"passed": false,
-				"checks": [
-					{
+					},{
 						"title": "Check for reachability of service at destination port",
 						"passed": false,
 						"success_msg": "",
@@ -413,16 +233,20 @@ func TestMakeRequests(t *testing.T) {
 
 	requestsForchefServer, ok := mapRequests[constants.CHEF_INFRA_SERVER]
 	assert.True(t, ok)
-	assert.Equal(t, len(requestsForchefServer), 6)
+	assert.Equal(t, 4, len(requestsForchefServer))
 
 	//As there are two postgress nodes which needs to interact with eachother
 	requestsForPostgres, ok := mapRequests[constants.POSTGRESQL]
 	assert.True(t, ok)
-	assert.Equal(t, len(requestsForPostgres), 12)
+	assert.Equal(t, len(requestsForPostgres), 10)
 
 	requestsForOpensearch, ok := mapRequests[constants.OPENSEARCH]
 	assert.True(t, ok)
-	assert.Equal(t, len(requestsForOpensearch), 10)
+	assert.Equal(t, len(requestsForOpensearch), 8)
+
+	requestsForBastion, ok := mapRequests[constants.BASTION]
+	assert.True(t, ok)
+	assert.Equal(t, len(requestsForBastion), 11)
 
 	require.Equal(t, expected[0].SourceNodeIP, requestsForautomate[0].SourceNodeIP)
 	require.Equal(t, expected[0].DestinationNodeIP, requestsForautomate[0].DestinationNodeIP)
@@ -644,12 +468,8 @@ func TestGetPortsForMockServer(t *testing.T) {
 	resp := fwc.GetPortsForMockServer()
 
 	assert.Equal(t, 4, len(resp))
-	assert.Equal(t, 2, len(resp["automate"]["tcp"]))
-	assert.Equal(t, 1, len(resp["automate"]["https"]))
-	assert.Equal(t, 2, len(resp["chef-infra-server"]["tcp"]))
-	assert.Equal(t, 1, len(resp["chef-infra-server"]["https"]))
-	assert.Equal(t, 5, len(resp["postgresql"]["tcp"]))
+	assert.Equal(t, 4, len(resp["postgresql"]["tcp"]))
 	assert.Equal(t, 1, len(resp["postgresql"]["udp"]))
-	assert.Equal(t, 4, len(resp["opensearch"]["tcp"]))
+	assert.Equal(t, 3, len(resp["opensearch"]["tcp"]))
 	assert.Equal(t, true, true)
 }
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger_test.go
index 9c0bb2dc8..d92f3362a 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger/sshuseraccesschecktrigger_test.go
@@ -11,7 +11,9 @@ import (
 
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/constants"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
+	"github.com/chef/automate/lib/io/fileutils"
 	"github.com/chef/automate/lib/logger"
+	"github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -76,12 +78,12 @@ func GetRequestJson() *models.Config {
 	json.Unmarshal([]byte(`{
 		"ssh_user": {
 			"user_name": "ubuntu",
-            "ssh_port": "1234",
-            "private_key": "test_key",
-            "sudo_password": "test@123"
-		},
-		"arch": "existing_nodes",
-		"backup": {
+			"private_key": "test_key",
+			"ssh_port":"22",
+			"sudo_password": "test@123"
+		  },
+		  "arch": "existing_nodes",
+		  "backup": {
 			"file_system": {
 				"mount_location": "/mnt/automate_backups"
 			}
@@ -154,7 +156,7 @@ func startMockServerOnCustomPort(mockServer *httptest.Server, port string) error
 
 func TestNewSshUserAccessCheck(t *testing.T) {
 	testPort := "1234"
-	cc := NewSshUserAccessCheck(logger.NewTestLogger(), testPort)
+	cc := NewSshUserAccessCheck(logger.NewTestLogger(), &fileutils.FileSystemUtils{}, testPort)
 	assert.NotNil(t, cc)
 	assert.NotNil(t, cc.log)
 	assert.Equal(t, constants.LOCAL_HOST_URL, cc.host)
@@ -184,7 +186,15 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 		assert.NoError(t, err)
 		defer mockServer.Close()
 
-		cc := NewSshUserAccessCheck(logger.NewTestLogger(), "1124")
+		cc := NewSshUserAccessCheck(logger.NewTestLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400, nil
+			},
+		}, "1124")
+
 		finalResp := cc.Run(request)
 		totalIps := request.Hardware.AutomateNodeCount + request.Hardware.ChefInfraServerNodeCount + request.Hardware.PostgresqlNodeCount + request.Hardware.OpenSearchNodeCount
 		assert.Equal(t, totalIps, len(finalResp))
@@ -208,6 +218,50 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 		}
 	})
 
+	t.Run("Returns Error if file reading fails", func(t *testing.T) {
+		request := GetRequestJson()
+		//starting the mock server on custom port
+		mockServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			req := r.Body
+			//not handling error because of test file
+			reader, _ := io.ReadAll(req)
+			var actualRequest models.SShUserRequest
+			json.Unmarshal([]byte(reader), &actualRequest)
+
+			sshRequest := GetSshRequest()
+			assert.NotNil(t, actualRequest)
+			assert.Equal(t, actualRequest.PrivateKey, sshRequest.PrivateKey)
+			assert.Equal(t, actualRequest.Username, sshRequest.Username)
+			assert.Equal(t, actualRequest.SudoPassword, sshRequest.SudoPassword)
+			w.WriteHeader(http.StatusOK)
+			w.Write([]byte(sshCheckSuccessResp))
+		}))
+		err := startMockServerOnCustomPort(mockServer, "1124")
+		assert.NoError(t, err)
+		defer mockServer.Close()
+
+		cc := NewSshUserAccessCheck(logger.NewTestLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte(""), errors.New("open test.pem: no such file or directory")
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400, nil
+			},
+		}, "1124")
+		finalResp := cc.Run(request)
+		totalIps := request.Hardware.AutomateNodeCount + request.Hardware.ChefInfraServerNodeCount + request.Hardware.PostgresqlNodeCount + request.Hardware.OpenSearchNodeCount
+		assert.Equal(t, totalIps, len(finalResp))
+
+		for _, resp := range finalResp {
+			if resp.Host == "14.15.16.17" {
+				triggerResp := resp
+				assert.Equal(t, triggerResp.Result.Skipped, false)
+				assert.Equal(t, triggerResp.Result.Passed, false)
+				assert.Equal(t, triggerResp.Result.Error.Code, 400)
+				assert.Equal(t, triggerResp.Result.Error.Message, "open test.pem: no such file or directory")
+			}
+		}
+	})
 	t.Run("Failure response", func(t *testing.T) {
 		//starting the mock server on custom port
 		mockServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -229,7 +283,14 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 		assert.NoError(t, err)
 		defer mockServer.Close()
 
-		cc := NewSshUserAccessCheck(logger.NewTestLogger(), "1235")
+		cc := NewSshUserAccessCheck(logger.NewTestLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400, nil
+			},
+		}, "1235")
 		request := GetRequestJson()
 		finalResp := cc.Run(request)
 		totalIps := request.Hardware.AutomateNodeCount + request.Hardware.ChefInfraServerNodeCount + request.Hardware.PostgresqlNodeCount + request.Hardware.OpenSearchNodeCount
@@ -255,7 +316,6 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 			}
 		}
 	})
-
 	t.Run("Returns error", func(t *testing.T) {
 		mockServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			w.WriteHeader(http.StatusOK)
@@ -265,7 +325,14 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 		assert.NoError(t, err)
 		defer mockServer.Close()
 
-		cc := NewSshUserAccessCheck(logger.NewTestLogger(), "1236")
+		cc := NewSshUserAccessCheck(logger.NewTestLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400, nil
+			},
+		}, "1236")
 		request := GetRequestJson()
 		finalResp := cc.Run(request)
 		totalIps := request.Hardware.AutomateNodeCount + request.Hardware.ChefInfraServerNodeCount + request.Hardware.PostgresqlNodeCount + request.Hardware.OpenSearchNodeCount
@@ -284,7 +351,14 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 			ExternalOS: nil,
 		}
 
-		newOS := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), "8080")
+		newOS := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400 , nil
+			},
+		}, "8080")
 		got := newOS.Run(config)
 		assert.Len(t, got, 4)
 		assert.Equal(t, constants.UNKNOWN_HOST, got[0].Host)
@@ -307,7 +381,7 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 			SSHUser: nil,
 		}
 
-		newOS := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), "8080")
+		newOS := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.FileSystemUtils{}, "8080")
 		got := newOS.Run(config)
 		assert.Len(t, got, 4)
 		for _, v := range got {
@@ -332,7 +406,7 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 			SSHUser: &models.SSHUser{},
 		}
 
-		newOS := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), "8080")
+		newOS := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.FileSystemUtils{}, "8080")
 		got := newOS.Run(config)
 		assert.Len(t, got, 4)
 		for _, v := range got {
@@ -346,29 +420,83 @@ func TestSshUserAccessCheck_Run(t *testing.T) {
 }
 
 func TestGetSShUserAPIRquest(t *testing.T) {
-	ip := "1.2.3.4"
-
-	expected := GetSshRequest()
 
-	actual := getSShUserAPIRquest(ip, GetRequestJson().SSHUser)
+	t.Run("Fail to get FilePermission", func(t *testing.T) {
+		fwc := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 0, errors.New("Unable to get the file on the path provided")
+			},
+		}, "1234")
+		ip := "1.2.3.4"
+		expected, err := models.SShUserRequest{}, errors.New("Unable to get the file on the path provided")
+		actual, actualerr := fwc.getSShUserAPIRequest(ip, GetRequestJson().SSHUser)
+		assert.Equal(t, expected, actual)
+		assert.Equal(t, err.Error(), actualerr.Error())
+	})
 
-	assert.Equal(t, expected, actual)
+	t.Run("Permission is greater the 400", func(t *testing.T) {
+		fwc := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 700, nil
+			},
+		}, "1234")
+		ip := "1.2.3.4"
+		expected, err := models.SShUserRequest{}, errors.New("Permissions on the ssh key file do not satisfy the requirement")
+		actual, actualerr := fwc.getSShUserAPIRequest(ip, GetRequestJson().SSHUser)
+		assert.Equal(t, expected, actual)
+		assert.Equal(t, err.Error(), actualerr.Error())
+	})
+	t.Run("Reading was successfull", func(t *testing.T) {
+		fwc := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte("test_key"), nil
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400, nil
+			},
+		}, "1234")
+		ip := "1.2.3.4"
+		expected := GetSshRequest()
+		actual, _ := fwc.getSShUserAPIRequest(ip, GetRequestJson().SSHUser)
+		assert.Equal(t, expected, actual)
+	})
 
+	t.Run("Reading was unsuccessfull", func(t *testing.T) {
+		fwc := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.MockFileSystemUtils{
+			ReadFileFunc: func(filepath string) ([]byte, error) {
+				return []byte(""), errors.New("open test.pem: no such file or directory")
+			},
+			GetFilePermissionFunc: func(filePath string) (int64, error) {
+				return 400, nil
+			},
+		}, "1234")
+		ip := "1.2.3.4"
+		expected, err := models.SShUserRequest{}, errors.New("open test.pem: no such file or directory")
+		got, gotErr := fwc.getSShUserAPIRequest(ip, GetRequestJson().SSHUser)
+		assert.Equal(t, expected, got)
+		assert.Equal(t, err.Error(), gotErr.Error())
+	})
 }
 
 func GetSshRequest() models.SShUserRequest {
 	request := models.SShUserRequest{
 		IP:           "1.2.3.4",
 		Username:     "ubuntu",
-		PrivateKey:   "test_key",
+		Port:         "22",
 		SudoPassword: "test@123",
-		Port:         "1234",
+		PrivateKey:   "test_key",
 	}
 	return request
 }
 
 func TestGetPortsForMockServer(t *testing.T) {
-	fwc := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), "1234")
+	fwc := NewSshUserAccessCheck(logger.NewLogrusStandardLogger(), &fileutils.FileSystemUtils{}, "1234")
 	resp := fwc.GetPortsForMockServer()
 
 	assert.Equal(t, 0, len(resp))
diff --git a/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable_test.go b/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable_test.go
index 185559d0f..f13b4ad6a 100644
--- a/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/portreachableservice/portreachable_test.go
@@ -388,6 +388,21 @@ func TestGetPortReachableDetails(t *testing.T) {
 				ResolutionMsg: "",
 			},
 		},
+		{
+			"HTTPS Server connection without root ca",
+			models.PortReachableRequest{
+				DestinationNodeIp:              LOCALHOST,
+				DestinationNodePort:            httpsTestPort,
+				DestinationNodeServiceProtocol: constants.HTTPS,
+			},
+			models.Checks{
+				Title:         constants.PORT_REACHABLE,
+				Passed:        true,
+				SuccessMsg:    fmt.Sprintf(constants.PORT_REACHABLE_SUCCESS_MSG, constants.HTTPS, LOCALHOST, httpsTestPort),
+				ErrorMsg:      "",
+				ResolutionMsg: "",
+			},
+		},
 		{
 			"HTTPS Server running there but giving different server rootCA",
 			models.PortReachableRequest{
diff --git a/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc_test.go b/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc_test.go
index 08358e07d..f2e8580f4 100644
--- a/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc_test.go
+++ b/components/automate-cli/pkg/verifysystemdcreate/systemdcreatesvc_test.go
@@ -64,6 +64,7 @@ func TestSystemdServiceCreate(t *testing.T) {
 			SystemdRunningFunc:           func() error { return nil },
 			CreateDestinationAndCopyFunc: createDestinationAndCopy,
 			ExecuteShellCommandFunc:      executeShellCommand,
+			GetEnvFunc:                   func() string { return "/home/ubuntu" },
 		}
 	}
 
@@ -192,7 +193,7 @@ ExecStart=%s/chef-automate verify serve
 Restart=always
 StandardOutput=journal
 StandardError=journal
-
+Environment="HOME=/home/ubuntu"
 [Install]
 WantedBy=multi-user.target
 `
diff --git a/lib/io/fileutils/fileutils_test.go b/lib/io/fileutils/fileutils_test.go
index 964a7ac8b..d0c16efa8 100644
--- a/lib/io/fileutils/fileutils_test.go
+++ b/lib/io/fileutils/fileutils_test.go
@@ -8,6 +8,7 @@ import (
 	"path/filepath"
 	"testing"
 
+	"github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
@@ -201,3 +202,26 @@ Age = 30
 		require.Error(t, err, "Failed to encode")
 	})
 }
+
+func TestGetFilePermission(t *testing.T) {
+	t.Run("Permission Was Successfully Recevied", func(t *testing.T) {
+		tempdir := t.TempDir()
+
+		testData := []byte("test data")
+		filePath := path.Join(tempdir, "file")
+		ioutil.WriteFile(filePath, testData, 0400)
+		res, err := fileutils.GetFilePermission(filePath)
+		assert.NoError(t, err)
+		assert.Equal(t, res, int64(400))
+	})
+
+	t.Run("Unable to get the filepath", func(t *testing.T) {
+		testData := []byte("test data")
+		filePath := path.Join("ssh", "file")
+		ioutil.WriteFile(filePath, testData, 0400)
+		got, gotErr := fileutils.GetFilePermission(filePath)
+		want, wantErr := int64(0), errors.New("Unable to get the file on the path provided")
+		assert.Equal(t, want, got)
+		assert.Equal(t, wantErr.Error(), gotErr.Error())
+	})
+}