aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/git-lfs-authenticate
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2023-12-30 22:20:50 +0100
committerLibravatar Rutger Broekhoff2023-12-30 22:20:50 +0100
commit42a2f9ce36240c28c729d605448dd12c5b6fc56c (patch)
tree1572b97e9190567de1906fe501e0d4270d531e8c /cmd/git-lfs-authenticate
parent45939098e918041f0ce524fa125cf0a1cdfd49c0 (diff)
downloadgitolfs3-42a2f9ce36240c28c729d605448dd12c5b6fc56c.tar.gz
gitolfs3-42a2f9ce36240c28c729d605448dd12c5b6fc56c.zip
git-lfs-authenticate: allow setting repo href base URL
Diffstat (limited to 'cmd/git-lfs-authenticate')
-rw-r--r--cmd/git-lfs-authenticate/main.go35
1 files changed, 27 insertions, 8 deletions
diff --git a/cmd/git-lfs-authenticate/main.go b/cmd/git-lfs-authenticate/main.go
index 027a2f9..7a8a778 100644
--- a/cmd/git-lfs-authenticate/main.go
+++ b/cmd/git-lfs-authenticate/main.go
@@ -8,8 +8,10 @@ import (
8 "errors" 8 "errors"
9 "fmt" 9 "fmt"
10 "io" 10 "io"
11 "net/url"
11 "os" 12 "os"
12 "os/exec" 13 "os/exec"
14 "path"
13 "strings" 15 "strings"
14 "sync" 16 "sync"
15 "sync/atomic" 17 "sync/atomic"
@@ -97,14 +99,16 @@ type customClaims struct {
97} 99}
98 100
99type authenticateResponse struct { 101type authenticateResponse struct {
102 // When providing href, the Git LFS client will use href as the base URL
103 // instead of building the base URL using the Service Discovery mechanism.
104 // It should end with /info/lfs. See
105 // https://github.com/git-lfs/git-lfs/blob/baf40ac99850a62fe98515175d52df5c513463ec/docs/api/server-discovery.md#ssh
106 HRef string `json:"href,omitempty"`
100 Header map[string]string `json:"header"` 107 Header map[string]string `json:"header"`
101 // In seconds. 108 // In seconds.
102 ExpiresIn int64 `json:"expires_in,omitempty"` 109 ExpiresIn int64 `json:"expires_in,omitempty"`
103 // The expires_at (RFC3339) property could also be used, but we leave it 110 // The expires_at (RFC3339) property could also be used, but we leave it
104 // out since we don't use it. It is also possibleto specify the href 111 // out since we don't use it.
105 // property, making the Git LFS use this instead of the usual Service
106 // Discovery mechanism. See
107 // https://github.com/git-lfs/git-lfs/blob/baf40ac99850a62fe98515175d52df5c513463ec/docs/api/server-discovery.md#ssh
108} 112}
109 113
110func wipe(b []byte) { 114func wipe(b []byte) {
@@ -128,12 +132,22 @@ func main() {
128 die("expected 2 arguments (path, operation), got %d", len(os.Args)-1) 132 die("expected 2 arguments (path, operation), got %d", len(os.Args)-1)
129 } 133 }
130 134
131 path := strings.TrimPrefix(strings.TrimSuffix(os.Args[1], ".git"), "/") 135 repoPath := strings.TrimPrefix(strings.TrimSuffix(os.Args[1], ".git"), "/")
132 operation := os.Args[2] 136 operation := os.Args[2]
133 if operation != "download" && operation != "upload" { 137 if operation != "download" && operation != "upload" {
134 die("expected operation to be upload or download, got %s", operation) 138 die("expected operation to be upload or download, got %s", operation)
135 } 139 }
136 140
141 repoHRefBaseStr := os.Getenv("REPO_HREF_BASE")
142 var repoHRefBase *url.URL
143 var err error
144 if repoHRefBaseStr != "" {
145 if repoHRefBase, err = url.Parse(repoHRefBaseStr); err != nil {
146 logger.logf("Failed to parse URL in environment variable REPO_HREF_BASE: %s", err)
147 dieReqID(reqID, "internal error")
148 }
149 }
150
137 user := os.Getenv("GL_USER") 151 user := os.Getenv("GL_USER")
138 if user == "" { 152 if user == "" {
139 logger.logf("Environment variable GL_USER is not set") 153 logger.logf("Environment variable GL_USER is not set")
@@ -165,10 +179,10 @@ func main() {
165 } 179 }
166 privateKey := ed25519.NewKeyFromSeed(seed) 180 privateKey := ed25519.NewKeyFromSeed(seed)
167 181
168 if !getGitoliteAccess(logger, reqID, path, user, "R") { 182 if !getGitoliteAccess(logger, reqID, repoPath, user, "R") {
169 die("repository not found") 183 die("repository not found")
170 } 184 }
171 if operation == "upload" && !getGitoliteAccess(logger, reqID, path, user, "W") { 185 if operation == "upload" && !getGitoliteAccess(logger, reqID, repoPath, user, "W") {
172 // User has read access but no write access 186 // User has read access but no write access
173 die("forbidden") 187 die("forbidden")
174 } 188 }
@@ -176,7 +190,7 @@ func main() {
176 expiresIn := time.Hour * 24 190 expiresIn := time.Hour * 24
177 claims := customClaims{ 191 claims := customClaims{
178 Gitolfs3: gitolfs3Claims{ 192 Gitolfs3: gitolfs3Claims{
179 Repository: path, 193 Repository: repoPath,
180 Permission: operation, 194 Permission: operation,
181 }, 195 },
182 RegisteredClaims: &jwt.RegisteredClaims{ 196 RegisteredClaims: &jwt.RegisteredClaims{
@@ -199,5 +213,10 @@ func main() {
199 }, 213 },
200 ExpiresIn: int64(expiresIn.Seconds()), 214 ExpiresIn: int64(expiresIn.Seconds()),
201 } 215 }
216 if repoHRefBase != nil {
217 response.HRef = repoHRefBase.ResolveReference(&url.URL{
218 Path: path.Join(repoPath, "/info/lfs"),
219 }).String()
220 }
202 json.NewEncoder(os.Stdout).Encode(response) 221 json.NewEncoder(os.Stdout).Encode(response)
203} 222}