Skip to content
This repository has been archived by the owner on Jun 21, 2022. It is now read-only.

Commit

Permalink
feat(analyzer): support AlmaLinux and Rocky Linux (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaineK00n authored Sep 19, 2021
1 parent 9538245 commit 8c6ed3d
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 50 deletions.
4 changes: 4 additions & 0 deletions analyzer/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ func TestAnalyzer_AnalyzerVersions(t *testing.T) {
"bundler": 1,
"cargo": 1,
"centos": 1,
"rocky": 1,
"alma": 1,
"composer": 1,
"debian": 1,
"dpkg": 2,
Expand Down Expand Up @@ -496,6 +498,8 @@ func TestAnalyzer_AnalyzerVersions(t *testing.T) {
"bundler": 1,
"cargo": 1,
"centos": 1,
"rocky": 1,
"alma": 1,
"composer": 1,
"debian": 1,
"dpkg": 2,
Expand Down
2 changes: 2 additions & 0 deletions analyzer/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const (
TypeDebian Type = "debian"
TypePhoton Type = "photon"
TypeCentOS Type = "centos"
TypeRocky Type = "rocky"
TypeAlma Type = "alma"
TypeFedora Type = "fedora"
TypeOracle Type = "oracle"
TypeRedHatBase Type = "redhat"
Expand Down
6 changes: 6 additions & 0 deletions analyzer/os/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ const (
// CentOS is done
CentOS = "centos"

// Rocky is done
Rocky = "rocky"

// Alma is done
Alma = "alma"

// Fedora is done
Fedora = "fedora"

Expand Down
59 changes: 59 additions & 0 deletions analyzer/os/redhatbase/alma.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package redhatbase

import (
"bufio"
"bytes"
"os"
"strings"

"github.com/aquasecurity/fanal/analyzer"

aos "github.com/aquasecurity/fanal/analyzer/os"
"github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/fanal/utils"
"golang.org/x/xerrors"
)

const almaAnalyzerVersion = 1

func init() {
analyzer.RegisterAnalyzer(&almaOSAnalyzer{})
}

type almaOSAnalyzer struct{}

func (a almaOSAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) {
scanner := bufio.NewScanner(bytes.NewBuffer(target.Content))
for scanner.Scan() {
line := scanner.Text()
result := redhatRe.FindStringSubmatch(strings.TrimSpace(line))
if len(result) != 3 {
return nil, xerrors.New("alma: invalid almalinux-release")
}

switch strings.ToLower(result[1]) {
case "alma", "almalinux", "alma linux":
return &analyzer.AnalysisResult{
OS: &types.OS{Family: aos.Alma, Name: result[2]},
}, nil
}
}

return nil, xerrors.Errorf("alma: %w", aos.AnalyzeOSError)
}

func (a almaOSAnalyzer) Required(filePath string, _ os.FileInfo) bool {
return utils.StringInSlice(filePath, a.requiredFiles())
}

func (a almaOSAnalyzer) requiredFiles() []string {
return []string{"etc/almalinux-release"}
}

func (a almaOSAnalyzer) Type() analyzer.Type {
return analyzer.TypeAlma
}

func (a almaOSAnalyzer) Version() int {
return almaAnalyzerVersion
}
52 changes: 52 additions & 0 deletions analyzer/os/redhatbase/alma_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package redhatbase

import (
"os"
"testing"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_almaOSAnalyzer_Analyze(t *testing.T) {
tests := []struct {
name string
inputFile string
want *analyzer.AnalysisResult
wantErr string
}{
{
name: "happy path",
inputFile: "testdata/alma/almalinux-release",
want: &analyzer.AnalysisResult{
OS: &types.OS{Family: "alma", Name: "8.4"},
},
},
{
name: "sad path",
inputFile: "testdata/not_redhatbase/empty",
wantErr: "alma: unable to analyze OS information",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := almaOSAnalyzer{}
b, err := os.ReadFile(tt.inputFile)
require.NoError(t, err)

got, err := a.Analyze(analyzer.AnalysisTarget{
FilePath: "etc/almalinux-release",
Content: b,
})
if tt.wantErr != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
4 changes: 4 additions & 0 deletions analyzer/os/redhatbase/redhatbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ func (a redhatOSAnalyzer) parseRelease(content []byte) (types.OS, error) {
switch strings.ToLower(result[1]) {
case "centos", "centos linux":
return types.OS{Family: aos.CentOS, Name: result[2]}, nil
case "rocky", "rocky linux":
return types.OS{Family: aos.Rocky, Name: result[2]}, nil
case "alma", "almalinux", "alma linux":
return types.OS{Family: aos.Alma, Name: result[2]}, nil
case "oracle", "oracle linux", "oracle linux server":
return types.OS{Family: aos.Oracle, Name: result[2]}, nil
case "fedora", "fedora linux":
Expand Down
59 changes: 59 additions & 0 deletions analyzer/os/redhatbase/rocky.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package redhatbase

import (
"bufio"
"bytes"
"os"
"strings"

"github.com/aquasecurity/fanal/analyzer"

aos "github.com/aquasecurity/fanal/analyzer/os"
"github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/fanal/utils"
"golang.org/x/xerrors"
)

const rockyAnalyzerVersion = 1

func init() {
analyzer.RegisterAnalyzer(&rockyOSAnalyzer{})
}

type rockyOSAnalyzer struct{}

func (a rockyOSAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) {
scanner := bufio.NewScanner(bytes.NewBuffer(target.Content))
for scanner.Scan() {
line := scanner.Text()
result := redhatRe.FindStringSubmatch(strings.TrimSpace(line))
if len(result) != 3 {
return nil, xerrors.New("rocky: invalid rocky-release")
}

switch strings.ToLower(result[1]) {
case "rocky", "rocky linux":
return &analyzer.AnalysisResult{
OS: &types.OS{Family: aos.Rocky, Name: result[2]},
}, nil
}
}

return nil, xerrors.Errorf("rocky: %w", aos.AnalyzeOSError)
}

func (a rockyOSAnalyzer) Required(filePath string, _ os.FileInfo) bool {
return utils.StringInSlice(filePath, a.requiredFiles())
}

func (a rockyOSAnalyzer) requiredFiles() []string {
return []string{"etc/rocky-release"}
}

func (a rockyOSAnalyzer) Type() analyzer.Type {
return analyzer.TypeRocky
}

func (a rockyOSAnalyzer) Version() int {
return rockyAnalyzerVersion
}
52 changes: 52 additions & 0 deletions analyzer/os/redhatbase/rocky_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package redhatbase

import (
"os"
"testing"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_rockyOSAnalyzer_Analyze(t *testing.T) {
tests := []struct {
name string
inputFile string
want *analyzer.AnalysisResult
wantErr string
}{
{
name: "happy path",
inputFile: "testdata/rocky/rocky-release",
want: &analyzer.AnalysisResult{
OS: &types.OS{Family: "rocky", Name: "8.4"},
},
},
{
name: "sad path",
inputFile: "testdata/not_redhatbase/empty",
wantErr: "rocky: unable to analyze OS information",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := rockyOSAnalyzer{}
b, err := os.ReadFile(tt.inputFile)
require.NoError(t, err)

got, err := a.Analyze(analyzer.AnalysisTarget{
FilePath: "etc/rocky-release",
Content: b,
})
if tt.wantErr != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
1 change: 1 addition & 0 deletions analyzer/os/redhatbase/testdata/alma/almalinux-release
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AlmaLinux release 8.4 (Electric Cheetah)
1 change: 1 addition & 0 deletions analyzer/os/redhatbase/testdata/rocky/rocky-release
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Rocky Linux release 8.4 (Green Obsidian)
Loading

0 comments on commit 8c6ed3d

Please sign in to comment.