package ubuntu import ( "context" "encoding/json" "os" "golang.org/x/exp/slices" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/types" ) func init() { analyzer.RegisterAnalyzer(&ubuntuESMAnalyzer{}) } const ( ESMAnalyzerVersion = 1 esmConfFilePath = "var/lib/ubuntu-advantage/status.json" esmServiceName = "esm-infra" esmStatusEnabled = "enabled" ) var ESMRequiredFiles = []string{ esmConfFilePath, } type ubuntuESMAnalyzer struct{} func (a ubuntuESMAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { st := status{} err := json.NewDecoder(input.Content).Decode(&st) if err != nil { return nil, xerrors.Errorf("ubuntu ESM analyze error: %w", err) } if esmEnabled(st) { return &analyzer.AnalysisResult{ OS: types.OS{ Family: types.Ubuntu, Extended: true, }, }, nil } // if ESM is disabled - return nil to reduce the amount of logic in the OS.Merge function return nil, nil } func (a ubuntuESMAnalyzer) Required(filePath string, _ os.FileInfo) bool { return slices.Contains(ESMRequiredFiles, filePath) } func (a ubuntuESMAnalyzer) Type() analyzer.Type { return analyzer.TypeUbuntuESM } func (a ubuntuESMAnalyzer) Version() int { return ESMAnalyzerVersion } // structs to parse ESM status type status struct { Services []service `json:"services"` } type service struct { Name string `json:"name"` Status string `json:"status"` } func esmEnabled(st status) bool { for _, s := range st.Services { // Find ESM Service if s.Name == esmServiceName && s.Status == esmStatusEnabled { return true } } return false }