Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Invert Keeper Flow #78

Merged
merged 20 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions app/keeper/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import (
"github.com/spiffe/spike-sdk-go/spiffe"

"github.com/spiffe/spike/app/keeper/internal/env"
api "github.com/spiffe/spike/app/keeper/internal/net"
"github.com/spiffe/spike/app/keeper/internal/route/handle"
"github.com/spiffe/spike/app/keeper/internal/state"
"github.com/spiffe/spike/app/keeper/internal/trust"
"github.com/spiffe/spike/internal/auth"
"github.com/spiffe/spike/internal/config"
Expand All @@ -37,34 +35,6 @@ func main() {

trust.Authenticate(spiffeid)

keeperState := state.ReadAppState()

if keeperState == state.AppStateError {
log.FatalLn(
"SPIKE Keeper is in ERROR state. Manual intervention required.",
)
}

if keeperState == state.AppStateNotReady {
log.Log().Info(appName,
"msg", "SPIKE Keeper is not ready. Will send shards")

go api.Contribute(source)

go state.WaitForShards()
}

if keeperState == state.AppStateReady ||
keeperState == state.AppStateRecovering {
// TODO: implement this case
// 1. Transition to a RECOVERING state, if not done already
// 2. Contact peers to recompute shard.
// 3. Try forever.
// 4. If something is irrevocably irrecoverable transition to ERROR state.
// 5. When everything is back to normal, transition to READY state.
panic("I started, but I don't know what to do.")
}

log.Log().Info(appName, "msg", fmt.Sprintf("Started service: %s v%s",
appName, config.KeeperVersion))
if err := net.ServeWithPredicate(
Expand Down
83 changes: 0 additions & 83 deletions app/keeper/internal/net/contribute.go

This file was deleted.

4 changes: 2 additions & 2 deletions app/keeper/internal/route/base/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ func Route(w http.ResponseWriter, r *http.Request, a *log.AuditEntry) error {
r.Method,
func(a net.SpikeKeeperApiAction, p net.ApiUrl) net.Handler {
switch {
// Get contribution from SPIKE Nexus
case a == net.ActionKeeperDefault && p == net.SpikeKeeperUrlContribute:
return store.RouteContribute
// Provide your shard to SPIKE Nexus
case a == net.ActionKeeperDefault && p == net.SpikeKeeperUrlShard:
return store.RouteShard
case a == net.ActionKeeperDefault && p == net.SpikeKeeperUrlStatus:
return store.RouteStatus
default:
return net.Fallback
}
Expand Down
3 changes: 1 addition & 2 deletions app/keeper/internal/route/store/contribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ func RouteContribute(

// Store decoded shard in the map.
state.Shards.Store(id, decodedShard)

log.Log().Info(fName, "msg", "Shard stored", "id", id, "shard", decodedShard)
log.Log().Info(fName, "msg", "Shard stored", "id", id)

responseBody := net.MarshalBody(reqres.ShardContributionResponse{}, w)

Expand Down
115 changes: 0 additions & 115 deletions app/keeper/internal/state/join.go

This file was deleted.

82 changes: 0 additions & 82 deletions app/keeper/internal/state/shard.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,79 +6,8 @@ package state

import (
"sync"
"time"

"github.com/spiffe/spike/internal/log"
"github.com/spiffe/spike/pkg/crypto"
)

// WaitForShards blocks until exactly 3 shards are collected in the global
// Shards map. Once collected, it computes the final key, generates shares,
// sets the internal shard, and performs validation checks.
//
// The function:
// - Polls the Shards map every 2 seconds until 3 shards are present
// - Panics if more than 3 shards are received
// - Processes the shards to generate the final distributed secret
//
// Panics:
// - If more than 3 shards are received
func WaitForShards() {
for {
shardCount := 0
Shards.Range(func(key, value any) bool {
shardCount++
return true
})

log.Log().Info(
"waitForShards", "msg", "Current shard count", "count", shardCount,
)

if shardCount < 3 {
time.Sleep(2 * time.Second)
continue
}

if shardCount > 3 {
// TODO: add an audit log, because this is a security incident likely.
log.FatalLn("waitForShards: Too many shards received")
}

finalKey := computeFinalKey()
secret, shares := computeShares(finalKey)
setInternalShard(shares)
sanityCheck(secret, shares)

break
}
}

var myContribution []byte
var myContributionLock sync.Mutex

// RandomContribution generates and caches a random contribution for the
// distributed secret. The contribution is generated only once and reused for
// subsequent calls.
//
// Returns:
// - []byte: Random contribution bytes from AES-256 seed
//
// Thread-safe through myContributionLock mutex.
func RandomContribution() []byte {
myContributionLock.Lock()
defer myContributionLock.Unlock()

if len(myContribution) == 0 {
mySeed, _ := crypto.Aes256Seed()
myContribution = []byte(mySeed)

return myContribution
}

return myContribution
}

var Shards sync.Map

var shard []byte
Expand Down Expand Up @@ -107,14 +36,3 @@ func Shard() []byte {
defer shardMutex.RUnlock()
return shard
}

// EraseIntermediateShards removes all entries from the global Shards map,
// cleaning up intermediate secret sharing data.
//
// Thread-safe through sync.Map operations.
func EraseIntermediateShards() {
Shards.Range(func(key, value interface{}) bool {
Shards.Delete(key)
return true
})
}
Loading
Loading