Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/auth
diff options
context:
space:
mode:
authorJacob Vosmaer <contact@jacobvosmaer.nl>2020-02-20 16:49:19 +0300
committerJacob Vosmaer <contact@jacobvosmaer.nl>2020-02-20 16:49:19 +0300
commita51521d682c0a424d22c4adba027030d7a8ccb4d (patch)
tree8257d89324e84f15380b1c16bb223589fcf8231c /auth
parentfde7ec76313edd43f55704239b5ad50dac6af663 (diff)
Clarify how Gitaly v2 auth works
Diffstat (limited to 'auth')
-rw-r--r--auth/README.md27
-rw-r--r--auth/rpccredentials.go44
2 files changed, 47 insertions, 24 deletions
diff --git a/auth/README.md b/auth/README.md
new file mode 100644
index 000000000..b5dc6f568
--- /dev/null
+++ b/auth/README.md
@@ -0,0 +1,27 @@
+# Gitaly authentication middleware for Go
+
+This package contains code that plugs into
+github.com/grpc-ecosystem/go-grpc-middleware/auth to provide client
+and server authentication middleware for Gitaly.
+
+Gitaly has two authentication schemes.
+
+## V1 authentication (deprecated)
+
+This scheme uses a shared secret. The shared secret is base64-encoded
+and passed by the client as a bearer token.
+
+## V2 authentication
+
+This scheme uses a time limited token derived from a shared secret.
+
+The client creates a timestamp and computes the SHA256 HMAC signature
+for that timestamp, treating the timestamp as the message. The shared
+secret is used as the key for the HMAC. The client then sends both the
+message and the signature to the server as a bearer token.
+
+The server takes the message and computes the signature. If the
+client-provided signature matches the computed signature the message is
+accepted. Next, the server checks if its current time is no more than
+30 seconds ahead or behind the timestamp. If the timestamp is too old
+or too new the request is denied. Otherwise it goes ahead.
diff --git a/auth/rpccredentials.go b/auth/rpccredentials.go
index ca54901da..fc39a620b 100644
--- a/auth/rpccredentials.go
+++ b/auth/rpccredentials.go
@@ -11,46 +11,42 @@ import (
)
// RPCCredentials can be used with grpc.WithPerRPCCredentials to create a
-// grpc.DialOption that inserts the supplied token for authentication
-// with a Gitaly server.
-func RPCCredentials(token string) credentials.PerRPCCredentials {
- return &rpcCredentials{token: base64.StdEncoding.EncodeToString([]byte(token))}
+// grpc.DialOption that uses v1 Gitaly authentication for authentication
+// with a Gitaly server. The shared secret must match the one used on the
+// Gitaly server.
+func RPCCredentials(sharedSecret string) credentials.PerRPCCredentials {
+ return &rpcCredentials{sharedSecret: base64.StdEncoding.EncodeToString([]byte(sharedSecret))}
}
type rpcCredentials struct {
- token string
+ sharedSecret string
}
func (*rpcCredentials) RequireTransportSecurity() bool { return false }
func (rc *rpcCredentials) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
- return map[string]string{"authorization": "Bearer " + rc.token}, nil
+ return map[string]string{"authorization": "Bearer " + rc.sharedSecret}, nil
}
-// RPCCredentialsV2 can be used with grpc.WithPerRPCCredentials to create a
-// grpc.DialOption that inserts an HMAC token with the current timestamp
-// for authentication with a Gitaly server.
-func RPCCredentialsV2(token string) credentials.PerRPCCredentials {
- return &rpcCredentialsV2{token: token}
+// RPCCredentialsV2 can be used with grpc.WithPerRPCCredentials to create
+// a grpc.DialOption that inserts an V2 (HMAC) token with the current
+// timestamp for authentication with a Gitaly server. The shared secret
+// must match the one used on the Gitaly server.
+func RPCCredentialsV2(sharedSecret string) credentials.PerRPCCredentials {
+ return &rpcCredentialsV2{sharedSecret: sharedSecret}
}
type rpcCredentialsV2 struct {
- token string
+ sharedSecret string
}
func (*rpcCredentialsV2) RequireTransportSecurity() bool { return false }
-func (rc *rpcCredentialsV2) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
- return map[string]string{"authorization": "Bearer " + rc.hmacToken()}, nil
-}
-
-func (rc *rpcCredentialsV2) hmacToken() string {
- return hmacToken("v2", []byte(rc.token), time.Now())
-}
-
-func hmacToken(version string, secret []byte, timestamp time.Time) string {
- intTime := timestamp.Unix()
- signedTimestamp := hmacSign(secret, strconv.FormatInt(intTime, 10))
+func (rc2 *rpcCredentialsV2) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
+ message := strconv.FormatInt(time.Now().Unix(), 10)
+ signature := hmacSign([]byte(rc2.sharedSecret), message)
- return fmt.Sprintf("%s.%x.%d", version, signedTimestamp, intTime)
+ return map[string]string{
+ "authorization": "Bearer " + fmt.Sprintf("v2.%x.%s", signature, message),
+ }, nil
}