From 33d3a68424b05d88c266c3bbf1815d9078b04081 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Thu, 23 Jul 2026 20:47:27 +0900 Subject: [PATCH 1/4] repo transfer, socket ownership check --- .github/workflows/test.yml | 2 +- .goreleaser.yml | 4 +-- Makefile | 6 ++-- README.md | 8 ++--- go.mod | 2 +- internal/statworker/command.go | 2 +- main.go | 41 ++++++++++++++++++++------ main_test.go | 4 +-- maxcpu.proto | 4 +-- maxcpu/maxcpu.pb.go | 4 +-- maxcpu/maxcpuconnect/maxcpu.connect.go | 7 ++--- 11 files changed, 53 insertions(+), 31 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6988eb1..6cc93de 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,4 +23,4 @@ jobs: uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 with: version: latest - args: build --snapshot \ No newline at end of file + args: build --snapshot diff --git a/.goreleaser.yml b/.goreleaser.yml index eb8678f..91c28ac 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -5,12 +5,10 @@ builds: goarch: - amd64 - arm64 - ldflags: - - -w -s -X main.version={{.Version}} -X github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu.version={{.Version}} archives: - format: zip name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" release: github: - owner: kazeburo + owner: monitoring-forge name: mackerel-plugin-maxcpu diff --git a/Makefile b/Makefile index 1796163..03fed53 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ VERSION=0.0.15 -LDFLAGS=-ldflags "-w -s -X main.version=${VERSION} -X github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu.version=${VERSION}" +GITCOMMIT?=$(shell git describe --dirty --always) +LDFLAGS=-ldflags "-w -s -X main.version=${VERSION} -X main.commit=${GITCOMMIT}" all: mackerel-plugin-maxcpu @@ -29,6 +30,7 @@ linux-check: mackerel-plugin-maxcpu pkill -f $$tmpfile' check: - go test ./... + go test -v ./... + go test -race ./... go vet ./... diff --git a/README.md b/README.md index 1d95e80..1a3224b 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ At the first time of execution, mackerel-plugin-maxcpu spawns the calculating da Sample ``` -$ ./mackerel-plugin-maxcpu --socket /tmp/maxcpu.sock -2020/10/30 10:40:54 rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /tmp/maxcpu.sock: connect: no such file or directory" +$ ./mackerel-plugin-maxcpu --socket /var/run/mackerel-agent/maxcpu.sock +2020/10/30 10:40:54 rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/mackerel-agent/maxcpu.sock: connect: no such file or directory" 2020/10/30 10:40:54 start background process -$ ./mackerel-plugin-maxcpu --socket /tmp/maxcpu.sock +$ ./mackerel-plugin-maxcpu --socket /var/run/mackerel-agent/maxcpu.sock maxcpu.us_sy_wa_si_st_usage.max 0.251256 1604022058 maxcpu.us_sy_wa_si_st_usage.min 0.250627 1604022058 maxcpu.us_sy_wa_si_st_usage.avg 0.250941 1604022058 @@ -40,5 +40,5 @@ maxcpu.us_sy_wa_si_st_usage.75pt 0.251256 1604022058 ## Install -Please download release page or `mkr plugin install kazeburo/mackerel-plugin-maxcpu`. +Please download release page or `mkr plugin install monitoring-forge/mackerel-plugin-maxcpu`. diff --git a/go.mod b/go.mod index 5916baa..b61709c 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/kazeburo/mackerel-plugin-maxcpu +module github.com/monitoring-forge/mackerel-plugin-maxcpu go 1.25.0 diff --git a/internal/statworker/command.go b/internal/statworker/command.go index e61827b..a7b1d14 100644 --- a/internal/statworker/command.go +++ b/internal/statworker/command.go @@ -9,7 +9,7 @@ import ( "time" "github.com/bufbuild/connect-go" - "github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu" + "github.com/monitoring-forge/mackerel-plugin-maxcpu/maxcpu" "google.golang.org/protobuf/types/known/emptypb" ) diff --git a/main.go b/main.go index 38c7557..f172496 100644 --- a/main.go +++ b/main.go @@ -9,19 +9,22 @@ import ( "os" "os/exec" "os/signal" + "os/user" + "path/filepath" "runtime" + "strconv" "syscall" "time" connect "github.com/bufbuild/connect-go" "github.com/jessevdk/go-flags" - "github.com/kazeburo/mackerel-plugin-maxcpu/internal/statworker" - maxcpuconnect "github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu/maxcpuconnect" + "github.com/monitoring-forge/mackerel-plugin-maxcpu/internal/statworker" + maxcpuconnect "github.com/monitoring-forge/mackerel-plugin-maxcpu/maxcpu/maxcpuconnect" "google.golang.org/protobuf/types/known/emptypb" ) -// version by Makefile var version string +var commit string type Opt struct { Socket string `short:"s" long:"socket" required:"true" description:"Socket file used calcurating daemon" ` @@ -167,9 +170,25 @@ func getStats(opt *Opt) int { } func makeClient(socket string) (maxcpuconnect.MaxCPUClient, error) { + user, err := user.Current() + if err != nil { + return nil, err + } httpClient := &http.Client{ Transport: &http.Transport{ DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + // check owner of socket file + fi, err := os.Stat(socket) + if err != nil { + return nil, err + } + stat, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return nil, fmt.Errorf("failed to get socket file stat") + } + if strconv.Itoa(int(stat.Uid)) != user.Uid { + return nil, fmt.Errorf("socket file owner is not current user") + } return net.DialTimeout("unix", socket, 1*time.Second) }, }, @@ -188,13 +207,17 @@ func _main() int { psr := flags.NewParser(opt, flags.HelpFlag|flags.PassDoubleDash) _, err := psr.Parse() if opt.Version { - fmt.Printf(`%s %s -Compiler: %s %s -`, - os.Args[0], + if commit == "" { + commit = "dev" + } + fmt.Printf( + "%s-%s\n%s/%s, %s, %s\n", + filepath.Base(os.Args[0]), version, - runtime.Compiler, - runtime.Version()) + runtime.GOOS, + runtime.GOARCH, + runtime.Version(), + commit) return 0 } if err != nil { diff --git a/main_test.go b/main_test.go index 03043d4..9ade424 100644 --- a/main_test.go +++ b/main_test.go @@ -10,8 +10,8 @@ import ( "time" connect "github.com/bufbuild/connect-go" - "github.com/kazeburo/mackerel-plugin-maxcpu/internal/statworker" - maxcpuconnect "github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu/maxcpuconnect" + "github.com/monitoring-forge/mackerel-plugin-maxcpu/internal/statworker" + maxcpuconnect "github.com/monitoring-forge/mackerel-plugin-maxcpu/maxcpu/maxcpuconnect" "google.golang.org/protobuf/types/known/emptypb" ) diff --git a/maxcpu.proto b/maxcpu.proto index 709bd09..9c68882 100644 --- a/maxcpu.proto +++ b/maxcpu.proto @@ -1,6 +1,6 @@ syntax = "proto3"; // go install google.golang.org/protobuf/cmd/protoc-gen-go@latest -// go install google.golang.org/grpc/protoc-gen-go-grpc@lastest +// go install google.golang.org/grpc/protoc-gen-go-grpc@latest // go install github.com/bufbuild/connect-go/cmd/protoc-gen-connect-go@latest // protoc --go_out=maxcpu --go_opt=paths=source_relative maxcpu.proto // protoc --connect-go_out=maxcpu --connect-go_opt=paths=source_relative maxcpu.proto @@ -8,7 +8,7 @@ syntax = "proto3"; import "google/protobuf/empty.proto"; package maxcpu; -option go_package = "github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu"; +option go_package = "github.com/monitoring-forge/mackerel-plugin-maxcpu/maxcpu"; service MaxCPU { rpc GetStats(google.protobuf.Empty) returns (StatsResponse) {} diff --git a/maxcpu/maxcpu.pb.go b/maxcpu/maxcpu.pb.go index 3827266..644c876 100644 --- a/maxcpu/maxcpu.pb.go +++ b/maxcpu/maxcpu.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.10 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: maxcpu.proto @@ -185,7 +185,7 @@ const file_maxcpu_proto_rawDesc = "" + "\x05Epoch\x18\x03 \x01(\x03R\x05Epoch2\x7f\n" + "\x06MaxCPU\x12;\n" + "\bGetStats\x12\x16.google.protobuf.Empty\x1a\x15.maxcpu.StatsResponse\"\x00\x128\n" + - "\x05Hello\x12\x16.google.protobuf.Empty\x1a\x15.maxcpu.HelloResponse\"\x00B3Z1github.com/kazeburo/mackerel-plugin-maxcpu/maxcpub\x06proto3" + "\x05Hello\x12\x16.google.protobuf.Empty\x1a\x15.maxcpu.HelloResponse\"\x00B;Z9github.com/monitoring-forge/mackerel-plugin-maxcpu/maxcpub\x06proto3" var ( file_maxcpu_proto_rawDescOnce sync.Once diff --git a/maxcpu/maxcpuconnect/maxcpu.connect.go b/maxcpu/maxcpuconnect/maxcpu.connect.go index e17cbcc..ae62ba7 100644 --- a/maxcpu/maxcpuconnect/maxcpu.connect.go +++ b/maxcpu/maxcpuconnect/maxcpu.connect.go @@ -7,12 +7,11 @@ package maxcpuconnect import ( context "context" errors "errors" - http "net/http" - strings "strings" - connect_go "github.com/bufbuild/connect-go" - maxcpu "github.com/kazeburo/mackerel-plugin-maxcpu/maxcpu" + maxcpu "github.com/monitoring-forge/mackerel-plugin-maxcpu/maxcpu" emptypb "google.golang.org/protobuf/types/known/emptypb" + http "net/http" + strings "strings" ) // This is a compile-time assertion to ensure that this generated file and the connect package are From 63c80052d096803477f19becd1fdb83b9f81c2c2 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Thu, 23 Jul 2026 20:58:53 +0900 Subject: [PATCH 2/4] more check and update sample --- README.md | 6 +++--- main.go | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1a3224b..f14a084 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ At the first time of execution, mackerel-plugin-maxcpu spawns the calculating da Sample ``` -$ ./mackerel-plugin-maxcpu --socket /var/run/mackerel-agent/maxcpu.sock -2020/10/30 10:40:54 rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/mackerel-agent/maxcpu.sock: connect: no such file or directory" +$ sudo ./mackerel-plugin-maxcpu --socket /var/run/maxcpu.sock +2020/10/30 10:40:54 rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/maxcpu.sock: connect: no such file or directory" 2020/10/30 10:40:54 start background process -$ ./mackerel-plugin-maxcpu --socket /var/run/mackerel-agent/maxcpu.sock +$ sudo ./mackerel-plugin-maxcpu --socket /var/run/maxcpu.sock maxcpu.us_sy_wa_si_st_usage.max 0.251256 1604022058 maxcpu.us_sy_wa_si_st_usage.min 0.250627 1604022058 maxcpu.us_sy_wa_si_st_usage.avg 0.250941 1604022058 diff --git a/main.go b/main.go index f172496..73a55d7 100644 --- a/main.go +++ b/main.go @@ -125,6 +125,10 @@ func runBackground(opt *Opt) int { log.Printf("%v", err) return 1 } + if err := os.Chmod(opt.Socket, 0600); err != nil { + log.Printf("%v", err) + return 1 + } srv := &http.Server{Handler: mux} go func() { if err := srv.Serve(unixListener); err != nil && err != http.ErrServerClosed { From 147c0cc751bee57a0c1fa16ed9a724f803cd715d Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Thu, 23 Jul 2026 21:30:24 +0900 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f14a084..df49bc5 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Sample ``` $ sudo ./mackerel-plugin-maxcpu --socket /var/run/maxcpu.sock -2020/10/30 10:40:54 rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/maxcpu.sock: connect: no such file or directory" +2020/10/30 10:40:54 check daemon alive failed: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/maxcpu.sock: connect: no such file or directory" 2020/10/30 10:40:54 start background process $ sudo ./mackerel-plugin-maxcpu --socket /var/run/maxcpu.sock From 4593200fd2635ffffa7edfdf39e54e0ac73a005e Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Thu, 23 Jul 2026 21:37:59 +0900 Subject: [PATCH 4/4] use osos.Geteuid and DialContext --- main.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 73a55d7..81884c2 100644 --- a/main.go +++ b/main.go @@ -9,10 +9,8 @@ import ( "os" "os/exec" "os/signal" - "os/user" "path/filepath" "runtime" - "strconv" "syscall" "time" @@ -174,10 +172,7 @@ func getStats(opt *Opt) int { } func makeClient(socket string) (maxcpuconnect.MaxCPUClient, error) { - user, err := user.Current() - if err != nil { - return nil, err - } + uid := os.Geteuid() httpClient := &http.Client{ Transport: &http.Transport{ DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { @@ -190,10 +185,13 @@ func makeClient(socket string) (maxcpuconnect.MaxCPUClient, error) { if !ok { return nil, fmt.Errorf("failed to get socket file stat") } - if strconv.Itoa(int(stat.Uid)) != user.Uid { + if int(stat.Uid) != uid { return nil, fmt.Errorf("socket file owner is not current user") } - return net.DialTimeout("unix", socket, 1*time.Second) + ctx, cancel := context.WithTimeout(ctx, 1*time.Second) + defer cancel() + var d net.Dialer + return d.DialContext(ctx, "unix", socket) }, }, }