aboutsummaryrefslogtreecommitdiff
path: root/cmd/main.go
blob: 0cd9eec1030a6f12cddd202a9b115281650b50b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main

import (
	"flag"
	"fmt"
	"log/slog"
	"net/http"
	"os"
	"time"

	"git.ofmax.li/go-git-server/internal/admin"
	"git.ofmax.li/go-git-server/internal/authz"
	"git.ofmax.li/go-git-server/internal/git"
	"git.ofmax.li/go-git-server/internal/modules"
)

var (
	reposDir           string
	mgmtRepo           bool
	backendCommand     string
	loggingLevel       string
	addr               string
	serverHost         string
	modelPath          string
	policyPath         string
	serverConfigPath   string
	tokenFilePath      string
	newToken           bool
	goGitServerVersion string
	showVersion        bool
)

var (
	logLevels = map[string]slog.Level{
		"DEBUG": slog.LevelDebug,
		"INFO":  slog.LevelInfo,
		"ERROR": slog.LevelError,
	}
)

func main() {
	flag.Parse()
	level, ok := logLevels[loggingLevel]
	slog.Info("log level", "found", loggingLevel)
	if !ok {
		slog.Error("log levels are DEBUG, INFO, ERROR", "found", loggingLevel)
		os.Exit(1)
	}
	slog.SetLogLoggerLevel(level)
	slog.Info("go-git-server", "version", goGitServerVersion)
	if showVersion {
		os.Exit(0)
	}
	if newToken {
		token, hash, err := authz.GenerateNewToken()
		if err != nil {
			slog.Error("error generating token", slog.Any("error", err))
			os.Exit(1)
		}
		fmt.Printf("token: %s\nhash: %s\n", token, hash)
		return
	}
	adminSvc, err := admin.NewService(modelPath, policyPath, serverConfigPath, reposDir, mgmtRepo)
	if err != nil {
		slog.Error("exiting due to error", "msg", err)
		os.Exit(1)
	}
	if err := adminSvc.InitServer(); err != nil {
		slog.Error("error initializing server", "msg", err)
	}
	// Load authentication tokens and identity mappings
	tokens := authz.NewSafeTokenMap()
	identities := authz.NewIdentityMap()

	// Load tokens from CSV file
	tokenMap, identityMap, err := authz.LoadTokensFromFile(tokenFilePath)
	if err != nil {
		slog.Error("error loading tokens", slog.Any("error", err))
		os.Exit(1)
	}

	// Update the token map with loaded values
	for id, hash := range tokenMap {
		tokens.Set(id, hash)
	}

	// Copy identity mappings
	for id, name := range identityMap.IDToName {
		identities.Register(id, name)
	}

	// Create git and module handlers
	gitHandler := git.GitHttpBackendHandler(reposDir, backendCommand)
	moduleHandler := modules.NewModuleHandler(reposDir, serverHost, adminSvc.Conf)

	router := http.NewServeMux()
	// TODO we don't want to use a global
	// de-reference args
	router.Handle("/mgmt/", admin.Hooks(adminSvc, gitHandler))

	// Apply authentication to git operations
	authenticatedGitHandler := authz.Authentication(tokens, identities, authz.Authorization(adminSvc, gitHandler))

	// Apply module middleware (handles module requests directly, passes git requests to auth)
	moduleMiddleware := modules.ModuleMiddleware(moduleHandler, authenticatedGitHandler)

	router.Handle("/", moduleMiddleware)
	server := &http.Server{
		Addr:              addr,
		ReadHeaderTimeout: 5 * time.Second,
		Handler:           router,
	}
	slog.Error("error while running exiting", slog.Any("error", server.ListenAndServe()))
	os.Exit(1)
}

func init() {
	logLevel, ok := os.LookupEnv("GO_GIT_SERVER_LOG_LEVEL")
	if !ok {
		logLevel = "INFO"
	}
	flag.StringVar(&backendCommand, "c", "git http-backend", "CGI binary to execute")
	flag.StringVar(&loggingLevel, "e", logLevel, "set log level")
	flag.StringVar(&addr, "l", ":8080", "Address/port to listen on")
	flag.StringVar(&serverHost, "h", "localhost:8080", "Public hostname for Go module discovery")
	flag.StringVar(&modelPath, "m", "./auth_model.ini", "casbin authentication model")
	flag.StringVar(&policyPath, "p", "./policy.csv", "casbin auth policy")
	flag.StringVar(&tokenFilePath, "t", "./tokens.csv", "casbin auth policy")
	flag.StringVar(&serverConfigPath, "s", "./gitserver.yaml", "serverconfig path, this should be relative to the git root or absolute if not using mgmt repo")
	flag.StringVar(&reposDir, "r", "./repos", "Directory containing git repositories")
	flag.BoolVar(&mgmtRepo, "a", false, "mgmt repo used for configuration")
	flag.BoolVar(&newToken, "g", false, "make a new token")
	flag.BoolVar(&showVersion, "v", false, "show version of go-git-server")
}