Compare commits

..

1 Commits

Author SHA1 Message Date
Chris F Ravenscroft 728d1e3274 fix: revert pam plugin to msteinert/pam v1
v2.1.0 fails to cross-compile for all five linux targets in the xgo
container (C.RTLD_NEXT unresolvable without _GNU_SOURCE), so the
v2.5.3 release shipped darwin pam plugins only. v1.2.0 cross-compiles
cleanly with an identical API surface for this plugin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014L5EoqGWsuZWr8fCVM6izP
2026-09-13 14:58:52 -07:00
9 changed files with 24 additions and 183 deletions
-54
View File
@@ -1,54 +0,0 @@
name: stale
on:
schedule:
# Daily, off the hour to avoid GitHub's scheduling congestion at :00
- cron: '17 4 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v11
with:
days-before-stale: 60
days-before-close: 14
stale-issue-label: stale
stale-pr-label: stale
stale-issue-message: >
This issue has had no activity for 60 days and has been marked stale.
It will be closed in 14 days unless there is new activity. If it is
still relevant, a comment saying so is enough to keep it open.
stale-pr-message: >
This pull request has had no activity for 60 days and has been marked
stale. It will be closed in 14 days unless there is new activity. If
you intend to continue the work, a comment saying so is enough to keep
it open.
close-issue-message: >
Closing this issue after 14 days with no further activity. If it is
still relevant, please comment and it can be reopened.
close-pr-message: >
Closing this pull request after 14 days with no further activity.
Please comment if you would like to pick the work back up.
# Never touch anything deliberately kept open.
exempt-issue-labels: 'pinned,security,blocked,help wanted,good first issue'
exempt-pr-labels: 'pinned,security,blocked,dependencies'
exempt-all-milestones: true
# Restarts the clock when someone comments, so an active discussion is
# never swept up.
remove-stale-when-updated: true
# Oldest first, so the genuine backlog is handled before recent items.
ascending: true
+1 -1
View File
@@ -1,3 +1,3 @@
{
"v2": "2.5.4"
"v2": "2.5.3"
}
-7
View File
@@ -1,12 +1,5 @@
# Changelog
## [2.5.4](https://github.com/glauth/glauth/compare/GLAuth-v2.5.3...GLAuth-v2.5.4) (2026-09-13)
### Bug Fixes
* revert pam plugin to msteinert/pam v1 ([#487](https://github.com/glauth/glauth/issues/487)) ([8d1ea39](https://github.com/glauth/glauth/commit/8d1ea390bacc74a54d9b2046e514b7e0336cb08b))
## [2.5.3](https://github.com/glauth/glauth/compare/GLAuth-v2.5.2...GLAuth-v2.5.3) (2026-09-13)
+1 -14
View File
@@ -58,21 +58,8 @@ mocks:
vet:
-go vet ./...
.PHONY: vet
#seedplugindb: @ stage the sqlite plugin and seed its test database
seedplugindb:
@if [ -f bin/sqlite-linux-amd64.so ]; then \
echo "- staging sqlite plugin and seeding gl.db"; \
cp -f bin/sqlite-linux-amd64.so bin/sqlite.so; \
rm -f gl.db; \
glauth=$$(ls bin/$(GOOS)$(GOARCH)/glauth bin/glauth-$(GOOS)-$(GOARCH) 2>/dev/null | head -1); \
"$$glauth" -c pkg/plugins/glauth-sqlite/sample-database.cfg >/dev/null 2>&1 & \
pid=$$!; sleep 2; kill -TERM $$pid 2>/dev/null; wait $$pid 2>/dev/null || true; \
sqlite3 gl.db < scripts/ci/seed-sqlite-plugin.sql; \
fi
.PHONY: seedplugindb
#test: @ runs package, root integration, and shell integration tests
test: mocks vet seedplugindb
test: mocks vet
go test -v -cover -coverprofile coverage.out ./pkg/... ./internal/... .
$(MAKE) runtest
#all: @ run build process for all binaries
+1 -1
View File
@@ -2,4 +2,4 @@ package version
// Version is the tag of the latest release, it gets changed by the ci
// process when a release is happening
const Version = "v2.5.4" // x-release-please-version
const Version = "v2.5.3" // x-release-please-version
+12 -6
View File
@@ -44,11 +44,12 @@ func InitLogging(reqdebug bool, reqsyslog bool, reqstructlog bool) zerolog.Logge
var logr zerolog.Logger
if reqsyslog {
s, err := syslog.New(syslog.LOG_INFO, "glauth")
if err == nil {
logr = zerolog.New(zerolog.SyslogLevelWriter(s)).Level(level).With().Timestamp().Logger()
} else {
if err != nil {
fmt.Println("Unable to write to syslog: ignoring...")
reqsyslog = false
} else {
writers := zerolog.MultiLevelWriter(mainWriter, zerolog.SyslogLevelWriter(s))
logr = zerolog.New(writers).Level(level).With().Timestamp().Logger()
}
}
@@ -56,13 +57,14 @@ func InitLogging(reqdebug bool, reqsyslog bool, reqstructlog bool) zerolog.Logge
logr = zerolog.New(mainWriter).Level(level).With().Timestamp().Logger()
}
log.SetOutput(customWriter{logr: logr})
log.SetOutput(customWriter{logr: logr, structlog: reqstructlog})
return logr
}
type customWriter struct {
logr zerolog.Logger
logr zerolog.Logger
structlog bool
}
func (e customWriter) Write(p []byte) (int, error) {
@@ -74,6 +76,10 @@ func (e customWriter) Write(p []byte) (int, error) {
if msg == "" {
msg = strings.TrimSpace(string(p))
}
e.logr.Info().Msg(msg)
if e.structlog {
fmt.Fprintf(os.Stderr, "{\"level\":\"info\",\"time\":\"%s\",\"message\":\"%s\"}\n", time.Now().Format(time.RFC1123Z), strings.Replace(strings.TrimSpace(msg), `"`, `\"`, -1))
} else {
e.logr.Info().Msg(msg)
}
return len(p), nil
}
-59
View File
@@ -1,59 +0,0 @@
package logging
import (
"bytes"
"encoding/json"
"strings"
"testing"
"github.com/rs/zerolog"
)
// customWriter adapts log output from libraries that emit unstructured text.
// Everything it receives must go through the logger, so that it lands wherever
// the logger points - notably syslog only, when syslog is enabled.
func TestCustomWriterEmitsValidJSONThroughTheLogger(t *testing.T) {
for _, tc := range []struct {
name string
in string
want string
}{
{"plain", "something happened", "something happened"},
{"quotes", `bind for "cn=foo"`, `bind for "cn=foo"`},
{"backslashes", `path C:\Users\x`, `path C:\Users\x`},
{"control characters", "tab\there\nand a newline", "tab\there\nand a newline"},
{
"library timestamp prefix is stripped",
"2026/09/13 16:50:54 connection closed",
"connection closed",
},
} {
t.Run(tc.name, func(t *testing.T) {
var buf bytes.Buffer
w := customWriter{logr: zerolog.New(&buf).With().Timestamp().Logger()}
if _, err := w.Write([]byte(tc.in)); err != nil {
t.Fatalf("Write: %v", err)
}
// One record, one line: an unescaped newline would split this.
if got := strings.Count(strings.TrimRight(buf.String(), "\n"), "\n"); got != 0 {
t.Fatalf("expected a single log line, got %d extra newlines in %q", got, buf.String())
}
var record struct {
Level string `json:"level"`
Message string `json:"message"`
}
if err := json.Unmarshal(buf.Bytes(), &record); err != nil {
t.Fatalf("emitted invalid JSON (%v): %s", err, buf.String())
}
if record.Message != tc.want {
t.Errorf("message = %q, want %q", record.Message, tc.want)
}
if record.Level != "info" {
t.Errorf("level = %q, want %q", record.Level, "info")
}
})
}
}
+9 -3
View File
@@ -4,6 +4,7 @@
package logging
import (
"fmt"
"io"
"log"
"os"
@@ -41,13 +42,14 @@ func InitLogging(reqdebug bool, reqsyslog bool, reqstructlog bool) zerolog.Logge
logr := zerolog.New(mainWriter).Level(level).With().Timestamp().Logger()
log.SetOutput(customWriter{logr: logr})
log.SetOutput(customWriter{logr: logr, structlog: reqstructlog})
return logr
}
type customWriter struct {
logr zerolog.Logger
logr zerolog.Logger
structlog bool
}
func (e customWriter) Write(p []byte) (int, error) {
@@ -59,6 +61,10 @@ func (e customWriter) Write(p []byte) (int, error) {
if msg == "" {
msg = strings.TrimSpace(string(p))
}
e.logr.Info().Msg(msg)
if e.structlog {
fmt.Fprintf(os.Stderr, "{\"level\":\"info\",\"time\":\"%s\",\"message\":\"%s\"}\n", time.Now().Format(time.RFC1123Z), strings.Replace(strings.TrimSpace(msg), `"`, `\"`, -1))
} else {
e.logr.Info().Msg(msg)
}
return len(p), nil
}
-38
View File
@@ -1,38 +0,0 @@
-- Seed data for TestSQLitePlugin. The schema itself is created by the plugin's
-- CreateSchema() on first start, so this file only inserts rows.
INSERT INTO ldapgroups(name, gidnumber)
VALUES('superheros', 5501);
INSERT INTO ldapgroups(name, gidnumber)
VALUES('svcaccts', 5502);
INSERT INTO ldapgroups(name, gidnumber)
VALUES('civilians', 5503);
INSERT INTO ldapgroups(name, gidnumber)
VALUES('caped', 5504);
INSERT INTO ldapgroups(name, gidnumber)
VALUES('lovesailing', 5505);
INSERT INTO ldapgroups(name, gidnumber)
VALUES('smoker', 5506);
INSERT INTO includegroups(parentgroupid, includegroupid)
VALUES(5503, 5501);
INSERT INTO includegroups(parentgroupid, includegroupid)
VALUES(5504, 5502);
INSERT INTO includegroups(parentgroupid, includegroupid)
VALUES(5504, 5501);
INSERT INTO users(name, uidnumber, primarygroup, passsha256)
VALUES('hackers', 5001, 5501,
'6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a');
INSERT INTO users(name, uidnumber, primarygroup, passsha256)
VALUES('johndoe', 5002, 5502,
'6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a');
INSERT INTO users(name, mail, uidnumber, primarygroup, passsha256)
VALUES('serviceuser', "serviceuser@example.com", 5003, 5502,
'652c7dc687d98c9889304ed2e408c74b611e86a40caa51c4b43f1dd5913c5cd0');
INSERT INTO users(name, uidnumber, primarygroup, passsha256, othergroups)
VALUES('user4', 5004, 5504,
'652c7dc687d98c9889304ed2e408c74b611e86a40caa51c4b43f1dd5913c5cd0',
'5505,5506');
INSERT INTO capabilities(userid, action, object)
VALUES(5001, "search", "ou=superheros,dc=glauth,dc=com");
INSERT INTO capabilities(userid, action, object)
VALUES(5003, "search", "*");