Initial commit
This commit is contained in:
110
vendor/github.com/hyperhq/hypercli/profiles/apparmor/apparmor.go
generated
vendored
Normal file
110
vendor/github.com/hyperhq/hypercli/profiles/apparmor/apparmor.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// +build linux
|
||||
|
||||
package apparmor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/docker/pkg/aaparser"
|
||||
)
|
||||
|
||||
var (
|
||||
// profileDirectory is the file store for apparmor profiles and macros.
|
||||
profileDirectory = "/etc/apparmor.d"
|
||||
// defaultProfilePath is the default path for the apparmor profile to be saved.
|
||||
defaultProfilePath = path.Join(profileDirectory, "docker")
|
||||
)
|
||||
|
||||
// profileData holds information about the given profile for generation.
|
||||
type profileData struct {
|
||||
// Name is profile name.
|
||||
Name string
|
||||
// ExecPath is the path to the docker binary.
|
||||
ExecPath string
|
||||
// Imports defines the apparmor functions to import, before defining the profile.
|
||||
Imports []string
|
||||
// InnerImports defines the apparmor functions to import in the profile.
|
||||
InnerImports []string
|
||||
// MajorVersion is the apparmor_parser major version.
|
||||
MajorVersion int
|
||||
// MinorVersion is the apparmor_parser minor version.
|
||||
MinorVersion int
|
||||
}
|
||||
|
||||
// generateDefault creates an apparmor profile from ProfileData.
|
||||
func (p *profileData) generateDefault(out io.Writer) error {
|
||||
compiled, err := template.New("apparmor_profile").Parse(baseTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if macroExists("tunables/global") {
|
||||
p.Imports = append(p.Imports, "#include <tunables/global>")
|
||||
} else {
|
||||
p.Imports = append(p.Imports, "@{PROC}=/proc/")
|
||||
}
|
||||
if macroExists("abstractions/base") {
|
||||
p.InnerImports = append(p.InnerImports, "#include <abstractions/base>")
|
||||
}
|
||||
if err := compiled.Execute(out, p); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// macrosExists checks if the passed macro exists.
|
||||
func macroExists(m string) bool {
|
||||
_, err := os.Stat(path.Join(profileDirectory, m))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// InstallDefault generates a default profile and installs it in the
|
||||
// ProfileDirectory with `apparmor_parser`.
|
||||
func InstallDefault(name string) error {
|
||||
// Make sure the path where they want to save the profile exists
|
||||
if err := os.MkdirAll(profileDirectory, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := profileData{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(defaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.generateDefault(f); err != nil {
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
|
||||
if err := aaparser.LoadProfile(defaultProfilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsLoaded checks if a passed profile as been loaded into the kernel.
|
||||
func IsLoaded(name string) error {
|
||||
file, err := os.Open("/sys/kernel/security/apparmor/profiles")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := bufio.NewReader(file)
|
||||
for {
|
||||
p, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasPrefix(p, name+" ") {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
50
vendor/github.com/hyperhq/hypercli/profiles/apparmor/template.go
generated
vendored
Normal file
50
vendor/github.com/hyperhq/hypercli/profiles/apparmor/template.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// +build linux
|
||||
|
||||
package apparmor
|
||||
|
||||
// baseTemplate defines the default apparmor profile for containers.
|
||||
const baseTemplate = `
|
||||
{{range $value := .Imports}}
|
||||
{{$value}}
|
||||
{{end}}
|
||||
|
||||
profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
|
||||
{{range $value := .InnerImports}}
|
||||
{{$value}}
|
||||
{{end}}
|
||||
|
||||
network,
|
||||
capability,
|
||||
file,
|
||||
umount,
|
||||
|
||||
deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
|
||||
# deny write to files not in /proc/<number>/** or /proc/sys/**
|
||||
deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w,
|
||||
deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
|
||||
deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/
|
||||
deny @{PROC}/sysrq-trigger rwklx,
|
||||
deny @{PROC}/mem rwklx,
|
||||
deny @{PROC}/kmem rwklx,
|
||||
deny @{PROC}/kcore rwklx,
|
||||
|
||||
deny mount,
|
||||
|
||||
deny /sys/[^f]*/** wklx,
|
||||
deny /sys/f[^s]*/** wklx,
|
||||
deny /sys/fs/[^c]*/** wklx,
|
||||
deny /sys/fs/c[^g]*/** wklx,
|
||||
deny /sys/fs/cg[^r]*/** wklx,
|
||||
deny /sys/firmware/efi/efivars/** rwklx,
|
||||
deny /sys/kernel/security/** rwklx,
|
||||
|
||||
{{if ge .MajorVersion 2}}{{if ge .MinorVersion 8}}
|
||||
# suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
|
||||
ptrace (trace,read) peer=docker-default,
|
||||
{{end}}{{end}}
|
||||
{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}}
|
||||
# docker daemon confinement requires explict allow rule for signal
|
||||
signal (receive) set=(kill,term) peer={{.ExecPath}},
|
||||
{{end}}{{end}}
|
||||
}
|
||||
`
|
||||
27
vendor/github.com/hyperhq/hypercli/profiles/seccomp/fixtures/example.json
generated
vendored
Executable file
27
vendor/github.com/hyperhq/hypercli/profiles/seccomp/fixtures/example.json
generated
vendored
Executable file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"defaultAction": "SCMP_ACT_ERRNO",
|
||||
"syscalls": [
|
||||
{
|
||||
"name": "clone",
|
||||
"action": "SCMP_ACT_ALLOW",
|
||||
"args": [
|
||||
{
|
||||
"index": 0,
|
||||
"value": 2080505856,
|
||||
"valueTwo": 0,
|
||||
"op": "SCMP_CMP_MASKED_EQ"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "open",
|
||||
"action": "SCMP_ACT_ALLOW",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "close",
|
||||
"action": "SCMP_ACT_ALLOW",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
94
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp.go
generated
vendored
Normal file
94
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// +build linux
|
||||
|
||||
package seccomp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/seccomp"
|
||||
)
|
||||
|
||||
// GetDefaultProfile returns the default seccomp profile.
|
||||
func GetDefaultProfile() *configs.Seccomp {
|
||||
return defaultSeccompProfile
|
||||
}
|
||||
|
||||
// LoadProfile takes a file path a decodes the seccomp profile.
|
||||
func LoadProfile(body string) (*configs.Seccomp, error) {
|
||||
var config types.Seccomp
|
||||
if err := json.Unmarshal([]byte(body), &config); err != nil {
|
||||
return nil, fmt.Errorf("Decoding seccomp profile failed: %v", err)
|
||||
}
|
||||
|
||||
return setupSeccomp(&config)
|
||||
}
|
||||
|
||||
func setupSeccomp(config *types.Seccomp) (newConfig *configs.Seccomp, err error) {
|
||||
if config == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// No default action specified, no syscalls listed, assume seccomp disabled
|
||||
if config.DefaultAction == "" && len(config.Syscalls) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
newConfig = new(configs.Seccomp)
|
||||
newConfig.Syscalls = []*configs.Syscall{}
|
||||
|
||||
// if config.Architectures == 0 then libseccomp will figure out the architecture to use
|
||||
if len(config.Architectures) > 0 {
|
||||
newConfig.Architectures = []string{}
|
||||
for _, arch := range config.Architectures {
|
||||
newArch, err := seccomp.ConvertStringToArch(string(arch))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newConfig.Architectures = append(newConfig.Architectures, newArch)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert default action from string representation
|
||||
newConfig.DefaultAction, err = seccomp.ConvertStringToAction(string(config.DefaultAction))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Loop through all syscall blocks and convert them to libcontainer format
|
||||
for _, call := range config.Syscalls {
|
||||
newAction, err := seccomp.ConvertStringToAction(string(call.Action))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newCall := configs.Syscall{
|
||||
Name: call.Name,
|
||||
Action: newAction,
|
||||
Args: []*configs.Arg{},
|
||||
}
|
||||
|
||||
// Loop through all the arguments of the syscall and convert them
|
||||
for _, arg := range call.Args {
|
||||
newOp, err := seccomp.ConvertStringToOperator(string(arg.Op))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newArg := configs.Arg{
|
||||
Index: arg.Index,
|
||||
Value: arg.Value,
|
||||
ValueTwo: arg.ValueTwo,
|
||||
Op: newOp,
|
||||
}
|
||||
|
||||
newCall.Args = append(newCall.Args, &newArg)
|
||||
}
|
||||
|
||||
newConfig.Syscalls = append(newConfig.Syscalls, &newCall)
|
||||
}
|
||||
|
||||
return newConfig, nil
|
||||
}
|
||||
1600
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp_default.go
generated
vendored
Normal file
1600
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp_default.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
19
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp_test.go
generated
vendored
Normal file
19
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp_test.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// +build linux
|
||||
|
||||
package seccomp
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadProfile(t *testing.T) {
|
||||
f, err := ioutil.ReadFile("fixtures/example.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := LoadProfile(string(f)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
9
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp_unsupported.go
generated
vendored
Normal file
9
vendor/github.com/hyperhq/hypercli/profiles/seccomp/seccomp_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build linux,!seccomp
|
||||
|
||||
package seccomp
|
||||
|
||||
import "github.com/opencontainers/runc/libcontainer/configs"
|
||||
|
||||
var (
|
||||
defaultSeccompProfile *configs.Seccomp
|
||||
)
|
||||
Reference in New Issue
Block a user