-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* expose password with API * update secret model * HTTP API sharing request for secret * improve peer p2p design * mock keychain for linux peer insecure running * linux keychain mock * Use same DB Connection for all app * sharing request p2p exchange * Encryption / Decryption during secret exchange
- Loading branch information
Showing
19 changed files
with
922 additions
and
104 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,4 +27,5 @@ | |
.idea | ||
bin | ||
peervault.db | ||
.peervault-linux.db | ||
.DS_Store |
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 |
---|---|---|
@@ -1,8 +1,41 @@ | ||
GOVERSION=1.12 | ||
DEFAULT_RELAY="/ip4/37.187.1.229/tcp/23003/ipfs/QmeFecyqtgzYx1TFN9vYTroMGNo3DELtDZ63FpjqUd6xfW" | ||
|
||
.peervault-linux.db: | ||
touch .peervault-linux.db | ||
|
||
# Code Style | ||
fmt: | ||
go fmt | ||
|
||
lint: | ||
golint src/... | ||
|
||
sanity: fmt lint | ||
|
||
build: | ||
cd src && go build -ldflags "-w" -o ../bin/peervault main.go | ||
cd src && GOOS=darwin go build -ldflags "-w" -o ../bin/peervault main.go | ||
|
||
build-linux: | ||
cd src && GOOS=linux go build -ldflags "-w" -o ../bin/peervault-linux main.go | ||
|
||
run-linux: build-linux .peervault-linux.db | ||
docker run \ | ||
--rm -it \ | ||
-p 4445:4444 -p 5556:5555 \ | ||
-v $$(pwd)/bin/peervault-linux:/usr/local/bin/peervault-linux \ | ||
-v $$(pwd)/.peervault-linux.db:/var/peervault.db \ | ||
golang:$(GOVERSION) \ | ||
/usr/local/bin/peervault-linux \ | ||
-dev \ | ||
--log 9 \ | ||
--apiAddr 0.0.0.0:4444 \ | ||
--wsAddr 0.0.0.0:5555 \ | ||
--relay "$(DEFAULT_RELAY)" \ | ||
--bbolt /var/peervault.db | ||
|
||
run: build | ||
./bin/peervault -dev --log 9 --relay "/ip4/37.187.1.229/tcp/23003/ipfs/QmeFecyqtgzYx1TFN9vYTroMGNo3DELtDZ63FpjqUd6xfW" --bbolt /Users/pierozi/.peervault/bbolt-dev.db | ||
./bin/peervault -dev --log 9 --relay "$(DEFAULT_RELAY)" --bbolt /Users/pierozi/.peervault/bbolt-dev.db | ||
|
||
test: | ||
cd src && go test -v -coverprofile=/tmp/profile.out github.com/Power-LAB/PeerVault/crypto |
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,205 @@ | ||
package exposure | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/Power-LAB/PeerVault/business/owner" | ||
"github.com/Power-LAB/PeerVault/business/secret" | ||
"github.com/Power-LAB/PeerVault/communication/peer" | ||
"github.com/Power-LAB/PeerVault/crypto" | ||
"github.com/google/uuid" | ||
"github.com/op/go-logging" | ||
"net/http" | ||
"path" | ||
"time" | ||
) | ||
|
||
var ( | ||
log = logging.MustGetLogger("peerVaultLogger") | ||
) | ||
|
||
// Manage Secret GET / POST | ||
func Controller(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
if !owner.PasswordVerification(r, true) { | ||
http.Error(w, "{\"error\": \"X-OWNER-CODE is required\"}", http.StatusUnauthorized) | ||
return | ||
} | ||
|
||
switch r.Method { | ||
case http.MethodGet: | ||
getSecretValue(w, r) | ||
default: | ||
http.Error(w, "Invalid request method.", 405) | ||
} | ||
} | ||
|
||
// Manage Exposure Request | ||
// POST : Create a request for sharing secret with other peer | ||
// GET : List requests, both sent and received | ||
// DELETE : Decline or remove request | ||
func ControllerRequest(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
switch r.Method { | ||
case http.MethodPost: | ||
createShareRequest(w, r) | ||
case http.MethodGet: | ||
getShareRequest(w, r) | ||
case http.MethodDelete: | ||
deleteShareRequest(w, r) | ||
case http.MethodPut: | ||
shareResponse(w, r) | ||
default: | ||
http.Error(w, "Invalid request method.", 405) | ||
} | ||
} | ||
|
||
func getSecretValue(w http.ResponseWriter, r *http.Request) { | ||
keyPath := []byte(path.Base(r.RequestURI)) | ||
s, err := secret.FetchSecret(keyPath) | ||
|
||
if err == secret.ErrorSecretNotFound { | ||
http.Error(w, "{\"error\": \"Secret Not Found\"}", http.StatusNotFound) | ||
return | ||
} | ||
if err != nil { | ||
log.Error(err) | ||
w.Header().Set("Content-Type", "application/json") | ||
http.Error(w, "{\"error\": \"internal server error\"}", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
o := owner.Owner{} | ||
if o.FetchOwner() != nil { | ||
log.Notice(err) | ||
http.Error(w, "{\"error\": \"Owner not found\"}", http.StatusNotFound) | ||
} | ||
identity, err := o.GetIdentity() | ||
if err != nil { | ||
log.Debug("Cannot find Identity of current owner") | ||
log.Error(err) | ||
http.Error(w, "{\"error\": \"Cannot find Identity of current owner\"}", http.StatusInternalServerError) | ||
} | ||
plainText, err := crypto.DecryptAes(identity.GetChildKeyAsByte(), []byte(s.Value)) | ||
if err != nil { | ||
log.Debug("Error during secret decipher") | ||
log.Error(err) | ||
http.Error(w, "{\"error\": \"Secret cannot be decrypted\"}", http.StatusInternalServerError) | ||
} | ||
s.Value = string(plainText) | ||
|
||
resultJson, _ := json.Marshal(s) | ||
w.WriteHeader(http.StatusOK) | ||
_, _ = w.Write(resultJson) | ||
} | ||
|
||
func createShareRequest(w http.ResponseWriter, r *http.Request) { | ||
shareRequest := &ShareRequest{} | ||
// Verify and decode Owner input data | ||
decoder := json.NewDecoder(r.Body) | ||
err := decoder.Decode(&shareRequest) | ||
if err != nil { | ||
w.WriteHeader(http.StatusBadRequest) | ||
_, _ = w.Write([]byte("{\"error\": \"Payload must be struct of ShareRequest\"}")) | ||
return | ||
} | ||
|
||
// Check if KeyPath exist | ||
_, err = secret.FetchSecret([]byte(shareRequest.KeyPath)) | ||
if err == secret.ErrorSecretNotFound { | ||
http.Error(w, "{\"error\": \"Not secret found with KeyPath specified\"}", http.StatusNotFound) | ||
return | ||
} | ||
if err != nil { | ||
log.Error(err) | ||
http.Error(w, "{\"error\": \"internal server error\"}", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
// Get Owner | ||
o := owner.Owner{} | ||
if o.FetchOwner() != nil { | ||
log.Notice(err) | ||
http.Error(w, "{\"error\": \"Owner not found\"}", http.StatusNotFound) | ||
} | ||
|
||
// Create Share | ||
share := &Share{ | ||
Uuid: uuid.New().String(), | ||
Sender: o.QmPeerId, | ||
Receiver: shareRequest.Receiver, | ||
Expiration: time.Now().UTC().Add(shareRequest.ExpirationDelay * time.Hour).Format(time.RFC3339), | ||
KeyPath: shareRequest.KeyPath, | ||
} | ||
err = share.Save() | ||
if err != nil { | ||
log.Error(err) | ||
http.Error(w, "{\"error\": \"internal server error\"}", http.StatusInternalServerError) | ||
return | ||
} | ||
resultJson, _ := json.Marshal(share) | ||
|
||
go func() { | ||
// Dial to receiver | ||
err := peer.Dial(shareRequest.Receiver, peer.PidShareRequest, resultJson) | ||
if err != nil { | ||
log.Error("Error during share request dial") | ||
} | ||
}() | ||
|
||
w.WriteHeader(http.StatusOK) | ||
_, _ = w.Write(resultJson) | ||
} | ||
|
||
// Retrieved share request | ||
func getShareRequest(w http.ResponseWriter, r *http.Request) { | ||
shares, err := FetchShares() | ||
if err != nil { | ||
fmt.Printf("INTERNAL ERROR: %s", err.Error()) | ||
http.Error(w, "{\"error\": \"internal server error\"}", http.StatusInternalServerError) | ||
return | ||
} | ||
resultJson, _ := json.Marshal(shares) | ||
w.WriteHeader(http.StatusOK) | ||
_, _ = w.Write(resultJson) | ||
} | ||
|
||
func deleteShareRequest(w http.ResponseWriter, r *http.Request) { | ||
share := &Share{ | ||
Uuid: path.Base(r.RequestURI), | ||
} | ||
err := share.Delete() | ||
if err != nil { | ||
log.Debug("Error during share request deletion") | ||
log.Error(err) | ||
http.Error(w, "{\"error\": \"internal server error\"}", http.StatusInternalServerError) | ||
return | ||
} | ||
w.WriteHeader(http.StatusOK) | ||
} | ||
|
||
func shareResponse(w http.ResponseWriter, r *http.Request) { | ||
shareResponse := &ShareResponse{} | ||
// Verify and decode Owner input data | ||
decoder := json.NewDecoder(r.Body) | ||
err := decoder.Decode(&shareResponse) | ||
if err != nil { | ||
w.WriteHeader(http.StatusBadRequest) | ||
_, _ = w.Write([]byte("{\"error\": \"Payload must be struct of ShareRequest\"}")) | ||
return | ||
} | ||
shareResponseJson, _ := json.Marshal(shareResponse) | ||
|
||
go func() { | ||
// Approve the request locally to trust data when secret will arrive | ||
if shareResponse.Approved { | ||
peer.ApproveLocalRequest(shareResponse.Uuid) | ||
} | ||
// Dial to sender to confirm share | ||
err := peer.Dial(shareResponse.Sender, peer.PidShareResponse, shareResponseJson) | ||
if err != nil { | ||
log.Error("Error during share response dial") | ||
} | ||
}() | ||
w.WriteHeader(http.StatusOK) | ||
} |
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 |
---|---|---|
@@ -1 +1,108 @@ | ||
package exposure | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/Power-LAB/PeerVault/database" | ||
"go.etcd.io/bbolt" | ||
"time" | ||
) | ||
|
||
type Share struct { | ||
Uuid string | ||
Sender string | ||
Receiver string | ||
Expiration string | ||
KeyPath string | ||
} | ||
|
||
type ShareRequest struct { | ||
Receiver string | ||
KeyPath string | ||
ExpirationDelay time.Duration // Hours during the sharing request will be valid | ||
} | ||
|
||
type ShareResponse struct { | ||
Uuid string | ||
Sender string | ||
Approved bool | ||
} | ||
|
||
func (s *Share) Save() error { | ||
db, err := database.GetConnection() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Share serialized to json. | ||
buf, err := json.Marshal(&s) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return db.Update(func(tx *bbolt.Tx) error { | ||
var b *bbolt.Bucket | ||
b = tx.Bucket([]byte("share")) | ||
if b == nil { | ||
log.Debug("bucket share is nil") | ||
b2, err := tx.CreateBucket([]byte("share")) | ||
if err != nil { | ||
log.Debug("bucket share create error nil") | ||
return err | ||
} | ||
b = b2 | ||
} | ||
return b.Put([]byte(s.Uuid), buf) | ||
}) | ||
} | ||
|
||
func (s *Share) Delete() error { | ||
db, err := database.GetConnection() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return db.Update(func(tx *bbolt.Tx) error { | ||
var b *bbolt.Bucket | ||
b = tx.Bucket([]byte("share")) | ||
if b == nil { | ||
return nil | ||
} | ||
log.Debugf("Delete the share uuid: %s", s.Uuid) | ||
if err := b.Delete([]byte(s.Uuid)); err != nil { | ||
return err | ||
} | ||
return nil | ||
}) | ||
} | ||
|
||
func FetchShares() ([]Share, error) { | ||
db, err := database.GetConnection() | ||
if err != nil { | ||
return nil, err | ||
} | ||
var shares []Share | ||
|
||
err = db.View(func(tx *bbolt.Tx) error { | ||
b := tx.Bucket([]byte("share")) | ||
if b == nil { | ||
return nil | ||
} | ||
c := b.Cursor() | ||
|
||
for k, v := c.First(); k != nil; k, v = c.Next() { | ||
var share Share | ||
err := json.Unmarshal(v, &share) | ||
if err != nil { | ||
return err | ||
} | ||
shares = append(shares, share) | ||
} | ||
|
||
return nil | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return shares, nil | ||
} |
Oops, something went wrong.