Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding check in system-user verify flow to verify HAB uid #8290

Merged
merged 6 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion components/automate-cli/cmd/chef-automate/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,9 @@ func (v *verifyCmdFlow) printResponse(batchCheckResults []models.BatchCheckResul
func buildReports(batchCheckResults []models.BatchCheckResult) []reporting.VerificationReport {
var reports []reporting.VerificationReport

for _, batchCheckResult := range batchCheckResults {
updatedReportForSystemUser(&batchCheckResults)

for _, batchCheckResult := range batchCheckResults {
for _, test := range batchCheckResult.Tests {

var errorMsgs, resolutionMsgs []string
Expand Down Expand Up @@ -751,6 +752,57 @@ func buildReports(batchCheckResults []models.BatchCheckResult) []reporting.Verif
return reports
}

func updatedReportForSystemUser(batchCheckResults *[]models.BatchCheckResult) {
isNFSCheckPresent := false
uids := []string{}

for _, batchCheckResult := range *batchCheckResults {
// Check all IDs
for _, test := range batchCheckResult.Tests {
if test.Check == constants.NFS_BACKUP_CONFIG && !test.Skipped {
isNFSCheckPresent = true
}
if test.Check == constants.SYSTEM_USER {
if len(test.Checks) == 0 {
continue
}
if !arrayutils.Contains(uids, test.Id.UserID) {
uids = append(uids, test.Id.UserID)
}

}
}
}

for _, batchCheckResult := range *batchCheckResults {
if isNFSCheckPresent {
for i, test := range batchCheckResult.Tests {
if test.Check == constants.SYSTEM_USER {
var newCheck models.Checks
if len(uids) == 1 {
newCheck = models.Checks{
Title: "User ID - validation",
Passed: true,
SuccessMsg: "hab uids are same across all nodes",
Skipped: false,
}
} else {
newCheck = models.Checks{
Title: "User ID - validation",
Passed: false,
ErrorMsg: fmt.Sprintf("hab uid: %s. hab uid is not same across all nodes", test.Id.UserID),
ResolutionMsg: "hab uid should be same across all nodes/machines",
Skipped: false,
}
batchCheckResult.Tests[i].Passed = false
}
batchCheckResult.Tests[i].Checks = append(batchCheckResult.Tests[i].Checks, newCheck)
}
}
}
}
}

func createTables(numberOfAutomateNodes, numberOfChefServerNodes, numberOfPostgreSQLNodes, numberOfOpenSearchNodes int) map[string]*reporting.Table {
bastionSummaryTableTitle := "Summary: Bastion <Node> - 1"
automateSummaryTableTitle := fmt.Sprintf("Summary: Automate <Nodes> - %d", numberOfAutomateNodes)
Expand Down
172 changes: 167 additions & 5 deletions components/automate-cli/cmd/chef-automate/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ import (
)

const (
CONFIG_FILE = "/config_valid_config_parser.toml"
STATUS_API_RESPONSE = `{"status":"SUCCESS","result":{"status":"OK","services":[],"cli_version":"20230622174936","error":"error getting services from hab svc status"}}`
BATCH_CHECK_REQUEST = `{"status":"SUCCESS","result":{"passed":true,"node_result":[]}}`
AWS_CONFIG_FILE = "/valid_config.toml"
DARWIN = "darwin"
CONFIG_FILE = "/config_valid_config_parser.toml"
STATUS_API_RESPONSE = `{"status":"SUCCESS","result":{"status":"OK","services":[],"cli_version":"20230622174936","error":"error getting services from hab svc status"}}`
BATCH_CHECK_REQUEST = `{"status":"SUCCESS","result":{"passed":true,"node_result":[]}}`
BATCH_CHECK_REQUEST_HAB_ID_WITH_NFS = `{"status":"SUCCESS","result":{"passed":true,"node_result":[{"node_type":"opensearch","ip":"10.0.164.66","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}},{"passed": true,"msg": "NFS Backup Config Check","check": "nfs-backup-config"}]},{"node_type":"opensearch","ip":"10.0.133.98","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"opensearch","ip":"10.0.146.192","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"chef-infra-server","ip":"10.0.128.167","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"automate","ip":"10.0.130.38","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"postgresql","ip":"10.0.139.234","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"postgresql","ip":"10.0.168.59","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"postgresql","ip":"10.0.159.200","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]}]}}`
BATCH_CHECK_REQUEST_HAB_ID_WITH_NFS_FAILURE = `{"status":"SUCCESS","result":{"passed":true,"node_result":[{"node_type":"opensearch","ip":"10.0.164.66","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}},{"passed": true,"msg": "NFS Backup Config Check","check": "nfs-backup-config"}]},{"node_type":"opensearch","ip":"10.0.133.98","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"opensearch","ip":"10.0.146.192","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1002","group_id":"1002"}}]},{"node_type":"chef-infra-server","ip":"10.0.128.167","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"automate","ip":"10.0.130.38","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"postgresql","ip":"10.0.139.234","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"postgresql","ip":"10.0.168.59","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]},{"node_type":"postgresql","ip":"10.0.159.200","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[{"title":"User creation/validation check","passed":true,"success_msg":"User is created or found successfully","skipped":false}],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]}]}}`
BATCH_CHECK_REQUEST_HAB_ID_WITH_NFS_FAILURE_2 = `{"status":"SUCCESS","result":{"passed":true,"node_result":[{"node_type":"opensearch","ip":"10.0.164.66","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}},{"passed": true,"msg": "NFS Backup Config Check","check": "nfs-backup-config"}]},{"node_type":"opensearch","ip":"10.0.133.98","tests":[{"passed":true,"msg":"System User Check","check":"system-user","checks":[],"skipped":false,"id":{"user_id":"1001","group_id":"1001"}}]}]}}`
AWS_CONFIG_FILE = "/valid_config.toml"
DARWIN = "darwin"
)

var AwsAutoTfvarsJsonStringEmpty = `
Expand Down Expand Up @@ -375,6 +378,165 @@ func TestRunVerifyCmd(t *testing.T) {
configFile: "",
wantErr: errors.New("Failed to populate HA common config"),
},
{
description: "bastion with aws automate-verify to check hab if with NFS - failure",
IsAws: true,
mockHttputils: &httputils.MockHTTPClient{
MakeRequestFunc: func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
if strings.Contains(url, "batch-check") {
return &http.Response{
StatusCode: http.StatusOK,
Body: nil,
}, []byte(BATCH_CHECK_REQUEST_HAB_ID_WITH_NFS_FAILURE), nil
}
return &http.Response{
StatusCode: http.StatusOK,
Body: nil,
}, []byte(STATUS_API_RESPONSE), nil
},
},
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, destDir string, removeFile bool, hostIPs []string) []sshutils.Result {
return []sshutils.Result{
{
HostIP: "",
Error: nil,
Output: "",
},
}
},
},
configFile: CONFIG_AWS_TOML_PATH + AWS_CONFIG_FILE,
wantErr: nil,
ConvTfvarToJsonFunc: func(string) string {
return AwsAutoTfvarsJsonStringEmpty
},
},
{
description: "bastion with aws automate-verify to check hab if with NFS - failure_2",
IsAws: true,
mockHttputils: &httputils.MockHTTPClient{
MakeRequestFunc: func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
if strings.Contains(url, "batch-check") {
return &http.Response{
StatusCode: http.StatusOK,
Body: nil,
}, []byte(BATCH_CHECK_REQUEST_HAB_ID_WITH_NFS_FAILURE_2), nil
}
return &http.Response{
StatusCode: http.StatusOK,
Body: nil,
}, []byte(STATUS_API_RESPONSE), nil
},
},
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, destDir string, removeFile bool, hostIPs []string) []sshutils.Result {
return []sshutils.Result{
{
HostIP: "",
Error: nil,
Output: "",
},
}
},
},
configFile: CONFIG_AWS_TOML_PATH + AWS_CONFIG_FILE,
wantErr: nil,
ConvTfvarToJsonFunc: func(string) string {
return AwsAutoTfvarsJsonStringEmpty
},
},
{
description: "bastion with aws automate-verify to check hab if with NFS - success",
IsAws: true,
mockHttputils: &httputils.MockHTTPClient{
MakeRequestFunc: func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
if strings.Contains(url, "batch-check") {
return &http.Response{
StatusCode: http.StatusOK,
Body: nil,
}, []byte(BATCH_CHECK_REQUEST_HAB_ID_WITH_NFS), nil
}
return &http.Response{
StatusCode: http.StatusOK,
Body: nil,
}, []byte(STATUS_API_RESPONSE), nil
},
},
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, destDir string, removeFile bool, hostIPs []string) []sshutils.Result {
return []sshutils.Result{
{
HostIP: "",
Error: nil,
Output: "",
},
}
},
},
configFile: CONFIG_AWS_TOML_PATH + AWS_CONFIG_FILE,
wantErr: nil,
ConvTfvarToJsonFunc: func(string) string {
return AwsAutoTfvarsJsonStringEmpty
},
},
}

for _, tt := range tests {
Expand Down
15 changes: 8 additions & 7 deletions components/automate-cli/pkg/verifyserver/models/batchcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,13 +521,14 @@ type CheckTriggerResponse struct {
CheckType string `json:"check_type"`
}
type ApiResult struct {
Passed bool `json:"passed"`
Message string `json:"msg"`
Check string `json:"check"`
Checks []Checks `json:"checks"`
Error *fiber.Error `json:"error,omitempty"`
Skipped bool `json:"skipped"`
SkipMessage string `json:"skip_message,omitempty"`
Passed bool `json:"passed"`
Message string `json:"msg"`
Check string `json:"check"`
Checks []Checks `json:"checks"`
Error *fiber.Error `json:"error,omitempty"`
Skipped bool `json:"skipped"`
SkipMessage string `json:"skip_message,omitempty"`
Id *SystemUserID `json:"id,omitempty"`
}

type Checks struct {
Expand Down
10 changes: 8 additions & 2 deletions components/automate-cli/pkg/verifyserver/models/systemuser.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package models

type SystemUserResponse struct {
Passed bool `json:"passed"`
Checks []*Checks `json:"checks"`
Passed bool `json:"passed"`
Checks []*Checks `json:"checks"`
Id *SystemUserID `json:"id,omitempty"`
}

type SystemUserID struct {
UserID string `json:"user_id,omitempty"`
GroupID string `json:"group_id,omitempty"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type SystemUserServiceImp struct {
}

func NewSystemUserService(log logger.Logger, exec executil.ExecCmdService, user userutils.UserUtil) *SystemUserServiceImp {
return &SystemUserServiceImp {
return &SystemUserServiceImp{
exec: exec,
user: user,
Log: log,
Expand All @@ -36,6 +36,16 @@ func (su *SystemUserServiceImp) GetSystemUserServiceDetails() *models.SystemUser
serviceResponse.Passed = false
}

// Gets UID for created/existing hab user
uid, err := su.getUserAndGroupID()
if err != nil {
serviceResponse.Passed = false
su.Log.Error("User ID for hab not found")
}
su.Log.Info("User ID for hab found")

serviceResponse.Id = uid

habGroupResponse := su.ValidateHabGroup()
if !habGroupResponse.Passed {
serviceResponse.Passed = false
Expand Down Expand Up @@ -81,6 +91,28 @@ func (su *SystemUserServiceImp) ValidateOrCreateHabUser() (*models.Checks, bool)
return successResponse(constants.SYSTEM_USER_HAB_VALIDATION_SUCCESS_TITLE, constants.SYSTEM_USER_HAB_SUCCESS_MSG), false
}

func (su *SystemUserServiceImp) getUserAndGroupID() (*models.SystemUserID, error) {

systemUserDetails := &models.SystemUserID{}

// Check for available ID in all machine (?)
ids, err := su.user.Lookup(constants.USER_NAME)
if err != nil {
su.Log.Error("User not found:", err)
return systemUserDetails, err
}

if ids != nil {
systemUserDetails.UserID = ids.Uid
systemUserDetails.GroupID = ids.Gid
su.Log.Infof("UID: %s\nGID: %s\n", systemUserDetails.UserID, systemUserDetails.GroupID)
} else {
su.Log.Info("UID not found.")
}
su.Log.Info("Created 'hab' user and group ")
return systemUserDetails, nil
}

func (su *SystemUserServiceImp) ValidateHabGroup() *models.Checks {
isHabGroupPresent := su.isHabGroupPresent(constants.GROUP_NAME)

Expand Down Expand Up @@ -146,7 +178,7 @@ func (su *SystemUserServiceImp) checkUserPrimaryGroup(username, groupname string
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+"'")
su.Log.Debug("User's primary group is hab with gid '" + sysUser.Gid + "'")
return true
}

Expand Down
Loading
Loading