-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bundle-server: implement simple user/pass auth middleware
Create and test a built-in auth mode for a single fixed username/password authenticated against a provided 'Authorization: Basic' header, implementing the AuthMiddleware interface. Add the mode to 'parseAuthConfig()' in 'git-bundle-web-server' to enable its usage in the web server. Update documentation for the mode in 'docs/technical/auth-config.md' and 'git-bundle-web-server' manpage, and an explicit example JSON in the 'examples/auth/config' directory. Signed-off-by: Victoria Dye <[email protected]>
- Loading branch information
Showing
7 changed files
with
396 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Auth configuration examples | ||
|
||
This directory contains examples of auth configurations that may be used as a | ||
reference for setting up auth for a bundle server. | ||
|
||
> **Warning** | ||
> | ||
> The examples contained within this directory should not be used directly in a | ||
> production context due to publicly-visible (in this repo) credentials. | ||
## Built-in modes | ||
|
||
### Fixed credential/single-user auth | ||
|
||
The file [`config/fixed.json`][fixed-config] configures [Basic | ||
authentication][basic] with username "admin" and password "bundle_server". | ||
|
||
[fixed-config]: ./config/fixed.json | ||
[basic]: ../../docs/technical/auth-config.md#basic-auth-server-wide |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"mode": "fixed", | ||
"parameters": { | ||
"username": "admin", | ||
"passwordHash": "c3c3520adf2f6e25672ba55dc70bcb3dd8b4ef3341bce1a5f38c5eca6571f372" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package auth | ||
|
||
import ( | ||
"crypto/sha256" | ||
"crypto/subtle" | ||
"encoding/hex" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/git-ecosystem/git-bundle-server/pkg/auth" | ||
) | ||
|
||
/* Built-in auth modes */ | ||
// Authorize users with a credentials matching a static username/password pair | ||
// that applies to the whole server. | ||
type fixedCredentialAuth struct { | ||
usernameHash [32]byte | ||
passwordHash [32]byte | ||
} | ||
|
||
type fixedCredentialAuthParams struct { | ||
Username string `json:"username"` | ||
PasswordHash string `json:"passwordHash"` | ||
} | ||
|
||
func NewFixedCredentialAuth(rawParameters json.RawMessage) (auth.AuthMiddleware, error) { | ||
if len(rawParameters) == 0 { | ||
return nil, fmt.Errorf("parameters JSON must exist") | ||
} | ||
|
||
var params fixedCredentialAuthParams | ||
err := json.Unmarshal(rawParameters, ¶ms) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Check for invalid username characters | ||
if strings.Contains(params.Username, ":") { | ||
return nil, fmt.Errorf("username contains a colon (\":\")") | ||
} | ||
|
||
// Make sure password hash is a valid hash | ||
passwordHashBytes, err := hex.DecodeString(params.PasswordHash) | ||
if err != nil { | ||
return nil, fmt.Errorf("passwordHash is invalid: %w", err) | ||
} else if len(passwordHashBytes) != 32 { | ||
return nil, fmt.Errorf("passwordHash is incorrect length (%d vs. expected 32)", len(passwordHashBytes)) | ||
} | ||
|
||
return &fixedCredentialAuth{ | ||
usernameHash: sha256.Sum256([]byte(params.Username)), | ||
passwordHash: [32]byte(passwordHashBytes), | ||
}, nil | ||
} | ||
|
||
func (a *fixedCredentialAuth) Authorize(r *http.Request, _ string, _ string) auth.AuthResult { | ||
username, password, ok := r.BasicAuth() | ||
if ok { | ||
usernameHash := sha256.Sum256([]byte(username)) | ||
passwordHash := sha256.Sum256([]byte(password)) | ||
|
||
usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], a.usernameHash[:]) == 1) | ||
passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], a.passwordHash[:]) == 1) | ||
|
||
if usernameMatch && passwordMatch { | ||
return auth.Allow() | ||
} else { | ||
// Return a 404 status even though the issue is that the user is | ||
// forbidden so we don't indirectly reveal which repositories are | ||
// configured in the bundle server. | ||
return auth.Deny(404) | ||
} | ||
} | ||
|
||
return auth.Deny(401, auth.Header{Key: "WWW-Authenticate", Value: `Basic realm="restricted", charset="UTF-8"`}) | ||
} |
Oops, something went wrong.