mirror of
https://github.com/hanzozt/zt.git
synced 2026-10-30 15:04:55 +00:00
- Repo names: ziti-* → zt-* - Go modules: github.com/hanzozt/ziti → github.com/hanzozt/zt - Docker images: hanzozt/ziti-* → hanzozt/zt-* - C/Java/JS symbols: ziti_* → zt_* - File and directory names updated
203 lines
5.2 KiB
Go
203 lines
5.2 KiB
Go
package posture
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/michaelquigley/pfxlog"
|
|
"github.com/hanzozt/foundation/v2/stringz"
|
|
"github.com/hanzozt/sdk-golang/pb/edge_client_pb"
|
|
"github.com/hanzozt/zt/v2/common/pb/edge_ctrl_pb"
|
|
"github.com/hanzozt/zt/v2/controller/db"
|
|
)
|
|
|
|
type ProcessCheck struct {
|
|
*edge_ctrl_pb.DataState_PostureCheck
|
|
*edge_ctrl_pb.DataState_PostureCheck_ProcessMulti
|
|
}
|
|
|
|
func (p *ProcessCheck) Evaluate(data *InstanceData) *CheckError {
|
|
switch p.Semantic {
|
|
case db.SemanticAllOf:
|
|
return p.requireAll(data)
|
|
case db.SemanticAnyOf:
|
|
return p.requireOne(data)
|
|
default:
|
|
pfxlog.Logger().Panicf("invalid semantic, expected %s or %s got [%s]", db.SemanticAllOf, db.SemanticAnyOf, p.Semantic)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (p *ProcessCheck) requireAll(data *InstanceData) *CheckError {
|
|
if data == nil {
|
|
return &CheckError{
|
|
Id: p.Id,
|
|
Name: p.Name,
|
|
Cause: NilStateError,
|
|
}
|
|
}
|
|
cacheProcesses := map[string]*edge_client_pb.PostureResponse_Process{}
|
|
|
|
for _, process := range data.ProcessList.Processes {
|
|
cacheProcesses[process.Path] = process
|
|
}
|
|
|
|
allInListError := &AllInListError[*edge_ctrl_pb.DataState_PostureCheck_Process]{}
|
|
|
|
for _, process := range p.Processes {
|
|
if process.Path == "" {
|
|
return &CheckError{
|
|
Id: p.Id,
|
|
Name: p.Name,
|
|
Cause: fmt.Errorf("invalid path in process check, '%s'", process.Path),
|
|
}
|
|
}
|
|
|
|
cacheProcess, ok := cacheProcesses[process.Path]
|
|
|
|
if !ok {
|
|
return &CheckError{
|
|
Id: p.Id,
|
|
Name: p.Name,
|
|
Cause: fmt.Errorf("the process path %s was not found, it hasn't been reported or isn't running on the client", process.Path),
|
|
}
|
|
}
|
|
|
|
failedValue := p.compareProcesses(data.Os.Os.Type, cacheProcess, process)
|
|
|
|
if failedValue != nil {
|
|
allInListError.FailedValues = append(allInListError.FailedValues, *failedValue)
|
|
}
|
|
}
|
|
|
|
if len(allInListError.FailedValues) > 0 {
|
|
for _, process := range data.ProcessList.Processes {
|
|
allInListError.GivenValues = append(allInListError.GivenValues, &edge_ctrl_pb.DataState_PostureCheck_Process{
|
|
OsType: data.Os.Os.Type,
|
|
Path: process.Path,
|
|
Hashes: []string{process.Hash},
|
|
Fingerprints: process.SignerFingerprints,
|
|
})
|
|
}
|
|
|
|
return &CheckError{
|
|
Id: p.Id,
|
|
Name: p.Name,
|
|
Cause: allInListError,
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *ProcessCheck) requireOne(data *InstanceData) *CheckError {
|
|
if data == nil {
|
|
return &CheckError{
|
|
Id: p.Id,
|
|
Name: p.Name,
|
|
Cause: NilStateError,
|
|
}
|
|
}
|
|
cacheProcesses := map[string]*edge_client_pb.PostureResponse_Process{}
|
|
|
|
if data.ProcessList == nil {
|
|
data.ProcessList = &edge_client_pb.PostureResponse_ProcessList{}
|
|
}
|
|
|
|
for _, process := range data.ProcessList.Processes {
|
|
cacheProcesses[process.Path] = process
|
|
}
|
|
|
|
anyInList := &AnyInListError[*edge_ctrl_pb.DataState_PostureCheck_Process]{}
|
|
|
|
osType := ""
|
|
|
|
if data.Os != nil && data.Os.Os != nil {
|
|
osType = data.Os.Os.Type
|
|
}
|
|
|
|
for _, process := range p.Processes {
|
|
cacheProcess := cacheProcesses[process.Path]
|
|
|
|
failedValue := p.compareProcesses(osType, cacheProcess, process)
|
|
|
|
if failedValue != nil {
|
|
anyInList.FailedValues = append(anyInList.FailedValues, *failedValue)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
for _, process := range data.ProcessList.Processes {
|
|
anyInList.GivenValues = append(anyInList.GivenValues, &edge_ctrl_pb.DataState_PostureCheck_Process{
|
|
OsType: data.Os.Os.Type,
|
|
Path: process.Path,
|
|
Hashes: []string{process.Hash},
|
|
Fingerprints: process.SignerFingerprints,
|
|
})
|
|
}
|
|
|
|
return &CheckError{
|
|
Id: p.Id,
|
|
Name: p.Name,
|
|
Cause: anyInList,
|
|
}
|
|
}
|
|
|
|
func (p *ProcessCheck) compareProcesses(osType string, given *edge_client_pb.PostureResponse_Process, valid *edge_ctrl_pb.DataState_PostureCheck_Process) *FailedValueError[*edge_ctrl_pb.DataState_PostureCheck_Process] {
|
|
result := &FailedValueError[*edge_ctrl_pb.DataState_PostureCheck_Process]{
|
|
ExpectedValue: valid,
|
|
GivenValue: nil,
|
|
Reason: nil,
|
|
}
|
|
|
|
if given == nil {
|
|
result.Reason = fmt.Errorf("no matching process by path %s, the process hasn't been sumitted or isn't running", valid.Path)
|
|
return result
|
|
}
|
|
|
|
if !given.IsRunning {
|
|
result.Reason = errors.New("process is reported as not running")
|
|
return result
|
|
}
|
|
|
|
if valid.Path != given.Path {
|
|
result.Reason = fmt.Errorf("paths do not match, given %s, expected: %s", given.Path, valid.Path)
|
|
return result
|
|
}
|
|
|
|
if !strings.EqualFold(strings.ToLower(valid.OsType), strings.ToLower(osType)) {
|
|
result.Reason = fmt.Errorf("os types do not match, given %s, expected: %s", osType, valid.OsType)
|
|
return result
|
|
}
|
|
|
|
if len(valid.Hashes) > 0 && !stringz.Contains(valid.Hashes, given.Hash) {
|
|
result.Reason = fmt.Errorf("hash is not valid, given %s, expected one of: %v", given.Hash, valid.Hashes)
|
|
return result
|
|
}
|
|
|
|
if len(valid.Fingerprints) > 0 {
|
|
validPrints := map[string]struct{}{}
|
|
|
|
for _, validPrint := range valid.Fingerprints {
|
|
validPrints[validPrint] = struct{}{}
|
|
}
|
|
|
|
validPrintFound := false
|
|
for _, givenPrint := range given.SignerFingerprints {
|
|
if _, ok := validPrints[givenPrint]; ok {
|
|
validPrintFound = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !validPrintFound {
|
|
result.Reason = fmt.Errorf("valid signer not found, given: %v, expected one of: %v", given.SignerFingerprints, valid.Hashes)
|
|
return result
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|