Skip to content

Commit

Permalink
Merge 5092582 into 3fe853a
Browse files Browse the repository at this point in the history
  • Loading branch information
tuxerrante authored Feb 13, 2023
2 parents 3fe853a + 5092582 commit 925e46f
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 23 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

# Kapparmor
- [Kapparmor](#kapparmor)
- [Features and constraints](#features-and-constraints)
- [Install](#install)
- [Testing](#testing)
- [How to initialize this project](#how-to-initialize-this-project)
- [Test the app locally](#test-the-app-locally)
Expand Down Expand Up @@ -32,6 +34,16 @@ You can view which profiles are loaded on a node by checking the /sys/kernel/sec

This work was inspired by [kubernetes/apparmor-loader](https://github.com/kubernetes/kubernetes/tree/master/test/images/apparmor-loader).

## Features and constraints
- Profile names have to start with 'custom.' and to be equal as the filename containing it

## Install
You can install the helm chart like this
```sh
helm repo add tuxerrante https://tuxerrante.github.io/kapparmor
helm upgrade kapparmor --install --atomic --timeout 30s --debug --set image.tag=dev tuxerrante/kapparmor

```
## Testing
[Set up a Microk8s environment](./docs/microk8s.md).

Expand All @@ -52,7 +64,6 @@ Test Helm Chart creation
# --- Check the Helm chart
# https://github.com/helm/chart-testing/issues/464
echo Linting the Helm chart

helm lint --debug --strict charts/kapparmor/

docker run -it --network host --workdir=/data --volume ~/.kube/config:/root/.kube/config:ro \
Expand Down
13 changes: 9 additions & 4 deletions charts/kapparmor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [ ] Update an existing profile
- [ ] Remove an existing profile
- [ ] Remove a non existing profile
1. Enforce profiles filenames to be the same as the profile names
- [ ] check current confinement state of the app
2. Remove kubernetes Service and DaemonSet exposed ports if useless
3. Evaluate an automatic changelog generation from commits like [googleapis/release-please](https://github.com/googleapis/release-please)
4. Add daemonset commands for checking readiness
5. Add tests for all the main functions
6. Add test for checking current confinement state of the app
7. Test on multiple nodes cluster

## [0.1.1]() - 2023-02-13
### Fixed
- Moved shared testing functions to a dedicated module
- Minor documentation and readme fixes
### Added
- Enforce profiles filenames to be the same as the profile names
- Changelog automatically read by chart-releaser


## [0.1.0](https://github.com/tuxerrante/kapparmor/releases/tag/kapparmor-0.1.0) - 2023-02-01
### Fixed
Expand Down
4 changes: 2 additions & 2 deletions charts/kapparmor/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ type: application
home: https://artifacthub.io
kubeVersion: ">= 1.23.0-0"

version: "0.1.0"
appVersion: "0.1.0"
version: "0.1.1"
appVersion: "0.1.1"

keywords:
- kubernetes
Expand Down
34 changes: 32 additions & 2 deletions go/src/app/filesystemOperations.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bufio"
"bytes"
"errors"
"fmt"
Expand All @@ -27,7 +28,7 @@ func preFlightChecks() int {
log.Fatal(err)
}

// Check if custom directory exists
// Check if custom directory exists, creates it otherwise
if _, err := os.Stat(ETC_APPARMORD); errors.Is(err, os.ErrNotExist) {
err := os.Mkdir(ETC_APPARMORD, os.ModePerm)
if err != nil {
Expand Down Expand Up @@ -68,7 +69,7 @@ func HasTheSameContent(fsys fs.FS, filePath1, filePath2 string) (bool, error) {
return false, err
}

log.Printf(" dir: %v, First file path: %v, Second file path: %v", dir, filePath1, filePath2)
log.Printf(" First file path: %v, Second file path: %v", filePath1, filePath2)

for _, file := range dir {
if filePath1 == file.Name() {
Expand Down Expand Up @@ -143,13 +144,42 @@ func areProfilesReadable(FOLDER_NAME string) (bool, map[string]bool) {
log.Printf("'%s' will be skipped.\n", filename)
continue
}

if err := IsProfileNameCorrect(FOLDER_NAME, filename); err != nil {
log.Fatalf("Profile name and filename '%s'are not the same!", filename)
}

log.Printf("- %s\n", filename)
filenames[filename] = true
}

return true, filenames
}

// isProfileNameCorrect returns true if the filename is the same as the profile name
func IsProfileNameCorrect(directory, filename string) error {

fileReader, err := os.Open(path.Join(directory, filename))
if err != nil {
return err
}
scanner := bufio.NewScanner(fileReader)
// Read only first line
scanner.Scan()
fileFirstLine := scanner.Text()
fileProfileNameSlice := strings.SplitAfterN(fileFirstLine, " ", 3)
if len(fileProfileNameSlice) < 2 {
return fmt.Errorf("there is an issue with the '%s' profile name, please check if the syntax is 'profile custom.YourName { ... }' or check again Unattached Profiles definition at https://documentation.suse.com/sles/15-SP1/html/SLES-all/cha-apparmor-profiles.html#sec-apparmor-profiles-types-unattached", filename)
}
fileProfileName := strings.TrimSpace(fileProfileNameSlice[1])

if filename != fileProfileName {
return fmt.Errorf("filename '%s' and profile name '%s' seems to be different", filename, fileProfileName)
}

return nil
}

// CopyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherwise, attempt to create a hard link
// between the two files. If that fail, copy the file contents from src to dst.
Expand Down
2 changes: 1 addition & 1 deletion go/src/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func loadNewProfiles() ([]string, error) {
log.Fatalf(">> Error reading existing profiles.\n%v", err)
}

// Clean eventually empty keys
// Clean possible empty keys
delete(customLoadedProfiles, "")
delete(loadedProfiles, "")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,3 @@ func TestHasTheSameContent(t *testing.T) {
assertBool(t, got, want)
})
}

func ok(t testing.TB, err error) {
if err != nil {
t.Fatalf("Function call returned an error:\n %s", err)
}
}

func assertBool(t *testing.T, got, want bool) {
t.Helper()
if got != want {
t.Fatalf("Bool check failed! Got %t, expected %t", got, want)
}
}
27 changes: 27 additions & 0 deletions go/src/app/t_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"testing"
)

func ok(t testing.TB, err error) {
if err != nil {
t.Fatalf("Function call returned an error:\n %s", err)
}
}

func assertBool(t *testing.T, got, want bool) {
t.Helper()
if got != want {
t.Fatalf("Bool check failed! Got %t, expected %t", got, want)
}
}

func assertError(t *testing.T, got, want error) {
t.Helper()
if want != nil {
if want.Error() != got.Error() {
t.Fatalf("Error check failed! Got %t, expected %t", got, want)
}
}
}
61 changes: 61 additions & 0 deletions go/src/app/t_profiles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package main

import (
"errors"
"log"
"os"
"path"
"testing"
)

const directory string = "."

/*
TestIsProfileNameCorrect checks if profile names and filenames match
The name must not begin with a : or . character.
If it contains a whitespace, it must be quoted.
If the name begins with a /, the profile is considered to be a standard profile,
https://documentation.suse.com/sles/15-SP1/html/SLES-all/cha-apparmor-profiles.html#sec-apparmor-profiles-types-unattached
*/
func TestIsProfileNameCorrect(t *testing.T) {

t.Parallel()

// table-driven tests
var tests = []struct {
name, filename, profileFirstLine string
want error
}{
{
name: "Confirm a filename equal as profile name is OK",
filename: "custom.myValidProfile",
profileFirstLine: "profile custom.myValidProfile flags=(attach_disconnected) {",
want: nil,
},
{
name: "Deny a filename different from profile name",
filename: "custom.myNotValidProfile",
profileFirstLine: "profile myNotValidProfile flags=(attach_disconnected) {",
want: errors.New("filename 'custom.myNotValidProfile' and profile name 'myNotValidProfile' seems to be different"),
},
{
name: "Deny a filename different from profile name",
filename: "custom.myNotValidProfile.bkp",
profileFirstLine: "profile custom.myNotValidProfile flags=(attach_disconnected) {",
want: errors.New("filename 'custom.myNotValidProfile.bkp' and profile name 'custom.myNotValidProfile' seems to be different"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := os.WriteFile(path.Join(directory, tt.filename), []byte(tt.profileFirstLine), 0666)
if err != nil {
log.Fatal(err)
}
defer os.Remove(path.Join(directory, tt.filename))

got := IsProfileNameCorrect(directory, tt.filename)
assertError(t, got, tt.want)
})
}
}

0 comments on commit 925e46f

Please sign in to comment.