satellite: Rename "acct mgmt api" to "rest api"
"REST API" is a more accurate descriptor of the generated API in the console package than "account management API". The generated API is very flexible and will allow us to implement many more endpoints outside the scope of "account management", and "account management" is not very well defined to begin with. Change-Id: Ie87faeaa3c743ef4371eaf0edd2826303d592da7
This commit is contained in:
parent
1ed36e9fea
commit
ed5ebb2527
@ -21,7 +21,7 @@ import (
|
||||
"storj.io/storj/private/version/checker"
|
||||
"storj.io/storj/satellite/admin"
|
||||
"storj.io/storj/satellite/buckets"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/metabase"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/stripecoinpayments"
|
||||
@ -65,8 +65,8 @@ type Admin struct {
|
||||
Service *buckets.Service
|
||||
}
|
||||
|
||||
AccountManagementAPIKeys struct {
|
||||
Service *accountmanagementapikeys.Service
|
||||
REST struct {
|
||||
Keys *restkeys.Service
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,8 +87,8 @@ func NewAdmin(log *zap.Logger, full *identity.FullIdentity, db DB, metabaseDB *m
|
||||
peer.Buckets.Service = buckets.NewService(db.Buckets(), metabaseDB)
|
||||
}
|
||||
|
||||
{ // setup account management api keys
|
||||
peer.AccountManagementAPIKeys.Service = accountmanagementapikeys.NewService(db.OIDC().OAuthTokens(), config.AccountManagementAPIKeys)
|
||||
{ // setup rest keys
|
||||
peer.REST.Keys = restkeys.NewService(db.OIDC().OAuthTokens(), config.RESTKeys)
|
||||
}
|
||||
|
||||
{ // setup debug
|
||||
@ -173,7 +173,7 @@ func NewAdmin(log *zap.Logger, full *identity.FullIdentity, db DB, metabaseDB *m
|
||||
adminConfig := config.Admin
|
||||
adminConfig.AuthorizationToken = config.Console.AuthToken
|
||||
|
||||
peer.Admin.Server = admin.NewServer(log.Named("admin"), peer.Admin.Listener, peer.DB, peer.Buckets.Service, peer.AccountManagementAPIKeys.Service, peer.Payments.Accounts, adminConfig)
|
||||
peer.Admin.Server = admin.NewServer(log.Named("admin"), peer.Admin.Listener, peer.DB, peer.Buckets.Service, peer.REST.Keys, peer.Payments.Accounts, adminConfig)
|
||||
peer.Servers.Add(lifecycle.Item{
|
||||
Name: "admin",
|
||||
Run: peer.Admin.Server.Run,
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (server *Server) addAccountManagementAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
func (server *Server) addRESTKey(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
@ -66,7 +66,7 @@ func (server *Server) addAccountManagementAPIKey(w http.ResponseWriter, r *http.
|
||||
}
|
||||
}
|
||||
|
||||
apiKey, expiresAt, err := server.accountManagementAPIKeys.Create(ctx, user.ID, expiration)
|
||||
apiKey, expiresAt, err := server.restKeys.Create(ctx, user.ID, expiration)
|
||||
if err != nil {
|
||||
sendJSONError(w, "api key creation failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
@ -91,7 +91,7 @@ func (server *Server) addAccountManagementAPIKey(w http.ResponseWriter, r *http.
|
||||
sendJSONData(w, http.StatusOK, data)
|
||||
}
|
||||
|
||||
func (server *Server) revokeAccountManagementAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
func (server *Server) revokeRESTKey(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
@ -102,7 +102,7 @@ func (server *Server) revokeAccountManagementAPIKey(w http.ResponseWriter, r *ht
|
||||
return
|
||||
}
|
||||
|
||||
err := server.accountManagementAPIKeys.Revoke(ctx, apiKey)
|
||||
err := server.restKeys.Revoke(ctx, apiKey)
|
||||
if err != nil {
|
||||
sendJSONError(w, "failed to revoke api key",
|
||||
err.Error(), http.StatusNotFound)
|
@ -22,7 +22,7 @@ import (
|
||||
"storj.io/storj/satellite/oidc"
|
||||
)
|
||||
|
||||
func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
func TestRESTKeys(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1,
|
||||
StorageNodeCount: 0,
|
||||
@ -35,14 +35,14 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
address := planet.Satellites[0].Admin.Admin.Listener.Addr()
|
||||
satellite := planet.Satellites[0]
|
||||
keyService := satellite.API.AccountManagementAPIKeys.Service
|
||||
keyService := satellite.API.REST.Keys
|
||||
|
||||
user, err := planet.Satellites[0].DB.Console().Users().GetByEmail(ctx, planet.Uplinks[0].Projects[0].Owner.Email)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("create with default expiration", func(t *testing.T) {
|
||||
body := strings.NewReader(`{"expiration":""}`)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("http://"+address.String()+"/api/accountmanagementapikeys/%s", user.Email), body)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("http://"+address.String()+"/api/restkeys/%s", user.Email), body)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", satellite.Config.Console.AuthToken)
|
||||
|
||||
@ -73,7 +73,7 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
require.False(t, exp.Before(now))
|
||||
|
||||
// check the expiration is around the time we expect
|
||||
defaultExpiration := satellite.Config.AccountManagementAPIKeys.DefaultExpiration
|
||||
defaultExpiration := satellite.Config.RESTKeys.DefaultExpiration
|
||||
require.True(t, output.ExpiresAt.After(now.Add(defaultExpiration)))
|
||||
require.True(t, output.ExpiresAt.Before(now.Add(defaultExpiration+time.Hour)))
|
||||
})
|
||||
@ -81,7 +81,7 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
t.Run("create with custom expiration", func(t *testing.T) {
|
||||
durationString := "3h"
|
||||
body := strings.NewReader(fmt.Sprintf(`{"expiration":"%s"}`, durationString))
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("http://"+address.String()+"/api/accountmanagementapikeys/%s", user.Email), body)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("http://"+address.String()+"/api/restkeys/%s", user.Email), body)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", satellite.Config.Console.AuthToken)
|
||||
|
||||
@ -125,13 +125,13 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
|
||||
expiresAt, err := keyService.InsertIntoDB(ctx, oidc.OAuthToken{
|
||||
UserID: user.ID,
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: hash,
|
||||
}, time.Now(), time.Hour)
|
||||
require.NoError(t, err)
|
||||
require.False(t, expiresAt.IsZero())
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("http://"+address.String()+"/api/accountmanagementapikeys/%s/revoke", apiKey), nil)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("http://"+address.String()+"/api/restkeys/%s/revoke", apiKey), nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", satellite.Config.Console.AuthToken)
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
adminui "storj.io/storj/satellite/admin/ui"
|
||||
"storj.io/storj/satellite/buckets"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/oidc"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/stripecoinpayments"
|
||||
@ -56,10 +56,10 @@ type Server struct {
|
||||
listener net.Listener
|
||||
server http.Server
|
||||
|
||||
db DB
|
||||
payments payments.Accounts
|
||||
buckets *buckets.Service
|
||||
accountManagementAPIKeys *accountmanagementapikeys.Service
|
||||
db DB
|
||||
payments payments.Accounts
|
||||
buckets *buckets.Service
|
||||
restKeys *restkeys.Service
|
||||
|
||||
nowFn func() time.Time
|
||||
|
||||
@ -67,16 +67,16 @@ type Server struct {
|
||||
}
|
||||
|
||||
// NewServer returns a new administration Server.
|
||||
func NewServer(log *zap.Logger, listener net.Listener, db DB, buckets *buckets.Service, accountManagementAPIKeys *accountmanagementapikeys.Service, accounts payments.Accounts, config Config) *Server {
|
||||
func NewServer(log *zap.Logger, listener net.Listener, db DB, buckets *buckets.Service, restKeys *restkeys.Service, accounts payments.Accounts, config Config) *Server {
|
||||
server := &Server{
|
||||
log: log,
|
||||
|
||||
listener: listener,
|
||||
|
||||
db: db,
|
||||
payments: accounts,
|
||||
buckets: buckets,
|
||||
accountManagementAPIKeys: accountManagementAPIKeys,
|
||||
db: db,
|
||||
payments: accounts,
|
||||
buckets: buckets,
|
||||
restKeys: restKeys,
|
||||
|
||||
nowFn: time.Now,
|
||||
|
||||
@ -110,8 +110,8 @@ func NewServer(log *zap.Logger, listener net.Listener, db DB, buckets *buckets.S
|
||||
api.HandleFunc("/projects/{project}/buckets/{bucket}/geofence", server.createGeofenceForBucket).Methods("POST")
|
||||
api.HandleFunc("/projects/{project}/buckets/{bucket}/geofence", server.deleteGeofenceForBucket).Methods("DELETE")
|
||||
api.HandleFunc("/apikeys/{apikey}", server.deleteAPIKey).Methods("DELETE")
|
||||
api.HandleFunc("/accountmanagementapikeys/{useremail}", server.addAccountManagementAPIKey).Methods("POST")
|
||||
api.HandleFunc("/accountmanagementapikeys/{apikey}/revoke", server.revokeAccountManagementAPIKey).Methods("PUT")
|
||||
api.HandleFunc("/restkeys/{useremail}", server.addRESTKey).Methods("POST")
|
||||
api.HandleFunc("/restkeys/{apikey}/revoke", server.revokeRESTKey).Methods("PUT")
|
||||
|
||||
// This handler must be the last one because it uses the root as prefix,
|
||||
// otherwise will try to serve all the handlers set after this one.
|
||||
|
@ -372,28 +372,28 @@ Blank fields will not be updated.`,
|
||||
}
|
||||
}
|
||||
],
|
||||
account_management_api_keys: [
|
||||
rest_api_keys: [
|
||||
{
|
||||
name: 'create',
|
||||
desc: 'Create an account management API key',
|
||||
desc: 'Create a REST key',
|
||||
//params: [['API key', new InputText('text', true)]],
|
||||
params: [
|
||||
["user's email", new InputText('text', true)],
|
||||
['expiration', new InputText('text', false)]
|
||||
],
|
||||
func: async (useremail: string, expiration?: string): Promise<Record<string, unknown>> => {
|
||||
return this.fetch('POST', `accountmanagementapikeys/${useremail}`, null, {
|
||||
return this.fetch('POST', `restkeys/${useremail}`, null, {
|
||||
expiration
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'revoke',
|
||||
desc: 'Revoke an account management API key',
|
||||
desc: 'Revoke a REST key',
|
||||
//params: [['API key', new InputText('text', true)]],
|
||||
params: [['api key', new InputText('text', true)]],
|
||||
func: async (apikey: string): Promise<Record<string, unknown>> => {
|
||||
return this.fetch('PUT', `accountmanagementapikeys/${apikey}/revoke`);
|
||||
return this.fetch('PUT', `restkeys/${apikey}/revoke`);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -34,9 +34,9 @@ import (
|
||||
"storj.io/storj/satellite/analytics"
|
||||
"storj.io/storj/satellite/buckets"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/consoleauth"
|
||||
"storj.io/storj/satellite/console/consoleweb"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/contact"
|
||||
"storj.io/storj/satellite/gracefulexit"
|
||||
"storj.io/storj/satellite/inspector"
|
||||
@ -137,8 +137,8 @@ type API struct {
|
||||
Stripe stripecoinpayments.StripeClient
|
||||
}
|
||||
|
||||
AccountManagementAPIKeys struct {
|
||||
Service *accountmanagementapikeys.Service
|
||||
REST struct {
|
||||
Keys *restkeys.Service
|
||||
}
|
||||
|
||||
Console struct {
|
||||
@ -578,7 +578,7 @@ func NewAPI(log *zap.Logger, full *identity.FullIdentity, db DB,
|
||||
}
|
||||
|
||||
{ // setup account management api keys
|
||||
peer.AccountManagementAPIKeys.Service = accountmanagementapikeys.NewService(peer.DB.OIDC().OAuthTokens(), config.AccountManagementAPIKeys)
|
||||
peer.REST.Keys = restkeys.NewService(peer.DB.OIDC().OAuthTokens(), config.RESTKeys)
|
||||
}
|
||||
|
||||
{ // setup console
|
||||
@ -595,7 +595,7 @@ func NewAPI(log *zap.Logger, full *identity.FullIdentity, db DB,
|
||||
peer.Log.Named("console:service"),
|
||||
&consoleauth.Hmac{Secret: []byte(consoleConfig.AuthTokenSecret)},
|
||||
peer.DB.Console(),
|
||||
peer.AccountManagementAPIKeys.Service,
|
||||
peer.REST.Keys,
|
||||
peer.DB.ProjectAccounting(),
|
||||
peer.Accounting.ProjectUsage,
|
||||
peer.Buckets.Service,
|
||||
|
@ -30,8 +30,8 @@ type APIKeys interface {
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
// AccountManagementAPIKeys is an interface for account management api key operations.
|
||||
type AccountManagementAPIKeys interface {
|
||||
// RESTKeys is an interface for rest key operations.
|
||||
type RESTKeys interface {
|
||||
Create(ctx context.Context, userID uuid.UUID, expiration time.Duration) (apiKey string, expiresAt time.Time, err error)
|
||||
GetUserAndExpirationFromKey(ctx context.Context, apiKey string) (userID uuid.UUID, exp time.Time, err error)
|
||||
Revoke(ctx context.Context, apiKey string) (err error)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// definition for REST API
|
||||
a := &apigen.API{
|
||||
Version: "v0",
|
||||
Description: "",
|
||||
|
@ -24,9 +24,9 @@ import (
|
||||
"storj.io/storj/satellite/accounting/live"
|
||||
"storj.io/storj/satellite/analytics"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/consoleauth"
|
||||
"storj.io/storj/satellite/console/consoleweb/consoleql"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/mailservice"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/paymentsconfig"
|
||||
@ -99,7 +99,7 @@ func TestGraphqlMutation(t *testing.T) {
|
||||
log.Named("console"),
|
||||
&consoleauth.Hmac{Secret: []byte("my-suppa-secret-key")},
|
||||
db.Console(),
|
||||
accountmanagementapikeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.AccountManagementAPIKeys),
|
||||
restkeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.RESTKeys),
|
||||
db.ProjectAccounting(),
|
||||
projectUsage,
|
||||
sat.API.Buckets.Service,
|
||||
|
@ -21,9 +21,9 @@ import (
|
||||
"storj.io/storj/satellite/accounting/live"
|
||||
"storj.io/storj/satellite/analytics"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/consoleauth"
|
||||
"storj.io/storj/satellite/console/consoleweb/consoleql"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/mailservice"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/paymentsconfig"
|
||||
@ -83,7 +83,7 @@ func TestGraphqlQuery(t *testing.T) {
|
||||
log.Named("console"),
|
||||
&consoleauth.Hmac{Secret: []byte("my-suppa-secret-key")},
|
||||
db.Console(),
|
||||
accountmanagementapikeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.AccountManagementAPIKeys),
|
||||
restkeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.RESTKeys),
|
||||
db.ProjectAccounting(),
|
||||
projectUsage,
|
||||
sat.API.Buckets.Service,
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package accountmanagementapikeys
|
||||
package restkeys
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -20,8 +20,8 @@ import (
|
||||
var mon = monkit.Package()
|
||||
|
||||
var (
|
||||
// Error describes internal account management api keys error.
|
||||
Error = errs.Class("account management api keys service")
|
||||
// Error describes internal rest keys error.
|
||||
Error = errs.Class("rest keys service")
|
||||
|
||||
// ErrDuplicateKey is error type that occurs when a generated account
|
||||
// management api key already exists.
|
||||
@ -32,18 +32,18 @@ var (
|
||||
ErrInvalidKey = errs.Class("invalid key")
|
||||
)
|
||||
|
||||
// Config contains configuration parameters for account management api keys.
|
||||
// Config contains configuration parameters for rest keys.
|
||||
type Config struct {
|
||||
DefaultExpiration time.Duration `help:"expiration to use if user does not specify an account management api key expiration" default:"720h"`
|
||||
DefaultExpiration time.Duration `help:"expiration to use if user does not specify an rest key expiration" default:"720h"`
|
||||
}
|
||||
|
||||
// Service handles operations regarding account management api keys.
|
||||
// Service handles operations regarding rest keys.
|
||||
type Service struct {
|
||||
db oidc.OAuthTokens
|
||||
config Config
|
||||
}
|
||||
|
||||
// NewService creates a new account management api keys service.
|
||||
// NewService creates a new rest keys service.
|
||||
func NewService(db oidc.OAuthTokens, config Config) *Service {
|
||||
return &Service{
|
||||
db: db,
|
||||
@ -51,7 +51,7 @@ func NewService(db oidc.OAuthTokens, config Config) *Service {
|
||||
}
|
||||
}
|
||||
|
||||
// Create creates and inserts an account management api key into the db.
|
||||
// Create creates and inserts an rest key into the db.
|
||||
func (s *Service) Create(ctx context.Context, userID uuid.UUID, expiration time.Duration) (apiKey string, expiresAt time.Time, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
@ -61,7 +61,7 @@ func (s *Service) Create(ctx context.Context, userID uuid.UUID, expiration time.
|
||||
}
|
||||
expiresAt, err = s.InsertIntoDB(ctx, oidc.OAuthToken{
|
||||
UserID: userID,
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: hash,
|
||||
}, time.Now(), expiration)
|
||||
if err != nil {
|
||||
@ -111,7 +111,7 @@ func (s *Service) InsertIntoDB(ctx context.Context, oAuthToken oidc.OAuthToken,
|
||||
|
||||
// The token column is the key to the OAuthTokens table, but the Create method does not return an error if a duplicate token insert is attempted.
|
||||
// We need to make sure a unique api key is created, so check that the value doesn't already exist.
|
||||
_, err = s.db.Get(ctx, oidc.KindAccountManagementTokenV0, oAuthToken.Token)
|
||||
_, err = s.db.Get(ctx, oidc.KindRESTTokenV0, oAuthToken.Token)
|
||||
if err != nil {
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
return time.Time{}, Error.Wrap(err)
|
||||
@ -144,7 +144,7 @@ func (s *Service) GetUserAndExpirationFromKey(ctx context.Context, apiKey string
|
||||
if err != nil {
|
||||
return uuid.UUID{}, time.Now(), err
|
||||
}
|
||||
keyInfo, err := s.db.Get(ctx, oidc.KindAccountManagementTokenV0, hash)
|
||||
keyInfo, err := s.db.Get(ctx, oidc.KindRESTTokenV0, hash)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return uuid.UUID{}, time.Now(), Error.Wrap(ErrInvalidKey.New("invalid account management api key"))
|
||||
@ -163,11 +163,11 @@ func (s *Service) Revoke(ctx context.Context, apiKey string) (err error) {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
_, err = s.db.Get(ctx, oidc.KindAccountManagementTokenV0, hash)
|
||||
_, err = s.db.Get(ctx, oidc.KindRESTTokenV0, hash)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
err = s.db.RevokeAccountManagementTokenV0(ctx, hash)
|
||||
err = s.db.RevokeRESTTokenV0(ctx, hash)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package accountmanagementapikeys_test
|
||||
package restkeys_test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -13,16 +13,16 @@ import (
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/common/testrand"
|
||||
"storj.io/storj/private/testplanet"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/oidc"
|
||||
)
|
||||
|
||||
func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
func TestRESTKeys(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
sat := planet.Satellites[0]
|
||||
service := sat.API.AccountManagementAPIKeys.Service
|
||||
service := sat.API.REST.Keys
|
||||
|
||||
id := testrand.UUID()
|
||||
now := time.Now()
|
||||
@ -42,14 +42,14 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = service.InsertIntoDB(ctx, oidc.OAuthToken{
|
||||
UserID: id,
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: hash,
|
||||
}, now, expires)
|
||||
require.True(t, accountmanagementapikeys.ErrDuplicateKey.Has(err))
|
||||
require.True(t, restkeys.ErrDuplicateKey.Has(err))
|
||||
|
||||
// test revocation
|
||||
require.NoError(t, service.Revoke(ctx, apiKey))
|
||||
token, err := sat.DB.OIDC().OAuthTokens().Get(ctx, oidc.KindAccountManagementTokenV0, hash)
|
||||
token, err := sat.DB.OIDC().OAuthTokens().Get(ctx, oidc.KindRESTTokenV0, hash)
|
||||
require.Equal(t, sql.ErrNoRows, err)
|
||||
require.True(t, token.ExpiresAt.IsZero())
|
||||
|
||||
@ -60,41 +60,41 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
|
||||
// test GetUserFromKey non existent key
|
||||
_, _, err = service.GetUserAndExpirationFromKey(ctx, nonexistent)
|
||||
require.True(t, accountmanagementapikeys.ErrInvalidKey.Has(err))
|
||||
require.True(t, restkeys.ErrInvalidKey.Has(err))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccountManagementAPIKeysExpiration(t *testing.T) {
|
||||
func TestRESTKeysExpiration(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
sat := planet.Satellites[0]
|
||||
service := sat.API.AccountManagementAPIKeys.Service
|
||||
service := sat.API.REST.Keys
|
||||
now := time.Now()
|
||||
|
||||
// test no expiration uses default
|
||||
expiresAt, err := service.InsertIntoDB(ctx, oidc.OAuthToken{
|
||||
UserID: testrand.UUID(),
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: "testhash0",
|
||||
}, now, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, now.Add(sat.Config.AccountManagementAPIKeys.DefaultExpiration), expiresAt)
|
||||
require.Equal(t, now.Add(sat.Config.RESTKeys.DefaultExpiration), expiresAt)
|
||||
|
||||
// test negative expiration uses default
|
||||
expiresAt, err = service.InsertIntoDB(ctx, oidc.OAuthToken{
|
||||
UserID: testrand.UUID(),
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: "testhash1",
|
||||
}, now, -10000)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, now.Add(sat.Config.AccountManagementAPIKeys.DefaultExpiration), expiresAt)
|
||||
require.Equal(t, now.Add(sat.Config.RESTKeys.DefaultExpiration), expiresAt)
|
||||
|
||||
// test regular expiration
|
||||
expiration := 14 * time.Hour
|
||||
expiresAt, err = service.InsertIntoDB(ctx, oidc.OAuthToken{
|
||||
UserID: testrand.UUID(),
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: "testhash2",
|
||||
}, now, expiration)
|
||||
require.NoError(t, err)
|
@ -104,16 +104,16 @@ var (
|
||||
type Service struct {
|
||||
Signer
|
||||
|
||||
log, auditLogger *zap.Logger
|
||||
store DB
|
||||
accountManagementAPIKeys AccountManagementAPIKeys
|
||||
projectAccounting accounting.ProjectAccounting
|
||||
projectUsage *accounting.Service
|
||||
buckets Buckets
|
||||
partners *rewards.PartnersService
|
||||
accounts payments.Accounts
|
||||
recaptchaHandler RecaptchaHandler
|
||||
analytics *analytics.Service
|
||||
log, auditLogger *zap.Logger
|
||||
store DB
|
||||
restKeys RESTKeys
|
||||
projectAccounting accounting.ProjectAccounting
|
||||
projectUsage *accounting.Service
|
||||
buckets Buckets
|
||||
partners *rewards.PartnersService
|
||||
accounts payments.Accounts
|
||||
recaptchaHandler RecaptchaHandler
|
||||
analytics *analytics.Service
|
||||
|
||||
config Config
|
||||
}
|
||||
@ -154,7 +154,7 @@ type PaymentsService struct {
|
||||
}
|
||||
|
||||
// NewService returns new instance of Service.
|
||||
func NewService(log *zap.Logger, signer Signer, store DB, accountManagementAPIKeys AccountManagementAPIKeys, projectAccounting accounting.ProjectAccounting, projectUsage *accounting.Service, buckets Buckets, partners *rewards.PartnersService, accounts payments.Accounts, analytics *analytics.Service, config Config) (*Service, error) {
|
||||
func NewService(log *zap.Logger, signer Signer, store DB, restKeys RESTKeys, projectAccounting accounting.ProjectAccounting, projectUsage *accounting.Service, buckets Buckets, partners *rewards.PartnersService, accounts payments.Accounts, analytics *analytics.Service, config Config) (*Service, error) {
|
||||
if signer == nil {
|
||||
return nil, errs.New("signer can't be nil")
|
||||
}
|
||||
@ -169,19 +169,19 @@ func NewService(log *zap.Logger, signer Signer, store DB, accountManagementAPIKe
|
||||
}
|
||||
|
||||
return &Service{
|
||||
log: log,
|
||||
auditLogger: log.Named("auditlog"),
|
||||
Signer: signer,
|
||||
store: store,
|
||||
accountManagementAPIKeys: accountManagementAPIKeys,
|
||||
projectAccounting: projectAccounting,
|
||||
projectUsage: projectUsage,
|
||||
buckets: buckets,
|
||||
partners: partners,
|
||||
accounts: accounts,
|
||||
recaptchaHandler: NewDefaultRecaptcha(config.Recaptcha.SecretKey),
|
||||
analytics: analytics,
|
||||
config: config,
|
||||
log: log,
|
||||
auditLogger: log.Named("auditlog"),
|
||||
Signer: signer,
|
||||
store: store,
|
||||
restKeys: restKeys,
|
||||
projectAccounting: projectAccounting,
|
||||
projectUsage: projectUsage,
|
||||
buckets: buckets,
|
||||
partners: partners,
|
||||
accounts: accounts,
|
||||
recaptchaHandler: NewDefaultRecaptcha(config.Recaptcha.SecretKey),
|
||||
analytics: analytics,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -1815,32 +1815,32 @@ func (s *Service) GetAPIKeys(ctx context.Context, projectID uuid.UUID, cursor AP
|
||||
return
|
||||
}
|
||||
|
||||
// CreateAccountManagementAPIKey creates an account management api key.
|
||||
func (s *Service) CreateAccountManagementAPIKey(ctx context.Context, expiration time.Duration) (apiKey string, expiresAt time.Time, err error) {
|
||||
// CreateRESTKey creates a satellite rest key.
|
||||
func (s *Service) CreateRESTKey(ctx context.Context, expiration time.Duration) (apiKey string, expiresAt time.Time, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
auth, err := s.getAuthAndAuditLog(ctx, "create account management api key")
|
||||
auth, err := s.getAuthAndAuditLog(ctx, "create rest key")
|
||||
if err != nil {
|
||||
return "", time.Time{}, Error.Wrap(err)
|
||||
}
|
||||
|
||||
apiKey, expiresAt, err = s.accountManagementAPIKeys.Create(ctx, auth.User.ID, expiration)
|
||||
apiKey, expiresAt, err = s.restKeys.Create(ctx, auth.User.ID, expiration)
|
||||
if err != nil {
|
||||
return "", time.Time{}, Error.Wrap(err)
|
||||
}
|
||||
return apiKey, expiresAt, nil
|
||||
}
|
||||
|
||||
// RevokeAccountManagementAPIKey revokes an account management api key.
|
||||
func (s *Service) RevokeAccountManagementAPIKey(ctx context.Context, apiKey string) (err error) {
|
||||
// RevokeRESTKey revokes a satellite REST key.
|
||||
func (s *Service) RevokeRESTKey(ctx context.Context, apiKey string) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
_, err = s.getAuthAndAuditLog(ctx, "revoke account management api key")
|
||||
_, err = s.getAuthAndAuditLog(ctx, "revoke rest key")
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
err = s.accountManagementAPIKeys.Revoke(ctx, apiKey)
|
||||
err = s.restKeys.Revoke(ctx, apiKey)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
@ -2219,7 +2219,7 @@ func (s *Service) keyAuth(ctx context.Context, r *http.Request) (context.Context
|
||||
|
||||
ctx = consoleauth.WithAPIKey(ctx, []byte(apikey))
|
||||
|
||||
userID, exp, err := s.accountManagementAPIKeys.GetUserAndExpirationFromKey(ctx, apikey)
|
||||
userID, exp, err := s.restKeys.GetUserAndExpirationFromKey(ctx, apikey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -692,7 +692,7 @@ func TestActivateAccountToken(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
func TestRESTKeys(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
@ -710,18 +710,18 @@ func TestAccountManagementAPIKeys(t *testing.T) {
|
||||
|
||||
now := time.Now()
|
||||
expires := 5 * time.Hour
|
||||
apiKey, expiresAt, err := service.CreateAccountManagementAPIKey(authCtx, expires)
|
||||
apiKey, expiresAt, err := service.CreateRESTKey(authCtx, expires)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, apiKey)
|
||||
require.True(t, expiresAt.After(now))
|
||||
require.True(t, expiresAt.Before(now.Add(expires+time.Hour)))
|
||||
|
||||
// test revocation
|
||||
require.NoError(t, service.RevokeAccountManagementAPIKey(authCtx, apiKey))
|
||||
require.NoError(t, service.RevokeRESTKey(authCtx, apiKey))
|
||||
|
||||
// test revoke non existent key
|
||||
nonexistent := testrand.UUID()
|
||||
err = service.RevokeAccountManagementAPIKey(authCtx, nonexistent.String())
|
||||
err = service.RevokeRESTKey(authCtx, nonexistent.String())
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -92,8 +92,8 @@ type OAuthTokens interface {
|
||||
// Create creates a new OAuthToken. If the token already exists, no value is modified and nil is returned.
|
||||
Create(ctx context.Context, token OAuthToken) error
|
||||
|
||||
// RevokeAccountManagementTokenV0 revokes a v0 account management token by setting its expires_at time to zero.
|
||||
RevokeAccountManagementTokenV0(ctx context.Context, token string) error
|
||||
// RevokeRESTTokenV0 revokes a v0 rest token by setting its expires_at time to zero.
|
||||
RevokeRESTTokenV0(ctx context.Context, token string) error
|
||||
}
|
||||
|
||||
// OAuthTokenKind defines an enumeration of different types of supported tokens.
|
||||
@ -106,8 +106,8 @@ const (
|
||||
KindAccessToken = 1
|
||||
// KindRefreshToken represents a refresh token within the database.
|
||||
KindRefreshToken = 2
|
||||
// KindAccountManagementTokenV0 represents an account management token within the database.
|
||||
KindAccountManagementTokenV0 = 3
|
||||
// KindRESTTokenV0 represents a REST token within the database.
|
||||
KindRESTTokenV0 = 3
|
||||
)
|
||||
|
||||
// OAuthCode represents a code stored within our database.
|
||||
|
@ -181,10 +181,10 @@ func (o *tokensDBX) Create(ctx context.Context, token OAuthToken) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeAccountManagementTokenV0 revokes a v0 account management token by setting its expires_at time to zero.
|
||||
func (o *tokensDBX) RevokeAccountManagementTokenV0(ctx context.Context, token string) error {
|
||||
// RevokeRESTTokenV0 revokes a v0 REST token by setting its expires_at time to zero.
|
||||
func (o *tokensDBX) RevokeRESTTokenV0(ctx context.Context, token string) error {
|
||||
return o.db.UpdateNoReturn_OauthToken_By_Token_And_Kind(ctx, dbx.OauthToken_Token([]byte(token)),
|
||||
dbx.OauthToken_Kind(int(KindAccountManagementTokenV0)),
|
||||
dbx.OauthToken_Kind(int(KindRESTTokenV0)),
|
||||
dbx.OauthToken_Update_Fields{
|
||||
ExpiresAt: dbx.OauthToken_ExpiresAt(time.Time{}),
|
||||
})
|
||||
|
@ -112,7 +112,7 @@ func TestOAuthTokens(t *testing.T) {
|
||||
{
|
||||
ClientID: clientID,
|
||||
UserID: userID,
|
||||
Kind: oidc.KindAccountManagementTokenV0,
|
||||
Kind: oidc.KindRESTTokenV0,
|
||||
Token: "testToken",
|
||||
CreatedAt: start,
|
||||
ExpiresAt: start.Add(time.Hour),
|
||||
@ -135,14 +135,14 @@ func TestOAuthTokens(t *testing.T) {
|
||||
}{
|
||||
{oidc.KindAccessToken, "expired", sql.ErrNoRows},
|
||||
{oidc.KindRefreshToken, "valid", nil},
|
||||
{oidc.KindAccountManagementTokenV0, "testToken", nil},
|
||||
{oidc.KindRESTTokenV0, "testToken", nil},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
_, err := tokens.Get(ctx, testCase.kind, testCase.token)
|
||||
require.Equal(t, testCase.err, err)
|
||||
if testCase.kind == oidc.KindAccountManagementTokenV0 {
|
||||
err = tokens.RevokeAccountManagementTokenV0(ctx, testCase.token)
|
||||
if testCase.kind == oidc.KindRESTTokenV0 {
|
||||
err = tokens.RevokeRESTTokenV0(ctx, testCase.token)
|
||||
require.NoError(t, err)
|
||||
token, err := tokens.Get(ctx, testCase.kind, testCase.token)
|
||||
require.Equal(t, sql.ErrNoRows, err)
|
||||
|
@ -18,8 +18,8 @@ import (
|
||||
"storj.io/storj/satellite/accounting/live"
|
||||
"storj.io/storj/satellite/analytics"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/consoleauth"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/paymentsconfig"
|
||||
"storj.io/storj/satellite/payments/stripecoinpayments"
|
||||
@ -78,7 +78,7 @@ func TestSignupCouponCodes(t *testing.T) {
|
||||
log.Named("console"),
|
||||
&consoleauth.Hmac{Secret: []byte("my-suppa-secret-key")},
|
||||
db.Console(),
|
||||
accountmanagementapikeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.AccountManagementAPIKeys),
|
||||
restkeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.RESTKeys),
|
||||
db.ProjectAccounting(),
|
||||
projectUsage,
|
||||
sat.API.Buckets.Service,
|
||||
|
@ -26,8 +26,8 @@ import (
|
||||
"storj.io/storj/satellite/buckets"
|
||||
"storj.io/storj/satellite/compensation"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/accountmanagementapikeys"
|
||||
"storj.io/storj/satellite/console/consoleweb"
|
||||
"storj.io/storj/satellite/console/restkeys"
|
||||
"storj.io/storj/satellite/contact"
|
||||
"storj.io/storj/satellite/gc"
|
||||
"storj.io/storj/satellite/gracefulexit"
|
||||
@ -145,8 +145,8 @@ type Config struct {
|
||||
|
||||
Payments paymentsconfig.Config
|
||||
|
||||
AccountManagementAPIKeys accountmanagementapikeys.Config
|
||||
Console consoleweb.Config
|
||||
RESTKeys restkeys.Config
|
||||
Console consoleweb.Config
|
||||
|
||||
Version version_checker.Config
|
||||
|
||||
|
6
scripts/testdata/satellite-config.yaml.lock
vendored
6
scripts/testdata/satellite-config.yaml.lock
vendored
@ -1,6 +1,3 @@
|
||||
# expiration to use if user does not specify an account management api key expiration
|
||||
# account-management-api-keys.default-expiration: 720h0m0s
|
||||
|
||||
# admin peer http listening address
|
||||
# admin.address: ""
|
||||
|
||||
@ -781,6 +778,9 @@ identity.key-path: /root/.local/share/storj/identity/satellite/identity.key
|
||||
# the time period that must pass before suspended nodes will be disqualified
|
||||
# reputation.suspension-grace-period: 168h0m0s
|
||||
|
||||
# expiration to use if user does not specify an rest key expiration
|
||||
# rest-keys.default-expiration: 720h0m0s
|
||||
|
||||
# age at which a rollup is archived
|
||||
# rollup-archive.archive-age: 2160h0m0s
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user