mirror of
https://github.com/openziti/zrok.git
synced 2026-08-24 10:14:56 -05:00
admin/create|delete|listSkipInterstitialGrant (#1210)
This commit is contained in:
@@ -72,7 +72,8 @@ func Run(inCfg *config.Config) error {
|
||||
api.AdminDeleteIdentityHandler = newDeleteIdentityHandler()
|
||||
api.AdminDeleteNamespaceHandler = newDeleteNamespaceHandler()
|
||||
api.AdminDeleteOrganizationHandler = newDeleteOrganizationHandler()
|
||||
api.AdminGrantsHandler = newGrantsHandler()
|
||||
api.AdminGetSkipInterstitialGrantHandler = newGetSkipInterstitialGrantHandler()
|
||||
api.AdminGrantSkipInterstitialHandler = newGrantSkipInterstitialHandler()
|
||||
api.AdminInviteTokenGenerateHandler = newInviteTokenGenerateHandler()
|
||||
api.AdminListAppliedLimitClassesHandler = newListAppliedLimitClassesHandler()
|
||||
api.AdminListFrontendsHandler = newListFrontendsHandler()
|
||||
@@ -86,6 +87,7 @@ func Run(inCfg *config.Config) error {
|
||||
api.AdminRemoveNamespaceFrontendMappingHandler = newRemoveNamespaceFrontendMappingHandler()
|
||||
api.AdminRemoveNamespaceGrantHandler = newRemoveNamespaceGrantHandler()
|
||||
api.AdminRemoveOrganizationMemberHandler = newRemoveOrganizationMemberHandler()
|
||||
api.AdminRevokeSkipInterstitialHandler = newRevokeSkipInterstitialHandler()
|
||||
api.AdminUpdateAccountPasswordHandler = newUpdateAccountPasswordHandler(cfg)
|
||||
api.AdminUpdateFrontendHandler = newUpdateFrontendHandler()
|
||||
api.AdminUpdateNamespaceHandler = newUpdateNamespaceHandler()
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/michaelquigley/df/dl"
|
||||
"github.com/openziti/zrok/v2/controller/automation"
|
||||
"github.com/openziti/zrok/v2/rest_model_zrok"
|
||||
"github.com/openziti/zrok/v2/rest_server_zrok/operations/admin"
|
||||
"github.com/openziti/zrok/v2/sdk/golang/sdk"
|
||||
)
|
||||
|
||||
type grantsHandler struct{}
|
||||
|
||||
func newGrantsHandler() *grantsHandler {
|
||||
return &grantsHandler{}
|
||||
}
|
||||
|
||||
func (h *grantsHandler) Handle(params admin.GrantsParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||
if !principal.Admin {
|
||||
dl.Errorf("invalid admin principal")
|
||||
return admin.NewGrantsUnauthorized()
|
||||
}
|
||||
|
||||
trx, err := str.Begin()
|
||||
if err != nil {
|
||||
dl.Errorf("error starting transaction: %v", err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
defer func() { _ = trx.Rollback() }()
|
||||
|
||||
acct, err := str.FindAccountWithEmail(params.Body.Email, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding account with email '%v': %v", params.Body.Email, err)
|
||||
return admin.NewGrantsNotFound()
|
||||
}
|
||||
|
||||
acctSkipInterstitial, err := str.IsAccountGrantedSkipInterstitial(acct.Id, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error checking account '%v' granted skip interstitial: %v", acct.Email, err)
|
||||
}
|
||||
|
||||
envs, err := str.FindEnvironmentsForAccount(acct.Id, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding environments for '%v': %v", acct.Email, err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
|
||||
ziti, err := automation.NewZitiAutomation(cfg.Ziti)
|
||||
if err != nil {
|
||||
dl.Errorf("error connecting to ziti: %v", err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
|
||||
for _, env := range envs {
|
||||
shrs, err := str.FindSharesForEnvironment(env.Id, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding shares for '%v': %v", acct.Email, err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
|
||||
for _, shr := range shrs {
|
||||
if shr.ShareMode == string(sdk.PublicShareMode) && shr.BackendMode != string(sdk.DriveBackendMode) {
|
||||
// find config by zrokShareToken tag
|
||||
filterOpts := &automation.FilterOptions{
|
||||
Filter: "tags.zrokShareToken=\"" + shr.Token + "\"",
|
||||
Limit: 0,
|
||||
Offset: 0,
|
||||
}
|
||||
configs, err := ziti.Configs.Find(filterOpts)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding config for share '%v': %v", shr.Token, err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
if len(configs) != 1 {
|
||||
dl.Errorf("expected 1 configuration for share '%v', found %v", shr.Token, len(configs))
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
config := configs[0]
|
||||
if config.ConfigType.Name != sdk.ZrokProxyConfig {
|
||||
dl.Errorf("expected '%v' config type for share '%v', found '%v'", sdk.ZrokProxyConfig, shr.Token, config.ConfigType.Name)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
|
||||
// parse the config data
|
||||
var shrCfg *sdk.FrontendConfig
|
||||
if v, ok := config.Data.(map[string]interface{}); ok {
|
||||
shrCfg, err = sdk.FrontendConfigFromMap(v)
|
||||
if err != nil {
|
||||
dl.Errorf("error parsing config data for share '%v': %v", shr.Token, err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
} else {
|
||||
dl.Errorf("unexpected config data type for share '%v'", shr.Token)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
|
||||
if shrCfg.Interstitial != !acctSkipInterstitial {
|
||||
shrCfg.Interstitial = !acctSkipInterstitial
|
||||
|
||||
// update config using automation
|
||||
configOpts := &automation.ConfigOptions{
|
||||
BaseOptions: automation.BaseOptions{
|
||||
Name: shr.Token,
|
||||
Tags: automation.ZrokShareTags(shr.Token),
|
||||
},
|
||||
ConfigTypeID: config.ConfigType.ID,
|
||||
Data: shrCfg,
|
||||
}
|
||||
err := ziti.Configs.Update(*config.ID, configOpts)
|
||||
if err != nil {
|
||||
dl.Errorf("error updating config for '%v': %v", shr.Token, err)
|
||||
return admin.NewGrantsInternalServerError()
|
||||
}
|
||||
} else {
|
||||
dl.Infof("skipping config update for '%v'", shr.Token)
|
||||
}
|
||||
} else {
|
||||
dl.Debugf("skipping share mode %v, backend mode %v", shr.ShareMode, shr.BackendMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return admin.NewGrantsOK()
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/michaelquigley/df/dl"
|
||||
"github.com/openziti/zrok/v2/controller/automation"
|
||||
"github.com/openziti/zrok/v2/controller/store"
|
||||
"github.com/openziti/zrok/v2/rest_model_zrok"
|
||||
"github.com/openziti/zrok/v2/rest_server_zrok/operations/admin"
|
||||
"github.com/openziti/zrok/v2/sdk/golang/sdk"
|
||||
)
|
||||
|
||||
// getSkipInterstitialGrant
|
||||
|
||||
type getSkipInterstitialGrantHandler struct{}
|
||||
|
||||
func newGetSkipInterstitialGrantHandler() *getSkipInterstitialGrantHandler {
|
||||
return &getSkipInterstitialGrantHandler{}
|
||||
}
|
||||
|
||||
func (h *getSkipInterstitialGrantHandler) Handle(params admin.GetSkipInterstitialGrantParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||
if !principal.Admin {
|
||||
dl.Error("invalid admin principal")
|
||||
return admin.NewGetSkipInterstitialGrantUnauthorized()
|
||||
}
|
||||
|
||||
trx, err := str.Begin()
|
||||
if err != nil {
|
||||
dl.Errorf("error starting transaction: %v", err)
|
||||
return admin.NewGetSkipInterstitialGrantInternalServerError()
|
||||
}
|
||||
defer func() { _ = trx.Rollback() }()
|
||||
|
||||
acct, err := str.FindAccountWithEmail(params.Email, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding account with email '%v': %v", params.Email, err)
|
||||
return admin.NewGetSkipInterstitialGrantNotFound()
|
||||
}
|
||||
|
||||
granted, err := str.IsAccountGrantedSkipInterstitial(acct.Id, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error checking skip interstitial grant for '%v': %v", params.Email, err)
|
||||
return admin.NewGetSkipInterstitialGrantInternalServerError()
|
||||
}
|
||||
|
||||
return admin.NewGetSkipInterstitialGrantOK().WithPayload(&admin.GetSkipInterstitialGrantOKBody{
|
||||
Email: acct.Email,
|
||||
Granted: granted,
|
||||
})
|
||||
}
|
||||
|
||||
// grantSkipInterstitial
|
||||
|
||||
type grantSkipInterstitialHandler struct{}
|
||||
|
||||
func newGrantSkipInterstitialHandler() *grantSkipInterstitialHandler {
|
||||
return &grantSkipInterstitialHandler{}
|
||||
}
|
||||
|
||||
func (h *grantSkipInterstitialHandler) Handle(params admin.GrantSkipInterstitialParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||
if !principal.Admin {
|
||||
dl.Error("invalid admin principal")
|
||||
return admin.NewGrantSkipInterstitialUnauthorized()
|
||||
}
|
||||
|
||||
trx, err := str.Begin()
|
||||
if err != nil {
|
||||
dl.Errorf("error starting transaction: %v", err)
|
||||
return admin.NewGrantSkipInterstitialInternalServerError()
|
||||
}
|
||||
defer func() { _ = trx.Rollback() }()
|
||||
|
||||
acct, err := str.FindAccountWithEmail(params.Body.Email, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding account with email '%v': %v", params.Body.Email, err)
|
||||
return admin.NewGrantSkipInterstitialNotFound()
|
||||
}
|
||||
|
||||
if err := str.GrantSkipInterstitial(acct.Id, trx); err != nil {
|
||||
dl.Errorf("error granting skip interstitial for '%v': %v", params.Body.Email, err)
|
||||
return admin.NewGrantSkipInterstitialInternalServerError()
|
||||
}
|
||||
|
||||
if err := trx.Commit(); err != nil {
|
||||
dl.Errorf("error committing transaction: %v", err)
|
||||
return admin.NewGrantSkipInterstitialInternalServerError()
|
||||
}
|
||||
|
||||
if err := syncSkipInterstitialForAccount(acct, true); err != nil {
|
||||
dl.Errorf("error syncing skip interstitial for '%v': %v", params.Body.Email, err)
|
||||
return admin.NewGrantSkipInterstitialInternalServerError()
|
||||
}
|
||||
|
||||
return admin.NewGrantSkipInterstitialOK()
|
||||
}
|
||||
|
||||
// revokeSkipInterstitial
|
||||
|
||||
type revokeSkipInterstitialHandler struct{}
|
||||
|
||||
func newRevokeSkipInterstitialHandler() *revokeSkipInterstitialHandler {
|
||||
return &revokeSkipInterstitialHandler{}
|
||||
}
|
||||
|
||||
func (h *revokeSkipInterstitialHandler) Handle(params admin.RevokeSkipInterstitialParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||
if !principal.Admin {
|
||||
dl.Error("invalid admin principal")
|
||||
return admin.NewRevokeSkipInterstitialUnauthorized()
|
||||
}
|
||||
|
||||
trx, err := str.Begin()
|
||||
if err != nil {
|
||||
dl.Errorf("error starting transaction: %v", err)
|
||||
return admin.NewRevokeSkipInterstitialInternalServerError()
|
||||
}
|
||||
defer func() { _ = trx.Rollback() }()
|
||||
|
||||
acct, err := str.FindAccountWithEmail(params.Body.Email, trx)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding account with email '%v': %v", params.Body.Email, err)
|
||||
return admin.NewRevokeSkipInterstitialNotFound()
|
||||
}
|
||||
|
||||
if err := str.RevokeSkipInterstitial(acct.Id, trx); err != nil {
|
||||
dl.Errorf("error revoking skip interstitial for '%v': %v", params.Body.Email, err)
|
||||
return admin.NewRevokeSkipInterstitialInternalServerError()
|
||||
}
|
||||
|
||||
if err := trx.Commit(); err != nil {
|
||||
dl.Errorf("error committing transaction: %v", err)
|
||||
return admin.NewRevokeSkipInterstitialInternalServerError()
|
||||
}
|
||||
|
||||
if err := syncSkipInterstitialForAccount(acct, false); err != nil {
|
||||
dl.Errorf("error syncing skip interstitial for '%v': %v", params.Body.Email, err)
|
||||
return admin.NewRevokeSkipInterstitialInternalServerError()
|
||||
}
|
||||
|
||||
return admin.NewRevokeSkipInterstitialOK()
|
||||
}
|
||||
|
||||
// syncSkipInterstitialForAccount synchronizes the interstitial setting on all
|
||||
// public (non-drive) share Ziti configs for the given account.
|
||||
func syncSkipInterstitialForAccount(acct *store.Account, skipInterstitial bool) error {
|
||||
trx, err := str.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = trx.Rollback() }()
|
||||
|
||||
envs, err := str.FindEnvironmentsForAccount(acct.Id, trx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ziti, err := automation.NewZitiAutomation(cfg.Ziti)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, env := range envs {
|
||||
shrs, err := str.FindSharesForEnvironment(env.Id, trx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, shr := range shrs {
|
||||
if shr.ShareMode == string(sdk.PublicShareMode) && shr.BackendMode != string(sdk.DriveBackendMode) {
|
||||
filterOpts := &automation.FilterOptions{
|
||||
Filter: "tags.zrokShareToken=\"" + shr.Token + "\"",
|
||||
Limit: 0,
|
||||
Offset: 0,
|
||||
}
|
||||
configs, err := ziti.Configs.Find(filterOpts)
|
||||
if err != nil {
|
||||
dl.Errorf("error finding config for share '%v': %v", shr.Token, err)
|
||||
return err
|
||||
}
|
||||
if len(configs) != 1 {
|
||||
dl.Errorf("expected 1 configuration for share '%v', found %v", shr.Token, len(configs))
|
||||
continue
|
||||
}
|
||||
config := configs[0]
|
||||
if config.ConfigType.Name != sdk.ZrokProxyConfig {
|
||||
dl.Errorf("expected '%v' config type for share '%v', found '%v'", sdk.ZrokProxyConfig, shr.Token, config.ConfigType.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
v, ok := config.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
dl.Errorf("unexpected config data type for share '%v'", shr.Token)
|
||||
continue
|
||||
}
|
||||
shrCfg, err := sdk.FrontendConfigFromMap(v)
|
||||
if err != nil {
|
||||
dl.Errorf("error parsing config data for share '%v': %v", shr.Token, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if shrCfg.Interstitial != !skipInterstitial {
|
||||
shrCfg.Interstitial = !skipInterstitial
|
||||
configOpts := &automation.ConfigOptions{
|
||||
BaseOptions: automation.BaseOptions{
|
||||
Name: shr.Token,
|
||||
Tags: automation.ZrokShareTags(shr.Token),
|
||||
},
|
||||
ConfigTypeID: config.ConfigType.ID,
|
||||
Data: shrCfg,
|
||||
}
|
||||
if err := ziti.Configs.Update(*config.ID, configOpts); err != nil {
|
||||
dl.Errorf("error updating config for '%v': %v", shr.Token, err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
dl.Infof("skipping config update for '%v'", shr.Token)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -16,3 +16,27 @@ func (str *Store) IsAccountGrantedSkipInterstitial(acctId int, trx *sqlx.Tx) (bo
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (str *Store) GrantSkipInterstitial(acctId int, trx *sqlx.Tx) error {
|
||||
stmt, err := trx.Prepare("insert into skip_interstitial_grants (account_id) values ($1)")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error preparing skip_interstitial_grants insert statement")
|
||||
}
|
||||
_, err = stmt.Exec(acctId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing skip_interstitial_grants insert statement")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (str *Store) RevokeSkipInterstitial(acctId int, trx *sqlx.Tx) error {
|
||||
stmt, err := trx.Prepare("update skip_interstitial_grants set deleted = true, updated_at = current_timestamp where account_id = $1 and not deleted")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error preparing skip_interstitial_grants update statement")
|
||||
}
|
||||
_, err = stmt.Exec(acctId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing skip_interstitial_grants update statement")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user