[ARVADOS] updated: 0384dc6b233e42537dc4e16e7de7283a2ef94897

git at public.curoverse.com git at public.curoverse.com
Wed Oct 7 16:49:34 EDT 2015


Summary of changes:
 sdk/go/arvadosclient/arvadosclient.go              |  4 +-
 {services/keepstore => sdk/go/keepclient}/perms.go | 52 ++++++++++------
 .../keepstore => sdk/go/keepclient}/perms_test.go  | 57 +++++-------------
 services/keepstore/perms.go                        | 69 ++++------------------
 services/keepstore/perms_test.go                   | 13 ++--
 tools/keep-rsync/keep-rsync.go                     |  4 +-
 6 files changed, 69 insertions(+), 130 deletions(-)
 copy {services/keepstore => sdk/go/keepclient}/perms.go (68%)
 copy {services/keepstore => sdk/go/keepclient}/perms_test.go (62%)

       via  0384dc6b233e42537dc4e16e7de7283a2ef94897 (commit)
       via  96dab84d9f1cd7d590f2c119ed6e484c8ed4888c (commit)
       via  d7712854004c2136b86f69617552559c93caf600 (commit)
       via  e1dbdc4b39eb8c75c088f971cee0e7bad92b2848 (commit)
       via  841bd266812983c8edd98a480b116c50000f47b9 (commit)
      from  8ff8be6aa9a21f9fe0d9f7398e2efb62da70df64 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 0384dc6b233e42537dc4e16e7de7283a2ef94897
Merge: d771285 96dab84
Author: radhika <radhika at curoverse.com>
Date:   Wed Oct 7 16:49:15 2015 -0400

    Merge branch '7167-keep-rsync-test-setup' into 7167-keep-rsync


commit 96dab84d9f1cd7d590f2c119ed6e484c8ed4888c
Author: radhika <radhika at curoverse.com>
Date:   Wed Oct 7 16:47:56 2015 -0400

    7167: move perms code from keepstore into keepclient go SDK.

diff --git a/services/keepstore/perms.go b/sdk/go/keepclient/perms.go
similarity index 68%
copy from services/keepstore/perms.go
copy to sdk/go/keepclient/perms.go
index 5579238..5b792a8 100644
--- a/services/keepstore/perms.go
+++ b/sdk/go/keepclient/perms.go
@@ -33,7 +33,7 @@ request. If the permissions do not match, or if the API token is not
 present, Keep returns a 401 error.
 */
 
-package main
+package keepclient
 
 import (
 	"crypto/hmac"
@@ -45,15 +45,29 @@ import (
 	"time"
 )
 
-// The PermissionSecret is the secret key used to generate SHA1
-// digests for permission hints. apiserver and Keep must use the same
-// key.
-var PermissionSecret []byte
+// KeepError types.
+//
+type KeepError struct {
+	HTTPCode int
+	ErrMsg   string
+}
+
+var (
+	PermissionError = &KeepError{403, "Forbidden"}
+	ExpiredError    = &KeepError{401, "Expired permission signature"}
+)
+
+func (e *KeepError) Error() string {
+	return e.ErrMsg
+}
 
-// MakePermSignature returns a string representing the signed permission
-// hint for the blob identified by blobHash, apiToken and expiration timestamp.
-func MakePermSignature(blobHash string, apiToken string, expiry string) string {
-	hmac := hmac.New(sha1.New, PermissionSecret)
+// makePermSignature returns a string representing the signed permission
+// hint for the blob identified by blobHash, apiToken, expiration timestamp, and permission secret.
+//
+// The permissionSecret is the secret key used to generate SHA1 digests
+// for permission hints. apiserver and Keep must use the same key.
+func makePermSignature(blobHash string, apiToken string, expiry string, permissionSecret []byte) string {
+	hmac := hmac.New(sha1.New, permissionSecret)
 	hmac.Write([]byte(blobHash))
 	hmac.Write([]byte("@"))
 	hmac.Write([]byte(apiToken))
@@ -63,12 +77,12 @@ func MakePermSignature(blobHash string, apiToken string, expiry string) string {
 	return fmt.Sprintf("%x", digest)
 }
 
-// SignLocator takes a blobLocator, an apiToken and an expiry time, and
-// returns a signed locator string.
-func SignLocator(blobLocator string, apiToken string, expiry time.Time) string {
+// SignLocator takes a blobLocator, an apiToken, an expiry time, and a permission secret
+// and returns a signed locator string.
+func SignLocator(blobLocator string, apiToken string, expiry time.Time, permissionSecret []byte) string {
 	// If no permission secret or API token is available,
 	// return an unsigned locator.
-	if PermissionSecret == nil || apiToken == "" {
+	if permissionSecret == nil || apiToken == "" {
 		return blobLocator
 	}
 	// Extract the hash from the blob locator, omitting any size hint that may be present.
@@ -76,7 +90,7 @@ func SignLocator(blobLocator string, apiToken string, expiry time.Time) string {
 	// Return the signed locator string.
 	timestampHex := fmt.Sprintf("%08x", expiry.Unix())
 	return blobLocator +
-		"+A" + MakePermSignature(blobHash, apiToken, timestampHex) +
+		"+A" + makePermSignature(blobHash, apiToken, timestampHex, permissionSecret) +
 		"@" + timestampHex
 }
 
@@ -87,7 +101,7 @@ var signedLocatorRe = regexp.MustCompile(`^([[:xdigit:]]{32}).*\+A([[:xdigit:]]{
 // either ExpiredError (if the timestamp has expired, which is
 // something the client could have figured out independently) or
 // PermissionError.
-func VerifySignature(signedLocator string, apiToken string) error {
+func VerifySignature(signedLocator string, apiToken string, permissionSecret []byte) error {
 	matches := signedLocatorRe.FindStringSubmatch(signedLocator)
 	if matches == nil {
 		// Could not find a permission signature at all
@@ -96,19 +110,19 @@ func VerifySignature(signedLocator string, apiToken string) error {
 	blobHash := matches[1]
 	sigHex := matches[2]
 	expHex := matches[3]
-	if expTime, err := ParseHexTimestamp(expHex); err != nil {
+	if expTime, err := parseHexTimestamp(expHex); err != nil {
 		return PermissionError
 	} else if expTime.Before(time.Now()) {
 		return ExpiredError
 	}
-	if sigHex != MakePermSignature(blobHash, apiToken, expHex) {
+	if sigHex != makePermSignature(blobHash, apiToken, expHex, permissionSecret) {
 		return PermissionError
 	}
 	return nil
 }
 
-// ParseHexTimestamp parses timestamp
-func ParseHexTimestamp(timestampHex string) (ts time.Time, err error) {
+// parseHexTimestamp parses timestamp
+func parseHexTimestamp(timestampHex string) (ts time.Time, err error) {
 	if tsInt, e := strconv.ParseInt(timestampHex, 16, 0); e == nil {
 		ts = time.Unix(tsInt, 0)
 	} else {
diff --git a/services/keepstore/perms_test.go b/sdk/go/keepclient/perms_test.go
similarity index 62%
copy from services/keepstore/perms_test.go
copy to sdk/go/keepclient/perms_test.go
index 59516af..61d10c1 100644
--- a/services/keepstore/perms_test.go
+++ b/sdk/go/keepclient/perms_test.go
@@ -1,4 +1,4 @@
-package main
+package keepclient
 
 import (
 	"testing"
@@ -23,103 +23,76 @@ const (
 )
 
 func TestSignLocator(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
-	if ts, err := ParseHexTimestamp(knownTimestamp); err != nil {
+	if ts, err := parseHexTimestamp(knownTimestamp); err != nil {
 		t.Errorf("bad knownTimestamp %s", knownTimestamp)
 	} else {
-		if knownSignedLocator != SignLocator(knownLocator, knownToken, ts) {
+		if knownSignedLocator != SignLocator(knownLocator, knownToken, ts, []byte(knownKey)) {
 			t.Fail()
 		}
 	}
 }
 
 func TestVerifySignature(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
-	if VerifySignature(knownSignedLocator, knownToken) != nil {
+	if VerifySignature(knownSignedLocator, knownToken, []byte(knownKey)) != nil {
 		t.Fail()
 	}
 }
 
 func TestVerifySignatureExtraHints(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
-	if VerifySignature(knownLocator+"+K at xyzzy"+knownSigHint, knownToken) != nil {
+	if VerifySignature(knownLocator+"+K at xyzzy"+knownSigHint, knownToken, []byte(knownKey)) != nil {
 		t.Fatal("Verify cannot handle hint before permission signature")
 	}
 
-	if VerifySignature(knownLocator+knownSigHint+"+Zfoo", knownToken) != nil {
+	if VerifySignature(knownLocator+knownSigHint+"+Zfoo", knownToken, []byte(knownKey)) != nil {
 		t.Fatal("Verify cannot handle hint after permission signature")
 	}
 
-	if VerifySignature(knownLocator+"+K at xyzzy"+knownSigHint+"+Zfoo", knownToken) != nil {
+	if VerifySignature(knownLocator+"+K at xyzzy"+knownSigHint+"+Zfoo", knownToken, []byte(knownKey)) != nil {
 		t.Fatal("Verify cannot handle hints around permission signature")
 	}
 }
 
 // The size hint on the locator string should not affect signature validation.
 func TestVerifySignatureWrongSize(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
-	if VerifySignature(knownHash+"+999999"+knownSigHint, knownToken) != nil {
+	if VerifySignature(knownHash+"+999999"+knownSigHint, knownToken, []byte(knownKey)) != nil {
 		t.Fatal("Verify cannot handle incorrect size hint")
 	}
 
-	if VerifySignature(knownHash+knownSigHint, knownToken) != nil {
+	if VerifySignature(knownHash+knownSigHint, knownToken, []byte(knownKey)) != nil {
 		t.Fatal("Verify cannot handle missing size hint")
 	}
 }
 
 func TestVerifySignatureBadSig(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
 	badLocator := knownLocator + "+Aaaaaaaaaaaaaaaa@" + knownTimestamp
-	if VerifySignature(badLocator, knownToken) != PermissionError {
+	if VerifySignature(badLocator, knownToken, []byte(knownKey)) != PermissionError {
 		t.Fail()
 	}
 }
 
 func TestVerifySignatureBadTimestamp(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
 	badLocator := knownLocator + "+A" + knownSignature + "@OOOOOOOl"
-	if VerifySignature(badLocator, knownToken) != PermissionError {
+	if VerifySignature(badLocator, knownToken, []byte(knownKey)) != PermissionError {
 		t.Fail()
 	}
 }
 
 func TestVerifySignatureBadSecret(t *testing.T) {
-	PermissionSecret = []byte("00000000000000000000")
-	defer func() { PermissionSecret = nil }()
-
-	if VerifySignature(knownSignedLocator, knownToken) != PermissionError {
+	if VerifySignature(knownSignedLocator, knownToken, []byte("00000000000000000000")) != PermissionError {
 		t.Fail()
 	}
 }
 
 func TestVerifySignatureBadToken(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
-	if VerifySignature(knownSignedLocator, "00000000") != PermissionError {
+	if VerifySignature(knownSignedLocator, "00000000", []byte(knownKey)) != PermissionError {
 		t.Fail()
 	}
 }
 
 func TestVerifySignatureExpired(t *testing.T) {
-	PermissionSecret = []byte(knownKey)
-	defer func() { PermissionSecret = nil }()
-
 	yesterday := time.Now().AddDate(0, 0, -1)
-	expiredLocator := SignLocator(knownHash, knownToken, yesterday)
-	if VerifySignature(expiredLocator, knownToken) != ExpiredError {
+	expiredLocator := SignLocator(knownHash, knownToken, yesterday, []byte(knownKey))
+	if VerifySignature(expiredLocator, knownToken, []byte(knownKey)) != ExpiredError {
 		t.Fail()
 	}
 }
diff --git a/services/keepstore/perms.go b/services/keepstore/perms.go
index 5579238..494e6b7 100644
--- a/services/keepstore/perms.go
+++ b/services/keepstore/perms.go
@@ -36,12 +36,7 @@ present, Keep returns a 401 error.
 package main
 
 import (
-	"crypto/hmac"
-	"crypto/sha1"
-	"fmt"
-	"regexp"
-	"strconv"
-	"strings"
+	"git.curoverse.com/arvados.git/sdk/go/keepclient"
 	"time"
 )
 
@@ -50,69 +45,25 @@ import (
 // key.
 var PermissionSecret []byte
 
-// MakePermSignature returns a string representing the signed permission
-// hint for the blob identified by blobHash, apiToken and expiration timestamp.
-func MakePermSignature(blobHash string, apiToken string, expiry string) string {
-	hmac := hmac.New(sha1.New, PermissionSecret)
-	hmac.Write([]byte(blobHash))
-	hmac.Write([]byte("@"))
-	hmac.Write([]byte(apiToken))
-	hmac.Write([]byte("@"))
-	hmac.Write([]byte(expiry))
-	digest := hmac.Sum(nil)
-	return fmt.Sprintf("%x", digest)
-}
-
 // SignLocator takes a blobLocator, an apiToken and an expiry time, and
 // returns a signed locator string.
 func SignLocator(blobLocator string, apiToken string, expiry time.Time) string {
-	// If no permission secret or API token is available,
-	// return an unsigned locator.
-	if PermissionSecret == nil || apiToken == "" {
-		return blobLocator
-	}
-	// Extract the hash from the blob locator, omitting any size hint that may be present.
-	blobHash := strings.Split(blobLocator, "+")[0]
-	// Return the signed locator string.
-	timestampHex := fmt.Sprintf("%08x", expiry.Unix())
-	return blobLocator +
-		"+A" + MakePermSignature(blobHash, apiToken, timestampHex) +
-		"@" + timestampHex
+	return keepclient.SignLocator(blobLocator, apiToken, expiry, PermissionSecret)
 }
 
-var signedLocatorRe = regexp.MustCompile(`^([[:xdigit:]]{32}).*\+A([[:xdigit:]]{40})@([[:xdigit:]]{8})`)
-
 // VerifySignature returns nil if the signature on the signedLocator
 // can be verified using the given apiToken. Otherwise it returns
 // either ExpiredError (if the timestamp has expired, which is
 // something the client could have figured out independently) or
 // PermissionError.
 func VerifySignature(signedLocator string, apiToken string) error {
-	matches := signedLocatorRe.FindStringSubmatch(signedLocator)
-	if matches == nil {
-		// Could not find a permission signature at all
-		return PermissionError
-	}
-	blobHash := matches[1]
-	sigHex := matches[2]
-	expHex := matches[3]
-	if expTime, err := ParseHexTimestamp(expHex); err != nil {
-		return PermissionError
-	} else if expTime.Before(time.Now()) {
-		return ExpiredError
-	}
-	if sigHex != MakePermSignature(blobHash, apiToken, expHex) {
-		return PermissionError
-	}
-	return nil
-}
-
-// ParseHexTimestamp parses timestamp
-func ParseHexTimestamp(timestampHex string) (ts time.Time, err error) {
-	if tsInt, e := strconv.ParseInt(timestampHex, 16, 0); e == nil {
-		ts = time.Unix(tsInt, 0)
-	} else {
-		err = e
+	err := keepclient.VerifySignature(signedLocator, apiToken, PermissionSecret)
+	if err != nil {
+		if err == keepclient.PermissionError {
+			return PermissionError
+		} else if err == keepclient.ExpiredError {
+			return ExpiredError
+		}
 	}
-	return ts, err
+	return err
 }
diff --git a/services/keepstore/perms_test.go b/services/keepstore/perms_test.go
index 59516af..9b4e30a 100644
--- a/services/keepstore/perms_test.go
+++ b/services/keepstore/perms_test.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"strconv"
 	"testing"
 	"time"
 )
@@ -26,12 +27,12 @@ func TestSignLocator(t *testing.T) {
 	PermissionSecret = []byte(knownKey)
 	defer func() { PermissionSecret = nil }()
 
-	if ts, err := ParseHexTimestamp(knownTimestamp); err != nil {
-		t.Errorf("bad knownTimestamp %s", knownTimestamp)
-	} else {
-		if knownSignedLocator != SignLocator(knownLocator, knownToken, ts) {
-			t.Fail()
-		}
+	tsInt, err := strconv.ParseInt(knownTimestamp, 16, 0)
+	if err != nil {
+		t.Fail()
+	}
+	if knownSignedLocator != SignLocator(knownLocator, knownToken, time.Unix(tsInt, 0)) {
+		t.Fail()
 	}
 }
 

commit d7712854004c2136b86f69617552559c93caf600
Merge: 8ff8be6 e1dbdc4
Author: radhika <radhika at curoverse.com>
Date:   Wed Oct 7 14:03:12 2015 -0400

    Merge branch '7167-keep-rsync-test-setup' into 7167-keep-rsync


commit e1dbdc4b39eb8c75c088f971cee0e7bad92b2848
Merge: 841bd26 ba019dd
Author: radhika <radhika at curoverse.com>
Date:   Wed Oct 7 13:52:33 2015 -0400

    Merge branch 'master' into 7167-keep-rsync-test-setup


commit 841bd266812983c8edd98a480b116c50000f47b9
Author: radhika <radhika at curoverse.com>
Date:   Wed Oct 7 13:51:16 2015 -0400

    7167: rename MakeArvadosClientWithConfig as New

diff --git a/sdk/go/arvadosclient/arvadosclient.go b/sdk/go/arvadosclient/arvadosclient.go
index cc99efd..af8bce4 100644
--- a/sdk/go/arvadosclient/arvadosclient.go
+++ b/sdk/go/arvadosclient/arvadosclient.go
@@ -102,11 +102,11 @@ func MakeArvadosClient() (ac ArvadosClient, err error) {
 	config.APIHostInsecure = matchTrue.MatchString(os.Getenv("ARVADOS_API_HOST_INSECURE"))
 	config.ExternalClient = matchTrue.MatchString(os.Getenv("ARVADOS_EXTERNAL_CLIENT"))
 
-	return MakeArvadosClientWithConfig(config)
+	return New(config)
 }
 
 // Create a new ArvadosClient, using the given input parameters.
-func MakeArvadosClientWithConfig(config APIConfig) (ac ArvadosClient, err error) {
+func New(config APIConfig) (ac ArvadosClient, err error) {
 	ac = ArvadosClient{
 		ApiServer:   config.APIHost,
 		ApiToken:    config.APIToken,
diff --git a/tools/keep-rsync/keep-rsync.go b/tools/keep-rsync/keep-rsync.go
index 1f00a9f..6bfbbac 100644
--- a/tools/keep-rsync/keep-rsync.go
+++ b/tools/keep-rsync/keep-rsync.go
@@ -137,13 +137,13 @@ var (
 // Initializes keep-rsync using the config provided
 func initializeKeepRsync() (err error) {
 	// arvSrc from srcConfig
-	arvSrc, err = arvadosclient.MakeArvadosClientWithConfig(srcConfig)
+	arvSrc, err = arvadosclient.New(srcConfig)
 	if err != nil {
 		return
 	}
 
 	// arvDst from dstConfig
-	arvDst, err = arvadosclient.MakeArvadosClientWithConfig(dstConfig)
+	arvDst, err = arvadosclient.New(dstConfig)
 	if err != nil {
 		return
 	}
diff --git a/tools/keep-rsync/keep-rsync_test.go b/tools/keep-rsync/keep-rsync_test.go
index ae80f45..4fdc6a8 100644
--- a/tools/keep-rsync/keep-rsync_test.go
+++ b/tools/keep-rsync/keep-rsync_test.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
-	"regexp"
 	"testing"
 
 	"git.curoverse.com/arvados.git/sdk/go/arvadostest"

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list