Skip to content

Commit

Permalink
Encode keys in URLs with base64url raw (hyperledger-labs#477)
Browse files Browse the repository at this point in the history
Signed-off-by: Yoav Tock <[email protected]>
Signed-off-by: senthil <[email protected]>
  • Loading branch information
tock-ibm authored and cendhu committed Jan 5, 2023
1 parent bc8c716 commit e49f216
Show file tree
Hide file tree
Showing 24 changed files with 578 additions and 87 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ cmd/bdb/bdb

#IDE artifacts
.idea

#Documentation with docusaurus
.docusaurus
node_modules
yarn.lock

3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ module github.com/hyperledger-labs/orion-server
go 1.16

require (
github.com/VictoriaMetrics/fastcache v1.12.0
github.com/cayleygraph/cayley v0.7.7
github.com/cayleygraph/quad v1.1.0
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.1
github.com/golang/snappy v0.0.4
github.com/google/uuid v1.1.1
github.com/gorilla/mux v1.7.4
github.com/hidal-go/hidalgo v0.0.0-20201109092204-05749a6d73df
Expand Down
13 changes: 11 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VictoriaMetrics/fastcache v1.12.0 h1:vnVi/y9yKDcD9akmc4NqAoqgQhJrOwUF+j9LTgn4QDE=
github.com/VictoriaMetrics/fastcache v1.12.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/badgerodon/peg v0.0.0-20130729175151-9e5f7f4d07ca/go.mod h1:TWe0N2hv5qvpLHT+K16gYcGBllld4h65dQ/5CNuirmk=
Expand All @@ -28,7 +32,10 @@ github.com/cayleygraph/quad v1.1.0 h1:w1nXAmn+nz07+qlw89dke9LwWkYpeX+OcvfTvGQRBp
github.com/cayleygraph/quad v1.1.0/go.mod h1:maWODEekEhrO0mdc9h5n/oP7cH1h/OTgqQ2qWbuI9M4=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down Expand Up @@ -141,8 +148,9 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
Expand Down Expand Up @@ -446,8 +454,9 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64 h1:D1v9ucDTYBtbz5vNuBbAhIMAGhQhJ6Ym5ah3maMVNX4=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
1 change: 1 addition & 0 deletions internal/httphandler/data_request_handler.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright IBM Corp. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package httphandler

import (
Expand Down
62 changes: 55 additions & 7 deletions internal/httphandler/data_request_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ func TestDataRequestHandler_DataQuery(t *testing.T) {
Key: "foo",
})

sigAbc := testutils.SignatureFromQuery(t, aliceSigner, &types.GetDataQuery{
UserId: submittingUserName,
DbName: dbName,
Key: "abc/def",
})

sigKey1 := testutils.SignatureFromQuery(t, aliceSigner, &types.GetDataQuery{
UserId: submittingUserName,
DbName: dbName,
Key: "key1",
})


testCases := []struct {
name string
requestFactory func() (*http.Request, error)
Expand Down Expand Up @@ -83,6 +96,41 @@ func TestDataRequestHandler_DataQuery(t *testing.T) {
},
expectedStatusCode: http.StatusOK,
},
{
name: "valid get data request - non URL",
expectedResponse: &types.GetDataResponseEnvelope{
Response: &types.GetDataResponse{
Header: &types.ResponseHeader{
NodeId: "testNodeID",
},
Value: []byte("bar"),
Metadata: &types.Metadata{
Version: &types.Version{
TxNum: 1,
BlockNum: 1,
},
},
},
Signature: []byte{0, 0, 0},
},
requestFactory: func() (*http.Request, error) {
req, err := http.NewRequest(http.MethodGet, constants.URLForGetData(dbName, "abc/def"), nil)
if err != nil {
return nil, err
}
req.Header.Set(constants.UserHeader, submittingUserName)
req.Header.Set(constants.SignatureHeader, base64.StdEncoding.EncodeToString(sigAbc))
return req, nil
},
dbMockFactory: func(response *types.GetDataResponseEnvelope) bcdb.DB {
db := &mocks.DB{}
db.On("GetCertificate", submittingUserName).Return(aliceCert, nil)
db.On("GetData", dbName, submittingUserName, "abc/def").Return(response, nil)
db.On("IsDBExists", dbName).Return(true)
return db
},
expectedStatusCode: http.StatusOK,
},
{
name: "submitting user is not eligible to update the key",
requestFactory: func() (*http.Request, error) {
Expand All @@ -102,29 +150,29 @@ func TestDataRequestHandler_DataQuery(t *testing.T) {
return db
},
expectedStatusCode: http.StatusForbidden,
expectedErr: "error while processing 'GET /data/test_database/foo' because access forbidden",
expectedErr: "error while processing 'GET /data/test_database/Zm9v' because access forbidden", // "Zm9v" is base64url of "foo"
},
{
name: "failed to get data",
requestFactory: func() (*http.Request, error) {
req, err := http.NewRequest(http.MethodGet, constants.URLForGetData(dbName, "foo"), nil)
req, err := http.NewRequest(http.MethodGet, constants.URLForGetData(dbName, "key1"), nil)
if err != nil {
return nil, err
}
req.Header.Set(constants.UserHeader, submittingUserName)
req.Header.Set(constants.SignatureHeader, base64.StdEncoding.EncodeToString(sigFoo))
req.Header.Set(constants.SignatureHeader, base64.StdEncoding.EncodeToString(sigKey1))
return req, nil
},
dbMockFactory: func(response *types.GetDataResponseEnvelope) bcdb.DB {
db := &mocks.DB{}
db.On("GetCertificate", submittingUserName).Return(aliceCert, nil)
db.On("IsDBExists", dbName).Return(true)
db.On("GetData", dbName, submittingUserName, "foo").
db.On("GetData", dbName, submittingUserName, "key1").
Return(nil, errors.New("failed to get data"))
return db
},
expectedStatusCode: http.StatusInternalServerError,
expectedErr: "error while processing 'GET /data/test_database/foo' because failed to get data",
expectedErr: "error while processing 'GET /data/test_database/a2V5MQ' because failed to get data", // "a2V5MQ" is base64url of "key1"
},
{
name: "user doesn't exist",
Expand Down Expand Up @@ -488,7 +536,7 @@ func TestDataRequestHandler_DataRangeQuery(t *testing.T) {
return db
},
expectedStatusCode: http.StatusForbidden,
expectedErr: "error while processing 'GET /data/test_database?startkey=\"key1\"&endkey=\"key10\"&limit=10' because access forbidden",
expectedErr: "error while processing 'GET /data/test_database?startkey=a2V5MQ&endkey=a2V5MTA&limit=10' because access forbidden", // "a2V5MQ" and "a2V5MTA" are the base64 url of "key1" and "key10", resp.
},
{
name: "failed to get data",
Expand All @@ -510,7 +558,7 @@ func TestDataRequestHandler_DataRangeQuery(t *testing.T) {
return db
},
expectedStatusCode: http.StatusInternalServerError,
expectedErr: "error while processing 'GET /data/test_database?startkey=\"key1\"&endkey=\"key10\"&limit=10' because failed to get data",
expectedErr: "error while processing 'GET /data/test_database?startkey=a2V5MQ&endkey=a2V5MTA&limit=10' because failed to get data", // "a2V5MQ" and "a2V5MTA" are the base64 url of "key1" and "key10", resp.
},
{
name: "user doesn't exist",
Expand Down
4 changes: 2 additions & 2 deletions internal/httphandler/ledger_request_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ func TestDataProofQuery(t *testing.T) {
return db
},
expectedStatusCode: http.StatusNotFound,
expectedErr: "error while processing 'GET /ledger/proof/data/bdb/key1?block=2' because no proof for block 2, db bdb, key key1, isDeleted false found",
expectedErr: "error while processing 'GET /ledger/proof/data/bdb/a2V5MQ?block=2' because no proof for block 2, db bdb, key key1, isDeleted false found", // "a2V5MQ" is base 64 url of "key1"
},
{
name: "no key exist, deleted is true",
Expand Down Expand Up @@ -907,7 +907,7 @@ func TestDataProofQuery(t *testing.T) {
return db
},
expectedStatusCode: http.StatusNotFound,
expectedErr: "error while processing 'GET /ledger/proof/data/bdb/key1?block=2&deleted=true' because no proof for block 2, db bdb, key key1, isDeleted true found",
expectedErr: "error while processing 'GET /ledger/proof/data/bdb/a2V5MQ?block=2&deleted=true' because no proof for block 2, db bdb, key key1, isDeleted true found", // "a2V5MQ" is base 64 url of "key1"
},
{
name: "wrong url, block param missing",
Expand Down
57 changes: 50 additions & 7 deletions internal/httphandler/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,42 @@ func extractVerifiedQueryPayload(w http.ResponseWriter, r *http.Request, queryTy

switch queryType {
case constants.GetData:
key, err := utils.GetBase64urlKey(params, "key")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, &types.HttpResponseErr{ErrMsg: err.Error()})
return nil, true
}

payload = &types.GetDataQuery{
UserId: querierUserID,
DbName: params["dbname"],
Key: params["key"],
Key: key,
}

case constants.GetDataRange:
limit, err := strconv.ParseUint(params["limit"], 10, 64)
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, &types.HttpResponseErr{ErrMsg: err.Error()})
return nil, true
}

startKey, err := utils.GetBase64urlKey(params, "startkey")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, &types.HttpResponseErr{ErrMsg: err.Error()})
return nil, true
}

endKey, err := utils.GetBase64urlKey(params, "endkey")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, &types.HttpResponseErr{ErrMsg: err.Error()})
return nil, true
}

payload = &types.GetDataRangeQuery{
UserId: querierUserID,
DbName: params["dbname"],
StartKey: params["startkey"][1 : len(params["startkey"])-1],
EndKey: params["endkey"][1 : len(params["endkey"])-1],
StartKey: startKey,
EndKey: endKey,
Limit: limit,
}
case constants.GetUser:
Expand Down Expand Up @@ -144,6 +163,12 @@ func extractVerifiedQueryPayload(w http.ResponseWriter, r *http.Request, queryTy
TxIndex: txIndex,
}
case constants.GetDataProof:
key, err := utils.GetBase64urlKey(params, "key")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, err)
return nil, true
}

blockNum, err := utils.GetBlockNum(params)
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, err)
Expand All @@ -163,7 +188,7 @@ func extractVerifiedQueryPayload(w http.ResponseWriter, r *http.Request, queryTy
UserId: querierUserID,
BlockNumber: blockNum,
DbName: params["dbname"],
Key: params["key"],
Key: key,
IsDeleted: deleted,
}
case constants.GetTxReceipt:
Expand All @@ -172,6 +197,12 @@ func extractVerifiedQueryPayload(w http.ResponseWriter, r *http.Request, queryTy
TxId: params["txId"],
}
case constants.GetHistoricalData:
key, err := utils.GetBase64urlKey(params, "key")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, err)
return nil, true
}

version, err := utils.GetVersion(params)
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, err)
Expand All @@ -191,23 +222,35 @@ func extractVerifiedQueryPayload(w http.ResponseWriter, r *http.Request, queryTy
payload = &types.GetHistoricalDataQuery{
UserId: querierUserID,
DbName: params["dbname"],
Key: params["key"],
Key: key,
Version: version,
Direction: params["direction"],
OnlyDeletes: isOnlyDeletesSet,
MostRecent: isMostRecentSet,
}
case constants.GetDataReaders:
key, err := utils.GetBase64urlKey(params, "key")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, err)
return nil, true
}

payload = &types.GetDataReadersQuery{
UserId: querierUserID,
DbName: params["dbname"],
Key: params["key"],
Key: key,
}
case constants.GetDataWriters:
key, err := utils.GetBase64urlKey(params, "key")
if err != nil {
utils.SendHTTPResponse(w, http.StatusBadRequest, err)
return nil, true
}

payload = &types.GetDataWritersQuery{
UserId: querierUserID,
DbName: params["dbname"],
Key: params["key"],
Key: key,
}
case constants.GetDataReadBy:
payload = &types.GetDataReadByQuery{
Expand Down
14 changes: 14 additions & 0 deletions internal/utils/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package utils

import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
Expand Down Expand Up @@ -126,3 +127,16 @@ func GetVersion(params map[string]string) (*types.Version, error) {
TxNum: txNum,
}, nil
}

func GetBase64urlKey(params map[string]string, name string) (string, error) {
base64urlKey, ok := params[name]
if !ok {
return "", &types.HttpResponseErr{ErrMsg: fmt.Sprintf("Missing key: %s (in base64 URL encoding)", name)}
}
keyBytes, err := base64.RawURLEncoding.DecodeString(base64urlKey)
if err != nil {
return "", &types.HttpResponseErr{ErrMsg: fmt.Sprintf("Failed to decode base64 URL key: %s: %s", name, err.Error())}
}

return string(keyBytes), nil
}
Loading

0 comments on commit e49f216

Please sign in to comment.