Skip to content

Commit 1643334

Browse files
Pranav GoyalGitHub Enterprise
authored andcommitted
Merge pull request #515 from mq-cloudpak/pranav-2308-removing-amicontained-dependency-cd
Pranav 2308 removing amicontained dependency in CD branch
2 parents 77ad496 + c9917ae commit 1643334

File tree

8 files changed

+293
-337
lines changed

8 files changed

+293
-337
lines changed

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ module github.com/ibm-messaging/mq-container
33
go 1.19
44

55
require (
6-
github.com/genuinetools/amicontained v0.4.3
76
github.com/ibm-messaging/mq-golang v2.0.0+incompatible
87
github.com/prometheus/client_golang v1.12.0
98
github.com/prometheus/client_model v0.2.0
9+
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
1010
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
1111
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
1212
software.sslmate.com/src/go-pkcs12 v0.0.0-20200830195227-52f69702a001
@@ -19,6 +19,5 @@ require (
1919
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
2020
github.com/prometheus/common v0.32.1 // indirect
2121
github.com/prometheus/procfs v0.7.3 // indirect
22-
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
2322
google.golang.org/protobuf v1.26.0 // indirect
2423
)

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
5757
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
5858
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
5959
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
60-
github.com/genuinetools/amicontained v0.4.3 h1:cqq9XiAHfWWY3dk8VU8bSJFu9yh8Il5coEdeTAPq72o=
61-
github.com/genuinetools/amicontained v0.4.3/go.mod h1:PAMZkg9CcUTa6gNyULQ6tOMTMEb2HTKJufvKeFqDw+o=
6260
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
6361
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
6462
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
/*
2+
The MIT License (MIT)
3+
Copyright (c) 2018 Jessica Frazelle
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18+
SOFTWARE.
19+
*/
20+
21+
/*
22+
The code for amicontained.go is forked from
23+
https://github.com/genuinetools/bpfd/blob/434b609b3d4a5aeb461109b1167b68e000b72f69/proc/proc.go
24+
The code was forked when the latest details are as "Latest commit 871fc34 on Sep 18, 2018"
25+
*/
26+
27+
package containerruntime
28+
29+
import (
30+
"fmt"
31+
"io/ioutil"
32+
"os"
33+
"path/filepath"
34+
"regexp"
35+
"strings"
36+
37+
"github.com/syndtr/gocapability/capability"
38+
"golang.org/x/sys/unix"
39+
)
40+
41+
// ContainerRuntime is the type for the various container runtime strings.
42+
type ContainerRuntime string
43+
44+
// SeccompMode is the type for the various seccomp mode strings.
45+
type SeccompMode string
46+
47+
const (
48+
// RuntimeDocker is the string for the docker runtime.
49+
RuntimeDocker ContainerRuntime = "docker"
50+
// RuntimeRkt is the string for the rkt runtime.
51+
RuntimeRkt ContainerRuntime = "rkt"
52+
// RuntimeNspawn is the string for the systemd-nspawn runtime.
53+
RuntimeNspawn ContainerRuntime = "systemd-nspawn"
54+
// RuntimeLXC is the string for the lxc runtime.
55+
RuntimeLXC ContainerRuntime = "lxc"
56+
// RuntimeLXCLibvirt is the string for the lxc-libvirt runtime.
57+
RuntimeLXCLibvirt ContainerRuntime = "lxc-libvirt"
58+
// RuntimeOpenVZ is the string for the openvz runtime.
59+
RuntimeOpenVZ ContainerRuntime = "openvz"
60+
// RuntimeKubernetes is the string for the kubernetes runtime.
61+
RuntimeKubernetes ContainerRuntime = "kube"
62+
// RuntimeGarden is the string for the garden runtime.
63+
RuntimeGarden ContainerRuntime = "garden"
64+
// RuntimePodman is the string for the podman runtime.
65+
RuntimePodman ContainerRuntime = "podman"
66+
// RuntimeNotFound is the string for when no container runtime is found.
67+
RuntimeNotFound ContainerRuntime = "not-found"
68+
69+
// SeccompModeDisabled is equivalent to "0" in the /proc/{pid}/status file.
70+
SeccompModeDisabled SeccompMode = "disabled"
71+
// SeccompModeStrict is equivalent to "1" in the /proc/{pid}/status file.
72+
SeccompModeStrict SeccompMode = "strict"
73+
// SeccompModeFiltering is equivalent to "2" in the /proc/{pid}/status file.
74+
SeccompModeFiltering SeccompMode = "filtering"
75+
76+
apparmorUnconfined = "unconfined"
77+
78+
uint32Max = 4294967295
79+
80+
statusFileValue = ":(.*)"
81+
)
82+
83+
var (
84+
// ContainerRuntimes contains all the container runtimes.
85+
ContainerRuntimes = []ContainerRuntime{
86+
RuntimeDocker,
87+
RuntimeRkt,
88+
RuntimeNspawn,
89+
RuntimeLXC,
90+
RuntimeLXCLibvirt,
91+
RuntimeOpenVZ,
92+
RuntimeKubernetes,
93+
RuntimeGarden,
94+
RuntimePodman,
95+
}
96+
97+
seccompModes = map[string]SeccompMode{
98+
"0": SeccompModeDisabled,
99+
"1": SeccompModeStrict,
100+
"2": SeccompModeFiltering,
101+
}
102+
103+
statusFileValueRegex = regexp.MustCompile(statusFileValue)
104+
)
105+
106+
// GetContainerRuntime returns the container runtime the process is running in.
107+
// If pid is less than one, it returns the runtime for "self".
108+
func GetContainerRuntime(tgid, pid int) ContainerRuntime {
109+
file := "/proc/self/cgroup"
110+
if pid > 0 {
111+
if tgid > 0 {
112+
file = fmt.Sprintf("/proc/%d/task/%d/cgroup", tgid, pid)
113+
} else {
114+
file = fmt.Sprintf("/proc/%d/cgroup", pid)
115+
}
116+
}
117+
118+
// read the cgroups file
119+
a := readFileString(file)
120+
runtime := getContainerRuntime(a)
121+
if runtime != RuntimeNotFound {
122+
return runtime
123+
}
124+
125+
// /proc/vz exists in container and outside of the container, /proc/bc only outside of the container.
126+
if fileExists("/proc/vz") && !fileExists("/proc/bc") {
127+
return RuntimeOpenVZ
128+
}
129+
130+
a = os.Getenv("container")
131+
runtime = getContainerRuntime(a)
132+
if runtime != RuntimeNotFound {
133+
return runtime
134+
}
135+
136+
// PID 1 might have dropped this information into a file in /run.
137+
// Read from /run/systemd/container since it is better than accessing /proc/1/environ,
138+
// which needs CAP_SYS_PTRACE
139+
a = readFileString("/run/systemd/container")
140+
runtime = getContainerRuntime(a)
141+
if runtime != RuntimeNotFound {
142+
return runtime
143+
}
144+
145+
return RuntimeNotFound
146+
}
147+
148+
func getContainerRuntime(input string) ContainerRuntime {
149+
if len(strings.TrimSpace(input)) < 1 {
150+
return RuntimeNotFound
151+
}
152+
153+
for _, runtime := range ContainerRuntimes {
154+
if strings.Contains(input, string(runtime)) {
155+
return runtime
156+
}
157+
}
158+
159+
return RuntimeNotFound
160+
}
161+
162+
func fileExists(file string) bool {
163+
if _, err := os.Stat(file); !os.IsNotExist(err) {
164+
return true
165+
}
166+
return false
167+
}
168+
169+
func readFile(file string) []byte {
170+
if !fileExists(file) {
171+
return nil
172+
}
173+
// filepath.clean was added to resolve the gosec build failure
174+
// with error "Potential file inclusion via variable"
175+
b, err := ioutil.ReadFile(filepath.Clean(file))
176+
if err != nil {
177+
return nil
178+
}
179+
return b
180+
}
181+
182+
// GetCapabilities returns the allowed capabilities for the process.
183+
// If pid is less than one, it returns the capabilities for "self".
184+
func GetCapabilities(pid int) (map[string][]string, error) {
185+
allCaps := capability.List()
186+
187+
caps, err := capability.NewPid(pid)
188+
if err != nil {
189+
return nil, err
190+
}
191+
192+
allowedCaps := map[string][]string{}
193+
allowedCaps["EFFECTIVE | PERMITTED | INHERITABLE"] = []string{}
194+
allowedCaps["BOUNDING"] = []string{}
195+
allowedCaps["AMBIENT"] = []string{}
196+
197+
for _, cap := range allCaps {
198+
if caps.Get(capability.CAPS, cap) {
199+
allowedCaps["EFFECTIVE | PERMITTED | INHERITABLE"] = append(allowedCaps["EFFECTIVE | PERMITTED | INHERITABLE"], cap.String())
200+
}
201+
if caps.Get(capability.BOUNDING, cap) {
202+
allowedCaps["BOUNDING"] = append(allowedCaps["BOUNDING"], cap.String())
203+
}
204+
if caps.Get(capability.AMBIENT, cap) {
205+
allowedCaps["AMBIENT"] = append(allowedCaps["AMBIENT"], cap.String())
206+
}
207+
}
208+
209+
return allowedCaps, nil
210+
}
211+
212+
// GetSeccompEnforcingMode returns the seccomp enforcing level (disabled, filtering, strict)
213+
// for a process.
214+
// If pid is less than one, it returns the seccomp enforcing mode for "self".
215+
func GetSeccompEnforcingMode(pid int) SeccompMode {
216+
file := "/proc/self/status"
217+
if pid > 0 {
218+
file = fmt.Sprintf("/proc/%d/status", pid)
219+
}
220+
221+
return getSeccompEnforcingMode(readFileString(file))
222+
}
223+
224+
func getSeccompEnforcingMode(input string) SeccompMode {
225+
mode := getStatusEntry(input, "Seccomp:")
226+
sm, ok := seccompModes[mode]
227+
if ok {
228+
return sm
229+
}
230+
231+
// Pre linux 3.8, check if Seccomp is supported, via CONFIG_SECCOMP.
232+
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
233+
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
234+
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
235+
return SeccompModeStrict
236+
}
237+
}
238+
239+
return SeccompModeDisabled
240+
}
241+
242+
// TODO: make this function more efficient and read the file line by line.
243+
func getStatusEntry(input, find string) string {
244+
// Split status file string by line
245+
statusMappings := strings.Split(input, "\n")
246+
statusMappings = deleteEmpty(statusMappings)
247+
248+
for _, line := range statusMappings {
249+
if strings.Contains(line, find) {
250+
matches := statusFileValueRegex.FindStringSubmatch(line)
251+
if len(matches) > 1 {
252+
return strings.TrimSpace(matches[1])
253+
}
254+
}
255+
}
256+
257+
return ""
258+
}
259+
260+
func deleteEmpty(s []string) []string {
261+
var r []string
262+
for _, str := range s {
263+
if strings.TrimSpace(str) != "" {
264+
r = append(r, strings.TrimSpace(str))
265+
}
266+
}
267+
return r
268+
}
269+
270+
func readFileString(file string) string {
271+
b := readFile(file)
272+
if b == nil {
273+
return ""
274+
}
275+
return strings.TrimSpace(string(b))
276+
}

internal/containerruntime/runtime.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
© Copyright IBM Corporation 2019
2+
© Copyright IBM Corporation 2019,2023
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -19,12 +19,10 @@ import (
1919
"fmt"
2020
"io/ioutil"
2121
"strings"
22-
23-
"github.com/genuinetools/amicontained/container"
2422
)
2523

26-
func GetContainerRuntime() (string, error) {
27-
return container.DetectRuntime()
24+
func DetectContainerRuntime() ContainerRuntime {
25+
return GetContainerRuntime(0, 1)
2826
}
2927

3028
func GetBaseImage() (string, error) {
@@ -45,17 +43,15 @@ func GetBaseImage() (string, error) {
4543
}
4644

4745
// GetCapabilities gets the Linux capabilities (e.g. setuid, setgid). See https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
48-
func GetCapabilities() (map[string][]string, error) {
49-
return container.Capabilities()
46+
func GetContainerCapabilities() (map[string][]string, error) {
47+
//passing the pid as 1 since runmqserver initializes, creates and starts a queue manager, as PID 1 in a container
48+
return GetCapabilities(1)
5049
}
5150

5251
// GetSeccomp gets the seccomp enforcing mode, which affects which kernel calls can be made
53-
func GetSeccomp() (string, error) {
54-
s, err := container.SeccompEnforcingMode()
55-
if err != nil {
56-
return "", fmt.Errorf("Failed to get container SeccompEnforcingMode: %v", err)
57-
}
58-
return s, nil
52+
func GetSeccomp() SeccompMode {
53+
//passing the pid as 1 since runmqserver initializes, creates and starts a queue manager, as PID 1 in a container
54+
return GetSeccompEnforcingMode(1)
5955
}
6056

6157
// GetSecurityAttributes gets the security attributes of the current process.

pkg/containerruntimelogger/logruntime.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ func LogContainerDetails(log *logger.Logger) error {
3636
if err == nil {
3737
log.Printf("Linux kernel version: %v", kv)
3838
}
39-
cr, err := containerruntime.GetContainerRuntime()
40-
if err == nil {
41-
log.Printf("Container runtime: %v", cr)
42-
}
39+
cr := containerruntime.DetectContainerRuntime()
40+
log.Printf("Container runtime: %v", cr)
41+
4342
bi, err := containerruntime.GetBaseImage()
4443
if err == nil {
4544
log.Printf("Base image: %v", bi)
@@ -55,7 +54,7 @@ func LogContainerDetails(log *logger.Logger) error {
5554
log.Printf("Running as user ID %v with primary group %v, and supplementary groups %v", u.UID, u.PrimaryGID, strings.Trim(strings.Join(strings.Fields(fmt.Sprint(u.SupplementalGID)), ","), "[]"))
5655
}
5756
}
58-
caps, err := containerruntime.GetCapabilities()
57+
caps, err := containerruntime.GetCapabilities(1)
5958
capLogged := false
6059
if err == nil {
6160
for k, v := range caps {
@@ -70,10 +69,9 @@ func LogContainerDetails(log *logger.Logger) error {
7069
} else {
7170
log.Errorf("Error getting capabilities: %v", err)
7271
}
73-
sc, err := containerruntime.GetSeccomp()
74-
if err == nil {
75-
log.Printf("seccomp enforcing mode: %v", sc)
76-
}
72+
sc := containerruntime.GetSeccomp()
73+
log.Printf("seccomp enforcing mode: %v", sc)
74+
7775
log.Printf("Process security attributes: %v", containerruntime.GetSecurityAttributes())
7876
m, err := containerruntime.GetMounts()
7977
if err == nil {

0 commit comments

Comments
 (0)