Skip to content

Commit

Permalink
feat: authentication with auth data stored in file
Browse files Browse the repository at this point in the history
  • Loading branch information
navetacandra committed Sep 5, 2024
1 parent 56425e7 commit ff64503
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 29 deletions.
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,8 @@ Flags

```
Usage of ./git-http-backend:
-require_auth bool
set require auth enable/disable
-auth_pass_env_var string
set an env var to provide the basic auth pass as
-auth_user_env_var string
set an env var to provide the basic auth user as
-auth_data string
set auth info data path
-default_env string
set the default env
-git_bin_path string
Expand Down
17 changes: 17 additions & 0 deletions authentication_info_example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"Username": "user1",
"Password": "123456",
"Repositories": [
"user1-repo0.git",
"user1-repo1.git"
]
},
{
"Username": "user2",
"Password": "abcdef",
"Repositories": [
"user2-repo0.git"
]
}
]
4 changes: 1 addition & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
)

func init() {
flag.BoolVar(&server.DefaultConfig.RequireAuth, "require_auth", server.DefaultConfig.RequireAuth, "enable basic auth")
flag.StringVar(&server.DefaultConfig.AuthPassEnvVar, "auth_pass_env_var", server.DefaultConfig.AuthPassEnvVar, "set an env var to provide the basic auth pass as")
flag.StringVar(&server.DefaultConfig.AuthUserEnvVar, "auth_user_env_var", server.DefaultConfig.AuthUserEnvVar, "set an env var to provide the basic auth user as")
flag.StringVar(&server.DefaultConfig.AuthInfoFilePath, "auth_data", server.DefaultConfig.AuthInfoFilePath, "set auth info data path")
flag.StringVar(&server.DefaultConfig.DefaultEnv, "default_env", server.DefaultConfig.DefaultEnv, "set the default env")
flag.StringVar(&server.DefaultConfig.ProjectRoot, "project_root", server.DefaultConfig.ProjectRoot, "set project root")
flag.StringVar(&server.DefaultConfig.GitBinPath, "git_bin_path", server.DefaultConfig.GitBinPath, "set git bin path")
Expand Down
90 changes: 70 additions & 20 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"compress/gzip"
"fmt"
"io"
"encoding/json"
"log"
"net/http"
"os"
Expand All @@ -16,16 +17,20 @@ import (
"time"
)

type AuthInfo struct {
Username string
Password string
Repositories []string
}

type Service struct {
Method string
Handler func(HandlerReq)
Rpc string
}

type Config struct {
RequireAuth bool
AuthPassEnvVar string
AuthUserEnvVar string
AuthInfoFilePath string
DefaultEnv string
ProjectRoot string
GitBinPath string
Expand All @@ -47,9 +52,7 @@ var (
DefaultAddress = ":8080"

DefaultConfig = Config{
RequireAuth: false,
AuthPassEnvVar: "",
AuthUserEnvVar: "",
AuthInfoFilePath: "/tmp/authentication_info_example.json",
DefaultEnv: "",
ProjectRoot: "/tmp",
GitBinPath: "/usr/bin/git",
Expand Down Expand Up @@ -122,28 +125,46 @@ func serviceRpc(hr HandlerReq) {
return
}

w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", rpc))
w.Header().Set("Connection", "Keep-Alive")
w.Header().Set("Transfer-Encoding", "chunked")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(http.StatusOK)

env := os.Environ()

if DefaultConfig.DefaultEnv != "" {
env = append(env, DefaultConfig.DefaultEnv)
}

user, password, authok := r.BasicAuth()
username, password, authok := r.BasicAuth()
user := FindUser(username)
if authok {
if DefaultConfig.AuthUserEnvVar != "" {
env = append(env, fmt.Sprintf("%s=%s", DefaultConfig.AuthUserEnvVar, user))
// Check is user has access to repository
if user.Username != "" && user.Password != "" {
requestRepo := strings.Replace(dir, DefaultConfig.ProjectRoot, "", 1)
allow := false
for _, repo := range user.Repositories {
if repo == requestRepo {
allow = true
break
}
}

if !allow {
renderNoAccess(w)
return
}
}

if user.Username != "" {
env = append(env, fmt.Sprintf("%s=%s", user.Username, username))
}
if DefaultConfig.AuthPassEnvVar != "" {
env = append(env, fmt.Sprintf("%s=%s", DefaultConfig.AuthPassEnvVar, password))
if user.Password != "" {
env = append(env, fmt.Sprintf("%s=%s", user.Password, password))
}
}

w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", rpc))
w.Header().Set("Connection", "Keep-Alive")
w.Header().Set("Transfer-Encoding", "chunked")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(http.StatusOK)

args := []string{rpc, "--stateless-rpc", dir}
cmd := exec.Command(DefaultConfig.GitBinPath, args...)
version := r.Header.Get("Git-Protocol")
Expand Down Expand Up @@ -214,13 +235,15 @@ func getInfoRefs(hr HandlerReq) {
access := hasAccess(r, dir, service_name, false)
version := r.Header.Get("Git-Protocol")

user, password, authok := r.BasicAuth()
if DefaultConfig.RequireAuth && !authok {
username, password, authok := r.BasicAuth()
if DefaultConfig.AuthInfoFilePath != "" && !authok {
renderAuthRequire(w)
return
}

if authok && user != DefaultConfig.AuthUserEnvVar && password != DefaultConfig.AuthPassEnvVar {
// Check user credential
user := FindUser(username)
if authok && !(username == user.Username && password == user.Password) {
w.WriteHeader(http.StatusUnauthorized)
return
}
Expand All @@ -244,6 +267,33 @@ func getInfoRefs(hr HandlerReq) {
}
}

func FindUser(username string) AuthInfo {
if username == "" {
return AuthInfo{}
}

var authInfo []AuthInfo
var user AuthInfo
content, err := os.ReadFile(DefaultConfig.AuthInfoFilePath)

Check failure on line 277 in server/server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: os.ReadFile
if err != nil {
log.Print(err)
}

err = json.Unmarshal(content, &authInfo)
if err != nil {
log.Print(err)
}

for _, auth := range authInfo {
if auth.Username == username {
user = auth
break
}
}

return user
}

func getInfoPacks(hr HandlerReq) {
hdrCacheForever(hr.w)
sendFile("text/plain; charset=utf-8", hr)
Expand Down

0 comments on commit ff64503

Please sign in to comment.