mirror of
https://github.com/glauth/glauth.git
synced 2026-10-27 06:26:59 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 251ec3ef66 | |||
| cf78b04400 | |||
| 0479c455fb | |||
| 156e917697 | |||
| 7832f9e94d | |||
| e8951481c8 | |||
| 4f5795965b |
@@ -13,7 +13,7 @@ jobs:
|
|||||||
go-version: [1.25.x]
|
go-version: [1.25.x]
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v7
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
- name: Updating packages database
|
- name: Updating packages database
|
||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
- name: Install CLI Dependencies
|
- name: Install CLI Dependencies
|
||||||
run: sudo apt-get install -y ldap-utils oathtool libpam0g-dev
|
run: sudo apt-get install -y ldap-utils oathtool libpam0g-dev
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v7
|
||||||
- name: Fetch Go dependencies
|
- name: Fetch Go dependencies
|
||||||
working-directory: ./v2
|
working-directory: ./v2
|
||||||
run: go get -t -v ./...
|
run: go get -t -v ./...
|
||||||
|
|||||||
@@ -24,18 +24,18 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v4
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
queries: +security-and-quality
|
queries: +security-and-quality
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v3
|
uses: github/codeql-action/autobuild@v4
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v4
|
||||||
with:
|
with:
|
||||||
category: "/language:${{ matrix.language }}"
|
category: "/language:${{ matrix.language }}"
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
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
|
||||||
+14
-1
@@ -58,8 +58,21 @@ mocks:
|
|||||||
vet:
|
vet:
|
||||||
-go vet ./...
|
-go vet ./...
|
||||||
.PHONY: 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: @ runs package, root integration, and shell integration tests
|
||||||
test: mocks vet
|
test: mocks vet seedplugindb
|
||||||
go test -v -cover -coverprofile coverage.out ./pkg/... ./internal/... .
|
go test -v -cover -coverprofile coverage.out ./pkg/... ./internal/... .
|
||||||
$(MAKE) runtest
|
$(MAKE) runtest
|
||||||
#all: @ run build process for all binaries
|
#all: @ run build process for all binaries
|
||||||
|
|||||||
@@ -44,12 +44,11 @@ func InitLogging(reqdebug bool, reqsyslog bool, reqstructlog bool) zerolog.Logge
|
|||||||
var logr zerolog.Logger
|
var logr zerolog.Logger
|
||||||
if reqsyslog {
|
if reqsyslog {
|
||||||
s, err := syslog.New(syslog.LOG_INFO, "glauth")
|
s, err := syslog.New(syslog.LOG_INFO, "glauth")
|
||||||
if err != nil {
|
if err == nil {
|
||||||
|
logr = zerolog.New(zerolog.SyslogLevelWriter(s)).Level(level).With().Timestamp().Logger()
|
||||||
|
} else {
|
||||||
fmt.Println("Unable to write to syslog: ignoring...")
|
fmt.Println("Unable to write to syslog: ignoring...")
|
||||||
reqsyslog = false
|
reqsyslog = false
|
||||||
} else {
|
|
||||||
writers := zerolog.MultiLevelWriter(mainWriter, zerolog.SyslogLevelWriter(s))
|
|
||||||
logr = zerolog.New(writers).Level(level).With().Timestamp().Logger()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,14 +56,13 @@ func InitLogging(reqdebug bool, reqsyslog bool, reqstructlog bool) zerolog.Logge
|
|||||||
logr = zerolog.New(mainWriter).Level(level).With().Timestamp().Logger()
|
logr = zerolog.New(mainWriter).Level(level).With().Timestamp().Logger()
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SetOutput(customWriter{logr: logr, structlog: reqstructlog})
|
log.SetOutput(customWriter{logr: logr})
|
||||||
|
|
||||||
return logr
|
return logr
|
||||||
}
|
}
|
||||||
|
|
||||||
type customWriter struct {
|
type customWriter struct {
|
||||||
logr zerolog.Logger
|
logr zerolog.Logger
|
||||||
structlog bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e customWriter) Write(p []byte) (int, error) {
|
func (e customWriter) Write(p []byte) (int, error) {
|
||||||
@@ -76,10 +74,6 @@ func (e customWriter) Write(p []byte) (int, error) {
|
|||||||
if msg == "" {
|
if msg == "" {
|
||||||
msg = strings.TrimSpace(string(p))
|
msg = strings.TrimSpace(string(p))
|
||||||
}
|
}
|
||||||
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)
|
e.logr.Info().Msg(msg)
|
||||||
}
|
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
package logging
|
package logging
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -42,14 +41,13 @@ func InitLogging(reqdebug bool, reqsyslog bool, reqstructlog bool) zerolog.Logge
|
|||||||
|
|
||||||
logr := zerolog.New(mainWriter).Level(level).With().Timestamp().Logger()
|
logr := zerolog.New(mainWriter).Level(level).With().Timestamp().Logger()
|
||||||
|
|
||||||
log.SetOutput(customWriter{logr: logr, structlog: reqstructlog})
|
log.SetOutput(customWriter{logr: logr})
|
||||||
|
|
||||||
return logr
|
return logr
|
||||||
}
|
}
|
||||||
|
|
||||||
type customWriter struct {
|
type customWriter struct {
|
||||||
logr zerolog.Logger
|
logr zerolog.Logger
|
||||||
structlog bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e customWriter) Write(p []byte) (int, error) {
|
func (e customWriter) Write(p []byte) (int, error) {
|
||||||
@@ -61,10 +59,6 @@ func (e customWriter) Write(p []byte) (int, error) {
|
|||||||
if msg == "" {
|
if msg == "" {
|
||||||
msg = strings.TrimSpace(string(p))
|
msg = strings.TrimSpace(string(p))
|
||||||
}
|
}
|
||||||
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)
|
e.logr.Info().Msg(msg)
|
||||||
}
|
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
-- 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", "*");
|
||||||
Reference in New Issue
Block a user