Repository: falcosecurity/driverkit
Pull request #180 (2022-07-07 09:48:32)

new(pkg/driverbuilder): added amazonlinux2022 builder.
**What type of PR is this?**

/kind feature

**Any specific area of the project related to this PR?**

/area pkg

**What this PR does / why we need it**:

It adds amazonlinux2022 builder.
Moreover, refactored amazonlinux file making it easier to implement new builders.
Finally, updated README with the new al2022 example.

Tested: it is able to find the headers; then it fails to build the kmod because of glibc version issues (we really **need** multiple builders). eBPF probe builds fine.

**Which issue(s) this PR fixes**:

Fixes #

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:

<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below.
If the PR requires additional action from users switching to the new release, prepend the string "action required:".
For example, `action required: change the API interface of the rule engine`.
-->

```release-note
new(pkg): added amazonlinux 2022 builder.
```


poiana: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/falcosecurity/driverkit/pull/180#" title="Author self-approved">FedeDP</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **dwindsor** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @dwindsor` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://prow.falco.org/command-help?repo=falcosecurity%2Fdriverkit).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/falcosecurity/driverkit/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["dwindsor"]} -->
FedeDP: Rebased on top of current master!
dwindsor: /lgtm
poiana: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/falcosecurity/driverkit/pull/180#issuecomment-1180405195" title="LGTM">dwindsor</a>*, *<a href="https://github.com/falcosecurity/driverkit/pull/180#" title="Author self-approved">FedeDP</a>*

The full list of commands accepted by this bot can be found [here](https://prow.falco.org/command-help?repo=falcosecurity%2Fdriverkit).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/falcosecurity/driverkit/blob/master/OWNERS)~~ [dwindsor]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/README.md b/README.md
index 22bebe4..335a874 100644
--- a/README.md
+++ b/README.md
@@ -141,7 +141,7 @@ kernelrelease: 4.14.26-46.32.amzn1.x86_64
 target: amazonlinux
 output:
     module: /tmp/falco_amazonlinux_4.14.26-46.32.amzn1.x86_64.ko
-driverversion: be1ea2d9482d0e6e2cb14a0fd7e08cbecf517f94
+driverversion: master
 ```
 
 ### amazonlinux 2
@@ -152,7 +152,18 @@ target: amazonlinux2
 output:
     module: /tmp/falco_amazonlinux2_4.14.171-136.231.amzn2.x86_64.ko
     probe: /tmp/falco_amazonlinux2_4.14.171-136.231.amzn2.x86_64.o
-driverversion: be1ea2d9482d0e6e2cb14a0fd7e08cbecf517f94
+driverversion: master
+```
+
+### amazonlinux 2022
+
+```yaml
+kernelrelease: 5.10.96-90.460.amzn2022.x86_64
+target: amazonlinux2022
+output:
+    module: /tmp/falco_amazonlinux2022_5.10.96-90.460.amzn2022.x86_64.ko
+    probe: /tmp/falco_amazonlinux2022_5.10.96-90.460.amzn2022.x86_64.o
+driverversion: master
 ```
 
 ### debian
diff --git a/pkg/driverbuilder/builder/amazonlinux.go b/pkg/driverbuilder/builder/amazonlinux.go
index cdf20cb..d77be5e 100644
--- a/pkg/driverbuilder/builder/amazonlinux.go
+++ b/pkg/driverbuilder/builder/amazonlinux.go
@@ -22,12 +22,26 @@ import (
 	logger "github.com/sirupsen/logrus"
 )
 
+type amazonBuilder interface {
+	Builder
+	repos() []string
+	baseUrl() string
+	ext() string
+	target() Type
+}
+
+type amazonlinux2022 struct {
+}
+
 type amazonlinux2 struct {
 }
 
 type amazonlinux struct {
 }
 
+// TargetTypeAmazonLinux2022 identifies the AmazonLinux2022 target.
+const TargetTypeAmazonLinux2022 Type = "amazonlinux2022"
+
 // TargetTypeAmazonLinux2 identifies the AmazonLinux2 target.
 const TargetTypeAmazonLinux2 Type = "amazonlinux2"
 
@@ -35,6 +49,7 @@ const TargetTypeAmazonLinux2 Type = "amazonlinux2"
 const TargetTypeAmazonLinux Type = "amazonlinux"
 
 func init() {
+	BuilderByTarget[TargetTypeAmazonLinux2022] = &amazonlinux2022{}
 	BuilderByTarget[TargetTypeAmazonLinux2] = &amazonlinux2{}
 	BuilderByTarget[TargetTypeAmazonLinux] = &amazonlinux{}
 }
@@ -95,18 +110,88 @@ type amazonlinuxTemplateData struct {
 	LLVMVersion        string
 }
 
+// Script compiles the script to build the kernel module and/or the eBPF probe.
+func (a amazonlinux2022) Script(c Config, kr kernelrelease.KernelRelease) (string, error) {
+	return script(a, c, kr)
+}
+
+func (a amazonlinux2022) repos() []string {
+	return []string{
+		"2022.0.20220202",
+		"2022.0.20220315",
+	}
+}
+
+func (a amazonlinux2022) baseUrl() string {
+	return "https://al2022-repos-us-east-1-9761ab97.s3.dualstack.us-east-1.amazonaws.com/core/mirrors"
+}
+
+func (a amazonlinux2022) ext() string {
+	return "gz"
+}
+
+func (a amazonlinux2022) target() Type {
+	return TargetTypeAmazonLinux2022
+}
+
 // Script compiles the script to build the kernel module and/or the eBPF probe.
 func (a amazonlinux2) Script(c Config, kr kernelrelease.KernelRelease) (string, error) {
-	return script(c, kr, TargetTypeAmazonLinux2)
+	return script(a, c, kr)
+}
+
+func (a amazonlinux2) repos() []string {
+	return []string{
+		"core/2.0",
+		"core/latest",
+		"extras/kernel-5.4/latest",
+		"extras/kernel-5.10/latest",
+	}
+}
+
+func (a amazonlinux2) baseUrl() string {
+	return "http://amazonlinux.us-east-1.amazonaws.com/2"
+}
+
+func (a amazonlinux2) ext() string {
+	return "gz"
+}
+
+func (a amazonlinux2) target() Type {
+	return TargetTypeAmazonLinux2
 }
 
 // Script compiles the script to build the kernel module and/or the eBPF probe.
 func (a amazonlinux) Script(c Config, kr kernelrelease.KernelRelease) (string, error) {
-	return script(c, kr, TargetTypeAmazonLinux)
+	return script(a, c, kr)
+}
+
+func (a amazonlinux) repos() []string {
+	return []string{
+		"latest/updates",
+		"latest/main",
+		"2017.03/updates",
+		"2017.03/main",
+		"2017.09/updates",
+		"2017.09/main",
+		"2018.03/updates",
+		"2018.03/main",
+	}
+}
+
+func (a amazonlinux) baseUrl() string {
+	return "http://repo.us-east-1.amazonaws.com"
+}
+
+func (a amazonlinux) ext() string {
+	return "bz2"
+}
+
+func (a amazonlinux) target() Type {
+	return TargetTypeAmazonLinux
 }
 
-func script(c Config, kv kernelrelease.KernelRelease, targetType Type) (string, error) {
-	t := template.New(string(targetType))
+func script(a amazonBuilder, c Config, kr kernelrelease.KernelRelease) (string, error) {
+	t := template.New(string(a.target()))
 	parsed, err := t.Parse(amazonlinuxTemplate)
 	if err != nil {
 		return "", err
@@ -116,7 +201,7 @@ func script(c Config, kv kernelrelease.KernelRelease, targetType Type) (string,
 	if c.KernelUrls == nil {
 		// Check (and filter) existing kernels before continuing
 		var packages []string
-		packages, err = fetchAmazonLinuxPackagesURLs(kv, targetType)
+		packages, err = fetchAmazonLinuxPackagesURLs(a, kr)
 		if err != nil {
 			return "", err
 		}
@@ -136,7 +221,7 @@ func script(c Config, kv kernelrelease.KernelRelease, targetType Type) (string,
 		ModuleFullPath:     ModuleFullPath,
 		BuildModule:        len(c.Build.ModuleFilePath) > 0,
 		BuildProbe:         len(c.Build.ProbeFilePath) > 0,
-		LLVMVersion:        amazonLLVMVersionFromKernelRelease(kv),
+		LLVMVersion:        amazonLLVMVersionFromKernelRelease(kr),
 	}
 
 	buf := bytes.NewBuffer(nil)
@@ -147,48 +232,46 @@ func script(c Config, kv kernelrelease.KernelRelease, targetType Type) (string,
 	return buf.String(), nil
 }
 
-var reposByTarget = map[Type][]string{
-	TargetTypeAmazonLinux2: []string{
-		"core/2.0",
-		"core/latest",
-		"extras/kernel-5.4/latest",
-		"extras/kernel-5.10/latest",
-	},
-	TargetTypeAmazonLinux: []string{
-		"latest/updates",
-		"latest/main",
-		"2017.03/updates",
-		"2017.03/main",
-		"2017.09/updates",
-		"2017.09/main",
-		"2018.03/updates",
-		"2018.03/main",
-	},
+func buildMirror(a amazonBuilder, r string, kv kernelrelease.KernelRelease) (string, error) {
+	var baseURL string
+	switch a.target() {
+	case TargetTypeAmazonLinux:
+		baseURL = fmt.Sprintf("%s/%s", a.baseUrl(), r)
+	case TargetTypeAmazonLinux2:
+		baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb())
+	case TargetTypeAmazonLinux2022:
+		baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb())
+	default:
+		return "", fmt.Errorf("unsupported target")
+	}
+
+	mirror := fmt.Sprintf("%s/%s", baseURL, "mirror.list")
+	logger.WithField("url", mirror).WithField("version", r).Debug("looking for repo...")
+	return mirror, nil
 }
 
-var baseByTarget = map[Type]string{
-	TargetTypeAmazonLinux:  "http://repo.us-east-1.amazonaws.com/%s",
-	TargetTypeAmazonLinux2: "http://amazonlinux.us-east-1.amazonaws.com/2/core/%s/%s",
+type unzipFunc func(io.Reader) ([]byte, error)
+
+func unzipFuncFromBuilder(a amazonBuilder) (unzipFunc, error) {
+	switch a.ext() {
+	case "gz":
+		return gunzip, nil
+	case "bz2":
+		return bunzip, nil
+	}
+	return nil, fmt.Errorf("unsupported extension: %s", a.ext())
 }
 
-func fetchAmazonLinuxPackagesURLs(kv kernelrelease.KernelRelease, targetType Type) ([]string, error) {
+func fetchAmazonLinuxPackagesURLs(a amazonBuilder, kv kernelrelease.KernelRelease) ([]string, error) {
 	urls := []string{}
-	visited := map[string]bool{}
-	amazonlinux2baseURL := "http://amazonlinux.us-east-1.amazonaws.com"
-
-	for _, v := range reposByTarget[targetType] {
-		var baseURL string
-		switch targetType {
-		case TargetTypeAmazonLinux:
-			baseURL = fmt.Sprintf("http://repo.us-east-1.amazonaws.com/%s", v)
-		case TargetTypeAmazonLinux2:
-			baseURL = fmt.Sprintf("%s/2/%s/%s", amazonlinux2baseURL, v, kv.Architecture.ToNonDeb())
-		default:
-			return nil, fmt.Errorf("unsupported target")
+	visited := make(map[string]struct{})
+
+	for _, v := range a.repos() {
+		mirror, err := buildMirror(a, v, kv)
+		if err != nil {
+			return nil, err
 		}
 
-		mirror := fmt.Sprintf("%s/%s", baseURL, "mirror.list")
-		logger.WithField("url", mirror).WithField("version", v).Debug("looking for repo...")
 		// Obtain the repo URL by getting mirror URL content
 		mirrorRes, err := http.Get(mirror)
 		if err != nil {
@@ -204,13 +287,9 @@ func fetchAmazonLinuxPackagesURLs(kv kernelrelease.KernelRelease, targetType Typ
 		if repo == "" {
 			return nil, fmt.Errorf("repository not found")
 		}
-		repo = strings.ReplaceAll(strings.TrimSuffix(string(repo), "\n"), "$basearch", kv.Architecture.ToNonDeb())
-
-		ext := "gz"
-		if targetType == TargetTypeAmazonLinux {
-			ext = "bz2"
-		}
-		repoDatabaseURL := fmt.Sprintf("%s/repodata/primary.sqlite.%s", repo, ext)
+		repo = strings.ReplaceAll(strings.TrimSuffix(repo, "\n"), "$basearch", kv.Architecture.ToNonDeb())
+		repo = strings.TrimSuffix(repo, "/")
+		repoDatabaseURL := fmt.Sprintf("%s/repodata/primary.sqlite.%s", repo, a.ext())
 		if _, ok := visited[repoDatabaseURL]; ok {
 			continue
 		}
@@ -221,20 +300,19 @@ func fetchAmazonLinuxPackagesURLs(kv kernelrelease.KernelRelease, targetType Typ
 			return nil, err
 		}
 		defer repoRes.Body.Close()
-		visited[repoDatabaseURL] = true
-		// Decompress the database
-		var unzipFunc func(io.Reader) ([]byte, error)
-		if targetType == TargetTypeAmazonLinux {
-			unzipFunc = bunzip
-		} else {
-			unzipFunc = gunzip
+		visited[repoDatabaseURL] = struct{}{}
+
+		unzip, err := unzipFuncFromBuilder(a)
+		if err != nil {
+			return nil, err
 		}
-		dbBytes, err := unzipFunc(repoRes.Body)
+
+		dbBytes, err := unzip(repoRes.Body)
 		if err != nil {
 			return nil, err
 		}
 		// Create the temporary database file
-		dbFile, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("%s-*.sqlite", targetType))
+		dbFile, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("%s-*.sqlite", string(a.target())))
 		if err != nil {
 			return nil, err
 		}
@@ -268,12 +346,7 @@ func fetchAmazonLinuxPackagesURLs(kv kernelrelease.KernelRelease, targetType Typ
 			if err != nil {
 				log.Fatal(err)
 			}
-			base := repo
-			if targetType == TargetTypeAmazonLinux2 {
-				base = amazonlinux2baseURL
-			}
-			href = strings.ReplaceAll(href, "../", "")
-			urls = append(urls, fmt.Sprintf("%s/%s", base, href))
+			urls = append(urls, fmt.Sprintf("%s/%s", repo, href))
 		}
 
 		if err := dbFile.Close(); err != nil {


Test patch:
diff --git a/cmd/testdata/completion-targets.txt b/cmd/testdata/completion-targets.txt
index 765ab29..beaa23d 100644
--- a/cmd/testdata/completion-targets.txt
+++ b/cmd/testdata/completion-targets.txt
@@ -1,5 +1,6 @@
 amazonlinux
 amazonlinux2
+amazonlinux2022
 centos
 debian
 flatcar