Skip to content

Commit

Permalink
Merge pull request #48 from spiffe/release/v0.2.0
Browse files Browse the repository at this point in the history
SPIKE v0.2.0
  • Loading branch information
v0lkan authored Nov 23, 2024
2 parents 0fbb46f + 7a920c6 commit b578a3b
Show file tree
Hide file tree
Showing 37 changed files with 311 additions and 210 deletions.
5 changes: 3 additions & 2 deletions app/keeper/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
const appName = "SPIKE Keeper"

func main() {
log.Log().Info(appName, "msg", appName, "version", config.KeeperVersion)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

Expand All @@ -33,9 +35,8 @@ func main() {
trust.Authenticate(spiffeid)

log.Log().Info(appName,
"msg", fmt.Sprintf("Starting service: %s v%s",
"msg", fmt.Sprintf("Started service: %s v%s",
appName, config.KeeperVersion))

if err := net.Serve(
source, handle.InitializeRoutes,
auth.CanTalkToKeeper,
Expand Down
32 changes: 0 additions & 32 deletions app/keeper/internal/route/base/factory.go

This file was deleted.

20 changes: 14 additions & 6 deletions app/keeper/internal/route/base/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package base
import (
"net/http"

"github.com/spiffe/spike/app/keeper/internal/route/store"
"github.com/spiffe/spike/internal/log"
"github.com/spiffe/spike/internal/net"
)
Expand All @@ -19,12 +20,19 @@ import (
// Parameters:
// - w: The HTTP ResponseWriter to write the response to
// - r: The HTTP Request containing the client's request details
func Route(
w http.ResponseWriter, r *http.Request, audit *log.AuditEntry,
) error {
return factory(
func Route(w http.ResponseWriter, r *http.Request, a *log.AuditEntry) error {
return net.RouteFactory[net.SpikeKeeperApiAction](
net.ApiUrl(r.URL.Path),
net.SpikeKeeperApiAction(r.URL.Query().Get("action")),
net.SpikeKeeperApiAction(r.URL.Query().Get(net.KeyApiAction)),
r.Method,
)(w, r, audit)
func(a net.SpikeKeeperApiAction, p net.ApiUrl) net.Handler {
switch {
case a == net.ActionKeeperDefault && p == net.SpikeKeeperUrlKeep:
return store.RouteKeep
case a == net.ActionKeeperRead && p == net.SpikeKeeperUrlKeep:
return store.RouteShow
default:
return net.Fallback
}
})(w, r, a)
}
9 changes: 6 additions & 3 deletions app/nexus/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package main
import (
"context"
"errors"
"fmt"
"time"

"github.com/spiffe/spike/app/nexus/internal/env"
Expand All @@ -24,6 +25,8 @@ import (
const appName = "SPIKE Nexus"

func main() {
log.Log().Info(appName, "msg", appName, "version", config.NexusVersion)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

Expand Down Expand Up @@ -53,9 +56,9 @@ func main() {
defer ticker.Stop()
go poll.Tick(ctx, source, ticker)

log.Log().Info(appName, "msg",
"Starting service.", "version", config.NexusVersion)

log.Log().Info(appName,
"msg", fmt.Sprintf("Started service: %s v%s",
appName, config.NexusVersion))
if err := net.Serve(
source, handle.InitializeRoutes,
auth.CanTalkToNexus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// \\\\\ Copyright 2024-present SPIKE contributors.
// \\\\\\\ SPDX-License-Identifier: Apache-2.0

package net
package api

import (
"net/url"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// \\\\\ Copyright 2024-present SPIKE contributors.
// \\\\\\\ SPDX-License-Identifier: Apache-2.0

package net
package cache

import (
"errors"

"github.com/go-jose/go-jose/v4/json"
"github.com/spiffe/go-spiffe/v2/workloadapi"

"github.com/spiffe/spike/app/nexus/internal/net/api"
"github.com/spiffe/spike/internal/auth"
"github.com/spiffe/spike/internal/entity/v1/reqres"
"github.com/spiffe/spike/internal/net"
Expand Down Expand Up @@ -63,7 +64,7 @@ func UpdateCache(
)
}

_, err = net.Post(client, UrlKeeperWrite(), md)
_, err = net.Post(client, api.UrlKeeperWrite(), md)
return err
}

Expand Down Expand Up @@ -109,7 +110,7 @@ func FetchFromCache(source *workloadapi.X509Source) (string, error) {
)
}

data, err := net.Post(client, UrlKeeperRead(), md)
data, err := net.Post(client, api.UrlKeeperRead(), md)
var res reqres.RootKeyReadResponse

if len(data) == 0 {
Expand Down
4 changes: 2 additions & 2 deletions app/nexus/internal/poll/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

"github.com/spiffe/go-spiffe/v2/workloadapi"

"github.com/spiffe/spike/app/nexus/internal/net"
"github.com/spiffe/spike/app/nexus/internal/net/cache"
state "github.com/spiffe/spike/app/nexus/internal/state/base"
"github.com/spiffe/spike/internal/log"
)
Expand Down Expand Up @@ -67,7 +67,7 @@ func Tick(
for {
select {
case <-ticker.C:
err := net.UpdateCache(source, key)
err := cache.UpdateCache(source, key)
if err != nil {
log.Log().Error("tick",
"msg", "Failed to update the cache",
Expand Down
4 changes: 3 additions & 1 deletion app/nexus/internal/route/auth/init_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import (
state "github.com/spiffe/spike/app/nexus/internal/state/base"
)

func updateStateForInit(recoveryToken string, adminTokenBytes, salt []byte) error {
func updateStateForInit(
recoveryToken string, adminTokenBytes, salt []byte,
) error {
iterationCount := env.Pbkdf2IterationCount()
hashLength := env.ShaHashLength()
recoveryTokenHash := pbkdf2.Key(
Expand Down
45 changes: 0 additions & 45 deletions app/nexus/internal/route/base/factory.go

This file was deleted.

30 changes: 26 additions & 4 deletions app/nexus/internal/route/base/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
package base

import (
"net/http"

"github.com/spiffe/spike/app/nexus/internal/route/auth"
"github.com/spiffe/spike/app/nexus/internal/route/store"
"github.com/spiffe/spike/internal/log"
"github.com/spiffe/spike/internal/net"
"net/http"
)

// Route handles all incoming HTTP requests by dynamically selecting and
Expand All @@ -19,11 +22,30 @@ import (
// - w: The HTTP ResponseWriter to write the response to
// - r: The HTTP Request containing the client's request details
func Route(
w http.ResponseWriter, r *http.Request, audit *log.AuditEntry,
w http.ResponseWriter, r *http.Request, a *log.AuditEntry,
) error {
return factory(
return net.RouteFactory[net.SpikeNexusApiAction](
net.ApiUrl(r.URL.Path),
net.SpikeNexusApiAction(r.URL.Query().Get(net.KeyApiAction)),
r.Method,
)(w, r, audit)
func(a net.SpikeNexusApiAction, p net.ApiUrl) net.Handler {
switch {
case a == net.ActionNexusDefault && p == net.SpikeNexusUrlInit:
return auth.RouteInit
case a == net.ActionNexusCheck && p == net.SpikeNexusUrlInit:
return auth.RouteInitCheck
case a == net.ActionNexusDefault && p == net.SpikeNexusUrlSecrets:
return store.RoutePutSecret
case a == net.ActionNexusGet && p == net.SpikeNexusUrlSecrets:
return store.RouteGetSecret
case a == net.ActionNexusDelete && p == net.SpikeNexusUrlSecrets:
return store.RouteDeleteSecret
case a == net.ActionNexusUndelete && p == net.SpikeNexusUrlSecrets:
return store.RouteUndeleteSecret
case a == net.ActionNexusList && p == net.SpikeNexusUrlSecrets:
return store.RouteListPaths
default:
return net.Fallback
}
})(w, r, a)
}
6 changes: 1 addition & 5 deletions app/nexus/internal/route/store/secret_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,7 @@ func RouteGetSecret(
return err
}

// res := reqres.SecretReadResponse{Data: secret}

res := reqres.SecretReadResponse{Data: secret}

responseBody := net.MarshalBody(res, w)
responseBody := net.MarshalBody(reqres.SecretReadResponse{Data: secret}, w)
if responseBody == nil {
return errors.New("failed to marshal response body")
}
Expand Down
5 changes: 5 additions & 0 deletions app/nexus/internal/state/backend/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ import (
type NoopStore struct {
}

// StoreAdminRecoveryMetadata saves the admin recovery metadata to the store.
// This implementation is a no-op and always returns nil.
func (s *NoopStore) StoreAdminRecoveryMetadata(
ctx context.Context, credentials data.RecoveryMetadata,
) error {
return nil
}

// LoadAdminRecoveryMetadata retrieves the admin recovery metadata from the
// store. This implementation always returns an empty RecoveryMetadata and
// nil error.
func (s *NoopStore) LoadAdminRecoveryMetadata(
ctx context.Context,
) (data.RecoveryMetadata, error) {
Expand Down
33 changes: 32 additions & 1 deletion app/nexus/internal/state/backend/sqlite/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ func (s *DataStore) StoreAdminToken(ctx context.Context, token string) error {
return nil
}

// LoadAdminToken retrieves and decrypts the stored admin token.
// LoadAdminSigningToken retrieves and decrypts the stored admin token.
//
// Returns:
// - ("", nil) if no token exists
Expand Down Expand Up @@ -357,6 +357,20 @@ func (s *DataStore) LoadAdminSigningToken(ctx context.Context) (string, error) {
return string(decrypted), nil
}

// LoadAdminRecoveryMetadata retrieves the admin recovery metadata from the
// database. It returns an empty RecoveryMetadata struct if no record exists, or
// an error if the query fails.
//
// The method is thread-safe and uses a read lock when accessing the database.
// It queries the admin_recovery_metadata table for the single record with id=1,
// containing the token hash, encrypted root key, and salt used for admin
// recovery.
//
// Returns:
// - RecoveryMetadata: The retrieved credentials containing recovery token
// hash, encrypted root key, and salt
// - error: nil on success, sql.ErrNoRows if no record exists, or wrapped
// error on query failure
func (s *DataStore) LoadAdminRecoveryMetadata(ctx context.Context) (data.RecoveryMetadata, error) {
s.mu.RLock()
defer s.mu.RUnlock()
Expand All @@ -380,6 +394,23 @@ func (s *DataStore) LoadAdminRecoveryMetadata(ctx context.Context) (data.Recover
return creds, nil
}

// StoreAdminRecoveryMetadata saves or updates the admin recovery metadata in
// the database. The operation is performed atomically within a serializable
// transaction.
//
// The method is thread-safe and uses a write lock when accessing the database.
// It uses REPLACE INTO to ensure only one record exists in the
// admin_recovery_metadata table with id=1. The record includes token hash,
// encrypted root key, salt, and creation timestamp.
//
// Parameters:
// - ctx: Context for the database operation
// - credentials: RecoveryMetadata containing the token hash, encrypted root
// key, and salt to be stored
//
// Returns:
// - error: nil on success, or wrapped error describing the failure
// (transaction, query, or commit errors)
func (s *DataStore) StoreAdminRecoveryMetadata(
ctx context.Context, credentials data.RecoveryMetadata,
) error {
Expand Down
Loading

0 comments on commit b578a3b

Please sign in to comment.