Skip to content

Commit 3878919

Browse files
authored
Merge pull request #128 from spiffe/feature/release-cleanup
v0.4.0 Crossing fingers and landing.
2 parents b8deba3 + 97405fb commit 3878919

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+5338
-11702
lines changed

app/keeper/cmd/main.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import (
99
"fmt"
1010

1111
"github.com/spiffe/spike-sdk-go/net"
12+
"github.com/spiffe/spike-sdk-go/security/mem"
1213
"github.com/spiffe/spike-sdk-go/spiffe"
14+
"github.com/spiffe/spike-sdk-go/spiffeid"
1315

1416
"github.com/spiffe/spike/app/keeper/internal/env"
1517
http "github.com/spiffe/spike/app/keeper/internal/route/base"
16-
"github.com/spiffe/spike/internal/auth"
1718
"github.com/spiffe/spike/internal/config"
1819
"github.com/spiffe/spike/internal/log"
1920
routing "github.com/spiffe/spike/internal/net"
@@ -24,6 +25,12 @@ const appName = "SPIKE Keeper"
2425
func main() {
2526
log.Log().Info(appName, "msg", appName, "version", config.SpikeKeeperVersion)
2627

28+
if mem.Lock() {
29+
log.Log().Info(appName, "msg", "Successfully locked memory.")
30+
} else {
31+
log.Log().Info(appName, "msg", "Memory is not locked. Please disable swap.")
32+
}
33+
2734
ctx, cancel := context.WithCancel(context.Background())
2835
defer cancel()
2936

@@ -34,7 +41,7 @@ func main() {
3441
defer spiffe.CloseSource(source)
3542

3643
// I should be a SPIKE Keeper.
37-
if !auth.IsKeeper(selfSpiffeid) {
44+
if !spiffeid.IsKeeper(selfSpiffeid) {
3845
log.FatalF("Authenticate: SPIFFE ID %s is not valid.\n", selfSpiffeid)
3946
}
4047

@@ -46,7 +53,7 @@ func main() {
4653
if err := net.ServeWithPredicate(
4754
source,
4855
func() { routing.HandleRoute(http.Route) },
49-
auth.PeerCanTalkToKeeper,
56+
spiffeid.PeerCanTalkToKeeper,
5057
env.TlsPort(),
5158
); err != nil {
5259
log.FatalF("%s: Failed to serve: %s\n", appName, err.Error())

app/nexus/cmd/main.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import (
99
"fmt"
1010

1111
"github.com/spiffe/spike-sdk-go/net"
12+
"github.com/spiffe/spike-sdk-go/security/mem"
1213
"github.com/spiffe/spike-sdk-go/spiffe"
14+
"github.com/spiffe/spike-sdk-go/spiffeid"
1315

1416
"github.com/spiffe/spike/app/nexus/internal/env"
1517
"github.com/spiffe/spike/app/nexus/internal/initialization"
1618
http "github.com/spiffe/spike/app/nexus/internal/route/base"
17-
"github.com/spiffe/spike/internal/auth"
1819
"github.com/spiffe/spike/internal/config"
1920
"github.com/spiffe/spike/internal/log"
2021
routing "github.com/spiffe/spike/internal/net"
@@ -23,8 +24,15 @@ import (
2324
const appName = "SPIKE Nexus"
2425

2526
func main() {
27+
2628
log.Log().Info(appName, "msg", appName, "version", config.SpikeNexusVersion)
2729

30+
if mem.Lock() {
31+
log.Log().Info(appName, "msg", "Successfully locked memory.")
32+
} else {
33+
log.Log().Info(appName, "msg", "Memory is not locked. Please disable swap.")
34+
}
35+
2836
ctx, cancel := context.WithCancel(context.Background())
2937
defer cancel()
3038

@@ -35,7 +43,7 @@ func main() {
3543
defer spiffe.CloseSource(source)
3644

3745
// I should be Nexus.
38-
if !auth.IsNexus(selfSpiffeid) {
46+
if !spiffeid.IsNexus(selfSpiffeid) {
3947
log.FatalF("Authenticate: SPIFFE ID %s is not valid.\n", selfSpiffeid)
4048
}
4149

app/nexus/internal/env/recovery.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,20 @@ func RecoveryOperationPollInterval() time.Duration {
5858

5959
return 5 * time.Second
6060
}
61+
62+
// RecoveryKeeperUpdateInterval returns the duration between keeper updates for
63+
// SPIKE Nexus. It first attempts to read the duration from the
64+
// SPIKE_NEXUS_KEEPER_UPDATE_INTERVAL environment variable. If the environment
65+
// variable is set and contains a valid duration string (as parsed by
66+
// time.ParseDuration), that duration is returned. Otherwise, it returns a
67+
// default value of 5 minutes.
68+
func RecoveryKeeperUpdateInterval() time.Duration {
69+
e := os.Getenv("SPIKE_NEXUS_KEEPER_UPDATE_INTERVAL")
70+
if e != "" {
71+
if d, err := time.ParseDuration(e); err == nil {
72+
return d
73+
}
74+
}
75+
76+
return 5 * time.Minute
77+
}

app/nexus/internal/initialization/recovery/recovery.go

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,17 @@ func HydrateMemoryFromBackingStore() {
123123
log.Log().Info(fName, "msg", "HydrateMemoryFromBackingStore")
124124

125125
secrets := persist.ReadAllSecrets()
126-
if len(secrets) == 0 {
127-
return
126+
if len(secrets) > 0 {
127+
state.ImportSecrets(secrets)
128128
}
129+
log.Log().Info(fName, "msg", "HydrateMemoryFromBackingStore: secrets loaded")
129130

130-
state.ImportSecrets(secrets)
131+
policies := persist.ReadAllPolicies()
132+
if len(policies) > 0 {
133+
state.ImportPolicies(policies)
134+
}
131135

132-
log.Log().Info(fName, "msg", "HydrateMemoryFromBackingStore: secrets loaded")
136+
log.Log().Info(fName, "msg", "HydrateMemoryFromBackingStore: policies loaded")
133137
}
134138

135139
// RestoreBackingStoreUsingPilotShards restores the backing store using the
@@ -153,13 +157,37 @@ func HydrateMemoryFromBackingStore() {
153157
func RestoreBackingStoreUsingPilotShards(shards []ShamirShard) {
154158
const fName = "RestoreBackingStoreUsingPilotShards"
155159

160+
log.Log().Info(fName, "msg", "Restoring backing store using pilot shards")
161+
162+
// Sanity check:
163+
for shard := range shards {
164+
value := shards[shard].Value
165+
id := shards[shard].Id
166+
167+
if mem.Zeroed32(value) || id == 0 {
168+
log.Log().Error(
169+
fName,
170+
"msg", "Bad input: ID or Value of a shard is zero. Exiting recovery",
171+
)
172+
return
173+
}
174+
}
175+
176+
log.Log().Info(fName,
177+
"msg", "Recovering backing store using pilot shards",
178+
"threshold", env.ShamirThreshold(),
179+
"len", len(shards),
180+
)
181+
156182
// Ensure we have at least the threshold number of shards
157183
if len(shards) < env.ShamirThreshold() {
158184
log.Log().Error(fName, "msg", "Insufficient shards for recovery",
159185
"provided", len(shards), "required", env.ShamirThreshold())
160186
return
161187
}
162188

189+
log.Log().Info(fName, "msg", "Recovering backing store using pilot shards")
190+
163191
// Recover the root key using the threshold number of shards
164192
binaryRec := RecoverRootKey(shards)
165193
// Security: Ensure the root key is zeroed out after use.
@@ -202,9 +230,7 @@ func SendShardsPeriodically(source *workloadapi.X509Source) {
202230

203231
log.Log().Info(fName, "msg", "Will send shards to keepers")
204232

205-
// TODO: get this from config.
206-
//ticker := time.NewTicker(5 * time.Minute)
207-
ticker := time.NewTicker(30 * time.Second)
233+
ticker := time.NewTicker(env.RecoveryKeeperUpdateInterval())
208234
defer ticker.Stop()
209235

210236
for range ticker.C {
@@ -255,6 +281,7 @@ func NewPilotRecoveryShards() map[int]*[32]byte {
255281
log.Log().Info(fName, "msg", "Generating pilot recovery shards")
256282

257283
if state.RootKeyZero() {
284+
log.Log().Info(fName, "msg", "No root key; skipping")
258285
return nil
259286
}
260287

@@ -271,6 +298,8 @@ func NewPilotRecoveryShards() map[int]*[32]byte {
271298
var result = make(map[int]*[32]byte)
272299

273300
for _, share := range rootShares {
301+
log.Log().Info(fName, "msg", "Generating share", "share.id", share.ID)
302+
274303
contribution, err := share.Value.MarshalBinary()
275304
if err != nil {
276305
log.Log().Error(fName, "msg", "Failed to marshal share")
@@ -282,8 +311,7 @@ func NewPilotRecoveryShards() map[int]*[32]byte {
282311
return nil
283312
}
284313

285-
var bb []byte
286-
err = share.ID.UnmarshalBinary(bb)
314+
bb, err := share.ID.MarshalBinary()
287315
if err != nil {
288316
log.Log().Error(fName, "msg", "Failed to unmarshal share Id")
289317
return nil
@@ -300,9 +328,12 @@ func NewPilotRecoveryShards() map[int]*[32]byte {
300328
var rs [32]byte
301329
copy(rs[:], contribution)
302330

331+
log.Log().Info(fName, "msg", "Generated shares", "len", len(rs))
332+
303333
result[int(ii)] = &rs
304334
}
305335

336+
log.Log().Info(fName, "msg", "Successfully generated pilot recovery shards.")
306337
return result
307338
}
308339

app/nexus/internal/initialization/recovery/shamir.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ func sanityCheck(secret group.Scalar, shares []shamir.Share) {
7474
func computeShares() (group.Scalar, []shamir.Share) {
7575
const fName = "computeShares"
7676

77+
log.Log().Info(fName, "msg", "Computing Shamir shares")
78+
7779
state.LockRootKey()
7880
defer state.UnlockRootKey()
7981
rk := state.RootKeyNoLock()
@@ -83,6 +85,8 @@ func computeShares() (group.Scalar, []shamir.Share) {
8385
t := uint(env.ShamirThreshold() - 1) // Need t+1 shares to reconstruct
8486
n := uint(env.ShamirShares()) // Total number of shares
8587

88+
log.Log().Info(fName, "t", t, "n", n)
89+
8690
// Create secret from our 32 byte key
8791
secret := g.NewScalar()
8892

@@ -99,7 +103,11 @@ func computeShares() (group.Scalar, []shamir.Share) {
99103
reader := crypto.NewDeterministicReader(rk[:])
100104
ss := shamir.New(reader, t, secret)
101105

106+
log.Log().Info(fName, "msg", "Generated Shamir shares")
107+
108+
computedShares := ss.Share(n)
109+
102110
// secret is a pointer type; ss.Share(n) is a slice
103111
// shares will have monotonically increasing IDs, starting from 1.
104-
return secret, ss.Share(n)
112+
return secret, computedShares
105113
}

app/nexus/internal/initialization/recovery/shard.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import (
1313
apiUrl "github.com/spiffe/spike-sdk-go/api/url"
1414
network "github.com/spiffe/spike-sdk-go/net"
1515
"github.com/spiffe/spike-sdk-go/security/mem"
16+
"github.com/spiffe/spike-sdk-go/spiffeid"
1617

17-
"github.com/spiffe/spike/internal/auth"
1818
"github.com/spiffe/spike/internal/log"
1919
"github.com/spiffe/spike/internal/net"
2020
)
@@ -45,7 +45,7 @@ func shardResponse(source *workloadapi.X509Source, u string) []byte {
4545
}
4646

4747
client, err := network.CreateMtlsClientWithPredicate(
48-
source, auth.IsKeeper,
48+
source, spiffeid.IsKeeper,
4949
)
5050

5151
if err != nil {
@@ -88,7 +88,7 @@ func shardContributionResponse(
8888
) []byte {
8989
const fName = "shardContributionResponse"
9090

91-
client, err := network.CreateMtlsClientWithPredicate(source, auth.IsKeeper)
91+
client, err := network.CreateMtlsClientWithPredicate(source, spiffeid.IsKeeper)
9292

9393
if err != nil {
9494
log.Log().Warn(fName,

app/nexus/internal/initialization/recovery/update.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import (
1616
apiUrl "github.com/spiffe/spike-sdk-go/api/url"
1717
network "github.com/spiffe/spike-sdk-go/net"
1818
"github.com/spiffe/spike-sdk-go/security/mem"
19+
"github.com/spiffe/spike-sdk-go/spiffeid"
1920

2021
state "github.com/spiffe/spike/app/nexus/internal/state/base"
21-
"github.com/spiffe/spike/internal/auth"
2222
"github.com/spiffe/spike/internal/log"
2323
"github.com/spiffe/spike/internal/net"
2424
)
@@ -64,6 +64,12 @@ func mustUpdateRecoveryInfo(rk *[32]byte) []secretsharing.Share {
6464
// 3. findShare() ensures each keeper receives its designated share
6565
// This approach simplifies the code flow and maintains consistency across
6666
// potential system restarts or failures.
67+
//
68+
// Note that sendSharesToKeepers optimistically moves on to the next SPIKE
69+
// Keeper in the list on error. This is okay, because SPIKE Nexus may not
70+
// need all keepers to be healthy all at once, and since we periodically
71+
// send shards to keepers, provided there is no configration mistake,
72+
// all SPIKE Keepers will get their shards eventually.
6773
func sendShardsToKeepers(
6874
source *workloadapi.X509Source, keepers map[string]string,
6975
) {
@@ -74,14 +80,6 @@ func sendShardsToKeepers(
7480
keeperApiRoot, string(apiUrl.SpikeKeeperUrlContribute),
7581
)
7682

77-
// TODO: The sendShardsToKeepers function continues to the next keeper
78-
// on error. This is reasonable, but consider if all keepers must receive
79-
// shares for safety.
80-
// For example, maybe configuration problems should cause a fatal error
81-
// instead of just bypassing the keeper.
82-
// Since this is done periodically in `SendShardsPeriodically()`, we
83-
// can overlook temporary issues.
84-
8583
if err != nil {
8684
log.Log().Warn(
8785
fName, "msg", "Failed to join path", "url", keeperApiRoot,
@@ -90,7 +88,7 @@ func sendShardsToKeepers(
9088
}
9189

9290
client, err := network.CreateMtlsClientWithPredicate(
93-
source, auth.IsKeeper,
91+
source, spiffeid.IsKeeper,
9492
)
9593

9694
if err != nil {

app/nexus/internal/route/base/route.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/spiffe/spike-sdk-go/api/url"
1717

18+
"github.com/spiffe/spike/app/nexus/internal/env"
1819
"github.com/spiffe/spike/app/nexus/internal/route/acl/policy"
1920
"github.com/spiffe/spike/app/nexus/internal/route/operator"
2021
"github.com/spiffe/spike/app/nexus/internal/route/secret"
@@ -40,9 +41,11 @@ func Route(
4041
r.Method,
4142
func(a url.ApiAction, p url.ApiUrl) net.Handler {
4243
emptyRootKey := state.RootKeyZero()
44+
inMemoryMode := env.BackendStoreType() == env.Memory
45+
4346
emergencyAction := p == url.SpikeNexusUrlOperatorRecover ||
4447
p == url.SpikeNexusUrlOperatorRestore
45-
if emptyRootKey && !emergencyAction {
48+
if !inMemoryMode && emptyRootKey && !emergencyAction {
4649
return net.NotReady
4750
}
4851

0 commit comments

Comments
 (0)