cmd/routed: use split database handlers
This commit is contained in:
parent
e91d1bb2b1
commit
2d2f894517
|
@ -170,7 +170,13 @@ retry_netrc:
|
||||||
|
|
||||||
tBody := uuid.New()
|
tBody := uuid.New()
|
||||||
|
|
||||||
_, err = db.PutToken(context.Background(), tBody, *tokenGenerateUsername, *tokenGenerateScopes)
|
tok := database.Token{
|
||||||
|
Body: uuid.New(),
|
||||||
|
Owner: *tokenGenerateUsername,
|
||||||
|
Scopes: *tokenGenerateScopes,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Tokens().Put(context.Background(), tok)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ln.FatalErr(ctx, err, ln.Action("add newly created token to database"))
|
ln.FatalErr(ctx, err, ln.Action("add newly created token to database"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func (s *Server) makeTwirpHooks() *twirp.ServerHooks {
|
||||||
|
|
||||||
tok := ck.Value
|
tok := ck.Value
|
||||||
|
|
||||||
t, err := s.db.GetToken(ctx, tok)
|
t, err := s.db.Tokens().Get(ctx, tok)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, err
|
return ctx, err
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,13 @@ func (s *Server) makeTwirpHooks() *twirp.ServerHooks {
|
||||||
"twirp_error_msg": e.Msg(),
|
"twirp_error_msg": e.Msg(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tr, ok := trace.FromContext(ctx)
|
||||||
|
if !ok {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.SetError()
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +115,12 @@ func (s *Server) getAuth(ctx context.Context, operation, scope string) (database
|
||||||
|
|
||||||
ok = false
|
ok = false
|
||||||
for _, sc := range t.Scopes {
|
for _, sc := range t.Scopes {
|
||||||
|
// the "admin" scope is implicitly allowed for everything.
|
||||||
|
if sc == "admin" {
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if sc == scope {
|
if sc == scope {
|
||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"git.xeserv.us/xena/route/internal/database"
|
||||||
"git.xeserv.us/xena/route/internal/elfs"
|
"git.xeserv.us/xena/route/internal/elfs"
|
||||||
proto "git.xeserv.us/xena/route/proto"
|
proto "git.xeserv.us/xena/route/proto"
|
||||||
"github.com/Xe/ln"
|
"github.com/Xe/ln"
|
||||||
|
@ -24,7 +25,7 @@ func (r *Route) Get(ctx context.Context, req *proto.GetRouteRequest) (*proto.Rou
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Get_getAuth"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Get_getAuth"})
|
||||||
}
|
}
|
||||||
|
|
||||||
val, err := r.db.GetRoute(ctx, req.Id)
|
val, err := r.db.Routes().Get(ctx, req.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "get single route from database", "id": req.Id})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "get single route from database", "id": req.Id})
|
||||||
}
|
}
|
||||||
|
@ -43,7 +44,7 @@ func (r *Route) GetAll(ctx context.Context, req *proto.Nil) (*proto.GetAllRoutes
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.GetAll_getAuth"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.GetAll_getAuth"})
|
||||||
}
|
}
|
||||||
|
|
||||||
routes, err := r.db.GetAllRoutes(ctx, clitok.Owner)
|
routes, err := r.db.Routes().GetAll(ctx, clitok.Owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "get all routes for user from database"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "get all routes for user from database"})
|
||||||
}
|
}
|
||||||
|
@ -70,12 +71,18 @@ func (r *Route) Put(ctx context.Context, rt *proto.Route) (*proto.Route, error)
|
||||||
rt.Host = elfs.MakeName() + r.cfg.DomainSuffix
|
rt.Host = elfs.MakeName() + r.cfg.DomainSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
drt, err := r.db.PutRoute(ctx, rt.Host, clitok.Owner)
|
rr := database.Route{
|
||||||
|
ID: rt.Id,
|
||||||
|
Hostname: rt.Host,
|
||||||
|
Creator: clitok.Owner,
|
||||||
|
}
|
||||||
|
|
||||||
|
drt, err := r.db.Routes().Put(ctx, rr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "put route to database"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "put route to database"})
|
||||||
}
|
}
|
||||||
|
|
||||||
ln.Log(ctx, drt, ln.Action("created new route"))
|
ln.Log(ctx, drt, ln.Action("put route to database"))
|
||||||
|
|
||||||
return drt.AsProto(), nil
|
return drt.AsProto(), nil
|
||||||
}
|
}
|
||||||
|
@ -86,7 +93,7 @@ func (r *Route) Delete(ctx context.Context, rt *proto.Route) (*proto.Nil, error)
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Delete_getAuth"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Delete_getAuth"})
|
||||||
}
|
}
|
||||||
|
|
||||||
drt, err := r.db.GetRoute(ctx, rt.Host)
|
drt, err := r.db.Routes().Get(ctx, rt.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "fetch route from database", "host": rt.Host})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "fetch route from database", "host": rt.Host})
|
||||||
}
|
}
|
||||||
|
@ -95,7 +102,7 @@ func (r *Route) Delete(ctx context.Context, rt *proto.Route) (*proto.Nil, error)
|
||||||
return nil, handleError(ctx, clitok, ErrNotAuthorized, ln.F{"action": "user not authorized to delete this route", "host": rt.Host})
|
return nil, handleError(ctx, clitok, ErrNotAuthorized, ln.F{"action": "user not authorized to delete this route", "host": rt.Host})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.db.DeleteRoute(ctx, rt.Id)
|
_, err = r.db.Routes().Delete(ctx, database.Route{ID: rt.Id})
|
||||||
f := drt.F()
|
f := drt.F()
|
||||||
f["action"] = "delete route from database"
|
f["action"] = "delete route from database"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -16,7 +16,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *storageWrapper) HasToken(token string) (string, []string, error) {
|
func (s *storageWrapper) HasToken(token string) (string, []string, error) {
|
||||||
t, err := s.Storage.GetToken(context.Background(), token)
|
t, err := s.Storage.Tokens().Get(context.Background(), token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ func (s *storageWrapper) HasToken(token string) (string, []string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storageWrapper) HasRoute(domain string) (string, error) {
|
func (s *storageWrapper) HasRoute(domain string) (string, error) {
|
||||||
r, err := s.Storage.GetRouteHost(context.Background(), domain)
|
r, err := s.Storage.Routes().GetHost(context.Background(), domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.xeserv.us/xena/route/internal/database"
|
||||||
proto "git.xeserv.us/xena/route/proto"
|
proto "git.xeserv.us/xena/route/proto"
|
||||||
"github.com/Xe/ln"
|
"github.com/Xe/ln"
|
||||||
"github.com/Xe/uuid"
|
"github.com/Xe/uuid"
|
||||||
|
@ -29,7 +32,7 @@ func (t *Token) Get(ctx context.Context, req *proto.GetTokenRequest) (*proto.Tok
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "must specify ID")
|
return nil, status.Errorf(codes.InvalidArgument, "must specify ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
dbt, err := t.db.GetTokenID(ctx, req.Id)
|
dbt, err := t.db.Tokens().Get(ctx, req.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -47,7 +50,7 @@ func (t *Token) GetAll(ctx context.Context, req *proto.Nil) (*proto.TokenSet, er
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.GetAll_getAuth"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.GetAll_getAuth"})
|
||||||
}
|
}
|
||||||
|
|
||||||
toks, err := t.db.GetTokensForOwner(ctx, clitok.Owner)
|
toks, err := t.db.Tokens().GetAll(ctx, clitok.Owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.GetAll_db.GetTokensForOwner"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.GetAll_db.GetTokensForOwner"})
|
||||||
}
|
}
|
||||||
|
@ -69,7 +72,13 @@ func (t *Token) Put(ctx context.Context, tok *proto.Token) (*proto.Token, error)
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "not authorized"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "not authorized"})
|
||||||
}
|
}
|
||||||
|
|
||||||
dbt, err := t.db.PutToken(ctx, uuid.New(), clitok.Owner, tok.Scopes)
|
dtok := database.Token{
|
||||||
|
ID: uuid.New(),
|
||||||
|
Owner: clitok.Owner,
|
||||||
|
Scopes: tok.Scopes,
|
||||||
|
}
|
||||||
|
|
||||||
|
dbt, err := t.db.Tokens().Put(ctx, dtok)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "put token into database", "scopes": tok.Scopes})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "put token into database", "scopes": tok.Scopes})
|
||||||
}
|
}
|
||||||
|
@ -85,7 +94,7 @@ func (t *Token) Delete(ctx context.Context, tok *proto.Token) (*proto.Nil, error
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "not authorized"})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "not authorized"})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = t.db.DeleteToken(ctx, tok.Id)
|
_, err = t.db.Tokens().Delete(ctx, tok.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "delete token from database", "token_id": tok.Id})
|
return nil, handleError(ctx, clitok, err, ln.F{"action": "delete token from database", "token_id": tok.Id})
|
||||||
}
|
}
|
||||||
|
@ -96,17 +105,5 @@ func (t *Token) Delete(ctx context.Context, tok *proto.Token) (*proto.Nil, error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Token) Deactivate(ctx context.Context, tok *proto.Token) (*proto.Nil, error) {
|
func (t *Token) Deactivate(ctx context.Context, tok *proto.Token) (*proto.Nil, error) {
|
||||||
clitok, err := t.getAuth(ctx, "deactivate single token", "token:deactivate")
|
return nil, errors.New("not implemented")
|
||||||
if err != nil {
|
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "not authorized"})
|
|
||||||
}
|
|
||||||
|
|
||||||
err = t.db.DeactivateToken(ctx, tok.Id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, handleError(ctx, clitok, err, ln.F{"action": "deactivate token in database", "token_id": tok.Id})
|
|
||||||
}
|
|
||||||
|
|
||||||
ln.Log(ctx, clitok, ln.Action("deactivated token"), ln.F{"token_id": tok.Id})
|
|
||||||
|
|
||||||
return &proto.Nil{}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,22 @@ var (
|
||||||
type BoltDBStorage struct {
|
type BoltDBStorage struct {
|
||||||
db *storm.DB
|
db *storm.DB
|
||||||
sb *simplebox.SimpleBox
|
sb *simplebox.SimpleBox
|
||||||
|
|
||||||
|
cs *boltCertificateStorage
|
||||||
|
rs *boltRouteStorage
|
||||||
|
ts *boltTokenStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type boltCertificateStorage struct {
|
||||||
|
*BoltDBStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type boltRouteStorage struct {
|
||||||
|
*BoltDBStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type boltTokenStorage struct {
|
||||||
|
*BoltDBStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBoltStorage creates a new Storage instance backed by BoltDB + Storm.
|
// NewBoltStorage creates a new Storage instance backed by BoltDB + Storm.
|
||||||
|
@ -43,24 +59,43 @@ func NewBoltStorage(path string, key *[32]byte) (Storage, error) {
|
||||||
sb: simplebox.NewFromSecretKey(key),
|
sb: simplebox.NewFromSecretKey(key),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.cs = &boltCertificateStorage{b}
|
||||||
|
b.rs = &boltRouteStorage{b}
|
||||||
|
b.ts = &boltTokenStorage{b}
|
||||||
|
|
||||||
return Storage(b), nil
|
return Storage(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Certs gets the certificate storage interface.
|
||||||
|
func (b *BoltDBStorage) Certs() Certs { return b.cs }
|
||||||
|
|
||||||
|
// Routes gets the route storage interface.
|
||||||
|
func (b *BoltDBStorage) Routes() Routes { return b.rs }
|
||||||
|
|
||||||
|
// Tokens gets the token storage interface.
|
||||||
|
func (b *BoltDBStorage) Tokens() Tokens { return b.ts }
|
||||||
|
|
||||||
|
// Close cleans up resources for this Storage.
|
||||||
|
func (b *BoltDBStorage) Close() error { return b.db.Close() }
|
||||||
|
|
||||||
// interface compliance
|
// interface compliance
|
||||||
var (
|
var (
|
||||||
_ Storage = &BoltDBStorage{}
|
_ Storage = &BoltDBStorage{}
|
||||||
|
_ Certs = &boltCertificateStorage{}
|
||||||
|
_ Routes = &boltRouteStorage{}
|
||||||
|
_ Tokens = &boltTokenStorage{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BoltDBStorage) GetRoute(ctx context.Context, id string) (Route, error) {
|
func (b *boltRouteStorage) Get(ctx context.Context, id string) (Route, error) {
|
||||||
return b.getRouteBy(ctx, "ID", id)
|
return b.getRouteBy(ctx, "ID", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BoltDBStorage) GetRouteHost(ctx context.Context, id string) (Route, error) {
|
func (b *boltRouteStorage) GetHost(ctx context.Context, id string) (Route, error) {
|
||||||
return b.getRouteBy(ctx, "Hostname", id)
|
return b.getRouteBy(ctx, "Hostname", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRouteBy gets a single route out of the database by a given field data.
|
// getRouteBy gets a single route out of the database by a given field data.
|
||||||
func (b *BoltDBStorage) getRouteBy(ctx context.Context, match, val string) (Route, error) {
|
func (b *boltRouteStorage) getRouteBy(ctx context.Context, match, val string) (Route, error) {
|
||||||
r := Route{}
|
r := Route{}
|
||||||
err := b.db.One(match, val, &r)
|
err := b.db.One(match, val, &r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -79,19 +114,17 @@ func (b *BoltDBStorage) getRouteBy(ctx context.Context, match, val string) (Rout
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllRoutes gets all routes out of the database for a given user by username.
|
// GetAll gets all routes out of the database for a given user by username.
|
||||||
func (b *BoltDBStorage) GetAllRoutes(ctx context.Context, user string) ([]Route, error) {
|
func (b *boltRouteStorage) GetAll(ctx context.Context, user string) ([]Route, error) {
|
||||||
rs := []Route{}
|
rs := []Route{}
|
||||||
err := b.db.All(&rs)
|
err := b.db.All(&rs)
|
||||||
return rs, err
|
return rs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutRoute creates a new route in the database.
|
// Put creates a new route in the database.
|
||||||
func (b *BoltDBStorage) PutRoute(ctx context.Context, domain, creator string) (Route, error) {
|
func (b *boltRouteStorage) Put(ctx context.Context, r Route) (Route, error) {
|
||||||
r := Route{
|
if r.ID == "" {
|
||||||
ID: uuid.New(),
|
r.ID = uuid.New()
|
||||||
Creator: creator,
|
|
||||||
Hostname: domain,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := b.db.Save(&r)
|
err := b.db.Save(&r)
|
||||||
|
@ -105,30 +138,30 @@ func (b *BoltDBStorage) PutRoute(ctx context.Context, domain, creator string) (R
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRoute removes a route from the database.
|
// Delete removes a route from the database.
|
||||||
func (b *BoltDBStorage) DeleteRoute(ctx context.Context, id string) error {
|
func (b *boltRouteStorage) Delete(ctx context.Context, inp Route) (Route, error) {
|
||||||
r := Route{}
|
r := Route{}
|
||||||
err := b.db.One("ID", id, &r)
|
err := b.db.One("ID", inp.ID, &r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return r, err
|
||||||
}
|
}
|
||||||
defer b.db.Commit()
|
defer b.db.Commit()
|
||||||
|
|
||||||
ln.Log(ctx, r, ln.Action("route deleted from database"))
|
ln.Log(ctx, r, ln.Action("route deleted from database"))
|
||||||
|
|
||||||
return b.db.DeleteStruct(&r)
|
return r, b.db.DeleteStruct(&r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetToken fetches a token from the database. This is mainly used in validation
|
// GetBody fetches a token from the database. This is mainly used in validation
|
||||||
// of tokens.
|
// of tokens.
|
||||||
func (b *BoltDBStorage) GetToken(ctx context.Context, token string) (Token, error) {
|
func (b *boltTokenStorage) GetBody(ctx context.Context, token string) (Token, error) {
|
||||||
t := Token{}
|
t := Token{}
|
||||||
err := b.db.One("Body", token, &t)
|
err := b.db.One("Body", token, &t)
|
||||||
return t, err
|
return t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTokenID fetches a token by a given token ID.
|
// Get fetches a token by a given token ID.
|
||||||
func (b *BoltDBStorage) GetTokenID(ctx context.Context, id string) (Token, error) {
|
func (b *boltTokenStorage) Get(ctx context.Context, id string) (Token, error) {
|
||||||
t := Token{}
|
t := Token{}
|
||||||
err := b.db.One("ID", id, &t)
|
err := b.db.One("ID", id, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -143,23 +176,19 @@ func (b *BoltDBStorage) GetTokenID(ctx context.Context, id string) (Token, error
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTokensForOwner fetches all of the tokens owned by a given owner.
|
// GetAll fetches all of the tokens owned by a given owner.
|
||||||
func (b *BoltDBStorage) GetTokensForOwner(ctx context.Context, owner string) ([]Token, error) {
|
func (b *boltTokenStorage) GetAll(ctx context.Context, owner string) ([]Token, error) {
|
||||||
ts := []Token{}
|
ts := []Token{}
|
||||||
err := b.db.Find("Owner", owner, &ts)
|
err := b.db.Find("Owner", owner, &ts)
|
||||||
return ts, err
|
return ts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutToken adds a new token to the database.
|
// Put adds a new token to the database.
|
||||||
func (b *BoltDBStorage) PutToken(ctx context.Context, token, owner string, scopes []string) (Token, error) {
|
func (b *boltTokenStorage) Put(ctx context.Context, t Token) (Token, error) {
|
||||||
t := Token{
|
if t.ID == "" {
|
||||||
ID: uuid.New(),
|
t.ID = uuid.New()
|
||||||
Body: token,
|
t.CreatedAt = time.Now()
|
||||||
Owner: owner,
|
t.Active = true
|
||||||
Scopes: scopes,
|
|
||||||
|
|
||||||
CreatedAt: time.Now(),
|
|
||||||
Active: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := b.db.Save(&t)
|
err := b.db.Save(&t)
|
||||||
|
@ -173,38 +202,53 @@ func (b *BoltDBStorage) PutToken(ctx context.Context, token, owner string, scope
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteToken removes a token from the database.
|
// Delete removes a token from the database.
|
||||||
func (b *BoltDBStorage) DeleteToken(ctx context.Context, id string) error {
|
func (b *boltTokenStorage) Delete(ctx context.Context, id string) (Token, error) {
|
||||||
t := Token{}
|
t := Token{}
|
||||||
err := b.db.One("ID", id, &t)
|
err := b.db.One("ID", id, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ln.Log(ctx, t, ln.Action("token deleted from database"))
|
ln.Log(ctx, t, ln.Action("token deleted from database"))
|
||||||
|
|
||||||
return b.db.DeleteStruct(&t)
|
return t, b.db.DeleteStruct(&t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeactivateToken de-activates a token in the database. This should be used
|
// DeleteExpired deletes all expired tokens.
|
||||||
// instead of deletion in many cases.
|
func (b *boltTokenStorage) DeleteExpired(ctx context.Context) error {
|
||||||
func (b *BoltDBStorage) DeactivateToken(ctx context.Context, id string) error {
|
return errors.New("not implemented")
|
||||||
t := Token{}
|
}
|
||||||
err := b.db.One("ID", id, &t)
|
|
||||||
|
// GetAll fetches all certificates and returns their DECRYPTED BODIES to the caller.
|
||||||
|
// This is intended for usage in migration tools only.
|
||||||
|
func (b *boltCertificateStorage) GetAll(ctx context.Context) ([]CachedCert, error) {
|
||||||
|
var cc []CachedCert
|
||||||
|
err := b.db.All(&cc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
|
||||||
defer b.db.Commit()
|
|
||||||
|
|
||||||
t.Active = false
|
|
||||||
|
|
||||||
ln.Log(ctx, t, ln.Action("token deactivated"))
|
|
||||||
|
|
||||||
return b.db.Save(&t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCert fetches a TLS certificate from the database.
|
var result []CachedCert
|
||||||
func (b *BoltDBStorage) GetCert(ctx context.Context, key string) ([]byte, error) {
|
|
||||||
|
for _, c := range cc {
|
||||||
|
r := CachedCert{
|
||||||
|
Key: c.Key,
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Body, err = b.sb.Decrypt(c.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get fetches a TLS certificate from the database.
|
||||||
|
func (b *boltCertificateStorage) Get(ctx context.Context, key string) ([]byte, error) {
|
||||||
cc := CachedCert{}
|
cc := CachedCert{}
|
||||||
err := b.db.One("Key", key, &cc)
|
err := b.db.One("Key", key, &cc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -213,10 +257,6 @@ func (b *BoltDBStorage) GetCert(ctx context.Context, key string) ([]byte, error)
|
||||||
|
|
||||||
var body []byte
|
var body []byte
|
||||||
|
|
||||||
switch cc.CryptoLevel {
|
|
||||||
case CryptoLevelNone:
|
|
||||||
body = cc.Body
|
|
||||||
case CryptoLevelSecretbox:
|
|
||||||
if b.sb == nil {
|
if b.sb == nil {
|
||||||
return nil, ErrCantDecryptCert
|
return nil, ErrCantDecryptCert
|
||||||
}
|
}
|
||||||
|
@ -225,21 +265,18 @@ func (b *BoltDBStorage) GetCert(ctx context.Context, key string) ([]byte, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutCert adds a new TLS certificate to the database.
|
// Put adds a new TLS certificate to the database.
|
||||||
func (b *BoltDBStorage) PutCert(ctx context.Context, key string, data []byte) error {
|
func (b *boltCertificateStorage) Put(ctx context.Context, key string, data []byte) error {
|
||||||
cc := CachedCert{
|
cc := CachedCert{
|
||||||
Key: key,
|
Key: key,
|
||||||
CryptoLevel: CryptoLevelNone,
|
|
||||||
Body: data,
|
Body: data,
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.sb != nil {
|
if b.sb != nil {
|
||||||
cc.CryptoLevel = CryptoLevelSecretbox
|
|
||||||
cc.Body = b.sb.Encrypt(data)
|
cc.Body = b.sb.Encrypt(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,8 +287,8 @@ func (b *BoltDBStorage) PutCert(ctx context.Context, key string, data []byte) er
|
||||||
return b.db.Save(&cc)
|
return b.db.Save(&cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteCert removes a certificate from the database.
|
// Delete removes a certificate from the database.
|
||||||
func (b *BoltDBStorage) DeleteCert(ctx context.Context, key string) error {
|
func (b *boltCertificateStorage) Delete(ctx context.Context, key string) error {
|
||||||
cc := CachedCert{}
|
cc := CachedCert{}
|
||||||
err := b.db.One("Key", key, &cc)
|
err := b.db.One("Key", key, &cc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -264,8 +301,3 @@ func (b *BoltDBStorage) DeleteCert(ctx context.Context, key string) error {
|
||||||
|
|
||||||
return b.db.DeleteStruct(&cc)
|
return b.db.DeleteStruct(&cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close ...
|
|
||||||
func (b *BoltDBStorage) Close() error {
|
|
||||||
return b.db.Close()
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,27 +16,17 @@ import (
|
||||||
type Certs interface {
|
type Certs interface {
|
||||||
io.Closer
|
io.Closer
|
||||||
autocert.Cache
|
autocert.Cache
|
||||||
|
|
||||||
|
GetAll(ctx context.Context) ([]CachedCert, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptoLevel indicates what form of cryptography the certificate is stored
|
|
||||||
// with.
|
|
||||||
type CryptoLevel int
|
|
||||||
|
|
||||||
// Crypto levels / strategies defined
|
|
||||||
const (
|
|
||||||
// NOTE: this is defined for debugging / testing usage only
|
|
||||||
CryptoLevelNone CryptoLevel = iota
|
|
||||||
|
|
||||||
// Use the global set of secretbox keys
|
|
||||||
CryptoLevelSecretbox
|
|
||||||
)
|
|
||||||
|
|
||||||
// CachedCert is an individual cached certificate in the database.
|
// CachedCert is an individual cached certificate in the database.
|
||||||
type CachedCert struct {
|
type CachedCert struct {
|
||||||
Key string `storm:"id"`
|
Key string `storm:"id" db:"domain"`
|
||||||
CryptoLevel CryptoLevel
|
|
||||||
// PEM-encoded bytes with the above crypto level as a filter.
|
// Encrypted data
|
||||||
Body []byte
|
Data string `storm:"-" db:"data"`
|
||||||
|
Body []byte // above as a byte slice
|
||||||
}
|
}
|
||||||
|
|
||||||
type storageManager struct {
|
type storageManager struct {
|
||||||
|
@ -44,24 +34,24 @@ type storageManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storageManager) Get(ctx context.Context, key string) ([]byte, error) {
|
func (s *storageManager) Get(ctx context.Context, key string) ([]byte, error) {
|
||||||
data, err := s.GetCert(ctx, key)
|
data, err := s.Certs().Get(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == storm.ErrNotFound {
|
if err == storm.ErrNotFound {
|
||||||
return nil, autocert.ErrCacheMiss
|
return nil, autocert.ErrCacheMiss
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storageManager) Put(ctx context.Context, key string, data []byte) error {
|
func (s *storageManager) Put(ctx context.Context, key string, data []byte) error {
|
||||||
return s.PutCert(ctx, key, data)
|
return s.Certs().Put(ctx, key, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storageManager) Delete(ctx context.Context, key string) error {
|
func (s *storageManager) Delete(ctx context.Context, key string) error {
|
||||||
return s.DeleteCert(ctx, key)
|
return s.Certs().Delete(ctx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache creates an autocert.Cache from a Storage instance.
|
// Cache creates an autocert.Cache from a Storage instance.
|
||||||
|
|
|
@ -194,7 +194,7 @@ func migrations1513982254_tokensUpSql() (*asset, error) {
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _migrationsPostgresSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x94\xdf\xeb\xda\x30\x14\xc5\xdf\xf3\x57\xdc\x37\x15\x9a\x87\x3d\x0d\x26\x52\x44\x33\x56\xa8\x0a\xb5\xdb\x1e\x25\x36\xd7\x2d\xac\x36\x92\x44\x99\xff\xfd\x48\x1b\xb5\xa9\x3f\x28\xe3\x2b\xf4\xa1\xa4\xdc\x73\x3e\xf7\xf4\xb4\x94\x42\xc5\xf7\xf8\x05\x64\x65\x50\x5b\x5a\xa0\xb6\x72\x27\x0b\x6e\x91\x90\x64\xb9\x66\x59\x0e\xc9\x32\x5f\xc1\xec\xf6\xc0\x10\x80\xa1\x50\x7b\x2e\xab\x08\x04\xb7\x7c\x44\x7e\x4c\xd3\xef\x6c\xed\xce\xe3\x08\xe2\xd1\x98\x90\xab\xf0\x4e\x56\x82\xaa\x0a\x43\xe9\x35\x4b\xd9\x2c\x77\x03\x52\x44\xd0\x16\x8b\xa0\xd0\xc8\x2d\x8a\x0d\xb7\x11\xa0\x90\x97\x5b\x5e\x58\x79\xc2\x11\xf9\x9a\xad\x16\x21\xce\xcf\x6f\x2c\x63\x5e\x64\x12\x93\x34\x59\x24\x39\x7c\x6a\x43\x68\xdc\xab\x13\xde\x63\xcc\x59\xca\x72\xf6\x5f\x92\x3e\x30\xad\x8e\xdd\xa8\x08\x40\xe6\x4e\xcd\xb0\xde\x44\xe9\x08\x7e\x2b\x63\xdd\x58\xbf\xa4\x6a\x4d\xba\x3d\x53\x29\xba\x49\xdd\x29\xf6\x8b\xab\xe1\xf1\x5b\x49\xf1\x78\xa3\x7b\x7f\x67\xf2\x0e\x82\xcb\xe8\x0b\x0e\x5e\x96\x0d\x87\xa1\x3b\xa5\xe9\xd1\xa0\x7e\x07\x89\xd7\x98\xc4\x6d\x00\x81\x25\x5a\xbc\x45\x11\xf6\xa4\x3d\x4f\xa0\x4e\x13\xa6\xcb\x79\x9f\xb2\x58\xf5\x07\xab\xb0\x2c\xb9\x3b\xaa\xbf\xa8\xad\x12\xe7\xd6\x52\xa6\x50\x07\x34\x11\xe0\xdf\x83\xd4\x68\x36\xdc\x76\xcb\xd3\x5c\x41\x85\x7e\xa1\xad\xb1\xbd\x51\x98\xd7\x13\x83\x20\xb3\xab\x59\x27\x34\x8f\xf9\xba\x40\x81\xbb\xeb\x8f\x73\x7c\x1b\x85\x13\x7a\xce\xe1\xfa\x53\x73\x3c\xef\xcf\x87\x91\x3c\x2c\x51\xeb\x97\xe3\xdf\x46\xbb\x44\xbd\xf2\xf4\x12\x0d\x84\xf0\xeb\xbc\xd0\xb9\xd1\x02\x05\x59\x59\xd4\x27\x5e\xc2\xe0\x33\x08\x7e\x36\x83\x31\xf9\x17\x00\x00\xff\xff\x85\x3d\x18\x01\xed\x05\x00\x00")
|
var _migrationsPostgresSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x94\x51\xeb\xda\x30\x14\xc5\xdf\xf3\x29\xee\xdb\xdf\x42\xf3\xb0\xa7\xc1\x44\x8a\x68\xc6\x0a\x55\xa1\x76\xdb\xa3\xc4\xe6\xba\x85\xd5\x46\x92\x28\xf3\xdb\x8f\xd4\xa8\x69\xd5\x22\x43\xc1\x07\x49\xc9\x39\xbf\x9c\x7b\x12\x4a\xa1\xe6\x5b\xfc\x02\xb2\x36\xa8\x2d\x2d\x51\x5b\xb9\x91\x25\xb7\x48\x48\x3a\x5f\xb2\xbc\x80\x74\x5e\x2c\x60\x72\xfd\x60\x08\xc0\x40\xa8\x2d\x97\x75\x0c\x82\x5b\x1e\x91\x1f\xe3\xec\x3b\x5b\xba\xf5\x24\x86\x24\x1a\x12\x72\x11\xde\xc8\x5a\x50\x55\x63\x5b\x7a\xc9\x32\x36\x29\xdc\x06\x29\x62\x08\xc5\x62\x28\x35\x72\x8b\x62\xc5\x6d\x0c\x28\xe4\xf9\x2f\x2f\xad\x3c\x60\x44\xbe\xe6\x8b\x59\x1b\xe7\xe7\x37\x96\x33\x2f\x32\x4a\x48\x96\xce\xd2\x02\x3e\x85\x10\x1a\xb7\xea\x80\xb7\x18\x53\x96\xb1\x82\xfd\x97\xe4\x2f\xb4\x94\x57\x55\xa8\x67\x5e\x7b\xae\xd0\xcd\x8f\x47\xab\x7d\x67\x30\x04\x20\x77\x8b\x66\xd0\xc8\x2b\x1d\xc3\x6f\x65\xac\xdb\xf5\xdc\x58\x1a\x49\xba\x3e\x52\x29\xba\xf8\x37\x8a\xcf\x9d\xe1\xc4\xe3\x23\x94\xe2\x7e\x7c\xb7\xfe\xce\xe4\x1d\x04\xe7\xad\x3d\x1c\x6e\x8e\x0d\x87\xa1\x1b\xa5\xe9\xde\xa0\x7e\x07\x89\xd7\x18\x25\x21\x80\xc0\x0a\x2d\x5e\xa3\x68\x97\x32\xdc\x4f\xa0\x49\x13\xc6\xf3\x69\x6f\x33\x7d\x57\xac\xfa\x83\x75\xfb\x12\x17\x6e\xa9\xb9\xbe\x6b\x25\x8e\xc1\xa1\x4c\xa9\x76\x68\x62\xc0\xbf\x3b\xa9\xd1\xac\xb8\xed\x96\xe7\xf4\x8b\xba\x37\xc0\x61\x7b\xa3\x76\x5e\x0f\x0c\x5a\x99\x5d\xcc\x3a\xa1\x79\xcc\xfe\x02\xb5\xdc\x5d\x7f\x9c\xe3\xdb\x28\x9c\x50\xff\x3b\xd0\x70\x3c\xee\xcf\xcb\x48\xee\x96\x28\x78\xdf\xfc\x34\xc2\x12\x3d\x95\xa7\x97\x38\x41\x08\x7f\x9c\x1e\x9d\x2b\x2d\x50\x90\xb5\x45\x7d\xe0\x15\x7c\x7c\x06\xc1\x8f\xe6\x63\x48\xfe\x05\x00\x00\xff\xff\x1c\x82\x69\x4c\x5a\x06\x00\x00")
|
||||||
|
|
||||||
func migrationsPostgresSqlBytes() ([]byte, error) {
|
func migrationsPostgresSqlBytes() ([]byte, error) {
|
||||||
return bindataRead(
|
return bindataRead(
|
||||||
|
@ -209,7 +209,7 @@ func migrationsPostgresSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "migrations/postgres.sql", size: 1517, mode: os.FileMode(420), modTime: time.Unix(1516557003, 0)}
|
info := bindataFileInfo{name: "migrations/postgres.sql", size: 1626, mode: os.FileMode(420), modTime: time.Unix(1516558817, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,12 @@ FROM Certificates
|
||||||
WHERE domain=?
|
WHERE domain=?
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
|
-- name: get-all-certificates
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
(id, domain, data, created_at, edited_at, active)
|
||||||
|
FROM Certificates;
|
||||||
|
|
||||||
-- name: insert-route
|
-- name: insert-route
|
||||||
|
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
|
|
|
@ -1,30 +1,10 @@
|
||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Storage is the parent interface for the database backends of route.
|
// Storage is the parent interface for the database backends of route.
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
// routes
|
Certs() Certs
|
||||||
GetRoute(ctx context.Context, id string) (Route, error)
|
Routes() Routes
|
||||||
GetRouteHost(ctx context.Context, host string) (Route, error)
|
Tokens() Tokens
|
||||||
GetAllRoutes(ctx context.Context, user string) ([]Route, error)
|
|
||||||
PutRoute(ctx context.Context, domain, kind string) (Route, error)
|
|
||||||
DeleteRoute(ctx context.Context, id string) error
|
|
||||||
|
|
||||||
// tokens
|
|
||||||
GetToken(ctx context.Context, token string) (Token, error)
|
|
||||||
GetTokenID(ctx context.Context, id string) (Token, error)
|
|
||||||
GetTokensForOwner(ctx context.Context, owner string) ([]Token, error)
|
|
||||||
PutToken(ctx context.Context, token, owner string, scopes []string) (Token, error)
|
|
||||||
DeleteToken(ctx context.Context, id string) error
|
|
||||||
DeactivateToken(ctx context.Context, id string) error
|
|
||||||
|
|
||||||
// certificates
|
|
||||||
GetCert(ctx context.Context, key string) ([]byte, error)
|
|
||||||
PutCert(ctx context.Context, key string, data []byte) error
|
|
||||||
DeleteCert(ctx context.Context, key string) error
|
|
||||||
|
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue