Sign responses as well
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Ensure promotion takes longer than demotion
|
// TODO: Ensure promotion takes longer than demotion
|
||||||
@@ -141,12 +142,12 @@ func (c *Candidate) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
js = lo.Must(json.Marshal(c.resp))
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
// TODO: Sign responses
|
w.Header().Set("Signature", mac(js, c.signingKey))
|
||||||
|
|
||||||
enc := json.NewEncoder(w)
|
_, err = w.Write(js)
|
||||||
|
|
||||||
err = enc.Encode(c.resp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(
|
http.Error(
|
||||||
w,
|
w,
|
||||||
|
|||||||
29
voter.go
29
voter.go
@@ -1,6 +1,7 @@
|
|||||||
package elect
|
package elect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
@@ -109,13 +110,12 @@ func (v *Voter) sendVote() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
js := lo.Must(json.Marshal(v.vote))
|
js := lo.Must(json.Marshal(v.vote))
|
||||||
vr := &voteResponse{}
|
|
||||||
|
|
||||||
resp, err := v.client.R().
|
resp, err := v.client.R().
|
||||||
SetHeader("Signature", mac(js, v.signingKey)).
|
SetHeader("Signature", mac(js, v.signingKey)).
|
||||||
SetHeader("Content-Type", "application/json").
|
SetHeader("Content-Type", "application/json").
|
||||||
|
SetHeader("Accept", "application/json").
|
||||||
SetBody(js).
|
SetBody(js).
|
||||||
SetResult(vr).
|
|
||||||
Post("")
|
Post("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("vote response: %s", err)
|
log.Printf("vote response: %s", err)
|
||||||
@@ -126,13 +126,32 @@ func (v *Voter) sendVote() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.IsError() {
|
if resp.IsError() {
|
||||||
log.Printf("vote response: [%d] %s\n%s", resp.StatusCode(), resp.Status(), resp.String())
|
v.log("response: [%d] %s\n%s", resp.StatusCode(), resp.Status(), resp.String())
|
||||||
|
|
||||||
v.vote.NumPollsSinceChange = 0
|
v.vote.NumPollsSinceChange = 0
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sig := resp.Header().Get("Signature")
|
||||||
|
if sig == "" {
|
||||||
|
v.log("missing Signature response header")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hmac.Equal([]byte(sig), []byte(mac(resp.Body(), v.signingKey))) {
|
||||||
|
v.log("invalid Signature response header")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vr := &voteResponse{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(resp.Body(), vr)
|
||||||
|
if err != nil {
|
||||||
|
v.log("invalid response: %s", resp.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if vr.CandidateID == v.vote.LastSeenCandidateID {
|
if vr.CandidateID == v.vote.LastSeenCandidateID {
|
||||||
v.vote.NumPollsSinceChange++
|
v.vote.NumPollsSinceChange++
|
||||||
} else {
|
} else {
|
||||||
@@ -140,3 +159,7 @@ func (v *Voter) sendVote() {
|
|||||||
v.vote.NumPollsSinceChange = 0
|
v.vote.NumPollsSinceChange = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Voter) log(format string, args ...any) {
|
||||||
|
log.Printf("[voter] "+format, args...)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user