elaborating the grants handler (#744)

This commit is contained in:
Michael Quigley 2024-09-05 13:34:07 -04:00
parent a37009249a
commit e5aac2358b
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
7 changed files with 309 additions and 0 deletions

View File

@ -2,8 +2,10 @@ package controller
import (
"github.com/go-openapi/runtime/middleware"
"github.com/openziti/zrok/controller/zrokEdgeSdk"
"github.com/openziti/zrok/rest_model_zrok"
"github.com/openziti/zrok/rest_server_zrok/operations/admin"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/sirupsen/logrus"
)
@ -18,5 +20,67 @@ func (h *grantsHandler) Handle(params admin.GrantsParams, principal *rest_model_
logrus.Errorf("invalid admin principal")
return admin.NewGrantsUnauthorized()
}
edge, err := zrokEdgeSdk.Client(cfg.Ziti)
if err != nil {
logrus.Errorf("error connecting to ziti: %v", err)
return admin.NewGrantsInternalServerError()
}
trx, err := str.Begin()
if err != nil {
logrus.Errorf("error starting transaction: %v", err)
return admin.NewGrantsInternalServerError()
}
defer func() { _ = trx.Rollback() }()
acct, err := str.FindAccountWithEmail(params.Body.Email, trx)
if err != nil {
logrus.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 {
logrus.Errorf("error checking account '%v' granted skip interstitial: %v", acct.Email, err)
}
envs, err := str.FindEnvironmentsForAccount(acct.Id, trx)
if err != nil {
logrus.Errorf("error finding environments for '%v': %v", acct.Email, err)
return admin.NewGrantsInternalServerError()
}
for _, env := range envs {
shrs, err := str.FindSharesForEnvironment(env.Id, trx)
if err != nil {
logrus.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) {
cfgZId, shrCfg, err := zrokEdgeSdk.GetConfig(shr.Token, edge)
if err != nil {
logrus.Errorf("error getting config for share '%v': %v", shr.Token, err)
return admin.NewGrantsInternalServerError()
}
if shrCfg.Interstitial != !acctSkipInterstitial {
logrus.Infof("updating config for '%v'", shr.Token)
err := zrokEdgeSdk.UpdateConfig(cfgZId, shrCfg, edge)
if err != nil {
logrus.Errorf("error updating config for '%v': %v", shr.Token, err)
return admin.NewGrantsInternalServerError()
}
} else {
logrus.Infof("skipping config update for '%v'", shr.Token)
}
} else {
logrus.Debugf("skipping share mode %v, backend mode %v", shr.ShareMode, shr.BackendMode)
}
}
}
return admin.NewGrantsOK()
}

View File

@ -8,6 +8,7 @@ import (
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/sirupsen/logrus"
"reflect"
"time"
)
@ -55,6 +56,41 @@ func CreateConfig(cfgTypeZId, envZId, shrToken string, options *FrontendOptions,
return cfgResp.Payload.Data.ID, nil
}
func GetConfig(shrToken string, edge *rest_management_api_client.ZitiEdgeManagement) (string, *sdk.FrontendConfig, error) {
filter := fmt.Sprintf("tags.zrokShareToken=\"%v\"", shrToken)
limit := int64(0)
offset := int64(0)
listReq := &config.ListConfigsParams{
Filter: &filter,
Limit: &limit,
Offset: &offset,
Context: context.Background(),
}
listReq.SetTimeout(30 * time.Second)
listResp, err := edge.Config.ListConfigs(listReq, nil)
if err != nil {
return "", nil, err
}
if len(listResp.Payload.Data) != 1 {
return "", nil, fmt.Errorf("expected 1 configuration, found %v", len(listResp.Payload.Data))
}
if listResp.Payload.Data[0].ConfigType.Name != sdk.ZrokProxyConfig {
return "", nil, fmt.Errorf("expected '%v', found '%v'", sdk.ZrokProxyConfig, listResp.Payload.Data[0].ConfigType.Name)
}
if v, ok := listResp.Payload.Data[0].Data.(map[string]interface{}); ok {
fec, err := sdk.FrontendConfigFromMap(v)
if err != nil {
return "", nil, err
}
return *listResp.Payload.Data[0].ID, fec, nil
}
return "", nil, fmt.Errorf("unknown data type '%v' unmarshaling config for '%v'", reflect.TypeOf(listResp.Payload.Data[0].Data), shrToken)
}
func UpdateConfig(cfgZId string, cfg *sdk.FrontendConfig, edge *rest_management_api_client.ZitiEdgeManagement) error {
return nil
}
func DeleteConfig(envZId, shrToken string, edge *rest_management_api_client.ZitiEdgeManagement) error {
filter := fmt.Sprintf("tags.zrokShareToken=\"%v\"", shrToken)
limit := int64(0)

View File

@ -34,6 +34,12 @@ func (o *GrantsReader) ReadResponse(response runtime.ClientResponse, consumer ru
return nil, err
}
return nil, result
case 404:
result := NewGrantsNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 500:
result := NewGrantsInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -157,6 +163,62 @@ func (o *GrantsUnauthorized) readResponse(response runtime.ClientResponse, consu
return nil
}
// NewGrantsNotFound creates a GrantsNotFound with default headers values
func NewGrantsNotFound() *GrantsNotFound {
return &GrantsNotFound{}
}
/*
GrantsNotFound describes a response with status code 404, with default header values.
not found
*/
type GrantsNotFound struct {
}
// IsSuccess returns true when this grants not found response has a 2xx status code
func (o *GrantsNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this grants not found response has a 3xx status code
func (o *GrantsNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this grants not found response has a 4xx status code
func (o *GrantsNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this grants not found response has a 5xx status code
func (o *GrantsNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this grants not found response a status code equal to that given
func (o *GrantsNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the grants not found response
func (o *GrantsNotFound) Code() int {
return 404
}
func (o *GrantsNotFound) Error() string {
return fmt.Sprintf("[POST /grants][%d] grantsNotFound ", 404)
}
func (o *GrantsNotFound) String() string {
return fmt.Sprintf("[POST /grants][%d] grantsNotFound ", 404)
}
func (o *GrantsNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewGrantsInternalServerError creates a GrantsInternalServerError with default headers values
func NewGrantsInternalServerError() *GrantsInternalServerError {
return &GrantsInternalServerError{}

View File

@ -557,6 +557,9 @@ func init() {
"401": {
"description": "unauthorized"
},
"404": {
"description": "not found"
},
"500": {
"description": "internal server error"
}
@ -2404,6 +2407,9 @@ func init() {
"401": {
"description": "unauthorized"
},
"404": {
"description": "not found"
},
"500": {
"description": "internal server error"
}

View File

@ -61,6 +61,31 @@ func (o *GrantsUnauthorized) WriteResponse(rw http.ResponseWriter, producer runt
rw.WriteHeader(401)
}
// GrantsNotFoundCode is the HTTP code returned for type GrantsNotFound
const GrantsNotFoundCode int = 404
/*
GrantsNotFound not found
swagger:response grantsNotFound
*/
type GrantsNotFound struct {
}
// NewGrantsNotFound creates GrantsNotFound with default headers values
func NewGrantsNotFound() *GrantsNotFound {
return &GrantsNotFound{}
}
// WriteResponse to the client
func (o *GrantsNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(404)
}
// GrantsInternalServerErrorCode is the HTTP code returned for type GrantsInternalServerError
const GrantsInternalServerErrorCode int = 500

View File

@ -2,6 +2,8 @@ package sdk
import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"reflect"
)
const ZrokProxyConfig = "zrok.proxy.v1"
@ -13,21 +15,133 @@ type FrontendConfig struct {
OauthAuth *OauthConfig `json:"oauth"`
}
func FrontendConfigFromMap(m map[string]interface{}) (*FrontendConfig, error) {
logrus.Info(m)
out := &FrontendConfig{}
if v, found := m["interstitial"]; found {
out.Interstitial = v.(bool)
}
if v, found := m["auth_scheme"]; found {
if vStr, ok := v.(string); ok {
out.AuthScheme = AuthScheme(vStr)
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
if v, found := m["basic_auth"]; found && v != nil {
if subMap, ok := v.(map[string]interface{}); ok {
ba, err := BasicAuthConfigFromMap(subMap)
if err != nil {
return nil, err
}
out.BasicAuth = ba
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
if v, found := m["oauth"]; found && v != nil {
if subMap, ok := v.(map[string]interface{}); ok {
o, err := OauthConfigFromMap(subMap)
if err != nil {
return nil, err
}
out.OauthAuth = o
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
return out, nil
}
type BasicAuthConfig struct {
Users []*AuthUserConfig `json:"users"`
}
func BasicAuthConfigFromMap(m map[string]interface{}) (*BasicAuthConfig, error) {
out := &BasicAuthConfig{}
if v, found := m["basic_auth"]; found {
if vArr, ok := v.([]interface{}); ok {
for _, vV := range vArr {
if v, ok := vV.(map[string]interface{}); ok {
if auc, err := AuthUserConfigFromMap(v); err == nil {
out.Users = append(out.Users, auc)
} else {
return nil, err
}
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
return out, nil
}
return nil, nil
}
type AuthUserConfig struct {
Username string `json:"username"`
Password string `json:"password"`
}
func AuthUserConfigFromMap(m map[string]interface{}) (*AuthUserConfig, error) {
auc := &AuthUserConfig{}
if v, found := m["username"]; found {
if vStr, ok := v.(string); ok {
auc.Username = vStr
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
if v, found := m["password"]; found {
if vStr, ok := v.(string); ok {
auc.Password = vStr
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
return auc, nil
}
type OauthConfig struct {
Provider string `json:"provider"`
EmailDomains []string `json:"email_domains"`
AuthorizationCheckInterval string `json:"authorization_check_interval"`
}
func OauthConfigFromMap(m map[string]interface{}) (*OauthConfig, error) {
oac := &OauthConfig{}
if v, found := m["provider"]; found {
if vStr, ok := v.(string); ok {
oac.Provider = vStr
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
if v, found := m["email_domains"]; found {
if vArr, ok := v.([]interface{}); ok {
for _, vV := range vArr {
if vStr, ok := vV.(string); ok {
oac.EmailDomains = append(oac.EmailDomains, vStr)
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(vV))
}
}
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
if v, found := m["authorization_check_interval"]; found {
if vStr, ok := v.(string); ok {
oac.AuthorizationCheckInterval = vStr
} else {
return nil, errors.Errorf("unexpected type '%v'", reflect.TypeOf(v))
}
}
return oac, nil
}
func ParseAuthScheme(authScheme string) (AuthScheme, error) {
switch authScheme {
case string(None):

View File

@ -326,6 +326,8 @@ paths:
description: ok
401:
description: unauthorized
404:
description: not found
500:
description: internal server error