Repository: chef/automate
Pull request #7920 (2023-05-26 09:45:40)

update to san_validator
### :nut_and_bolt: Description: What code changed, and why?

<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

### :chains: Related Resources

### :+1: Definition of Done

### :athletic_shoe: How to Build and Test the Change

### :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:

- [ ] Tests added/updated? (all new code needs new tests)
- [ ] Docs added/updated? (all customer-facing changes)

*Please add a note next to any checkbox above if you are NOT ticking it.*

### :camera: Screenshots, if applicable


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


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 60635383f3495e262fb3dfb42f613977f27290b3 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/chef-automate/deploys/64707fc639bfe00008b313b6 |
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=7920)

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

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


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

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

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



Patch:
diff --git a/.bldr.toml b/.bldr.toml
index 5f3d1df6a..29319dd3d 100644
--- a/.bldr.toml
+++ b/.bldr.toml
@@ -442,6 +442,7 @@ paths = [
   "lib/config/*",
   "lib/config_parser/*",
   "lib/db/*",
+  "lib/executil/*",
   "lib/grpc/*",
   "lib/httputils/*",
   "lib/io/*",
@@ -460,6 +461,7 @@ paths = [
   "lib/tls/*",
   "lib/tracing/*",
   "lib/user/*",
+  "lib/userutils/*",
   "lib/uuid4/*",
   "lib/verification/*",
   "lib/version/*"
diff --git a/VERSION b/VERSION
index b6b64bf82..da8326116 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.7.25
\ No newline at end of file
+4.7.27
\ No newline at end of file
diff --git a/components/automate-cli/pkg/verifyserver/constants/externalpostgresqlconstants.go b/components/automate-cli/pkg/verifyserver/constants/externalpostgresqlconstants.go
new file mode 100644
index 000000000..01c8cbbdd
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/constants/externalpostgresqlconstants.go
@@ -0,0 +1,9 @@
+package constants
+
+const (
+	EXTERNAL_PG_SUCCESS_CONNECTION_TITLE  = "Machine is able to connect with external managed PostgreSQL"
+	EXTERNAL_PG_FAIL_CONNECTION_TITLE     = "External PostgreSQL connection failed"
+	EXTERNAL_PG_CONNECTION_ERROR_MSG      = "Machine is unable to connect with external managed PostgreSQL"
+	EXTERNAL_PG_CONNECTION_RESOLUTION_MSG = "Ensure that the PostgreSQL configuration provided is correct. Review security group or firewall settings as well on the infrastructure"
+	EXTERNAL_PG_CONNECTION_SUCCESS_MSG    = "Connection successfully tested"
+)
diff --git a/components/automate-cli/pkg/verifyserver/constants/systemuserconstant.go b/components/automate-cli/pkg/verifyserver/constants/systemuserconstant.go
new file mode 100644
index 000000000..328b60130
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/constants/systemuserconstant.go
@@ -0,0 +1,24 @@
+package constants
+
+const (
+	USER_NAME                                  = "hab"
+	GROUP_NAME                                 = "hab"
+	USER_ADD_CMD                               = "useradd"
+	USER_DEL_CMD                               = "userdel"
+	GROUP_DEL_CMD                              = "groupdel"
+	SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE   = "User creation/validation check"
+	SYSTEM_USER_HAB_SUCCESS_MSG                = "User is created or found successfully"
+	SYSTEM_GROUP_HAB_VALIDATION_SUCCESS_TITLE  = "Group creation/validation check"
+	SYSTEM_GROUP_HAB_SUCCESS_MSG               = "Group is created or found successfully"
+	SYSTEM_USERANDGROUP_MAPPING_SUCCESS_TITLE  = "User and group mapping successfully"
+	SYSTEM_USERANDGROUP_MAPPING_SUCCESS_MSG    = "User and group mapping successful"
+	SYSTEM_USER_HAB_VALIDATION_FAILURE_TITLE   = "User validation failure"
+	SYSTEM_USER_HAB_ERROR_MSG                  = "Hab user creation failed"
+	SYSTEM_USER_HAB_RESOLUTION_MSG             = "Check the user name"
+	SYSTEM_GROUP_HAB_VALIDATION_FAILURE_TITLE  = "Group validation failure"
+	SYSTEM_GROUP_HAB_ERROR_MSG                 = "Hab group not found"
+	SYSTEM_GROUP_HAB_RESOLUTION_MSG            = "Check the group name"
+	SYSTEM_USERANDGROUP_MAPPING_FAILURE_TITLE  = "User and group mapping failed"
+	SYSTEM_PRIMARYGROUP_MATCH_ERROR_MSG        = "Primary group mapping for user hab is not hab group"
+	SYSTEM_USERANDGROUP_MAPPING_RESOLUTION_MSG = "Verify the mapping for the user and the group"
+)
diff --git a/components/automate-cli/pkg/verifyserver/models/externalpostgresql.go b/components/automate-cli/pkg/verifyserver/models/externalpostgresql.go
new file mode 100644
index 000000000..9a344823a
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/models/externalpostgresql.go
@@ -0,0 +1,25 @@
+package models
+
+type ExternalPgConnectionDetails struct {
+	Title         string `json:"title"`
+	Passed        bool   `json:"passed"`
+	Status        string `json:"status"`
+	SuccessMsg    string `json:"success_msg"`
+	ErrorMsg      string `json:"error_msg"`
+	ResolutionMsg string `json:"resolution_msg"`
+}
+
+type ExternalPgRequest struct {
+	PostgresqlInstanceUrl       string `json:"postgresql_instance_url"`
+	PostgresqlInstancePort      string `json:"postgresql_instance_port"`
+	PostgresqlSuperUserUserName string `json:"postgresql_superuser_username"`
+	PostgresqlSuperUserPassword string `json:"postgresql_superuser_password"`
+	PostgresqlDbUserUserName    string `json:"postgresql_dbuser_username"`
+	PostgresqlDbUserPassword    string `json:"postgresql_dbuser_password"`
+	PostgresqlRootCert          string `json:"postgresql_root_cert"`
+}
+
+type ExternalPgResponse struct {
+	Passed bool                          `json:"passed"`
+	Checks []ExternalPgConnectionDetails `json:"checks"`
+}
diff --git a/components/automate-cli/pkg/verifyserver/models/systemuser.go b/components/automate-cli/pkg/verifyserver/models/systemuser.go
new file mode 100644
index 000000000..9b0178f33
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/models/systemuser.go
@@ -0,0 +1,6 @@
+package models
+
+type SystemUserResponse struct {
+	Passed bool     `json:"passed"`
+	Checks []*Checks `json:"checks"`
+}
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/externalpostgresql.go b/components/automate-cli/pkg/verifyserver/server/api/v1/externalpostgresql.go
new file mode 100644
index 000000000..89cb671a3
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/externalpostgresql.go
@@ -0,0 +1,33 @@
+package v1
+
+import (
+	"net/http"
+
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/response"
+	"github.com/gofiber/fiber/v2"
+)
+
+func (h *Handler) CheckExternalPostgresql(c *fiber.Ctx) error {
+	req := new(models.ExternalPgRequest)
+	if err := c.BodyParser(&req); err != nil {
+		h.Logger.Error("External postgresql config request body parsing failed:", err)
+		return fiber.NewError(fiber.StatusBadRequest, err.Error())
+	}
+	if len(req.PostgresqlInstanceUrl) == 0 ||
+		len(req.PostgresqlInstancePort) == 0 ||
+		len(req.PostgresqlSuperUserUserName) == 0 ||
+		len(req.PostgresqlSuperUserPassword) == 0 ||
+		len(req.PostgresqlDbUserUserName) == 0 ||
+		len(req.PostgresqlDbUserPassword) == 0 ||
+		len(req.PostgresqlRootCert) == 0 {
+		return fiber.NewError(http.StatusBadRequest, "Request Parameters cannot be empty")
+
+	}
+	pgConnection, err := h.ExternalPostgresqlService.GetPgConnection(req)
+	if err != nil {
+		h.Logger.Error("Error while getting  Details: ", err)
+		return fiber.NewError(fiber.StatusInternalServerError, err.Error())
+	}
+	return c.JSON(response.BuildSuccessResponse(pgConnection))
+}
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/handler.go b/components/automate-cli/pkg/verifyserver/server/api/v1/handler.go
index bc7dff6cc..da5cac20e 100644
--- a/components/automate-cli/pkg/verifyserver/server/api/v1/handler.go
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/handler.go
@@ -2,6 +2,7 @@ package v1
 
 import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/hardwareresourcecount"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/nfsmountservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/opensearchbackupservice"
@@ -11,6 +12,7 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/startmockserverservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/statusservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/stopmockserverservice"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/systemuserservice"
 	"github.com/chef/automate/lib/logger"
 )
 
@@ -26,6 +28,8 @@ type Handler struct {
 	StopMockServersService       stopmockserverservice.IStopMockServerService
 	OSBackupService              opensearchbackupservice.IOSS3BackupService
 	PortReachableService         portreachableservice.IPortReachableService
+	ExternalPostgresqlService    externalpostgresqlservice.ExternalPostgresqlService
+	SystemUserService            systemuserservice.SystemUserService
 }
 
 func NewHandler(logger logger.Logger) *Handler {
@@ -71,6 +75,11 @@ func (h *Handler) AddStopMockServerService(sm stopmockserverservice.IStopMockSer
 	return h
 }
 
+func (h *Handler) AddSystemUserService(su systemuserservice.SystemUserService) *Handler {
+	h.SystemUserService = su
+	return h
+}
+
 func (h *Handler) AddOSS3BackupService(ss opensearchbackupservice.IOSS3BackupService) *Handler {
 	h.OSBackupService = ss
 	return h
@@ -80,3 +89,8 @@ func (h *Handler) AddPortReachableService(pr portreachableservice.IPortReachable
 	h.PortReachableService = pr
 	return h
 }
+
+func (h *Handler) AddExternalPostgresqlService(pg externalpostgresqlservice.ExternalPostgresqlService) *Handler {
+	h.ExternalPostgresqlService = pg
+	return h
+}
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/systemuser.go b/components/automate-cli/pkg/verifyserver/server/api/v1/systemuser.go
new file mode 100644
index 000000000..43cfc5c99
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/systemuser.go
@@ -0,0 +1,11 @@
+package v1
+
+import (
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/response"
+	"github.com/gofiber/fiber/v2"
+)
+
+func (h *Handler) CheckSystemUser(c *fiber.Ctx) error {
+	checks := h.SystemUserService.GetSystemUserServiceDetails()
+	return c.JSON(response.BuildSuccessResponse(checks))
+}
diff --git a/components/automate-cli/pkg/verifyserver/server/routes.go b/components/automate-cli/pkg/verifyserver/server/routes.go
index 541c8a619..0e022a5ed 100644
--- a/components/automate-cli/pkg/verifyserver/server/routes.go
+++ b/components/automate-cli/pkg/verifyserver/server/routes.go
@@ -18,6 +18,9 @@ func (vs *VerifyServer) SetupRoutes() {
 	apiChecksGroup.Get("/software-versions", vs.Handler.CheckSoftwareVersion)
 	apiChecksGroup.Post("/s3-config", vs.Handler.GetS3Config)
 	apiChecksGroup.Post("/port-reachable", vs.Handler.PortReachable)
+	apiChecksGroup.Post("/external-postgresql", vs.Handler.CheckExternalPostgresql)
+	
+	apiChecksGroup.Get("/system-user", vs.Handler.CheckSystemUser)
 
 	apiStartGroup := apiV1Group.Group("/start")
 	apiStartGroup.Post("/mock-server", vs.Handler.StartMockServer)
@@ -25,6 +28,6 @@ func (vs *VerifyServer) SetupRoutes() {
 
 	apiStopGroup := apiV1Group.Group("/stop")
 	apiStopGroup.Post("/mock-server", vs.Handler.StopMockServer)
-
+	
 	fiberutils.LogResgisteredRoutes(vs.App.Stack(), vs.Log)
 }
diff --git a/components/automate-cli/pkg/verifyserver/server/server.go b/components/automate-cli/pkg/verifyserver/server/server.go
index db55ea2e3..65320a3c4 100644
--- a/components/automate-cli/pkg/verifyserver/server/server.go
+++ b/components/automate-cli/pkg/verifyserver/server/server.go
@@ -16,6 +16,7 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/sshuseraccesschecktrigger"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/systemresourcechecktrigger"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/systemuserchecktrigger"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/hardwareresourcecount"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/nfsmountservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/opensearchbackupservice"
@@ -26,8 +27,13 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/statusservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/stopmockserverservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/awsutils"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/db"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/systemuserservice"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/fiberutils"
+	"github.com/chef/automate/lib/io/fileutils"
+	"github.com/chef/automate/lib/executil"
 	"github.com/chef/automate/lib/logger"
+	"github.com/chef/automate/lib/userutils"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gofiber/fiber/v2/middleware/cors"
 	fiberlogger "github.com/gofiber/fiber/v2/middleware/logger"
@@ -96,7 +102,9 @@ func NewVerifyServer(port string, debug bool) (*VerifyServer, error) {
 		AddS3ConfigService(s3configservice.NewS3ConfigService(l, awsutils.NewAwsUtils())).
 		AddStopMockServerService(stopmockserverservice.NewStopMockServerService(l)).
 		AddOSS3BackupService(opensearchbackupservice.NewOSS3BackupService(l)).
-		AddPortReachableService(portreachableservice.NewPortReachableService(l, constants.TIMEOUT))
+		AddPortReachableService(portreachableservice.NewPortReachableService(l, constants.TIMEOUT)).
+		AddExternalPostgresqlService(externalpostgresqlservice.NewExternalPostgresqlService(db.NewDBImpl(),fileutils.NewFileSystemUtils(),l)).
+		AddSystemUserService(systemuserservice.NewSystemUserService(l, executil.NewExecCmdServiceImp(), userutils.NewUserUtilImp()))
 	vs := &VerifyServer{
 		Port:    port,
 		Log:     l,
diff --git a/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/externalpostgresqlservice.go b/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/externalpostgresqlservice.go
new file mode 100644
index 000000000..549f7efc4
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/externalpostgresqlservice.go
@@ -0,0 +1,103 @@
+package externalpostgresqlservice
+
+import (
+	"fmt"
+
+	"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/utils/db"
+	"github.com/chef/automate/lib/io/fileutils"
+	"github.com/chef/automate/lib/logger"
+)
+
+type ExternalPostgresqlService interface {
+	GetPgConnection(*models.ExternalPgRequest) (*models.ExternalPgResponse, error)
+}
+
+type ExternalPostgresqlServiceImpl struct {
+	logger    logger.Logger
+	DBUtils   db.DB
+	fileUtils fileutils.FileUtils
+	Req       *models.ExternalPgRequest
+}
+
+func NewExternalPostgresqlService(db db.DB, fileutils fileutils.FileUtils, logger logger.Logger) *ExternalPostgresqlServiceImpl {
+	return &ExternalPostgresqlServiceImpl{
+		logger:    logger,
+		DBUtils:   db,
+		fileUtils: fileutils,
+	}
+}
+
+func (pg *ExternalPostgresqlServiceImpl) GetPgConnection(req *models.ExternalPgRequest) (*models.ExternalPgResponse, error) {
+	pg.Req = req
+
+	//creating a temp file to copy the content of a rootcert into a file
+	rootcert, err := pg.fileUtils.CreateTempFile(req.PostgresqlRootCert, "root-cert")
+	if err != nil {
+		return nil, err
+	}
+
+	var resp *models.ExternalPgResponse
+	err = pg.CheckExternalPgConnection(rootcert)
+	if err != nil {
+		pg.logger.Error(err)
+		resp = &models.ExternalPgResponse{
+			Passed: false,
+			Checks: []models.ExternalPgConnectionDetails{failResponse(constants.EXTERNAL_PG_FAIL_CONNECTION_TITLE, constants.EXTERNAL_PG_CONNECTION_ERROR_MSG, constants.EXTERNAL_PG_CONNECTION_RESOLUTION_MSG)},
+		}
+		return resp, nil
+	}
+
+	resp = &models.ExternalPgResponse{
+		Passed: true,
+		Checks: []models.ExternalPgConnectionDetails{successResponse(constants.EXTERNAL_PG_SUCCESS_CONNECTION_TITLE, constants.EXTERNAL_PG_CONNECTION_SUCCESS_MSG)},
+	}
+
+	// delete the file when its done
+	defer pg.fileUtils.DeleteTempFile(rootcert)
+
+	return resp, nil
+}
+func (p *ExternalPostgresqlServiceImpl) CheckExternalPgConnection(rootcert string) error {
+
+	connStr := fmt.Sprintf("host=%s port=%s user=%s "+
+		"password=%s dbname=postgres sslmode=verify-ca sslrootcert=%s",
+		p.Req.PostgresqlInstanceUrl, p.Req.PostgresqlInstancePort, "%s", "%s", rootcert)
+
+	superUserConnStr := fmt.Sprintf(connStr, p.Req.PostgresqlSuperUserUserName, p.Req.PostgresqlSuperUserPassword)
+	DbUserConnStr := fmt.Sprintf(connStr, p.Req.PostgresqlDbUserUserName, p.Req.PostgresqlDbUserPassword)
+
+	QueryStr := []string{superUserConnStr, DbUserConnStr}
+
+	for i := 0; i < len(QueryStr); i++ {
+		err := p.DBUtils.InitPostgresDB(QueryStr[i])
+		if err != nil {
+			p.logger.Error("External Postgresql Connection failed: ", err.Error())
+			return err
+		}
+		p.logger.Info("External Postgresql aws connection success", i)
+	}
+	return nil
+}
+
+func successResponse(Title string, SuccessMsg string) models.ExternalPgConnectionDetails {
+	Resp := models.ExternalPgConnectionDetails{
+		Title:         constants.EXTERNAL_PG_SUCCESS_CONNECTION_TITLE,
+		Passed:        true,
+		SuccessMsg:    constants.EXTERNAL_PG_CONNECTION_SUCCESS_MSG,
+		ErrorMsg:      "",
+		ResolutionMsg: "",
+	}
+	return Resp
+}
+func failResponse(Title string, ErrorMsg string, ResolutionMsg string) models.ExternalPgConnectionDetails {
+	Resp := models.ExternalPgConnectionDetails{
+		Title:         constants.EXTERNAL_PG_FAIL_CONNECTION_TITLE,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      constants.EXTERNAL_PG_CONNECTION_ERROR_MSG,
+		ResolutionMsg: constants.EXTERNAL_PG_CONNECTION_RESOLUTION_MSG,
+	}
+	return Resp
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/mockexternalpostgresqlservice.go b/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/mockexternalpostgresqlservice.go
new file mode 100644
index 000000000..1f40016ee
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/mockexternalpostgresqlservice.go
@@ -0,0 +1,11 @@
+package externalpostgresqlservice
+
+import "github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
+
+type MockExternalPostgresqlService struct {
+	GetPgConnectionFunc func(*models.ExternalPgRequest) (*models.ExternalPgResponse, error)
+}
+
+func (mss *MockExternalPostgresqlService) GetPgConnection(req *models.ExternalPgRequest) (*models.ExternalPgResponse, error) {
+	return mss.GetPgConnectionFunc(req)
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/systemuserservice/mocksystemuserservice.go b/components/automate-cli/pkg/verifyserver/services/systemuserservice/mocksystemuserservice.go
new file mode 100644
index 000000000..338e2786c
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/services/systemuserservice/mocksystemuserservice.go
@@ -0,0 +1,12 @@
+package systemuserservice
+
+import "github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
+
+type MockSystemUserService struct {
+	GetSystemUserServiceDetailsFunc func() *models.SystemUserResponse
+}
+
+// GetSystemUserServiceDetails implements SystemUser
+func (msu *MockSystemUserService) GetSystemUserServiceDetails() *models.SystemUserResponse {
+	return msu.GetSystemUserServiceDetailsFunc()
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/systemuserservice/systemuserservice.go b/components/automate-cli/pkg/verifyserver/services/systemuserservice/systemuserservice.go
new file mode 100644
index 000000000..e6693f3ad
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/services/systemuserservice/systemuserservice.go
@@ -0,0 +1,173 @@
+package systemuserservice
+
+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/executil"
+	"github.com/chef/automate/lib/logger"
+	"github.com/chef/automate/lib/userutils"
+)
+
+type SystemUserService interface {
+	GetSystemUserServiceDetails() *models.SystemUserResponse
+}
+
+type SystemUserServiceImp struct {
+	exec executil.ExecCmdService
+	user userutils.UserUtil
+	Log  logger.Logger
+}
+
+func NewSystemUserService(log logger.Logger, exec executil.ExecCmdService, user userutils.UserUtil) *SystemUserServiceImp {
+	return &SystemUserServiceImp {
+		exec: exec,
+		user: user,
+		Log:  log,
+	}
+}
+
+func (su *SystemUserServiceImp) GetSystemUserServiceDetails() *models.SystemUserResponse {
+	serviceResponse := &models.SystemUserResponse{}
+	serviceResponse.Passed = true
+	serviceResponseArray := []*models.Checks{}
+
+	habUserResponse, isHabUserCreated := su.ValidateOrCreateHabUser()
+	if !habUserResponse.Passed {
+		serviceResponse.Passed = false
+	}
+
+	habGroupResponse := su.ValidateHabGroup()
+	if !habGroupResponse.Passed {
+		serviceResponse.Passed = false
+	}
+
+	habUserAndGroupMapResponse := su.ValidateHabUserAndGroupMapping()
+	if !habUserAndGroupMapResponse.Passed {
+		serviceResponse.Passed = false
+	}
+
+	if isHabUserCreated {
+		defer func() {
+			_, _ = su.exec.Command(constants.USER_DEL_CMD, []string{constants.USER_NAME})
+
+			if su.isHabGroupPresent(constants.GROUP_NAME) {
+				_, _ = su.exec.Command(constants.GROUP_DEL_CMD, []string{constants.GROUP_NAME})
+				su.Log.Debug("Group hab deleted")
+			}
+		}()
+
+	}
+
+	serviceResponseArray = append(serviceResponseArray, habUserResponse, habGroupResponse, habUserAndGroupMapResponse)
+
+	serviceResponse.Checks = serviceResponseArray
+	return serviceResponse
+
+}
+
+func (su *SystemUserServiceImp) ValidateOrCreateHabUser() (*models.Checks, bool) {
+	isHabUserPresent := su.isHabUserPresent(constants.USER_NAME)
+
+	if !isHabUserPresent {
+		_, err := su.exec.Command(constants.USER_ADD_CMD, []string{"-U", constants.USER_NAME})
+		if err != nil {
+			su.Log.Error("Failed to create user 'hab':", err)
+			return failureResponse(constants.SYSTEM_USER_HAB_VALIDATION_FAILURE_TITLE, constants.SYSTEM_USER_HAB_ERROR_MSG, constants.SYSTEM_USER_HAB_RESOLUTION_MSG), false
+		}
+		su.Log.Debug("Created 'hab' user and group ")
+		return successResponse(constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE, constants.SYSTEM_USER_HAB_SUCCESS_MSG), true
+	}
+	su.Log.Debug("User 'hab' found successfully")
+	return successResponse(constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE, constants.SYSTEM_USER_HAB_SUCCESS_MSG), false
+}
+
+func (su *SystemUserServiceImp) ValidateHabGroup() *models.Checks {
+	isHabGroupPresent := su.isHabGroupPresent(constants.GROUP_NAME)
+
+	if !isHabGroupPresent {
+		su.Log.Error("Group 'hab' doesn't exists")
+		return failureResponse(constants.SYSTEM_GROUP_HAB_VALIDATION_FAILURE_TITLE, constants.SYSTEM_GROUP_HAB_ERROR_MSG, constants.SYSTEM_GROUP_HAB_RESOLUTION_MSG)
+	}
+	su.Log.Debug("Group 'hab' found successfully")
+	return successResponse(constants.SYSTEM_GROUP_HAB_VALIDATION_SUCCESS_TITLE, constants.SYSTEM_GROUP_HAB_SUCCESS_MSG)
+}
+
+func (su *SystemUserServiceImp) ValidateHabUserAndGroupMapping() *models.Checks {
+	// Check if "hab" user's primary group is "hab" group
+	userPrimaryGroup := su.checkUserPrimaryGroup(constants.USER_NAME, constants.GROUP_NAME)
+
+	if !userPrimaryGroup {
+		su.Log.Error("Validation failed: Primary group mapping for user 'hab' is not 'hab' group")
+		return failureResponse(constants.SYSTEM_USERANDGROUP_MAPPING_FAILURE_TITLE, constants.SYSTEM_PRIMARYGROUP_MATCH_ERROR_MSG, constants.SYSTEM_USERANDGROUP_MAPPING_RESOLUTION_MSG)
+	}
+	su.Log.Debug("Validation passed: Primary group mapping for user 'hab' is 'hab' group")
+
+	return successResponse(constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_TITLE, constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_MSG)
+}
+
+// Check if "hab" user exists
+func (su *SystemUserServiceImp) isHabUserPresent(username string) bool {
+	_, err := su.user.Lookup(username)
+	if err != nil {
+		su.Log.Error("Hab user not present: ", err)
+		return false
+	}
+	su.Log.Debug("Hab user exists")
+	return true
+}
+
+// Check if "hab" group exists
+func (su *SystemUserServiceImp) isHabGroupPresent(groupname string) bool {
+	_, err := su.user.LookupGroup(groupname)
+	if err != nil {
+		su.Log.Error("Hab group not present: ", err)
+		return false
+	}
+	su.Log.Debug("Hab group exists")
+	return true
+}
+
+// Check for user's primary group
+func (su *SystemUserServiceImp) checkUserPrimaryGroup(username, groupname string) bool {
+	sysUser, err := su.user.Lookup(username)
+	if err != nil {
+		su.Log.Error("User not found: ", err)
+		return false
+	}
+
+	// Get the user's primary group
+	group, err := su.user.LookupGroupId(sysUser.Gid)
+	if err != nil {
+		su.Log.Error("Group not found by Gid '"+sysUser.Gid+"': ", err)
+		return false
+	}
+
+	if group.Name != groupname {
+		su.Log.Debug("User's primary group is not hab")
+		return false
+	}
+	su.Log.Debug("User's primary group is hab with gid '"+ sysUser.Gid+"'")
+	return true
+}
+
+func successResponse(title string, successMsg string) *models.Checks {
+	checkResponse := &models.Checks{
+		Title:         title,
+		Passed:        true,
+		SuccessMsg:    successMsg,
+		ErrorMsg:      "",
+		ResolutionMsg: "",
+	}
+	return checkResponse
+}
+
+func failureResponse(title string, errorMsg string, resolutionMsg string) *models.Checks {
+	checkResponse := &models.Checks{
+		Title:         title,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      errorMsg,
+		ResolutionMsg: resolutionMsg,
+	}
+	return checkResponse
+}
diff --git a/components/automate-cli/pkg/verifyserver/utils/db/db.go b/components/automate-cli/pkg/verifyserver/utils/db/db.go
new file mode 100644
index 000000000..294891415
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/utils/db/db.go
@@ -0,0 +1,33 @@
+package db
+
+import (
+	"database/sql"
+
+	_ "github.com/lib/pq"
+)
+
+type DBImpl struct {
+}
+type DB interface {
+	InitPostgresDB(con string) error
+}
+
+func NewDBImpl() DB {
+	return &DBImpl{}
+}
+
+func (di *DBImpl) InitPostgresDB(con string) error {
+
+	db, err := sql.Open("postgres", con)
+	if err != nil {
+		return err
+	}
+
+	defer db.Close()
+
+	err = db.Ping()
+	if err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/components/automate-cli/pkg/verifyserver/utils/db/mockdb.go b/components/automate-cli/pkg/verifyserver/utils/db/mockdb.go
new file mode 100644
index 000000000..635082756
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/utils/db/mockdb.go
@@ -0,0 +1,9 @@
+package db
+
+type MockDB struct {
+	InitPostgresDBFunc func(con string) error
+}
+
+func (m *MockDB) InitPostgresDB(con string) error {
+	return m.InitPostgresDBFunc(con)
+}
diff --git a/components/automate-cli/pkg/verifyserver/utils/fiberutils/os.go b/components/automate-cli/pkg/verifyserver/utils/fiberutils/os.go
index 10c94aee1..0588e828d 100644
--- a/components/automate-cli/pkg/verifyserver/utils/fiberutils/os.go
+++ b/components/automate-cli/pkg/verifyserver/utils/fiberutils/os.go
@@ -1,6 +1,8 @@
 package fiberutils
 
-import "os/exec"
+import (
+	"os/exec"
+)
 
 func ExecuteShellCommand(cmd string) ([]byte, error) {
 	return exec.Command("/bin/sh", "-c", cmd).CombinedOutput()
diff --git a/dev/san_validator.sh b/dev/san_validator.sh
index 34bd55397..748a37ef2 100644
--- a/dev/san_validator.sh
+++ b/dev/san_validator.sh
@@ -2,26 +2,65 @@
 
 cert_path="$1"
 
-# Check for empty certificate path
-if [ -z "$cert_path" ]; then
-    echo "Error: Certificate path not provided"
-    echo "usage:"
-    echo "bash san_validator.sh <certificate path>"
-    exit 1
-fi
+validate_cert() {
+    input_path="$1"
+    cert_info=$(openssl x509 -in "$input_path" -noout -text 2>/dev/null)
+    if echo "$cert_info" | grep -q "Subject Alternative Name"; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+is_root_ca() {
+    input_path="$1"
+
+    #Check the certificate is RootCA is not
+    is_self_signed=$(openssl verify -CAfile "$cert" "$cert" 2>&1)
+
+    #enable case insensitive match for reg-ex
+    shopt -s nocasematch
+    if [[ ! -z $(cat "$cert") ]] && [[ $is_self_signed == *error* ]]; then
+            #disable case insensitive match for reg-ex
+            shopt -u nocasematch
+            return 1
+    else
+            #disable case insensitive match for reg-ex
+            shopt -u nocasematch
+            return 0
+    fi
 
-# Check for the certificate file exists
-if [ ! -f "$cert_path" ]; then
-    echo "Error: Certificate file not found."
+}
+
+# If the certificate path provide validate only that certificate
+if [ "$cert_path" ]; then
+    # Check for the certificate file exists
+    if [ ! -f "$cert_path" ]; then
+            echo "Error: Certificate file not found."
+            exit 1
+    fi
+
+    if validate_cert "$cert_path"; then
+        echo "Pass: your certificate is a valid SAN certificate"
+    else
+        echo "Fail: your certificate is not a valid SAN certificate"
+    fi
     exit 1
 fi
 
-# Get the certificate information
-cert_info=$(openssl x509 -in "$cert_path" -noout -text 2>/dev/null)
 
-# Check if the certificate has SAN or not
-if echo "$cert_info" | grep -q "Subject Alternative Name"; then
-    echo "Pass: your certificate is a valid SAN certificate"
-else
-    echo "Fail: your certificate is not a valid SAN certificate"
-fi
\ No newline at end of file
+# Get all the internal certificates with extension(.crt), gets the RootCA and public certificates
+certs=$(find /hab/svc -type f -name "*.crt")
+invalid_certs=()
+
+for cert in $certs; do
+        if ! is_root_ca "$cert" && ! validate_cert "$cert"; then
+                invalid_certs+=("$cert")
+        fi
+done
+
+# Print the list of invalid certs
+echo "Invalid certificates:"
+for cert in "${invalid_certs[@]}"; do
+    echo "$cert"
+done
\ No newline at end of file
diff --git a/lib/executil/exec.go b/lib/executil/exec.go
new file mode 100644
index 000000000..9ce66c21f
--- /dev/null
+++ b/lib/executil/exec.go
@@ -0,0 +1,17 @@
+package executil
+
+import "os/exec"
+
+type ExecCmdService interface {
+	Command(name string, args []string) ([]byte, error)
+}
+
+type ExecCmdServiceImp struct{}
+
+func NewExecCmdServiceImp() ExecCmdService {
+	return &ExecCmdServiceImp{}
+}
+
+func (s *ExecCmdServiceImp) Command(name string, args []string) ([]byte, error) {
+	return exec.Command(name, args...).Output()
+}
\ No newline at end of file
diff --git a/lib/executil/mockexec.go b/lib/executil/mockexec.go
new file mode 100644
index 000000000..93caf0c0c
--- /dev/null
+++ b/lib/executil/mockexec.go
@@ -0,0 +1,9 @@
+package executil
+
+type ExecCmdServiceMock struct {
+	CommandFunc func(name string, args []string) ([]byte, error)
+}
+
+func (s *ExecCmdServiceMock) Command(name string, args []string) ([]byte, error) {
+	return s.CommandFunc(name, args)
+}
\ No newline at end of file
diff --git a/lib/io/fileutils/fileutils.go b/lib/io/fileutils/fileutils.go
index 9d60fdb01..834f09270 100644
--- a/lib/io/fileutils/fileutils.go
+++ b/lib/io/fileutils/fileutils.go
@@ -28,10 +28,16 @@ type FileUtils interface {
 	WriteToFile(filepath string, data []byte) error
 	ReadFile(filename string) ([]byte, error)
 	WriteFile(filepath string, data []byte, perm os.FileMode) error
+	CreateTempFile(content string, filename string) (string, error)
+	DeleteTempFile(tempFile string) error
 }
 
 type FileSystemUtils struct{}
 
+func NewFileSystemUtils() FileUtils {
+	return &FileSystemUtils{}
+}
+
 func (fsu *FileSystemUtils) PathExists(path string) (bool, error) {
 	return PathExists(path)
 }
@@ -59,6 +65,12 @@ func (fsu *FileSystemUtils) ReadFile(filename string) ([]byte, error) {
 func (fsu *FileSystemUtils) WriteFile(filepath string, data []byte, perm os.FileMode) error {
 	return WriteFile(filepath, data, perm)
 }
+func (fsu *FileSystemUtils) CreateTempFile(content string, filename string) (string, error) {
+	return CreateTempFile(content, filename)
+}
+func (fsu *FileSystemUtils) DeleteTempFile(tempFile string) error {
+	return DeleteTempFile(tempFile)
+}
 
 // LogCLose closes the given io.Closer, logging any error.
 func LogClose(c io.Closer, log logrus.FieldLogger, msg string) {
@@ -147,3 +159,19 @@ func ReadFile(filename string) ([]byte, error) {
 func WriteFile(filepath string, data []byte, perm os.FileMode) error {
 	return ioutil.WriteFile(filepath, data, perm) // nosemgrep
 }
+
+func CreateTempFile(content string, filename string) (string, error) {
+	tempFile, err := os.CreateTemp("", filename)
+	if err != nil {
+		return "", errors.Wrap(err, "file creation failed ")
+	}
+	_, err = tempFile.WriteString((content))
+	if err != nil {
+		return "", errors.Wrap(err, "writing to a file failed ")
+	}
+	return tempFile.Name(), nil
+}
+
+func DeleteTempFile(tempFile string) error {
+	return os.Remove(tempFile)
+}
diff --git a/lib/io/fileutils/mockFileUtils.go b/lib/io/fileutils/mockFileUtils.go
index 6bb177367..dbad5bc1b 100644
--- a/lib/io/fileutils/mockFileUtils.go
+++ b/lib/io/fileutils/mockFileUtils.go
@@ -1,6 +1,8 @@
 package fileutils
 
-import "os"
+import (
+	"os"
+)
 
 type MockFileSystemUtils struct {
 	PathExistsFunc             func(path string) (bool, error)
@@ -12,6 +14,8 @@ type MockFileSystemUtils struct {
 	WriteToFileFunc            func(filepath string, data []byte) error
 	ReadFileFunc               func(filepath string) ([]byte, error)
 	WriteFileFunc              func(filepath string, data []byte, perm os.FileMode) error
+	CreateTempFileFunc         func(content string, filename string) (string, error)
+	DeleteTempFileFunc         func(tempFile string) error
 }
 
 func (fsu *MockFileSystemUtils) PathExists(path string) (bool, error) {
@@ -41,3 +45,9 @@ func (fsu *MockFileSystemUtils) ReadFile(filepath string) ([]byte, error) {
 func (fsu *MockFileSystemUtils) WriteFile(filepath string, data []byte, perm os.FileMode) error {
 	return fsu.WriteFileFunc(filepath, data, perm)
 }
+func (fsu *MockFileSystemUtils) CreateTempFile(content string, filename string) (string, error) {
+	return fsu.CreateTempFileFunc(content, filename)
+}
+func (fsu *MockFileSystemUtils) DeleteTempFile(tempFile string) error {
+	return fsu.DeleteTempFileFunc(tempFile)
+}
diff --git a/lib/userutils/mockuser.go b/lib/userutils/mockuser.go
new file mode 100644
index 000000000..93819c8c7
--- /dev/null
+++ b/lib/userutils/mockuser.go
@@ -0,0 +1,21 @@
+package userutils
+
+import "os/user"
+
+type UserUtilMock struct {
+	LookupFunc        func(name string) (*user.User, error)
+	LookupGroupFunc   func(name string) (*user.Group, error)
+	LookupGroupIdFunc func(name string) (*user.Group, error)
+}
+
+func (mock *UserUtilMock) Lookup(name string) (*user.User, error) {
+	return mock.LookupFunc(name)
+}
+
+func (mock *UserUtilMock) LookupGroup(name string) (*user.Group, error) {
+	return mock.LookupGroupFunc(name)
+}
+
+func (mock *UserUtilMock) LookupGroupId(name string) (*user.Group, error) {
+	return mock.LookupGroupIdFunc(name)
+}
diff --git a/lib/userutils/user.go b/lib/userutils/user.go
new file mode 100644
index 000000000..74219ce12
--- /dev/null
+++ b/lib/userutils/user.go
@@ -0,0 +1,27 @@
+package userutils
+
+import "os/user"
+
+type UserUtil interface {
+	Lookup(name string) (*user.User, error)
+	LookupGroup(name string) (*user.Group, error)
+	LookupGroupId(name string) (*user.Group, error)
+}
+
+type UserUtilImp struct{}
+
+func NewUserUtilImp() UserUtil {
+	return &UserUtilImp{}
+}
+
+func (s *UserUtilImp) Lookup(name string) (*user.User, error) {
+	return user.Lookup(name)
+}
+
+func (s *UserUtilImp) LookupGroup(name string) (*user.Group, error) {
+	return user.LookupGroup(name)
+}
+
+func (s *UserUtilImp) LookupGroupId(name string) (*user.Group, error) {
+	return user.LookupGroupId(name)
+}


Test patch:
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/externalpostgresql_test.go b/components/automate-cli/pkg/verifyserver/server/api/v1/externalpostgresql_test.go
new file mode 100644
index 000000000..888e8a954
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/externalpostgresql_test.go
@@ -0,0 +1,179 @@
+package v1_test
+
+import (
+	"errors"
+	"io"
+	"net/http/httptest"
+	"strings"
+	"testing"
+
+	"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/server"
+	v1 "github.com/chef/automate/components/automate-cli/pkg/verifyserver/server/api/v1"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/fiberutils"
+	"github.com/chef/automate/lib/logger"
+	"github.com/gofiber/fiber/v2"
+	"github.com/stretchr/testify/assert"
+)
+
+var (
+	ExternalPgsuccessMessage      = "{\"status\":\"SUCCESS\",\"result\":{\"passed\":true,\"checks\":[{\"title\":\"Machine is able to connect with external managed PostgreSQL\",\"passed\":true,\"status\":\"\",\"success_msg\":\"Connection successfully tested\",\"error_msg\":\"\",\"resolution_msg\":\"\"}]}}"
+	ExternalPgfailureMessage      = "{\"status\":\"SUCCESS\",\"result\":{\"passed\":false,\"checks\":[{\"title\":\"External Postgresql connection failed\",\"passed\":false,\"status\":\"\",\"success_msg\":\"\",\"error_msg\":\"Machine is unable to connect with external managed PostgreSQL\",\"resolution_msg\":\"Ensure that the PostgreSQL configuration provided is correct. Review security group or firewall settings as well on the infrastructure\"}]}}"
+	ExternalPgInternalServerError = "{\"status\":\"FAILED\",\"result\":null,\"error\":{\"code\":500,\"message\":\"Internal Server Error\"}}"
+	ErrorBodyParser               = "{\"status\":\"FAILED\",\"result\":null,\"error\":{\"code\":400,\"message\":\"invalid character '}' looking for beginning of object key string\"}}"
+	InvalidRequest                = "{\"status\":\"FAILED\",\"result\":null,\"error\":{\"code\":400,\"message\":\"Request Parameters cannot be empty\"}}"
+)
+
+func SetupMockExternalPostgresqlService(responseBody *models.ExternalPgResponse, err error) externalpostgresqlservice.ExternalPostgresqlService {
+	return &externalpostgresqlservice.MockExternalPostgresqlService{
+		GetPgConnectionFunc: func(*models.ExternalPgRequest) (*models.ExternalPgResponse, error) {
+			return responseBody, err
+		},
+	}
+}
+
+func SetupExternalPostgresqlHandlers(pg externalpostgresqlservice.ExternalPostgresqlService) (*fiber.App, error) {
+	log, _ := logger.NewLogger("text", "debug")
+	fconf := fiber.Config{
+		ServerHeader: server.SERVICE,
+		ErrorHandler: fiberutils.CustomErrorHandler,
+	}
+	app := fiber.New(fconf)
+	handler := v1.NewHandler(log).
+		AddExternalPostgresqlService(pg)
+	vs := &server.VerifyServer{
+		Port:    server.DEFAULT_PORT,
+		Log:     log,
+		App:     app,
+		Handler: handler,
+	}
+	vs.SetupRoutes()
+	return vs.App, nil
+}
+
+func TestExternalPostgresql(t *testing.T) {
+	tests := []struct {
+		description   string
+		responseBody  *models.ExternalPgResponse
+		expectedCode  int
+		expectedBody  string
+		expectedError error
+		body          string
+	}{
+		{
+			description: "200:success status route",
+			responseBody: &models.ExternalPgResponse{
+				Passed: true,
+				Checks: []models.ExternalPgConnectionDetails{
+					{
+						Title:         constants.EXTERNAL_PG_SUCCESS_CONNECTION_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.EXTERNAL_PG_CONNECTION_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+				},
+			},
+			expectedCode: 200,
+			expectedBody: ExternalPgsuccessMessage,
+			body: `{
+				"postgresql_instance_url": "A.B.C.D",
+				"postgresql_instance_port": "7432",
+				"postgresql_superuser_username": "postgres",
+				"postgresql_superuser_password": "Progress123",
+				"postgresql_dbuser_username": "postgres",
+				"postgresql_dbuser_password": "Progress123",
+				"postgresql_root_cert": "----- BEGIN CERTIFICATE ------"
+			}`,
+		},
+		{
+			description:  "400: body parser error",
+			responseBody: nil,
+			expectedCode: 400,
+			expectedBody: ErrorBodyParser,
+			body: `{
+						"postgresql_instance_url": "A.B.C.D",
+						"postgresq_instance_port": "7432",
+					}`,
+		},
+		{
+			description:  "400: body parser error with special character",
+			responseBody: nil,
+			expectedCode: 400,
+			expectedBody: InvalidRequest,
+			body: `{
+				"postgresql&_instance_url": "A.B.C.D",
+				"postgresql_instance_port": "7432",
+				"postgresql_superuser_username": "postgres",
+				"postgresql_superuser_password": "Progress123",
+				"postgresql_dbuser_username": "postgres",
+				"postgresql_dbuser_password": "Progress123",
+				"postgresql_root_cert": ""
+				}`,
+		},
+		{
+			description:  "400: body parser error with invalid type",
+			responseBody: nil,
+			expectedCode: 400,
+			expectedBody: InvalidRequest,
+			body: `{
+				"postgresql&_instance_url": 1234,
+				"postgresql_instance_port": "7432",
+				"postgresql_superuser_username": "postgres",
+				"postgresql_superuser_password": "Progress123",
+				"postgresql_dbuser_username": "postgres",
+				"postgresql_dbuser_password": "Progress123",
+				"postgresql_root_cert": ""
+				}`,
+		},
+		{
+			description:  "400: Request validator with empty string",
+			responseBody: nil,
+			expectedCode: 400,
+			expectedBody: InvalidRequest,
+			body: `{
+				"postgresql_instance_url": "A.B.C.D",
+				"postgresql_instance_port": "7432",
+				"postgresql_superuser_username": "postgres",
+				"postgresql_superuser_password": "Progress123",
+				"postgresql_dbuser_username": "postgres",
+				"postgresql_dbuser_password": "Progress123",
+				"postgresql_root_cert": ""
+				}`,
+		},
+		{
+			description:   "500: Internal Server error",
+			responseBody:  nil,
+			expectedCode:  500,
+			expectedBody:  ExternalPgInternalServerError,
+			expectedError: errors.New("Internal Server Error"),
+			body: `{
+						"postgresql_instance_url": "A.B.C.D",
+						"postgresql_instance_port": "7432",
+						"postgresql_superuser_username": "postgres",
+						"postgresql_superuser_password": "Progress123",
+						"postgresql_dbuser_username": "postgres",
+						"postgresql_dbuser_password": "Progress123",
+						"postgresql_root_cert": "----- BEGIN CERTIFICATE ------"
+					}`,
+		},
+	}
+	ExternalPostgresqlEndpoint := "/api/v1/checks/external-postgresql"
+
+	for _, test := range tests {
+		t.Run(test.description, func(t *testing.T) {
+			app, _ := SetupExternalPostgresqlHandlers(SetupMockExternalPostgresqlService(test.responseBody, test.expectedError))
+			req := httptest.NewRequest("POST", ExternalPostgresqlEndpoint, strings.NewReader(test.body))
+			req.Header.Add("Content-Type", "application/json")
+			res, err := app.Test(req, -1)
+			assert.NoError(t, err)
+			body, err := io.ReadAll(res.Body)
+			t.Log(body, "body")
+			assert.NoError(t, err, test.description)
+			assert.Contains(t, string(body), test.expectedBody)
+			assert.Equal(t, res.StatusCode, test.expectedCode)
+		})
+	}
+}
diff --git a/components/automate-cli/pkg/verifyserver/server/api/v1/systemuser_test.go b/components/automate-cli/pkg/verifyserver/server/api/v1/systemuser_test.go
new file mode 100644
index 000000000..2132b10c8
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/server/api/v1/systemuser_test.go
@@ -0,0 +1,104 @@
+package v1_test
+
+import (
+	"io/ioutil"
+	"net/http/httptest"
+	"testing"
+
+	"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/server"
+	v1 "github.com/chef/automate/components/automate-cli/pkg/verifyserver/server/api/v1"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/services/systemuserservice"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/fiberutils"
+	"github.com/chef/automate/lib/logger"
+	"github.com/gofiber/fiber/v2"
+	"github.com/stretchr/testify/assert"
+)
+
+func SetupMockSystemUserHandlers(su systemuserservice.SystemUserService) (*fiber.App, error) {
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		return nil, err
+	}
+	fconf := fiber.Config{
+		ServerHeader: server.SERVICE,
+		ErrorHandler: fiberutils.CustomErrorHandler,
+	}
+	app := fiber.New(fconf)
+	handler := v1.NewHandler(log).
+		AddSystemUserService(su)
+	vs := &server.VerifyServer{
+		Port:    server.DEFAULT_PORT,
+		Log:     log,
+		App:     app,
+		Handler: handler,
+	}
+	vs.SetupRoutes()
+	return vs.App, nil
+}
+
+func SetupMockSystemUserService(response models.SystemUserResponse) systemuserservice.SystemUserService {
+	return &systemuserservice.MockSystemUserService{
+		GetSystemUserServiceDetailsFunc: func() *models.SystemUserResponse {
+			return &response
+		},
+	}
+}
+
+func TestSystemUserService(t *testing.T) {
+	tests := []struct {
+		description  string
+		expectedCode int
+		responseBody models.SystemUserResponse
+		expectedBody string
+	}{
+		{
+			description:  "200:User and Group verified and mapping validated",
+			expectedCode: 200,
+			responseBody: models.SystemUserResponse{
+				Passed: true,
+				Checks: []*models.Checks{
+					{
+						Title:         constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.SYSTEM_USER_HAB_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+					{
+						Title:         constants.SYSTEM_GROUP_HAB_VALIDATION_SUCCESS_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.SYSTEM_GROUP_HAB_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+					{
+						Title:         constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+				},
+			},
+			expectedBody: "{\"status\":\"SUCCESS\",\"result\":{\"passed\":true,\"checks\":[{\"title\":\"User creation/validation check\",\"passed\":true,\"success_msg\":\"User is created or found successfully\",\"error_msg\":\"\",\"resolution_msg\":\"\"},{\"title\":\"Group creation/validation check\",\"passed\":true,\"success_msg\":\"Group is created or found successfully\",\"error_msg\":\"\",\"resolution_msg\":\"\"},{\"title\":\"User and group mapping successfully\",\"passed\":true,\"success_msg\":\"User and group mapping successful\",\"error_msg\":\"\",\"resolution_msg\":\"\"}]}}",
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.description, func(t *testing.T) {
+			systemuserCheckEndpoint := "/api/v1/checks/system-user"
+			app, err := SetupMockSystemUserHandlers(SetupMockSystemUserService(test.responseBody))
+			assert.NoError(t, err)
+			req := httptest.NewRequest("GET", systemuserCheckEndpoint, nil)
+			req.Header.Add("Content-Type", "application/json")
+			res, err := app.Test(req, -1)
+			assert.NoError(t, err)
+			body, err := ioutil.ReadAll(res.Body)
+			assert.NoError(t, err, test.description)
+			assert.Contains(t, string(body), test.expectedBody)
+			assert.Equal(t, res.StatusCode, test.expectedCode)
+		})
+	}
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/externalpostgresqlservice_test.go b/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/externalpostgresqlservice_test.go
new file mode 100644
index 000000000..70feb6c27
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/services/externalpostgresqlservice/externalpostgresqlservice_test.go
@@ -0,0 +1,100 @@
+package externalpostgresqlservice_test
+
+import (
+	"errors"
+	"testing"
+
+	"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/externalpostgresqlservice"
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/utils/db"
+	"github.com/chef/automate/lib/io/fileutils"
+	"github.com/chef/automate/lib/logger"
+	"github.com/stretchr/testify/assert"
+)
+
+var (
+	req = models.ExternalPgRequest{
+		PostgresqlInstanceUrl:       "A.B.C.D",
+		PostgresqlInstancePort:      "7432",
+		PostgresqlSuperUserUserName: "postgres",
+		PostgresqlSuperUserPassword: "Progress123",
+		PostgresqlDbUserUserName:    "postgres",
+		PostgresqlDbUserPassword:    "Progress123",
+		PostgresqlRootCert:          "----- BEGIN CERTIFICATE ------",
+	}
+)
+
+func TestExternalPostgresqlService(t *testing.T) {
+	log, _ := logger.NewLogger("text", "debug")
+	cs := externalpostgresqlservice.NewExternalPostgresqlService(&db.MockDB{
+		InitPostgresDBFunc: func(con string) error {
+			return nil
+		},
+	}, &fileutils.MockFileSystemUtils{
+		CreateTempFileFunc: func(content string, filename string) (string, error) {
+			return "", nil
+		},
+		DeleteTempFileFunc: func(tempFile string) error {
+			return nil
+		},
+	}, log)
+	services, _ := cs.GetPgConnection(&models.ExternalPgRequest{
+		PostgresqlInstanceUrl:       "A.B.C.D",
+		PostgresqlInstancePort:      "7432",
+		PostgresqlSuperUserUserName: "postgres",
+		PostgresqlSuperUserPassword: "Progress123",
+		PostgresqlDbUserUserName:    "postgres",
+		PostgresqlDbUserPassword:    "Progress123",
+		PostgresqlRootCert:          "----- BEGIN CERTIFICATE ------",
+	})
+	assert.Equal(t, &models.ExternalPgResponse{
+		Passed: true,
+		Checks: []models.ExternalPgConnectionDetails{
+			{
+				Title:         constants.EXTERNAL_PG_SUCCESS_CONNECTION_TITLE,
+				Passed:        true,
+				SuccessMsg:    constants.EXTERNAL_PG_CONNECTION_SUCCESS_MSG,
+				ErrorMsg:      "",
+				ResolutionMsg: "",
+			},
+		},
+	}, services)
+}
+
+func TestExternalPostgresqlServiceFailure(t *testing.T) {
+	log, _ := logger.NewLogger("text", "debug")
+	csf := externalpostgresqlservice.NewExternalPostgresqlService(&db.MockDB{
+		InitPostgresDBFunc: func(con string) error {
+			return errors.New("")
+		},
+	}, &fileutils.MockFileSystemUtils{
+		CreateTempFileFunc: func(content string, filename string) (string, error) {
+			return "", nil
+		},
+		DeleteTempFileFunc: func(tempFile string) error {
+			return nil
+		},
+	}, log)
+	services, _ := csf.GetPgConnection(&models.ExternalPgRequest{
+		PostgresqlInstanceUrl:       "A.B.C.D",
+		PostgresqlInstancePort:      "7432",
+		PostgresqlSuperUserUserName: "postgres",
+		PostgresqlSuperUserPassword: "Progress123",
+		PostgresqlDbUserUserName:    "postgres",
+		PostgresqlRootCert:          "-----",
+	})
+	assert.Equal(t, &models.ExternalPgResponse{
+		Passed: false,
+		Checks: []models.ExternalPgConnectionDetails{
+			{
+				Title:         constants.EXTERNAL_PG_FAIL_CONNECTION_TITLE,
+				Passed:        false,
+				SuccessMsg:    "",
+				ErrorMsg:      constants.EXTERNAL_PG_CONNECTION_ERROR_MSG,
+				ResolutionMsg: constants.EXTERNAL_PG_CONNECTION_RESOLUTION_MSG,
+			},
+		},
+	}, services)
+
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/systemuserservice/systemuserservice_test.go b/components/automate-cli/pkg/verifyserver/services/systemuserservice/systemuserservice_test.go
new file mode 100644
index 000000000..827a40a86
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/services/systemuserservice/systemuserservice_test.go
@@ -0,0 +1,451 @@
+package systemuserservice
+
+import (
+	"errors"
+	"os/user"
+	"testing"
+
+	"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/userutils"
+	"github.com/chef/automate/lib/executil"
+	"github.com/chef/automate/lib/logger"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewSystemUserService(t *testing.T) {
+	log, err := logger.NewLogger("text", "debug")
+	assert.NoError(t, err)
+
+	s := NewSystemUserService(log, executil.NewExecCmdServiceImp(), userutils.NewUserUtilImp())
+	assert.NotEqual(t, s, nil)
+}
+
+func TestValidateHabUserSuccess(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{}, nil
+		},
+	}
+
+	mockExec := &executil.ExecCmdServiceMock{
+		CommandFunc: func(name string, args []string) ([]byte, error) {
+			return []byte{}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+		exec: mockExec,
+	}
+	service, _ := s.ValidateOrCreateHabUser()
+	assert.Equal(t, service.Passed, true)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE,
+		Passed:        true,
+		SuccessMsg:    constants.SYSTEM_USER_HAB_SUCCESS_MSG,
+		ErrorMsg:      "",
+		ResolutionMsg: "",
+	}, service)
+}
+
+func TestValidateHabUserFailure(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{}, errors.New("user not found")
+		},
+	}
+
+	mockExec := &executil.ExecCmdServiceMock{
+		CommandFunc: func(name string, args []string) ([]byte, error) {
+			return []byte{}, errors.New("exit status 1")
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+		exec: mockExec,
+	}
+	service, _ := s.ValidateOrCreateHabUser()
+	assert.Equal(t, service.Passed, false)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USER_HAB_VALIDATION_FAILURE_TITLE,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      constants.SYSTEM_USER_HAB_ERROR_MSG ,
+		ResolutionMsg: constants.SYSTEM_USER_HAB_RESOLUTION_MSG,
+	}, service)
+}
+
+func TestValidateHabUserCreatedSuccess(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{}, errors.New("user not found")
+		},
+	}
+
+	mockExec := &executil.ExecCmdServiceMock{
+		CommandFunc: func(name string, args []string) ([]byte, error) {
+			return []byte{}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+		exec: mockExec,
+	}
+	service, _ := s.ValidateOrCreateHabUser()
+	assert.Equal(t, service.Passed, true)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE,
+		Passed:        true,
+		SuccessMsg:    constants.SYSTEM_USER_HAB_SUCCESS_MSG,
+		ErrorMsg:      "",
+		ResolutionMsg: "",
+	}, service)
+}
+
+func TestValidateHabGroup(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupGroupFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+	}
+	service := s.ValidateHabGroup()
+	assert.Equal(t, service.Passed, true)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_GROUP_HAB_VALIDATION_SUCCESS_TITLE,
+		Passed:        true,
+		SuccessMsg:    constants.SYSTEM_GROUP_HAB_SUCCESS_MSG,
+		ErrorMsg:      "",
+		ResolutionMsg: "",
+	}, service)
+}
+
+func TestValidateHabGroupFailed(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupGroupFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, errors.New("Group 'hab' doesn't exists")
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+	}
+	service := s.ValidateHabGroup()
+	assert.Equal(t, service.Passed, false)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_GROUP_HAB_VALIDATION_FAILURE_TITLE,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      constants.SYSTEM_GROUP_HAB_ERROR_MSG,
+		ResolutionMsg: constants.SYSTEM_GROUP_HAB_RESOLUTION_MSG,
+	}, service)
+}
+
+func TestValidateHabUserAndGroupMappingFailed(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{
+				Uid:      "1001",
+				Gid:      "1001",
+				Username: "hab",
+				Name:     "hab",
+				HomeDir:  "",
+			}, nil
+		},
+		LookupGroupIdFunc: func(name string) (*user.Group, error) {
+			return &user.Group{
+				Gid:  "1002",
+				Name: "test",
+			}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+	}
+	service := s.ValidateHabUserAndGroupMapping()
+	assert.Equal(t, service.Passed, false)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USERANDGROUP_MAPPING_FAILURE_TITLE,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      constants.SYSTEM_PRIMARYGROUP_MATCH_ERROR_MSG,
+		ResolutionMsg: constants.SYSTEM_USERANDGROUP_MAPPING_RESOLUTION_MSG,
+	}, service)
+}
+
+func TestValidateHabUserAndGroupMappingSuccess(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{
+				Uid:      "1001",
+				Gid:      "1001",
+				Username: "hab",
+				Name:     "hab",
+				HomeDir:  "",
+			}, nil
+		},
+		LookupGroupIdFunc: func(name string) (*user.Group, error) {
+			return &user.Group{
+				Gid:  "1001",
+				Name: "hab",
+			}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+	}
+	service := s.ValidateHabUserAndGroupMapping()
+	assert.Equal(t, service.Passed, true)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_TITLE,
+		Passed:        true,
+		SuccessMsg:    constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_MSG,
+		ErrorMsg:      "",
+		ResolutionMsg: "",
+	}, service)
+}
+
+func TestValidateHabUserAndGroupMappingFailedForLookupUsernameError(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{}, errors.New("User not found")
+		},
+		LookupGroupIdFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+	}
+	service := s.ValidateHabUserAndGroupMapping()
+	assert.Equal(t, service.Passed, false)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USERANDGROUP_MAPPING_FAILURE_TITLE,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      constants.SYSTEM_PRIMARYGROUP_MATCH_ERROR_MSG,
+		ResolutionMsg: constants.SYSTEM_USERANDGROUP_MAPPING_RESOLUTION_MSG,
+	}, service)
+}
+
+func TestValidateHabUserAndGroupMappingFailedForLookUpGroupId(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{
+				Uid:      "1001",
+				Gid:      "1001",
+				Username: "hab",
+				Name:     "hab",
+				HomeDir:  "",
+			}, nil
+		},
+		LookupGroupIdFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, errors.New("Group not found with Gid")
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		user: mockUser,
+	}
+	service := s.ValidateHabUserAndGroupMapping()
+	assert.Equal(t, service.Passed, false)
+	assert.Equal(t, &models.Checks{
+		Title:         constants.SYSTEM_USERANDGROUP_MAPPING_FAILURE_TITLE,
+		Passed:        false,
+		SuccessMsg:    "",
+		ErrorMsg:      constants.SYSTEM_PRIMARYGROUP_MATCH_ERROR_MSG,
+		ResolutionMsg: constants.SYSTEM_USERANDGROUP_MAPPING_RESOLUTION_MSG,
+	}, service)
+}
+
+func TestGetSystemUserServiceDetailsSuccess(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{
+				Uid:      "1001",
+				Gid:      "1001",
+				Username: "hab",
+				Name:     "hab",
+				HomeDir:  "",
+			}, nil
+		},
+		LookupGroupFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, nil
+		},
+		LookupGroupIdFunc: func(name string) (*user.Group, error) {
+			return &user.Group{
+				Gid:  "1001",
+				Name: "hab",
+			}, nil
+		},
+	}
+	mockExec := &executil.ExecCmdServiceMock{
+		CommandFunc: func(name string, args []string) ([]byte, error) {
+			return []byte{}, nil
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		exec: mockExec,
+		user: mockUser,
+	}
+
+	tests := []struct {
+		description  string
+		expectedBody *models.SystemUserResponse
+	}{
+		{
+			description: "User and group not validated and mapping not successful",
+			expectedBody: &models.SystemUserResponse{
+				Passed: true,
+				Checks: []*models.Checks{
+					{
+						Title:         constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.SYSTEM_USER_HAB_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+					{
+						Title:         constants.SYSTEM_GROUP_HAB_VALIDATION_SUCCESS_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.SYSTEM_GROUP_HAB_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+					{
+						Title:         constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_TITLE,
+						Passed:        true,
+						SuccessMsg:    constants.SYSTEM_USERANDGROUP_MAPPING_SUCCESS_MSG,
+						ErrorMsg:      "",
+						ResolutionMsg: "",
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			got := s.GetSystemUserServiceDetails()
+			assert.Equal(t, tt.expectedBody, got)
+		})
+	}
+}
+
+func TestGetSystemUserServiceDetailsFailed(t *testing.T) {
+	mockUser := &userutils.UserUtilMock{
+		LookupFunc: func(name string) (*user.User, error) {
+			return &user.User{}, errors.New("user not found")
+		},
+		LookupGroupFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, errors.New("Group 'hab' doesn't exists")
+		},
+		LookupGroupIdFunc: func(name string) (*user.Group, error) {
+			return &user.Group{}, errors.New("Primary group mapping failed")
+		},
+	}
+	mockExec := &executil.ExecCmdServiceMock{
+		CommandFunc: func(name string, args []string) ([]byte, error) {
+			return []byte{}, errors.New("exit status 1")
+		},
+	}
+	log, err := logger.NewLogger("text", "debug")
+	if err != nil {
+		assert.Error(t, err)
+	}
+	s := &SystemUserServiceImp{
+		Log:  log,
+		exec: mockExec,
+		user: mockUser,
+	}
+
+	tests := []struct {
+		description  string
+		expectedBody *models.SystemUserResponse
+	}{
+		{
+			description: "User and group not validated and mapping not successful",
+			expectedBody: &models.SystemUserResponse{
+				Passed: false,
+				Checks: []*models.Checks{
+					{
+						Title:         constants.SYSTEM_USER_HAB_VALIDATION_FAILURE_TITLE,
+						Passed:        false,
+						SuccessMsg:    "",
+						ErrorMsg:      constants.SYSTEM_USER_HAB_ERROR_MSG ,
+						ResolutionMsg: constants.SYSTEM_USER_HAB_RESOLUTION_MSG,
+					},
+					{
+						Title:         constants.SYSTEM_GROUP_HAB_VALIDATION_FAILURE_TITLE,
+						Passed:        false,
+						SuccessMsg:    "",
+						ErrorMsg:      constants.SYSTEM_GROUP_HAB_ERROR_MSG,
+						ResolutionMsg: constants.SYSTEM_GROUP_HAB_RESOLUTION_MSG,
+					},
+					{
+						Title:         constants.SYSTEM_USERANDGROUP_MAPPING_FAILURE_TITLE,
+						Passed:        false,
+						SuccessMsg:    "",
+						ErrorMsg:      constants.SYSTEM_PRIMARYGROUP_MATCH_ERROR_MSG,
+						ResolutionMsg: constants.SYSTEM_USERANDGROUP_MAPPING_RESOLUTION_MSG,
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			got := s.GetSystemUserServiceDetails()
+			assert.Equal(t, tt.expectedBody, got)
+		})
+	}
+}
diff --git a/components/automate-cli/pkg/verifyserver/utils/db/db_test.go b/components/automate-cli/pkg/verifyserver/utils/db/db_test.go
new file mode 100644
index 000000000..9ad0149ca
--- /dev/null
+++ b/components/automate-cli/pkg/verifyserver/utils/db/db_test.go
@@ -0,0 +1,19 @@
+package db
+
+import (
+	"strings"
+	"testing"
+)
+
+func TestInitPostgresDB(t *testing.T) {
+	//create DBImpl
+	di := &DBImpl{}
+
+	err := di.InitPostgresDB("mock-con-sting")
+	expectedError := `missing "=" after "mock-con-sting" in connection info string`
+	actualError := strings.TrimRight(err.Error(), `"`)
+
+	if actualError != expectedError {
+		t.Errorf("Extected error '%s', got '%s'", expectedError, actualError)
+	}
+}
diff --git a/lib/executil/exec_test.go b/lib/executil/exec_test.go
new file mode 100644
index 000000000..80e41a8fd
--- /dev/null
+++ b/lib/executil/exec_test.go
@@ -0,0 +1,17 @@
+package executil_test
+
+import (
+	"testing"
+
+	"github.com/chef/automate/lib/executil"
+	"github.com/stretchr/testify/assert"
+)
+
+
+func TestCommand(t *testing.T) {
+	f := &executil.ExecCmdServiceImp{}
+
+	output, err := f.Command("echo", []string{"Hello"})
+	assert.Contains(t, string(output), "Hello")
+	assert.Equal(t, nil, err)
+}
\ No newline at end of file
diff --git a/lib/io/fileutils/fileutils_test.go b/lib/io/fileutils/fileutils_test.go
index 9960c1370..a6698c846 100644
--- a/lib/io/fileutils/fileutils_test.go
+++ b/lib/io/fileutils/fileutils_test.go
@@ -50,3 +50,35 @@ func TestIsSymlink(t *testing.T) {
 		assert.False(t, isSymlink, "%s should not be a symlink", filePath)
 	})
 }
+
+func TestCreateTempFile(t *testing.T) {
+	content := "abc"
+	filename := "file-name"
+	t.Run("It creates the file", func(t *testing.T) {
+		res1, err := fileutils.CreateTempFile(content, filename)
+		require.NoError(t, err)
+		res2, err := fileutils.CreateTempFile(content, filename)
+		require.NoError(t, err)
+		res3, err := fileutils.CreateTempFile(content, filename)
+		require.NoError(t, err)
+		res4, err := fileutils.CreateTempFile(content, filename)
+		require.NoError(t, err)
+		assert.Contains(t, res1, "file-name")
+		assert.Contains(t, res2, "file-name")
+		assert.Contains(t, res3, "file-name")
+		assert.Contains(t, res4, "file-name")
+	})
+}
+
+func TestDeleteTempFile(t *testing.T) {
+	tempFile, err := os.CreateTemp("", "testfile")
+	if err != nil {
+		return
+	}
+	defer tempFile.Close()
+
+	err = fileutils.DeleteTempFile(tempFile.Name())
+	if err != nil {
+		return
+	}
+}
diff --git a/lib/userutils/user_test.go b/lib/userutils/user_test.go
new file mode 100644
index 000000000..2073e5562
--- /dev/null
+++ b/lib/userutils/user_test.go
@@ -0,0 +1,35 @@
+package userutils_test
+
+import (
+	"os/user"
+	"testing"
+
+	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/constants"
+	"github.com/chef/automate/lib/userutils"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestLookup(t *testing.T) {
+	s := &userutils.UserUtilImp{}
+	sysUser, err := s.Lookup(constants.USER_NAME)
+	if sysUser == nil {
+		assert.Equal(t, user.UnknownUserError(constants.USER_NAME), err)
+	}
+}
+
+func TestLookupGroup(t *testing.T) {
+	s := &userutils.UserUtilImp{}
+	group, err := s.LookupGroup(constants.GROUP_NAME)
+	if group == nil {
+		assert.Equal(t, user.UnknownGroupError(constants.GROUP_NAME), err)
+	}
+}
+
+func TestLookupGroupId(t *testing.T) {
+	s := &userutils.UserUtilImp{}
+	gid := "1000"
+	group, err := s.LookupGroupId(gid)
+	if group == nil {
+		assert.Equal(t, user.UnknownGroupIdError(gid), err)
+	}
+}