Skip to content
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
11 changes: 5 additions & 6 deletions asgard/heimdallr.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ package asgard
import (
"context"
"encoding/pem"
"log/slog"
"net/http"
"net/url"

Expand Down Expand Up @@ -51,14 +50,14 @@ func Heimdallr(h HeaderName, ns uuid.UUID) func(http.Handler) http.Handler {

certHeader := r.Header.Get(h.String())
if certHeader == "" {
slog.ErrorContext(ctx, "missing authorization header")
bifrost.Logger().ErrorContext(ctx, "missing authorization header")
http.Error(w, errBadAuthHeader, http.StatusServiceUnavailable)
return
}

certPEM, err := url.PathUnescape(certHeader)
if err != nil {
slog.ErrorContext(
bifrost.Logger().ErrorContext(
ctx, "error decoding header",
"headerName", h.String(),
"headerValue", certHeader,
Expand All @@ -69,7 +68,7 @@ func Heimdallr(h HeaderName, ns uuid.UUID) func(http.Handler) http.Handler {

block, _ := pem.Decode([]byte(certPEM))
if block == nil {
slog.ErrorContext(
bifrost.Logger().ErrorContext(
ctx, "no PEM data found in authorization header",
"headerName", h.String(),
"headerValue", certPEM,
Expand All @@ -80,13 +79,13 @@ func Heimdallr(h HeaderName, ns uuid.UUID) func(http.Handler) http.Handler {

cert, err := bifrost.ParseCertificate(block.Bytes)
if err != nil {
slog.ErrorContext(ctx, "error parsing client certificate", "error", err)
bifrost.Logger().ErrorContext(ctx, "error parsing client certificate", "error", err)
http.Error(w, errBadAuthHeader, http.StatusServiceUnavailable)
return
}

if cert.Namespace != ns {
slog.ErrorContext(
bifrost.Logger().ErrorContext(
ctx, "client certificate namespace mismatch",
"expected", ns,
"actual", cert.Namespace,
Expand Down
6 changes: 3 additions & 3 deletions asgard/hofund.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package asgard

import (
"encoding/pem"
"log/slog"
"net/http"
"net/url"

Expand All @@ -29,13 +28,14 @@ func Hofund(h HeaderName, ns uuid.UUID) func(http.Handler) http.Handler {

cert, err := bifrost.NewCertificate(r.TLS.PeerCertificates[0])
if err != nil {
slog.ErrorContext(ctx, "error validating client certificate", "error", err)
bifrost.Logger().
ErrorContext(ctx, "error validating client certificate", "error", err)
http.Error(w, "invalid client certificate", http.StatusUnauthorized)
return
}

if cert.Namespace != ns {
slog.ErrorContext(
bifrost.Logger().ErrorContext(
ctx, "client certificate namespace mismatch",
"expected", ns,
"actual", cert.Namespace,
Expand Down
38 changes: 38 additions & 0 deletions bifrost.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Package bifrost contains an API client for the Bifrost CA service.
package bifrost

import (
"context"
"log/slog"
"sync/atomic"
)

var (
// LogLevel is the log level used by the bifrost logger.
LogLevel = new(slog.LevelVar)

logger atomic.Pointer[slog.Logger]
)

// Logger returns the global Bifrost logger.
func Logger() *slog.Logger {
return logger.Load()
}

// SetLogger sets the [*slog.Logger] used by bifrost.
// The default handler disables logging.
func SetLogger(l *slog.Logger) {
logger.Store(l)
}

func init() {
SetLogger(slog.New(discardHandler{}))
}

// discardHandler is an [slog.Handler] which is always disabled and therefore logs nothing.
type discardHandler struct{}

func (discardHandler) Enabled(context.Context, slog.Level) bool { return false }
func (discardHandler) Handle(context.Context, slog.Record) error { return nil }
func (d discardHandler) WithAttrs([]slog.Attr) slog.Handler { return d }
func (d discardHandler) WithGroup(string) slog.Handler { return d }
6 changes: 5 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ func (cr *certRefresher) GetClientCertificate(
}

// If the certificate is nil or is going to expire soon, request a new one.
if cert := cr.cert.Load(); cert == nil || cert.NotAfter.Before(time.Now().Add(-time.Minute*10)) {
if cert := cr.cert.Load(); cert == nil ||
cert.NotAfter.Before(time.Now().Add(-time.Minute*10)) {
Logger().DebugContext(ctx, "refreshing client certificate")

cert, err := RequestCertificate(ctx, cr.url, cr.privkey)
if err != nil {
return nil, err
Expand All @@ -66,6 +69,7 @@ func (cr *certRefresher) GetClientCertificate(
break
}
}
Logger().InfoContext(ctx, "got new client certificate")
}

tlsCert := X509ToTLSCertificate(cr.cert.Load().Certificate, cr.privkey.PrivateKey)
Expand Down
35 changes: 18 additions & 17 deletions cmd/bf/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"encoding/pem"
"errors"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"time"

"github.com/RealImage/bifrost"
"github.com/RealImage/bifrost/cafiles"
"github.com/RealImage/bifrost/internal/webapp"
"github.com/RealImage/bifrost/tinyca"
Expand Down Expand Up @@ -82,10 +82,10 @@ var caServeCmd = &cli.Command{
Action: func(ctx context.Context, _ *cli.Command) error {
cert, key, err := cafiles.GetCertKey(ctx, caCertUri, caPrivKeyUri)
if err != nil {
slog.ErrorContext(ctx, "error reading cert/key", "error", err)
bifrost.Logger().ErrorContext(ctx, "error reading cert/key", "error", err)
return cli.Exit("Error reading cert/key", 1)
}
slog.DebugContext(
bifrost.Logger().DebugContext(
ctx, "loaded CA certificate and private key",
"subject", cert.Subject,
"notBefore", cert.NotBefore,
Expand All @@ -94,13 +94,13 @@ var caServeCmd = &cli.Command{

gauntlet, err := tinyca.LoadGauntlet(gauntletPlugin)
if err != nil {
slog.ErrorContext(ctx, "error loading interceptor plugin", "error", err)
bifrost.Logger().ErrorContext(ctx, "error loading interceptor plugin", "error", err)
return cli.Exit("Error loading interceptor plugin", 1)
}

ca, err := tinyca.New(cert, key, gauntlet)
if err != nil {
slog.ErrorContext(ctx, "error creating CA", "error", err)
bifrost.Logger().ErrorContext(ctx, "error creating CA", "error", err)
return cli.Exit("Error creating CA", 1)
}
defer ca.Close()
Expand All @@ -115,13 +115,14 @@ var caServeCmd = &cli.Command{
}

addr := fmt.Sprintf("%s:%d", caHost, caPort)
slog.InfoContext(ctx, "starting server", "address", addr, "namespace", cert.Namespace)
bifrost.Logger().
InfoContext(ctx, "starting server", "address", addr, "namespace", cert.Namespace)

server := http.Server{Addr: addr, Handler: hdlr}

go func() {
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
slog.ErrorContext(ctx, "error starting server", "error", err)
bifrost.Logger().ErrorContext(ctx, "error starting server", "error", err)
os.Exit(1)
}
}()
Expand All @@ -134,11 +135,11 @@ var caServeCmd = &cli.Command{
ctx, cancel = context.WithTimeout(context.Background(), serverShutdownTimeout)
defer cancel()

slog.DebugContext(ctx, "shutting down server")
bifrost.Logger().DebugContext(ctx, "shutting down server")
if err := server.Shutdown(ctx); err != nil {
return err
}
slog.InfoContext(ctx, "server shut down")
bifrost.Logger().InfoContext(ctx, "server shut down")

return nil
},
Expand Down Expand Up @@ -174,20 +175,20 @@ var caIssueCmd = &cli.Command{
Action: func(ctx context.Context, _ *cli.Command) error {
caCert, caKey, err := cafiles.GetCertKey(ctx, caCertUri, caPrivKeyUri)
if err != nil {
slog.ErrorContext(ctx, "error reading cert/key", "error", err)
bifrost.Logger().ErrorContext(ctx, "error reading cert/key", "error", err)
return cli.Exit("Error reading cert/key", 1)
}

ca, err := tinyca.New(caCert, caKey, nil)
if err != nil {
slog.ErrorContext(ctx, "error creating CA", "error", err)
bifrost.Logger().ErrorContext(ctx, "error creating CA", "error", err)
return cli.Exit("Error creating CA", 1)
}
defer ca.Close()

clientKey, err := cafiles.GetPrivateKey(ctx, clientPrivKeyUri)
if err != nil {
slog.ErrorContext(ctx, "error reading client key", "error", err)
bifrost.Logger().ErrorContext(ctx, "error reading client key", "error", err)
return cli.Exit("Error reading client key", 1)
}

Expand All @@ -198,30 +199,30 @@ var caIssueCmd = &cli.Command{
},
}, clientKey)
if err != nil {
slog.ErrorContext(ctx, "error creating certificate request", "error", err)
bifrost.Logger().ErrorContext(ctx, "error creating certificate request", "error", err)
return cli.Exit("Error creating certificate request", 1)
}

notBefore, notAfter, err := tinyca.ParseValidity(notBeforeTime, notAfterTime)
if err != nil {
slog.ErrorContext(ctx, "error parsing validity", "error", err)
bifrost.Logger().ErrorContext(ctx, "error parsing validity", "error", err)
return cli.Exit("Error parsing validity", 1)
}

cert, err := ca.IssueCertificate(csr, notBefore, notAfter)
if err != nil {
slog.ErrorContext(ctx, "error issuing certificate", "error", err)
bifrost.Logger().ErrorContext(ctx, "error issuing certificate", "error", err)
return cli.Exit("Error issuing certificate", 1)
}

out, cls, err := getOutputWriter()
if err != nil {
slog.ErrorContext(ctx, "error getting output writer", "error", err)
bifrost.Logger().ErrorContext(ctx, "error getting output writer", "error", err)
return cli.Exit("Error getting output writer", 1)
}
defer func() {
if err := cls(); err != nil {
slog.ErrorContext(ctx, "error closing output writer", "error", err)
bifrost.Logger().ErrorContext(ctx, "error closing output writer", "error", err)
}
}()

Expand Down
8 changes: 4 additions & 4 deletions cmd/bf/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
"log/slog"
"os"

"github.com/RealImage/bifrost"
Expand Down Expand Up @@ -36,7 +35,7 @@ var idCmd = &cli.Command{

id, err := bifrost.ParseIdentity(data)
if err != nil {
slog.ErrorContext(ctx, "error parsing id file", "error", err)
bifrost.Logger().ErrorContext(ctx, "error parsing id file", "error", err)
return cli.Exit("Error parsing file", 1)
}

Expand All @@ -46,15 +45,16 @@ var idCmd = &cli.Command{

// Either we got a namespace from the file or the namespace flag is set
if id.Namespace != uuid.Nil && namespace != uuid.Nil && id.Namespace != namespace {
slog.ErrorContext(ctx, "namespace mismatch", "file", id.Namespace, "flag", namespace)
bifrost.Logger().
ErrorContext(ctx, "namespace mismatch", "file", id.Namespace, "flag", namespace)
return cli.Exit("Namespace mismatch", 1)
}

if namespace != uuid.Nil {
id.Namespace = namespace
}

slog.Debug("using", "namespace", id.Namespace)
bifrost.Logger().Debug("using", "namespace", id.Namespace)
fmt.Println(id.UUID())

return nil
Expand Down
12 changes: 8 additions & 4 deletions cmd/bf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import (
"log/slog"
"os"

"github.com/RealImage/bifrost"
"github.com/urfave/cli/v3"
)

var version = "devel"

func main() {
logLevel := new(slog.LevelVar)
hdlr := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel})
slog.SetDefault(slog.New(hdlr))
logger := slog.New(
slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: bifrost.LogLevel}),
)

slog.SetDefault(logger)
bifrost.SetLogger(logger)

cli := &cli.Command{
Name: "bifrost",
Expand All @@ -27,7 +31,7 @@ func main() {
Sources: cli.EnvVars("LOG_LEVEL"),
Value: slog.LevelInfo.String(),
Action: func(_ context.Context, _ *cli.Command, level string) error {
return logLevel.UnmarshalText([]byte(level))
return bifrost.LogLevel.UnmarshalText([]byte(level))
},
},
},
Expand Down
13 changes: 8 additions & 5 deletions cmd/bf/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"log/slog"

"github.com/RealImage/bifrost"
"github.com/RealImage/bifrost/cafiles"
Expand Down Expand Up @@ -35,7 +34,8 @@ var newCmd = &cli.Command{
}
defer func() {
if err := cls(); err != nil {
slog.ErrorContext(ctx, "error closing output writer", "error", err)
bifrost.Logger().
ErrorContext(ctx, "error closing output writer", "error", err)
}
}()

Expand Down Expand Up @@ -67,7 +67,8 @@ var newCmd = &cli.Command{
}
defer func() {
if err := cls(); err != nil {
slog.ErrorContext(ctx, "error closing output writer", "error", err)
bifrost.Logger().
ErrorContext(ctx, "error closing output writer", "error", err)
}
}()

Expand Down Expand Up @@ -110,7 +111,8 @@ var newCmd = &cli.Command{
}
defer func() {
if err := cls(); err != nil {
slog.ErrorContext(ctx, "error closing output writer", "error", err)
bifrost.Logger().
ErrorContext(ctx, "error closing output writer", "error", err)
}
}()

Expand Down Expand Up @@ -173,7 +175,8 @@ var newCmd = &cli.Command{
}
defer func() {
if err := cls(); err != nil {
slog.ErrorContext(ctx, "error closing output writer", "error", err)
bifrost.Logger().
ErrorContext(ctx, "error closing output writer", "error", err)
}
}()

Expand Down
Loading
Loading