178 lines
4.4 KiB
Go
178 lines
4.4 KiB
Go
/*
|
|
© Copyright IBM Corporation 2017, 2018
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os/user"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/genuinetools/amicontained/container"
|
|
)
|
|
|
|
func logContainerRuntime() error {
|
|
r, err := container.DetectRuntime()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Printf("Container runtime: %v", r)
|
|
return nil
|
|
}
|
|
|
|
func logBaseImage() error {
|
|
buf, err := ioutil.ReadFile("/etc/os-release")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
lines := strings.Split(string(buf), "\n")
|
|
for _, l := range lines {
|
|
if strings.HasPrefix(l, "PRETTY_NAME=") {
|
|
words := strings.Split(l, "\"")
|
|
if len(words) >= 2 {
|
|
log.Printf("Base image: %v", words[1])
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func logUser() {
|
|
u, err := user.Current()
|
|
if err == nil {
|
|
g, err := u.GroupIds()
|
|
if err != nil {
|
|
log.Printf("Running as user ID %v (%v) with primary group %v", u.Uid, u.Name, u.Gid)
|
|
} else {
|
|
// Look for the primary group in the list of group IDs
|
|
for i, v := range g {
|
|
if v == u.Gid {
|
|
// Remove the element from the slice
|
|
g = append(g[:i], g[i+1:]...)
|
|
}
|
|
}
|
|
log.Printf("Running as user ID %v (%v) with primary group %v, and supplemental groups %v", u.Uid, u.Name, u.Gid, strings.Join(g, ","))
|
|
}
|
|
}
|
|
}
|
|
|
|
// logCapabilities logs the Linux capabilities (e.g. setuid, setgid). See https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
|
|
func logCapabilities() error {
|
|
caps, err := container.Capabilities()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for k, v := range caps {
|
|
if len(v) > 0 {
|
|
log.Printf("Capabilities (%s set): %v", strings.ToLower(k), strings.Join(v, ","))
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// logSeccomp logs the seccomp enforcing mode, which affects which kernel calls can be made
|
|
func logSeccomp() error {
|
|
s, err := container.SeccompEnforcingMode()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Printf("seccomp enforcing mode: %v", s)
|
|
return nil
|
|
}
|
|
|
|
// logSecurityAttributes logs the security attributes of the current process.
|
|
// The security attributes indicate whether AppArmor or SELinux are being used,
|
|
// and what the level of confinement is.
|
|
func logSecurityAttributes() error {
|
|
a, err := readProc("/proc/self/attr/current")
|
|
// On some systems, if AppArmor or SELinux are not installed, you get an
|
|
// error when you try and read `/proc/self/attr/current`, even though the
|
|
// file exists.
|
|
if err != nil || a == "" {
|
|
a = "none"
|
|
}
|
|
log.Printf("Process security attributes: %v", a)
|
|
return nil
|
|
}
|
|
|
|
func readProc(filename string) (value string, err error) {
|
|
buf, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return strings.TrimSpace(string(buf)), nil
|
|
}
|
|
|
|
func readMounts() error {
|
|
all, err := readProc("/proc/mounts")
|
|
if err != nil {
|
|
log.Print("Error: Couldn't read /proc/mounts")
|
|
return err
|
|
}
|
|
lines := strings.Split(all, "\n")
|
|
detected := false
|
|
for i := range lines {
|
|
parts := strings.Split(lines[i], " ")
|
|
//dev := parts[0]
|
|
mountPoint := parts[1]
|
|
fsType := parts[2]
|
|
if strings.Contains(mountPoint, "/mnt") {
|
|
log.Printf("Detected '%v' volume mounted to %v", fsType, mountPoint)
|
|
detected = true
|
|
}
|
|
}
|
|
if !detected {
|
|
log.Print("No volume detected. Persistent messages may be lost")
|
|
} else {
|
|
return checkFS("/mnt/mqm")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func logConfig() error {
|
|
log.Printf("CPU architecture: %v", runtime.GOARCH)
|
|
if runtime.GOOS == "linux" {
|
|
var err error
|
|
osr, err := readProc("/proc/sys/kernel/osrelease")
|
|
if err != nil {
|
|
log.Print(err)
|
|
} else {
|
|
log.Printf("Linux kernel version: %v", osr)
|
|
}
|
|
logContainerRuntime()
|
|
logBaseImage()
|
|
fileMax, err := readProc("/proc/sys/fs/file-max")
|
|
if err != nil {
|
|
log.Print(err)
|
|
} else {
|
|
log.Printf("Maximum file handles: %v", fileMax)
|
|
}
|
|
logUser()
|
|
logCapabilities()
|
|
logSeccomp()
|
|
logSecurityAttributes()
|
|
err = readMounts()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
return fmt.Errorf("Unsupported platform: %v", runtime.GOOS)
|
|
}
|
|
return nil
|
|
}
|