Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ jobs:
- uses: docker/setup-buildx-action@v3 # NOSONAR githubactions:S7637 - verified action creator

- name: Log in to the container registry
if: github.event_name != 'pull_request'
if: true
uses: docker/login-action@v3 # NOSONAR githubactions:S7637 - verified action creator
with:
registry: ghcr.io
Expand All @@ -157,7 +157,7 @@ jobs:
uses: docker/build-push-action@v6 # NOSONAR githubactions:S7637 - verified action creator
with:
context: ./
push: ${{ github.event_name != 'pull_request' }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
Expand Down Expand Up @@ -244,7 +244,7 @@ jobs:
version: latest

- name: "[build] Upload packages to gcp internal repositories"
if: github.event_name != 'pull_request'
if: true
working-directory: ./dist
run: |
for deb in $(find * -name '*.deb'); do
Expand Down
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,10 @@ COPY --from=build /app/extension /extension
COPY --from=build /app/licenses /licenses

#We declare the javaagent directory a volume, so we can write the heartbeat to it, when read only
VOLUME /javaagent
COPY --chown=$USER_UID:$USER_GID javaagents/download/target/javaagent /javaagent


ENV STEADYBIT_EXTENSION_JAVA_AGENT_PATH=/javaagent
ENV STEADYBIT_EXTENSION_JAVA_AGENT_PATH=/javaagent:/tmp/javaagent
EXPOSE 8085 8081

ENTRYPOINT ["/extension"]
17 changes: 9 additions & 8 deletions extjvm/action_commons_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package extjvm

import (
"fmt"
"io"
"os/exec"
"strconv"
"time"

"github.com/shirou/gopsutil/v4/process"
"github.com/steadybit/action-kit/go/action_kit_api/v2"
"github.com/steadybit/extension-jvm/extjvm/jvm"
"github.com/steadybit/extension-jvm/extjvm/jvm/starttime"
"github.com/stretchr/testify/mock"
"io"
"os/exec"
"strconv"
"time"
)

type mockJavaFacade struct {
Expand Down Expand Up @@ -153,12 +154,12 @@ func (f *FakeJvm) VmArgs() string {
return ""
}

func (f *FakeJvm) UserId() string {
return ""
func (f *FakeJvm) UserId() int {
return -1
}

func (f *FakeJvm) GroupId() string {
return ""
func (f *FakeJvm) GroupId() int {
return -1
}

func (f *FakeJvm) Path() string {
Expand Down
2 changes: 1 addition & 1 deletion extjvm/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var (

func Exec(ctx context.Context, containerId string, name string, args ...string) *exec.Cmd {
runtime := path.Base(cfg.Path)
runtimeArgs := []string{"--root", cfg.Root, "exec", containerId, name}
runtimeArgs := []string{"--root", cfg.Root, "exec", "--user", "0:0", containerId, name}
if cfg.Debug {
runtimeArgs = append([]string{"--debug"}, runtimeArgs...)
}
Expand Down
18 changes: 9 additions & 9 deletions extjvm/jvm/java_process_inspector_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package jvm

import (
"github.com/steadybit/extension-jvm/extjvm/jvm/hsperf"
"github.com/steadybit/extension-jvm/extjvm/jvm/test"
"github.com/steadybit/extension-jvm/extjvm/utils"
"github.com/stretchr/testify/assert"
"os"
"strconv"
"strings"
"testing"
"time"

"github.com/steadybit/extension-jvm/extjvm/jvm/hsperf"
"github.com/steadybit/extension-jvm/extjvm/jvm/test"
"github.com/steadybit/extension-jvm/extjvm/utils"
"github.com/stretchr/testify/assert"
)

var hostname string
Expand Down Expand Up @@ -37,8 +37,8 @@ func Test_should_inspect_host_process_via_process(t *testing.T) {
case j := <-inspector.JavaVms:
assert.Equal(t, jvm.Pid(), j.Pid())
assert.Contains(t, j.CommandLine(), "60000")
assert.Equal(t, strconv.Itoa(os.Geteuid()), j.UserId())
assert.Equal(t, strconv.Itoa(os.Geteuid()), j.UserId())
assert.Equal(t, os.Getuid(), j.UserId())
assert.Equal(t, os.Getgid(), j.GroupId())
assert.Equal(t, hostname, j.Hostname())
assert.True(t, j.IsRunning())
assert.Condition(t, func() bool {
Expand Down Expand Up @@ -81,8 +81,8 @@ func Test_should_inspect_host_process_via_hsperf(t *testing.T) {
case j := <-inspector.JavaVms:
assert.Equal(t, jvm.Pid(), j.Pid())
assert.Contains(t, j.CommandLine(), "60000")
assert.Equal(t, strconv.Itoa(os.Geteuid()), j.UserId())
assert.Equal(t, strconv.Itoa(os.Geteuid()), j.UserId())
assert.Equal(t, os.Getuid(), j.UserId())
assert.Equal(t, os.Getgid(), j.GroupId())
assert.Equal(t, hostname, j.Hostname())
assert.True(t, j.IsRunning())
assert.Condition(t, func() bool {
Expand Down
49 changes: 35 additions & 14 deletions extjvm/jvm/jvm_attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"fmt"
"os"
"os/exec"
"os/user"
"runtime"
"strings"
"sync"
"time"

"github.com/rs/zerolog/log"
"github.com/steadybit/extension-jvm/extjvm/utils"
)

type Attachment interface {
Expand All @@ -23,12 +25,36 @@ const (
initJarName = "javaagent-init.jar"
)

var (
javaagentWorkDir string
javaagentWorkDirOnce = sync.OnceFunc(func() {
paths := strings.SplitN(os.Getenv("STEADYBIT_EXTENSION_JAVA_AGENT_PATH"), ":", 2)
if len(paths) == 0 {
panic("STEADYBIT_EXTENSION_JAVA_AGENT_PATH not set")
}

if len(paths) == 1 {
javaagentWorkDir = paths[0]
return
}

// A single time we copy the javaagent files to a writable location, as there will be also the heartbeat file created
javaagentWorkDir = paths[1]
if out, err := utils.RootCommandContext(context.Background(), "mkdir", "-p", javaagentWorkDir).CombinedOutput(); err != nil {
panic("Could not create javaagent working directory: " + err.Error() + ":\n" + string(out))
}

if err := os.CopyFS(javaagentWorkDir, os.DirFS(paths[0])); err != nil {
panic("Could not copy javaagent: " + err.Error())
}

log.Info().Str("dir", javaagentWorkDir).Msg("prepared javaagent directory")
})
)

func javaagentPath() string {
pathByEnv := os.Getenv("STEADYBIT_EXTENSION_JAVA_AGENT_PATH")
if pathByEnv != "" {
return pathByEnv
}
panic("STEADYBIT_EXTENSION_JAVA_AGENT_PATH not set")
javaagentWorkDirOnce()
return javaagentWorkDir
}

func GetAttachment(jvm JavaVm) Attachment {
Expand Down Expand Up @@ -66,7 +92,7 @@ func externalAttach(jvm JavaVm, agentJar, initJar string, heartbeatFile string,
}

if needsUserSwitch(jvm) {
attachCommand = append(attachCommand, "uid="+jvm.UserId(), "gid="+jvm.GroupId())
attachCommand = append(attachCommand, fmt.Sprintf("uid=%d", jvm.UserId()), fmt.Sprintf("gid=%d", jvm.GroupId()))
}

var ctx, cancel = context.WithTimeout(context.Background(), time.Duration(60)*time.Second)
Expand All @@ -86,16 +112,11 @@ func externalAttach(jvm JavaVm, agentJar, initJar string, heartbeatFile string,
}

func needsUserSwitch(jvm JavaVm) bool {
if jvm.UserId() == "" || jvm.GroupId() == "" {
if jvm.UserId() == -1 || jvm.GroupId() == -1 {
return false
}

current, err := user.Current()
if err != nil {
log.Warn().Err(err).Msg("Could not determine current user")
return false
}
return jvm.UserId() != current.Uid || jvm.GroupId() != current.Gid
return jvm.UserId() != os.Getuid() || jvm.GroupId() != os.Getgid()
}

func getExecutable(jvm JavaVm) string {
Expand Down
33 changes: 18 additions & 15 deletions extjvm/jvm/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ import (
"context"
"errors"
"fmt"
"strings"

"github.com/rs/zerolog/log"
"github.com/shirou/gopsutil/v4/process"
"github.com/steadybit/extension-jvm/extjvm/jvm/starttime"
"github.com/steadybit/extension-kit/extruntime"
"strings"
)

type JavaVm interface {
Pid() int32
CommandLine() string
MainClass() string
ClassPath() string
UserId() string
GroupId() string
UserId() int
GroupId() int
Path() string
Hostname() string
HostFQDN() string
Expand All @@ -43,8 +44,8 @@ type defaultJavaVm struct {
vmVendor string
vmName string
vmArgs string
userId string
groupId string
userId int
groupId int
path string
discoveredVia string
hostname string
Expand All @@ -68,11 +69,11 @@ func (vm defaultJavaVm) ClassPath() string {
return vm.classPath
}

func (vm defaultJavaVm) UserId() string {
func (vm defaultJavaVm) UserId() int {
return vm.userId
}

func (vm defaultJavaVm) GroupId() string {
func (vm defaultJavaVm) GroupId() int {
return vm.groupId
}

Expand Down Expand Up @@ -126,11 +127,15 @@ func newJavaVm(p *process.Process, via string) *defaultJavaVm {
}

if uids, err := p.Uids(); err == nil && len(uids) > 0 {
vm.userId = fmt.Sprintf("%d", uids[0])
vm.userId = int(uids[0])
} else {
vm.userId = -1
}

if gids, err := p.Gids(); err == nil && len(gids) > 0 {
vm.groupId = fmt.Sprintf("%d", gids[0])
vm.groupId = int(gids[0])
} else {
vm.groupId = -1
}

if processPath, err := getProcessPath(context.Background(), p); err == nil && processPath != "" {
Expand All @@ -155,13 +160,12 @@ func (vm defaultJavaVm) StartTime() starttime.Time {
}

func (vm defaultJavaVm) ToDebugString() string {
return fmt.Sprintf("JavaVm{pid=%d, discoveredVia=%s, commandLine=%s, mainClass=%s, classpath=%s, vmVersion=%s, vmVendor=%s, vmName=%s, vmArgs=%s, userId=%s, groupId=%s, path=%s}",
return fmt.Sprintf("JavaVm{pid=%d, discoveredVia=%s, commandLine=%s, mainClass=%s, classpath=%s, vmVersion=%s, vmVendor=%s, vmName=%s, vmArgs=%s, userId=%d, groupId=%d, path=%s}",
vm.p.Pid, vm.discoveredVia, vm.commandLine, vm.mainClass, vm.classPath, vm.vmVersion, vm.vmVendor, vm.vmName, vm.vmArgs, vm.userId, vm.groupId, vm.path)
}

func (vm defaultJavaVm) ToInfoString() string {
return fmt.Sprintf("JavaVm{pid=%d, discoveredVia=%s, mainClass=%s}",
vm.p.Pid, vm.discoveredVia, vm.mainClass)
return fmt.Sprintf("JavaVm{pid=%d (%d:%d), discoveredVia=%s, mainClass=%s}", vm.p.Pid, vm.userId, vm.groupId, vm.discoveredVia, vm.mainClass)
}

type defaultJavaVmInContainer struct {
Expand All @@ -179,11 +183,10 @@ func (vm defaultJavaVmInContainer) PidInContainer() int32 {
}

func (vm defaultJavaVmInContainer) ToDebugString() string {
return fmt.Sprintf("JavaVm{pid=%d, containerId=%s, pidInContainer=%d, discoveredVia=%s, commandLine=%s, mainClass=%s, classpath=%s, vmVersion=%s, vmVendor=%s, vmName=%s, vmArgs=%s, userId=%s, groupId=%s, path=%s}",
return fmt.Sprintf("JavaVm{pid=%d, containerId=%s, pidInContainer=%d, discoveredVia=%s, commandLine=%s, mainClass=%s, classpath=%s, vmVersion=%s, vmVendor=%s, vmName=%s, vmArgs=%s, userId=%d, groupId=%d, path=%s}",
vm.p.Pid, vm.containerId, vm.pidInContainer, vm.discoveredVia, vm.commandLine, vm.mainClass, vm.classPath, vm.vmVersion, vm.vmVendor, vm.vmName, vm.vmArgs, vm.userId, vm.groupId, vm.path)
}

func (vm defaultJavaVmInContainer) ToInfoString() string {
return fmt.Sprintf("JavaVm{pid=%d, containerId=%s, discoveredVia=%s, mainClass=%s}",
vm.p.Pid, vm.containerId, vm.discoveredVia, vm.mainClass)
return fmt.Sprintf("JavaVm{pid=%d (%d:%d), containerId=%s, discoveredVia=%s, mainClass=%s}", vm.p.Pid, vm.userId, vm.groupId, vm.containerId, vm.discoveredVia, vm.mainClass)
}
Loading