Merge pull request #1441 from openziti/upgrade.sdk.0.20

updates golang sdk to v0.20.0
This commit is contained in:
Andrew
2023-04-26 23:59:50 -04:00
committed by GitHub
53 changed files with 806 additions and 505 deletions
+53 -26
View File
@@ -34,6 +34,7 @@ import (
clientOperations "github.com/openziti/edge-api/rest_client_api_server/operations"
managementServer "github.com/openziti/edge-api/rest_management_api_server"
managementOperations "github.com/openziti/edge-api/rest_management_api_server/operations"
"github.com/openziti/edge-api/rest_model"
edgeConfig "github.com/openziti/edge/controller/config"
"github.com/openziti/edge/controller/internal/permissions"
"github.com/openziti/edge/controller/model"
@@ -48,10 +49,10 @@ import (
"github.com/openziti/fabric/controller/xctrl"
"github.com/openziti/fabric/controller/xmgmt"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/foundation/v2/stringz"
"github.com/openziti/identity"
"github.com/openziti/metrics"
"github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti/constants"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/storage/boltz"
"github.com/openziti/xweb/v2"
cmap "github.com/orcaman/concurrent-map/v2"
@@ -64,12 +65,14 @@ import (
var _ model.Env = &AppEnv{}
const ZitiSession = "zt-session"
type AppEnv struct {
BoltStores *persistence.Stores
Managers *model.Managers
Config *edgeConfig.Config
Versions *config.Versions
Versions *ziti.Versions
ApiServerCsrSigner cert.Signer
ApiClientCsrSigner cert.Signer
@@ -299,18 +302,9 @@ func (ae *AppEnv) FillRequestContext(rc *response.RequestContext) error {
return err
}
totpRequired := rc.ApiSession.MfaRequired || rc.AuthPolicy.Secondary.RequireTotp
ProcessAuthQueries(ae, rc)
isPartialAuth := false
if totpRequired && !rc.ApiSession.MfaComplete {
isPartialAuth = true
}
if rc.AuthPolicy.Secondary.RequiredExtJwtSigner != nil {
if !processSecondaryJwtSigner(ae, rc) {
isPartialAuth = true
}
}
isPartialAuth := len(rc.AuthQueries) > 0
if isPartialAuth {
rc.ActivePermissions = append(rc.ActivePermissions, permissions.PartiallyAuthenticatePermission)
@@ -322,28 +316,61 @@ func (ae *AppEnv) FillRequestContext(rc *response.RequestContext) error {
rc.ActivePermissions = append(rc.ActivePermissions, permissions.AdminPermission)
}
}
return nil
}
func processSecondaryJwtSigner(ae *AppEnv, rc *response.RequestContext) bool {
func NewAuthQueryZitiMfa() *rest_model.AuthQueryDetail {
provider := rest_model.MfaProvidersZiti
return &rest_model.AuthQueryDetail{
TypeID: "MFA",
Format: rest_model.MfaFormatsAlphaNumeric,
HTTPMethod: http.MethodPost,
HTTPURL: "./authenticate/mfa",
MaxLength: model.TotpMaxLength,
MinLength: model.TotpMinLength,
Provider: &provider,
}
}
func NewAuthQueryExtJwt(url string) *rest_model.AuthQueryDetail {
return &rest_model.AuthQueryDetail{
HTTPURL: url,
TypeID: "EXT-JWT",
}
}
// ProcessAuthQueries will inspect a response.RequestContext and set the AuthQueries
// with the current outstanding authentication queries.
func ProcessAuthQueries(ae *AppEnv, rc *response.RequestContext) {
if rc.ApiSession == nil || rc.AuthPolicy == nil {
return
}
totpRequired := rc.ApiSession.MfaRequired || rc.AuthPolicy.Secondary.RequireTotp
if totpRequired && !rc.ApiSession.MfaComplete {
rc.AuthQueries = append(rc.AuthQueries, NewAuthQueryZitiMfa())
}
if rc.AuthPolicy.Secondary.RequiredExtJwtSigner != nil {
rc.AuthStatus.SecondaryExtJwtSignerId = *rc.AuthPolicy.Secondary.RequiredExtJwtSigner
extJwtAuthVal := ae.GetAuthRegistry().GetByMethod(model.AuthMethodExtJwt)
extJwtAuth := extJwtAuthVal.(*model.AuthModuleExtJwt)
if extJwtAuth != nil {
authResult, err := extJwtAuth.ProcessSecondary(model.NewAuthContextHttp(rc.Request, model.AuthMethodExtJwt, nil, rc.NewChangeContext()))
if err != nil {
return false
if err != nil || !authResult.IsSuccessful() {
signer, err := ae.Managers.ExternalJwtSigner.Read(*rc.AuthPolicy.Secondary.RequiredExtJwtSigner)
authUrl := ""
if err == nil {
authUrl = stringz.OrEmpty(signer.ExternalAuthUrl)
}
rc.AuthQueries = append(rc.AuthQueries, NewAuthQueryExtJwt(authUrl))
}
return authResult.IsSuccessful()
}
return false
}
return true
}
func NewAppEnv(c *edgeConfig.Config, host HostController) *AppEnv {
@@ -365,7 +392,7 @@ func NewAppEnv(c *edgeConfig.Config, host HostController) *AppEnv {
ae := &AppEnv{
Config: c,
Versions: &config.Versions{
Versions: &ziti.Versions{
Api: "1.0.0",
EnrollmentApi: "1.0.0",
},
@@ -499,7 +526,7 @@ func getJwtSigningMethod(cert *tls.Certificate) jwt.SigningMethod {
}
func (ae *AppEnv) GetSessionTokenFromRequest(r *http.Request) string {
return r.Header.Get(constants.ZitiSession)
return r.Header.Get(ZitiSession)
}
func (ae *AppEnv) CreateRequestContext(rw http.ResponseWriter, r *http.Request) *response.RequestContext {
@@ -24,7 +24,6 @@ import (
"github.com/openziti/edge/controller/response"
"github.com/openziti/fabric/controller/models"
"github.com/openziti/foundation/v2/stringz"
"net/http"
"path"
)
@@ -61,11 +60,6 @@ func MapApiSessionToRestInterface(ae *env.AppEnv, _ *response.RequestContext, ap
}
func MapApiSessionToRestModel(ae *env.AppEnv, apiSession *model.ApiSession) (*rest_model.APISessionDetail, error) {
authQueries := rest_model.AuthQueryList{}
if apiSession.MfaRequired && !apiSession.MfaComplete {
authQueries = append(authQueries, newAuthCheckZitiMfa())
}
lastActivityAt := strfmt.DateTime(apiSession.LastActivityAt)
@@ -76,7 +70,7 @@ func MapApiSessionToRestModel(ae *env.AppEnv, apiSession *model.ApiSession) (*re
Token: &apiSession.Token,
IPAddress: &apiSession.IPAddress,
ConfigTypes: stringz.SetToSlice(apiSession.ConfigTypes),
AuthQueries: authQueries,
AuthQueries: rest_model.AuthQueryList{}, //not in a request context, can't fill
IsMfaComplete: &apiSession.MfaComplete,
IsMfaRequired: &apiSession.MfaRequired,
LastActivityAt: lastActivityAt,
@@ -96,16 +90,3 @@ func MapApiSessionToRestModel(ae *env.AppEnv, apiSession *model.ApiSession) (*re
return ret, nil
}
func newAuthCheckZitiMfa() *rest_model.AuthQueryDetail {
provider := rest_model.MfaProvidersZiti
return &rest_model.AuthQueryDetail{
TypeID: "MFA",
Format: rest_model.MfaFormatsAlphaNumeric,
HTTPMethod: http.MethodPost,
HTTPURL: "./authenticate/mfa",
MaxLength: model.TotpMaxLength,
MinLength: model.TotpMinLength,
Provider: &provider,
}
}
@@ -31,7 +31,6 @@ import (
"github.com/openziti/edge/controller/response"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/metrics"
"github.com/openziti/sdk-golang/ziti/constants"
"net"
"net/http"
"time"
@@ -92,6 +91,8 @@ func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, h
return
}
rc.AuthPolicy = authResult.AuthPolicy()
identity := authResult.Identity()
if identity.EnvInfo == nil {
identity.EnvInfo = &model.EnvInfo{}
@@ -189,15 +190,18 @@ func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, h
ae.GetManagers().PostureResponse.SetSdkInfo(identity.Id, sessionId, identity.SdkInfo)
apiSession := MapToCurrentApiSessionRestModel(ae, filledApiSession, ae.Config.SessionTimeoutDuration())
rc.ApiSession = filledApiSession
env.ProcessAuthQueries(ae, rc)
apiSession := MapToCurrentApiSessionRestModel(ae, rc, ae.Config.SessionTimeoutDuration())
//re-calc session headers as they were not set when ApiSession == NIL
response.AddSessionHeaders(rc)
envelope := &rest_model.CurrentAPISessionDetailEnvelope{Data: apiSession, Meta: &rest_model.Meta{}}
rc.ResponseWriter.Header().Set(constants.ZitiSession, filledApiSession.Token)
rc.ResponseWriter.Header().Set(env.ZitiSession, filledApiSession.Token)
ro.createTimer.UpdateSince(start)
+4 -4
View File
@@ -30,7 +30,7 @@ import (
"github.com/openziti/edge/controller/model"
"github.com/openziti/edge/controller/response"
"github.com/openziti/fabric/controller/fields"
"github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/storage/boltz"
"github.com/pkg/errors"
"net/http"
@@ -264,7 +264,7 @@ func (r *CaRouter) generateJwt(ae *env.AppEnv, rc *response.RequestContext) {
method := "ca"
claims := &config.EnrollmentClaims{
claims := &ziti.EnrollmentClaims{
EnrollmentMethod: method,
StandardClaims: jwt.StandardClaims{
ExpiresAt: notAfter,
@@ -278,7 +278,7 @@ func (r *CaRouter) generateJwt(ae *env.AppEnv, rc *response.RequestContext) {
return
}
jwt, genErr := ae.GetJwtSigner().Generate(ca.Id, ca.Id, mapClaims)
jwtStr, genErr := ae.GetJwtSigner().Generate(ca.Id, ca.Id, mapClaims)
if genErr != nil {
rc.RespondWithError(errors.New("could not generate claims"))
@@ -287,5 +287,5 @@ func (r *CaRouter) generateJwt(ae *env.AppEnv, rc *response.RequestContext) {
rc.ResponseWriter.Header().Set("content-type", "application/jwt")
rc.ResponseWriter.WriteHeader(http.StatusOK)
_, _ = rc.ResponseWriter.Write([]byte(jwt))
_, _ = rc.ResponseWriter.Write([]byte(jwtStr))
}
@@ -55,9 +55,11 @@ func (factory *CurrentApiSessionLinkFactoryImpl) Links(entity models.Entity) res
}
}
func MapToCurrentApiSessionRestModel(ae *env.AppEnv, apiSession *model.ApiSession, sessionTimeout time.Duration) *rest_model.CurrentAPISessionDetail {
func MapToCurrentApiSessionRestModel(ae *env.AppEnv, rc *response.RequestContext, sessionTimeout time.Duration) *rest_model.CurrentAPISessionDetail {
detail, err := MapApiSessionToRestModel(ae, apiSession)
detail, err := MapApiSessionToRestModel(ae, rc.ApiSession)
MapApiSessionAuthQueriesToRestEntity(ae, rc, detail)
if err != nil {
pfxlog.Logger().Errorf("error could not convert apiSession to rest model: %v", err)
@@ -67,7 +69,7 @@ func MapToCurrentApiSessionRestModel(ae *env.AppEnv, apiSession *model.ApiSessio
detail = &rest_model.APISessionDetail{}
}
expiresAt := strfmt.DateTime(time.Time(detail.LastActivityAt).Add(sessionTimeout))
expirationSeconds := int64(apiSession.ExpirationDuration.Seconds())
expirationSeconds := int64(rc.ApiSession.ExpirationDuration.Seconds())
ret := &rest_model.CurrentAPISessionDetail{
APISessionDetail: *detail,
@@ -78,8 +80,22 @@ func MapToCurrentApiSessionRestModel(ae *env.AppEnv, apiSession *model.ApiSessio
return ret
}
func MapApiSessionCertificateToRestEntity(appEnv *env.AppEnv, context *response.RequestContext, i *model.ApiSessionCertificate) (interface{}, error) {
return MapApiSessionCertificateToRestModel(i)
func MapApiSessionAuthQueriesToRestEntity(ae *env.AppEnv, rc *response.RequestContext, detail *rest_model.APISessionDetail) {
for _, authQuery := range rc.AuthQueries {
detail.AuthQueries = append(detail.AuthQueries, &rest_model.AuthQueryDetail{
Format: authQuery.Format,
HTTPMethod: authQuery.HTTPMethod,
HTTPURL: authQuery.HTTPURL,
MaxLength: authQuery.MaxLength,
MinLength: authQuery.MinLength,
Provider: authQuery.Provider,
TypeID: authQuery.TypeID,
})
}
}
func MapApiSessionCertificateToRestEntity(appEnv *env.AppEnv, context *response.RequestContext, cert *model.ApiSessionCertificate) (interface{}, error) {
return MapApiSessionCertificateToRestModel(cert)
}
func MapApiSessionCertificateToRestModel(apiSessionCert *model.ApiSessionCertificate) (*rest_model.CurrentAPISessionCertificateDetail, error) {
@@ -25,7 +25,6 @@ import (
"github.com/openziti/edge/controller/env"
"github.com/openziti/edge/controller/internal/permissions"
"github.com/openziti/edge/controller/response"
"github.com/openziti/foundation/v2/stringz"
"net/http"
"time"
)
@@ -86,23 +85,7 @@ func (router *CurrentSessionRouter) Register(ae *env.AppEnv) {
}
func (router *CurrentSessionRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) {
apiSession := MapToCurrentApiSessionRestModel(ae, rc.ApiSession, ae.Config.SessionTimeoutDuration())
if rc.AuthStatus.SecondaryExtJwtSignerId != "" && !rc.AuthStatus.PassedSecondaryExtJwtSignerId {
extJwtSigner, err := ae.GetManagers().ExternalJwtSigner.Read(rc.AuthStatus.SecondaryExtJwtSignerId)
if err != nil {
rc.RespondWithError(err)
return
}
authQuery := &rest_model.AuthQueryDetail{
TypeID: "EXT-JWT",
HTTPURL: stringz.OrEmpty(extJwtSigner.ExternalAuthUrl),
}
apiSession.AuthQueries = append(apiSession.AuthQueries, authQuery)
}
apiSession := MapToCurrentApiSessionRestModel(ae, rc, ae.Config.SessionTimeoutDuration())
rc.Respond(rest_model.CurrentAPISessionDetailEnvelope{Data: apiSession, Meta: &rest_model.Meta{}}, http.StatusOK)
}
@@ -29,6 +29,7 @@ import (
"github.com/openziti/edge/controller/persistence"
"github.com/openziti/edge/controller/response"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/foundation/v2/stringz"
"github.com/openziti/storage/boltz"
"github.com/pkg/errors"
"net/http"
@@ -57,7 +58,7 @@ func (r *CurrentIdentityRouter) Register(ae *env.AppEnv) {
ae.ClientApi.CurrentIdentityDeleteMfaHandler = clientCurrentIdentity.DeleteMfaHandlerFunc(func(params clientCurrentIdentity.DeleteMfaParams, i interface{}) middleware.Responder {
return ae.IsAllowed(func(ae *env.AppEnv, rc *response.RequestContext) {
r.removeMfa(ae, rc, params.MfaValidation, params.MfaValidationCode)
r.removeMfa(ae, rc, params.MfaValidationCode)
}, params.HTTPRequest, "", "", permissions.IsAuthenticated())
})
@@ -104,7 +105,7 @@ func (r *CurrentIdentityRouter) Register(ae *env.AppEnv) {
ae.ManagementApi.CurrentIdentityDeleteMfaHandler = managementCurrentIdentity.DeleteMfaHandlerFunc(func(params managementCurrentIdentity.DeleteMfaParams, i interface{}) middleware.Responder {
return ae.IsAllowed(func(ae *env.AppEnv, rc *response.RequestContext) {
r.removeMfa(ae, rc, params.MfaValidation, params.MfaValidationCode)
r.removeMfa(ae, rc, params.MfaValidationCode)
}, params.HTTPRequest, "", "", permissions.IsAuthenticated())
})
@@ -220,14 +221,8 @@ func (r *CurrentIdentityRouter) detailMfa(ae *env.AppEnv, rc *response.RequestCo
})
}
func (r *CurrentIdentityRouter) removeMfa(ae *env.AppEnv, rc *response.RequestContext, mfaValidationBody *rest_model.MfaCode, mfaCodeHeader *string) {
code := ""
if mfaValidationBody != nil && mfaValidationBody.Code != nil {
code = *mfaValidationBody.Code
} else if mfaCodeHeader != nil {
code = *mfaCodeHeader
}
func (r *CurrentIdentityRouter) removeMfa(ae *env.AppEnv, rc *response.RequestContext, requestCode *string) {
code := stringz.OrEmpty(requestCode)
err := ae.Managers.Mfa.DeleteForIdentity(rc.Identity, code, rc.NewChangeContext())
+2 -2
View File
@@ -23,7 +23,7 @@ import (
"github.com/openziti/edge/controller/persistence"
"github.com/openziti/fabric/controller/models"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/storage/boltz"
"go.etcd.io/bbolt"
"time"
@@ -59,7 +59,7 @@ func (entity *Enrollment) FillJwtInfoWithExpiresAt(env Env, subject string, expi
entity.Token = uuid.New().String()
}
enrollmentClaims := config.EnrollmentClaims{
enrollmentClaims := ziti.EnrollmentClaims{
EnrollmentMethod: entity.Method,
StandardClaims: jwt.StandardClaims{
Audience: "",
+2 -6
View File
@@ -18,6 +18,7 @@ package response
import (
"errors"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/controller/model"
"github.com/openziti/fabric/controller/change"
"net/http"
@@ -35,7 +36,7 @@ type RequestContext struct {
ApiSession *model.ApiSession
Identity *model.Identity
AuthPolicy *model.AuthPolicy
AuthStatus AuthStatus
AuthQueries rest_model.AuthQueryList
ActivePermissions []string
ResponseWriter http.ResponseWriter
Request *http.Request
@@ -46,11 +47,6 @@ type RequestContext struct {
StartTime time.Time
}
type AuthStatus struct {
SecondaryExtJwtSignerId string
PassedSecondaryExtJwtSignerId bool
}
func (rc *RequestContext) GetId() string {
return rc.Id
}
+3 -2
View File
@@ -29,13 +29,13 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/netfoundry/secretstream v0.1.5
github.com/openziti/channel/v2 v2.0.62
github.com/openziti/edge-api v0.25.11
github.com/openziti/edge-api v0.25.17
github.com/openziti/fabric v0.23.1
github.com/openziti/foundation/v2 v2.0.21
github.com/openziti/identity v1.0.47
github.com/openziti/jwks v1.0.3
github.com/openziti/metrics v1.2.19
github.com/openziti/sdk-golang v0.18.76
github.com/openziti/sdk-golang v0.20.0
github.com/openziti/storage v0.2.0
github.com/openziti/transport/v2 v2.0.75
github.com/openziti/x509-claims v1.0.3
@@ -108,6 +108,7 @@ require (
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/openziti/secretstream v0.1.6 // indirect
github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
+6 -4
View File
@@ -455,8 +455,8 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openziti/channel/v2 v2.0.62 h1:WmNYAugoyQ2HFu2VEhOH4WExzXsX6+dzSQDzNfHf5M8=
github.com/openziti/channel/v2 v2.0.62/go.mod h1:TS2FJs1GuCZXUfSFfptrNWKeTuQRO7YJ9K7C2jWMznA=
github.com/openziti/edge-api v0.25.11 h1:HHjDgoybPZGRZ+tM2udehI+U5Xv991iGED8E6CtDb9w=
github.com/openziti/edge-api v0.25.11/go.mod h1:PBFMYELgr7JUuaCqHobq1U+WESsutzgEDoELU/9qFOg=
github.com/openziti/edge-api v0.25.17 h1:SLmcI2bPg9ZK+HgJy9Jr2D6iYx+rvK/kWl3aN1ITg8c=
github.com/openziti/edge-api v0.25.17/go.mod h1:TC+hI2eI9X5PvqT0UtnOpEDQBkMK5yUEc8BtDJhyCCE=
github.com/openziti/fabric v0.23.1 h1:9RFRmApJ9EGUNNwIP4OSZcgFmiBdVLTvLfYsYRID8ws=
github.com/openziti/fabric v0.23.1/go.mod h1:p5EI0s0LvNi6HipLR+PWDon89C3dhfyX/jac/3cwmpA=
github.com/openziti/foundation/v2 v2.0.21 h1:3EDDmSunsbd2DlULuY/vqj12LHRZOknH/m3lf6Ws5Nw=
@@ -467,8 +467,10 @@ github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc=
github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ=
github.com/openziti/metrics v1.2.19 h1:gQO3e2lUotRHBdGUXYBPWMIErIyyF5hw0EakwQbJzuM=
github.com/openziti/metrics v1.2.19/go.mod h1:ovvxTpDBxGLcVLHgPTFFvwT4ur8p4Z76BPUhIE5iwqc=
github.com/openziti/sdk-golang v0.18.76 h1:D+UW1lpGHBBgfVrObpauq9RvJV/TFPdEEshfuPkiMcI=
github.com/openziti/sdk-golang v0.18.76/go.mod h1:kw/5rWDLwx52iwW/4a0VRQMUi7GPSI3aETx+G5TvdFQ=
github.com/openziti/sdk-golang v0.20.0 h1:a5pwPOpp1mS66+5lHEU74kWIEU3D2ySE/sZnNLNdf4M=
github.com/openziti/sdk-golang v0.20.0/go.mod h1:5deFxXx5JWeOVCfRkyi6EfeALbhQ7avx2hymLJj9Q98=
github.com/openziti/secretstream v0.1.6 h1:TbpTwW/lc/0kuvaoRNjpiyebxh2Hyx8XSTB269QtHN4=
github.com/openziti/secretstream v0.1.6/go.mod h1:Gc6fhaDC46UUvwJD4ogbYji22YSdz3fe8bno+BFIpcE=
github.com/openziti/storage v0.2.0 h1:uwSoZQEZCzxp4+KZEi7fOWezbm0knmcCbRhni/DGHSo=
github.com/openziti/storage v0.2.0/go.mod h1:rJjLObUtJBNcm7MvnTr4DHCXZ+ppg0OMeoJ5tfi1aJI=
github.com/openziti/transport/v2 v2.0.75 h1:KZmnyRH1SOXSI6DXqDRsbRxRJE2cWv5EDCiQqC+R+hQ=
+6 -5
View File
@@ -1,6 +1,7 @@
package edge_ctrl_pb
import (
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/fabric/controller/xt"
"github.com/openziti/sdk-golang/ziti"
)
@@ -114,18 +115,18 @@ func GetPrecedence(p ziti.Precedence) TerminatorPrecedence {
return TerminatorPrecedence_Default
}
func (self TerminatorPrecedence) GetZitiLabel() string {
func (self TerminatorPrecedence) GetZitiLabel() rest_model.TerminatorPrecedence {
if self == TerminatorPrecedence_Default {
return ziti.PrecedenceDefaultLabel
return rest_model.TerminatorPrecedenceDefault
}
if self == TerminatorPrecedence_Required {
return ziti.PrecedenceRequiredLabel
return rest_model.TerminatorPrecedenceRequired
}
if self == TerminatorPrecedence_Failed {
return ziti.PrecedenceFailedLabel
return rest_model.TerminatorPrecedenceFailed
}
return ziti.PrecedenceDefaultLabel
return rest_model.TerminatorPrecedenceDefault
}
+3 -3
View File
@@ -29,7 +29,7 @@ import (
"github.com/openziti/edge/router/internal/edgerouter"
"github.com/openziti/fabric/router"
"github.com/openziti/identity/certtools"
"github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/enroll"
"gopkg.in/resty.v1"
"net/http"
@@ -44,7 +44,7 @@ type apiPost struct {
}
type Enroller interface {
Enroll(jwt []byte, silent bool, engine string, keyAlg config.KeyAlgVar) error
Enroll(jwt []byte, silent bool, engine string, keyAlg ziti.KeyAlgVar) error
LoadConfig(cfgmap map[interface{}]interface{}) error
}
@@ -78,7 +78,7 @@ func (re *RestEnroller) LoadConfig(cfgmap map[interface{}]interface{}) error {
return nil
}
func (re *RestEnroller) Enroll(jwtBuf []byte, silent bool, engine string, keyAlg config.KeyAlgVar) error {
func (re *RestEnroller) Enroll(jwtBuf []byte, silent bool, engine string, keyAlg ziti.KeyAlgVar) error {
log := pfxlog.Logger()
if re.config == nil {
+23 -13
View File
@@ -3,17 +3,17 @@ package handler_edge_ctrl
import (
"encoding/json"
"github.com/openziti/channel/v2"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/pb/edge_ctrl_pb"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/sirupsen/logrus"
"google.golang.org/protobuf/proto"
)
type ServiceListHandler struct {
handler func(ch channel.Channel, lastUpdateToken []byte, list []*edge.Service)
handler func(ch channel.Channel, lastUpdateToken []byte, list []*rest_model.ServiceDetail)
}
func NewServiceListHandler(handler func(ch channel.Channel, lastUpdateToken []byte, list []*edge.Service)) *ServiceListHandler {
func NewServiceListHandler(handler func(ch channel.Channel, lastUpdateToken []byte, list []*rest_model.ServiceDetail)) *ServiceListHandler {
return &ServiceListHandler{
handler: handler,
}
@@ -34,15 +34,25 @@ func (self *ServiceListHandler) HandleReceive(msg *channel.Message, ch channel.C
}
func (self *ServiceListHandler) handleServicesList(ch channel.Channel, list *edge_ctrl_pb.ServicesList) {
var serviceList []*edge.Service
var serviceList []*rest_model.ServiceDetail
for _, entry := range list.Services {
service := &edge.Service{
Id: entry.Id,
Name: entry.Name,
Permissions: entry.Permissions,
Encryption: entry.Encryption,
Configs: map[string]map[string]interface{}{},
Tags: map[string]string{},
var permissions rest_model.DialBindArray
for _, perm := range entry.Permissions {
permissions = append(permissions, rest_model.DialBind(perm))
}
service := &rest_model.ServiceDetail{
BaseEntity: rest_model.BaseEntity{
ID: &entry.Id,
Tags: &rest_model.Tags{},
},
Name: &entry.Name,
Permissions: permissions,
EncryptionRequired: &entry.Encryption,
Config: map[string]map[string]interface{}{},
}
err := json.Unmarshal(entry.Config, &service.Configs)
@@ -50,7 +60,7 @@ func (self *ServiceListHandler) handleServicesList(ch channel.Channel, list *edg
logrus.
WithError(err).
WithField("json", string(entry.Config)).
WithField("service", service.Id).
WithField("service", *service.ID).
Error("unable to unmarshal config json")
return
}
@@ -60,7 +70,7 @@ func (self *ServiceListHandler) handleServicesList(ch channel.Channel, list *edg
logrus.
WithError(err).
WithField("json", string(entry.Tags)).
WithField("service", service.Id).
WithField("service", *service.ID).
Error("unable to unmarshal tag json")
return
}
+2 -2
View File
@@ -25,7 +25,7 @@ import (
"github.com/openziti/foundation/v2/concurrenz"
"github.com/openziti/foundation/v2/info"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/openziti/sdk-golang/ziti/edge/impl"
"github.com/openziti/sdk-golang/ziti/edge/network"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"io"
@@ -194,7 +194,7 @@ func (self *XgressConn) ReadPayload() ([]byte, map[uint8][]byte, error) {
if err == nil {
err = cryptoErr
} else {
err = impl.MultipleErrors{err, cryptoErr}
err = network.MultipleErrors{err, cryptoErr}
}
}
}
+23 -20
View File
@@ -24,6 +24,7 @@ import (
"github.com/netfoundry/secretstream/kx"
"github.com/openziti/channel/v2"
"github.com/openziti/channel/v2/protobufs"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/pb/edge_ctrl_pb"
"github.com/openziti/edge/router/xgress_common"
"github.com/openziti/edge/tunnel"
@@ -48,6 +49,10 @@ import (
"time"
)
func ToPtr[T any](in T) *T {
return &in
}
func newProvider(factory *Factory, tunneler *tunneler) *fabricProvider {
return &fabricProvider{
factory: factory,
@@ -64,7 +69,7 @@ type fabricProvider struct {
apiSessionLock sync.Mutex
apiSessionTokens map[string]string
currentIdentity *edge.CurrentIdentity
currentIdentity *rest_model.IdentityDetail
dialSessions cmap.ConcurrentMap[string, string]
bindSessions cmap.ConcurrentMap[string, string]
@@ -92,14 +97,16 @@ func (self *fabricProvider) updateApiSession(ctrlId string, resp *edge_ctrl_pb.C
self.tunneler.stateManager.RemoveConnectedApiSession(currentToken)
self.apiSessionTokens[ctrlId] = resp.Token
self.currentIdentity = &edge.CurrentIdentity{
Id: resp.IdentityId,
Name: resp.IdentityName,
DefaultHostingPrecedence: strings.ToLower(resp.DefaultHostingPrecedence.String()),
DefaultHostingCost: uint16(resp.DefaultHostingCost),
AppData: map[string]interface{}{},
ServiceHostingPrecedences: map[string]interface{}{},
ServiceHostingCosts: map[string]interface{}{},
self.currentIdentity = &rest_model.IdentityDetail{
BaseEntity: rest_model.BaseEntity{
ID: &resp.IdentityId,
},
Name: &resp.IdentityName,
DefaultHostingPrecedence: rest_model.TerminatorPrecedence(strings.ToLower(resp.DefaultHostingPrecedence.String())),
DefaultHostingCost: ToPtr(rest_model.TerminatorCost(int64(resp.DefaultHostingCost))),
AppData: &rest_model.Tags{},
ServiceHostingPrecedences: rest_model.TerminatorPrecedenceMap{},
ServiceHostingCosts: rest_model.TerminatorCostMap{},
}
for k, v := range resp.ServicePrecedences {
@@ -107,7 +114,7 @@ func (self *fabricProvider) updateApiSession(ctrlId string, resp *edge_ctrl_pb.C
}
for k, v := range resp.ServiceCosts {
self.currentIdentity.ServiceHostingCosts[k] = float64(v)
self.currentIdentity.ServiceHostingCosts[k] = ToPtr(rest_model.TerminatorCost(v))
}
if resp.AppDataJson != "" {
@@ -123,21 +130,17 @@ func (self *fabricProvider) updateApiSession(ctrlId string, resp *edge_ctrl_pb.C
}
func (self *fabricProvider) authenticate() error {
info := sdkinfo.GetSdkInfo()
envInfo, _ := sdkinfo.GetSdkInfo()
buildInfo := build.GetBuildInfo()
osVersion := "unknown"
osRelease := "unknown"
if val, ok := info["osVersion"]; ok {
if valStr, ok := val.(string); ok {
osVersion = valStr
}
if envInfo.OsVersion != "" {
osVersion = envInfo.OsVersion
}
if val, ok := info["osRelease"]; ok {
if valStr, ok := val.(string); ok {
osRelease = valStr
}
if envInfo.OsRelease != "" {
osRelease = envInfo.OsRelease
}
request := &edge_ctrl_pb.CreateApiSessionRequest{
@@ -189,7 +192,7 @@ func (self *fabricProvider) authenticate() error {
func (self *fabricProvider) PrepForUse(string) {}
func (self *fabricProvider) GetCurrentIdentity() (*edge.CurrentIdentity, error) {
func (self *fabricProvider) GetCurrentIdentity() (*rest_model.IdentityDetail, error) {
return self.currentIdentity, nil
}
+9 -9
View File
@@ -19,9 +19,9 @@ limitations under the License.
import (
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/tunnel/intercept"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
cmap "github.com/orcaman/concurrent-map/v2"
"github.com/sirupsen/logrus"
"reflect"
@@ -31,7 +31,7 @@ import (
func newServicePoller(fabricProvider *fabricProvider) *servicePoller {
result := &servicePoller{
services: cmap.New[*edge.Service](),
services: cmap.New[*rest_model.ServiceDetail](),
servicesLastUpdateToken: cmap.New[[]byte](),
fabricProvider: fabricProvider,
}
@@ -40,7 +40,7 @@ func newServicePoller(fabricProvider *fabricProvider) *servicePoller {
}
type servicePoller struct {
services cmap.ConcurrentMap[string, *edge.Service]
services cmap.ConcurrentMap[string, *rest_model.ServiceDetail]
serviceListener *intercept.ServiceListener
servicesLastUpdateToken cmap.ConcurrentMap[string, []byte]
serviceListenerLock sync.Mutex
@@ -48,7 +48,7 @@ type servicePoller struct {
fabricProvider *fabricProvider
}
func (self *servicePoller) handleServiceListUpdate(ch channel.Channel, lastUpdateToken []byte, services []*edge.Service) {
func (self *servicePoller) handleServiceListUpdate(ch channel.Channel, lastUpdateToken []byte, services []*rest_model.ServiceDetail) {
self.serviceListenerLock.Lock()
defer self.serviceListenerLock.Unlock()
@@ -61,16 +61,16 @@ func (self *servicePoller) handleServiceListUpdate(ch channel.Channel, lastUpdat
self.servicesLastUpdateToken.Set(ch.Id(), lastUpdateToken)
idMap := make(map[string]*edge.Service)
idMap := make(map[string]*rest_model.ServiceDetail)
for _, s := range services {
idMap[s.Id] = s
idMap[*s.ID] = s
}
var toRemove []string
// process Deletes
self.services.IterCb(func(k string, svc *edge.Service) {
if _, found := idMap[svc.Id]; !found {
self.services.IterCb(func(k string, svc *rest_model.ServiceDetail) {
if _, found := idMap[*svc.ID]; !found {
toRemove = append(toRemove, k)
self.serviceListener.HandleServicesChange(ziti.ServiceRemoved, svc)
}
@@ -82,7 +82,7 @@ func (self *servicePoller) handleServiceListUpdate(ch channel.Channel, lastUpdat
// Adds and Updates
for _, s := range services {
self.services.Upsert(s.Id, s, func(exist bool, valueInMap *edge.Service, newValue *edge.Service) *edge.Service {
self.services.Upsert(*s.ID, s, func(exist bool, valueInMap *rest_model.ServiceDetail, newValue *rest_model.ServiceDetail) *rest_model.ServiceDetail {
if !exist {
self.serviceListener.HandleServicesChange(ziti.ServiceAdded, s)
return s
+1 -1
View File
@@ -142,7 +142,7 @@ func Test_AddressableTerminatorSameIdentity(t *testing.T) {
listener.(edge.SessionListener).SetErrorEventHandler(errorHandler)
defer func() { _ = listener.Close() }()
context2 := ziti.NewContextWithConfig(identity.config)
context2 := ziti.NewContext(identity.config)
listener2, err := context2.ListenWithOptions(service.Name, &ziti.ListenOptions{
BindUsingEdgeIdentity: true,
ConnectTimeout: 5 * time.Second,
+2 -2
View File
@@ -46,7 +46,7 @@ func Test_ApiSession(t *testing.T) {
expected := s(configType1.Id, configType2.Id)
sort.Strings(expected)
sort.Strings(session.configTypes)
ctx.Req.Equal(expected, session.configTypes)
sort.Strings(session.AuthResponse.ConfigTypes)
ctx.Req.Equal(expected, session.AuthResponse.ConfigTypes)
})
}
+7 -7
View File
@@ -29,12 +29,12 @@ import (
"fmt"
"github.com/Jeffail/gabs"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/controller/env"
"github.com/openziti/edge/controller/model"
"github.com/openziti/edge/eid"
"github.com/openziti/edge/internal/cert"
"github.com/openziti/fabric/controller/change"
nfPem "github.com/openziti/foundation/v2/pem"
"github.com/openziti/sdk-golang/ziti/constants"
"github.com/stretchr/testify/require"
"net/http"
"reflect"
@@ -147,7 +147,7 @@ func (test *authCertTests) testAuthenticateValidCertEmptyBody(t *testing.T) {
standardJsonResponseTests(resp, http.StatusOK, t)
t.Run("returns a session token HTTP headers", func(t *testing.T) {
require.New(t).NotEmpty(resp.Header().Get(constants.ZitiSession), fmt.Sprintf("HTTP header %s is empty", constants.ZitiSession))
require.New(t).NotEmpty(resp.Header().Get(env.ZitiSession), fmt.Sprintf("HTTP header %s is empty", env.ZitiSession))
})
t.Run("returns a session token in body", func(t *testing.T) {
@@ -167,7 +167,7 @@ func (test *authCertTests) testAuthenticateValidCertEmptyBody(t *testing.T) {
r.NoError(err)
bodyToken := data.Path("data.token").Data().(string)
headerToken := resp.Header().Get(constants.ZitiSession)
headerToken := resp.Header().Get(env.ZitiSession)
r.Equal(bodyToken, headerToken)
})
@@ -209,7 +209,7 @@ func (test *authCertTests) testAuthenticateValidCertValidClientInfoBody(t *testi
standardJsonResponseTests(resp, http.StatusOK, t)
t.Run("returns a session token HTTP headers", func(t *testing.T) {
require.New(t).NotEmpty(resp.Header().Get(constants.ZitiSession), fmt.Sprintf("HTTP header %s is empty", constants.ZitiSession))
require.New(t).NotEmpty(resp.Header().Get(env.ZitiSession), fmt.Sprintf("HTTP header %s is empty", env.ZitiSession))
})
t.Run("returns a session token in body", func(t *testing.T) {
@@ -229,7 +229,7 @@ func (test *authCertTests) testAuthenticateValidCertValidClientInfoBody(t *testi
r.NoError(err)
bodyToken := data.Path("data.token").Data().(string)
headerToken := resp.Header().Get(constants.ZitiSession)
headerToken := resp.Header().Get(env.ZitiSession)
r.Equal(bodyToken, headerToken)
})
@@ -342,7 +342,7 @@ func (test *authCertTests) testAuthenticateValidCertInvalidJson(t *testing.T) {
standardErrorJsonResponseTests(resp, "COULD_NOT_PARSE_BODY", http.StatusBadRequest, t)
t.Run("returns without a ziti session header", func(t *testing.T) {
require.New(t).Equal("", resp.Header().Get(constants.ZitiSession))
require.New(t).Equal("", resp.Header().Get(env.ZitiSession))
})
}
@@ -425,7 +425,7 @@ rv1CXRECfHglY+vO0CFumQOV5bec2R8=
standardErrorJsonResponseTests(resp, "INVALID_AUTH", http.StatusUnauthorized, t)
t.Run("returns without a ziti session header", func(t *testing.T) {
require.New(t).Equal("", resp.Header().Get(constants.ZitiSession))
require.New(t).Equal("", resp.Header().Get(env.ZitiSession))
})
}
+7 -7
View File
@@ -151,7 +151,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: *validJwtSigner.Issuer,
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtToken.Header["kid"] = *validJwtSigner.Kid
@@ -183,7 +183,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: "fake.issuer",
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtToken.Header["kid"] = *notEnabledJwtSigner.Kid
@@ -210,7 +210,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: "i will cause this to fail",
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtToken.Header["kid"] = *validJwtSigner.Kid
@@ -237,7 +237,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: *validJwtSigner.Issuer,
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtToken.Header["kid"] = *validJwtSigner.Kid
@@ -264,7 +264,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: "fake.issuer",
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtStrSigned, err := jwtToken.SignedString(validJwtSignerPrivateKey)
@@ -289,7 +289,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: "fake.issuer",
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtToken.Header["kid"] = *validJwtSigner.Kid
@@ -316,7 +316,7 @@ func Test_Authenticate_External_Jwt(t *testing.T) {
IssuedAt: time.Now().Unix(),
Issuer: "fake.issuer",
NotBefore: time.Now().Unix(),
Subject: ctx.AdminManagementSession.identityId,
Subject: *ctx.AdminManagementSession.AuthResponse.IdentityID,
}
jwtToken.Header["kid"] = invalidJwtSignerCertFingerprint
+15 -41
View File
@@ -1,3 +1,4 @@
//go:build apitests && perftests
// +build apitests,perftests
/*
@@ -19,13 +20,8 @@
package tests
import (
identity2 "github.com/openziti/identity"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/openziti/sdk-golang/ziti/edge/api"
"github.com/openziti/sdk-golang/ziti/sdkinfo"
"github.com/rcrowley/go-metrics"
"net/url"
"os"
"testing"
"time"
@@ -48,25 +44,14 @@ func Test_AuthPerformance(t *testing.T) {
identity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
config := ctx.AdminManagementSession.testContext.EnrollIdentity(identity.Id)
context := ziti.NewContextWithConfig(config)
_, _ = context.GetServices()
ctrlUrl, err := url.Parse(config.ZtAPI)
ctx.Req.NoError(err)
id, err := identity2.LoadIdentity(config.ID)
ctx.Req.NoError(err)
client, err := api.NewClient(ctrlUrl, id.ClientTLSConfig(), s("all"))
ctx.Req.NoError(err)
info := sdkinfo.GetSdkInfo()
_, err = client.Login(info)
context, err := ziti.NewContext(config)
ctx.Req.NoError(err)
for i := 0; i < 25; i++ {
go func() {
for {
start := time.Now()
_, err := client.Login(info)
err := context.Authenticate()
ctx.Req.NoError(err)
meter.Mark(1)
done := time.Now()
@@ -103,27 +88,21 @@ func Test_CombinedSessionCreatePerformance(t *testing.T) {
identity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
config := ctx.AdminManagementSession.testContext.EnrollIdentity(identity.Id)
context := ziti.NewContextWithConfig(config)
_, _ = context.GetServices()
ctrlUrl, err := url.Parse(config.ZtAPI)
ctx.Req.NoError(err)
id, err := identity2.LoadIdentity(config.ID)
ctx.Req.NoError(err)
client, err := api.NewClient(ctrlUrl, id.ClientTLSConfig(), s("all"))
context, err := ziti.NewContext(config)
ctx.Req.NoError(err)
info := sdkinfo.GetSdkInfo()
_, err = client.Login(info)
err = context.Authenticate()
ctx.Req.NoError(err)
client := context.(*ziti.ContextImpl).CtrlClt
service := ctx.AdminManagementSession.RequireNewServiceAccessibleToAll("smartrouting")
for i := 0; i < 25; i++ {
go func() {
for {
start := time.Now()
_, err := client.Login(info)
err := context.Authenticate()
ctx.Req.NoError(err)
apiSessionCreateMeter.Mark(1)
done := time.Now()
@@ -131,7 +110,8 @@ func Test_CombinedSessionCreatePerformance(t *testing.T) {
apiSessionCreateHistogram.Update(diff.Milliseconds())
start = time.Now()
_, err = client.CreateSession(service.Id, edge.SessionDial)
_, err = client.CreateSession(service.Id, ziti.SessionType(ziti.SessionDial))
ctx.Req.NoError(err)
sessionCreateMeter.Mark(1)
done = time.Now()
@@ -165,25 +145,19 @@ func Test_SessionCreatePerformance(t *testing.T) {
identity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
config := ctx.AdminManagementSession.testContext.EnrollIdentity(identity.Id)
context := ziti.NewContextWithConfig(config)
_, _ = context.GetServices()
ctrlUrl, err := url.Parse(config.ZtAPI)
ctx.Req.NoError(err)
id, err := identity2.LoadIdentity(config.ID)
ctx.Req.NoError(err)
client, err := api.NewClient(ctrlUrl, id.ClientTLSConfig(), s("all"))
context, err := ziti.NewContext(config)
ctx.Req.NoError(err)
info := sdkinfo.GetSdkInfo()
_, err = client.Login(info)
err = context.Authenticate()
ctx.Req.NoError(err)
client := context.(*ziti.ContextImpl).CtrlClt
for i := 0; i < 50; i++ {
go func() {
for {
start := time.Now()
_, err := client.CreateSession(service.Id, edge.SessionDial)
_, err := client.CreateSession(service.Id, ziti.SessionType(ziti.SessionDial))
ctx.Req.NoError(err)
meter.Mark(1)
done := time.Now()
+5
View File
@@ -1421,6 +1421,11 @@ func Test_AuthPolicies(t *testing.T) {
ctx.Req.NotEmpty(currentApiSessionEnv.Data.AuthQueries)
//API Session from auth ahs the auth query
ctx.Req.Equal("EXT-JWT", apiSession.AuthResponse.AuthQueries[0].TypeID)
ctx.Req.Equal(*extJwtSignerAllowed.ExternalAuthURL, apiSession.AuthResponse.AuthQueries[0].HTTPURL)
//API Session from get current has auth query
ctx.Req.Equal("EXT-JWT", currentApiSessionEnv.Data.AuthQueries[0].TypeID)
ctx.Req.Equal(*extJwtSignerAllowed.ExternalAuthURL, currentApiSessionEnv.Data.AuthQueries[0].HTTPURL)
+3 -3
View File
@@ -22,7 +22,7 @@ package tests
import (
"fmt"
"github.com/Jeffail/gabs"
"github.com/openziti/sdk-golang/ziti/constants"
"github.com/openziti/edge/controller/env"
"github.com/stretchr/testify/require"
"net/http"
"testing"
@@ -151,7 +151,7 @@ func (tests *authUpdbTests) testAuthenticateUPDBDefaultAdminSuccess(t *testing.T
standardJsonResponseTests(resp, http.StatusOK, t)
t.Run("returns a session token HTTP headers", func(t *testing.T) {
require.New(t).NotEmpty(resp.Header().Get(constants.ZitiSession), fmt.Sprintf("HTTP header %s is empty", constants.ZitiSession))
require.New(t).NotEmpty(resp.Header().Get(env.ZitiSession), fmt.Sprintf("HTTP header %s is empty", env.ZitiSession))
})
t.Run("returns a session token in body", func(t *testing.T) {
@@ -171,7 +171,7 @@ func (tests *authUpdbTests) testAuthenticateUPDBDefaultAdminSuccess(t *testing.T
r.NoError(err)
bodyToken := data.Path("data.token").Data().(string)
headerToken := resp.Header().Get(constants.ZitiSession)
headerToken := resp.Header().Get(env.ZitiSession)
r.Equal(bodyToken, headerToken)
})
+80 -72
View File
@@ -18,20 +18,25 @@ package tests
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"fmt"
"github.com/Jeffail/gabs"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/controller/env"
"github.com/openziti/edge/eid"
"github.com/openziti/edge/internal/cert"
"github.com/openziti/foundation/v2/stringz"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/constants"
"github.com/pkg/errors"
"gopkg.in/resty.v1"
"math/big"
"net/http"
"net/url"
"sort"
@@ -116,7 +121,14 @@ func (authenticator *certAuthenticator) Authenticate(ctx *TestContext, apiPath s
sess.client.SetHostURL(resolvedUrl)
apiSession := &rest_model.CurrentAPISessionDetail{}
envelope := &rest_model.CurrentAPISessionDetailEnvelope{
Data: apiSession,
Meta: &rest_model.Meta{},
}
resp, err := sess.client.R().
SetResult(envelope).
SetHeader("content-type", "application/json").
Post("authenticate?method=cert")
@@ -128,9 +140,8 @@ func (authenticator *certAuthenticator) Authenticate(ctx *TestContext, apiPath s
return nil, errors.Errorf("failed to authenticate via CERT: invalid response code encountered, got %d, expected %d: %s", resp.StatusCode(), http.StatusOK, string(resp.Body()))
}
if err = sess.parseSessionInfoFromResponse(ctx, resp); err != nil {
return nil, err
}
sess.AuthResponse = apiSession
sess.lastServiceUpdate = time.Time(*apiSession.CreatedAt)
return sess, nil
}
@@ -212,9 +223,17 @@ func (authenticator *updbAuthenticator) Authenticate(ctx *TestContext, apiPath s
_, _ = body.SetP(authenticator.ConfigTypes, "configTypes")
}
apiSession := &rest_model.CurrentAPISessionDetail{}
envelope := &rest_model.CurrentAPISessionDetailEnvelope{
Data: apiSession,
Meta: &rest_model.Meta{},
}
resp, err := sess.client.R().
SetHeader("content-type", "application/json").
SetBody(body.String()).
SetResult(envelope).
Post("authenticate?method=password")
if err != nil {
@@ -225,26 +244,21 @@ func (authenticator *updbAuthenticator) Authenticate(ctx *TestContext, apiPath s
return nil, errors.Errorf("failed to authenticate via UPDB as %v: invalid response code encountered, got %d, expected %d", authenticator, resp.StatusCode(), http.StatusOK)
}
if err = sess.parseSessionInfoFromResponse(ctx, resp); err != nil {
return nil, err
}
sess.AuthResponse = apiSession
sess.lastServiceUpdate = time.Time(*apiSession.CreatedAt)
return sess, nil
}
type session struct {
authenticator authenticator
id string
token string
identityId string
createdAt time.Time
lastServiceUpdate time.Time
configTypes []string
testContext *TestContext
baseUrl string
authenticator authenticator
testContext *TestContext
baseUrl string
authenticatedRequests
apiPath string
client *resty.Client
apiPath string
client *resty.Client
AuthResponse *rest_model.CurrentAPISessionDetail
lastServiceUpdate time.Time
}
// Clone allows a session to be cloned with a new internal Resty Client that targets another API. Useful for
@@ -253,15 +267,11 @@ type session struct {
func (sess *session) Clone(ctx *TestContext, apiPath string) (*session, error) {
clone := &session{
authenticator: sess.authenticator,
id: sess.id,
token: sess.token,
identityId: sess.identityId,
createdAt: sess.createdAt,
lastServiceUpdate: sess.lastServiceUpdate,
configTypes: sess.configTypes,
AuthResponse: sess.AuthResponse,
testContext: sess.testContext,
baseUrl: sess.baseUrl,
apiPath: apiPath,
lastServiceUpdate: sess.lastServiceUpdate,
client: resty.NewWithClient(sess.client.GetClient()),
}
@@ -294,8 +304,12 @@ func (sess *session) CloneToManagementApi(ctx *TestContext) (*session, error) {
}
func (sess *session) NewRequest() *resty.Request {
sess.client.R()
return sess.client.R().SetHeader(constants.ZitiSession, sess.token)
if sess.AuthResponse != nil && sess.AuthResponse.Token != nil {
return sess.client.R().SetHeader(env.ZitiSession, *sess.AuthResponse.Token)
}
return sess.client.R()
}
// resolveApiUrl takes a URL prefix, apiHost, in the format of "https://domain:port" and joins
@@ -318,50 +332,6 @@ func (sess *session) resolveApiUrl(apiHost string, apiPath string) (string, erro
return resolvedUrl.String(), nil
}
func (sess *session) parseSessionInfoFromResponse(ctx *TestContext, response *resty.Response) error {
respBody := response.Body()
if len(respBody) == 0 {
return errors.Errorf("failed to authenticate via UPDB %v: encountered zero length body", sess.authenticator)
}
ctx.logJson(respBody)
bodyContainer, err := gabs.ParseJSON(respBody)
if err != nil {
return errors.Errorf("failed to authenticate via UPDB as %v: failed to parse response: %s", sess.authenticator, err)
}
if sessionId, ok := bodyContainer.Path("data.id").Data().(string); ok {
sess.id = sessionId
} else {
return errors.Errorf("failed to authenticate via UPDB as %v: failed to find session id", sess.authenticator)
}
if sessionToken, ok := bodyContainer.Path("data.token").Data().(string); ok {
sess.token = sessionToken
} else {
return errors.Errorf("failed to authenticate via UPDB as %v: failed to find session token", sess.authenticator)
}
if identityId, ok := bodyContainer.Path("data.identity.id").Data().(string); ok {
sess.identityId = identityId
} else {
return errors.Errorf("failed to authenticate via UPDB as %v: failed to find identity id", sess.authenticator)
}
if createdAt, ok := bodyContainer.Path("data.createdAt").Data().(string); ok {
t, err := time.Parse(time.RFC3339, createdAt)
ctx.Req.NoError(err)
sess.createdAt = t
sess.lastServiceUpdate = t
}
sess.configTypes = ctx.toStringSlice(bodyContainer.Path("data.configTypes"))
return nil
}
func (sess *session) logout() error {
resp, err := sess.NewRequest().Delete("current-api-session")
@@ -370,7 +340,7 @@ func (sess *session) logout() error {
}
if resp.StatusCode() != http.StatusOK {
return errors.Errorf("could not delete current session %s for logout: got status code %d expected %d", sess.token, resp.StatusCode(), http.StatusOK)
return errors.Errorf("could not delete current session %s for logout: got status code %d expected %d", *sess.AuthResponse.Token, resp.StatusCode(), http.StatusOK)
}
return nil
@@ -394,7 +364,13 @@ func (request *authenticatedRequests) newAuthenticatedRequestWithBody(body inter
func (request *authenticatedRequests) RequireCreateSdkContext(roleAttributes ...string) (*identity, ziti.Context) {
identity := request.RequireNewIdentityWithOtt(false, roleAttributes...)
identity.config = request.testContext.EnrollIdentity(identity.Id)
context := ziti.NewContextWithConfig(identity.config)
context, err := ziti.NewContext(identity.config)
if err != nil {
pfxlog.Logger().Fatalf("could not create new context with config: %v", err)
}
return identity, context
}
@@ -1087,3 +1063,35 @@ func (request *authenticatedRequests) getIdentityJwt(identityId string) string {
data := request.testContext.RequireGetNonNilPathValue(jsonBody, "data", "enrollment", "ott", "jwt")
return data.Data().(string)
}
func newSelfSignedCert(commonName string) (*x509.Certificate, crypto.PrivateKey) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: commonName,
Organization: []string{"API Test Co"},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 180),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
der, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
panic(err)
}
cert, err := x509.ParseCertificate(der)
if err != nil {
panic(err)
}
return cert, priv
}
+4 -4
View File
@@ -112,7 +112,7 @@ func Test_Authenticators_AdminUsingAdminEndpoints(t *testing.T) {
session, err := authenticator.AuthenticateClientApi(ctx)
req.NoError(err)
req.NotEmpty(session.id)
req.NotNil(session.AuthResponse)
})
})
@@ -329,7 +329,7 @@ func Test_Authenticators_AdminUsingAdminEndpoints(t *testing.T) {
ctx.NoError(err)
ctx.NotNil(session)
ctx.NotEmpty(session.token)
ctx.NotEmpty(session.AuthResponse.Token)
})
})
@@ -371,7 +371,7 @@ func Test_Authenticators_AdminUsingAdminEndpoints(t *testing.T) {
ctx.NoError(err)
ctx.NotNil(session)
ctx.NotEmpty(session.token)
ctx.NotEmpty(session.AuthResponse.Token)
})
})
})
@@ -639,7 +639,7 @@ func Test_Authenticators_NonAdminUsingSelfServiceEndpoints(t *testing.T) {
id, ok := updbAuthenticatorListBody.Search("data").Index(0).Path("identityId").Data().(string)
req.True(ok)
req.Equal(updbNonAdminSession.identityId, id)
req.Equal(*updbNonAdminSession.AuthResponse.IdentityID, id)
})
t.Run("can get the detail of the authenticator", func(t *testing.T) {
+6 -6
View File
@@ -102,7 +102,7 @@ func Test_CA(t *testing.T) {
ctx.Req.NoError(err)
identity := ctx.AdminManagementSession.requireQuery("identities/" + enrolledSession.identityId)
identity := ctx.AdminManagementSession.requireQuery("identities/" + *enrolledSession.AuthResponse.IdentityID)
sort.Strings(ca.identityRoles)
ctx.pathEqualsStringSlice(identity, ca.identityRoles, path("data", "roleAttributes"))
})
@@ -139,7 +139,7 @@ func Test_CA(t *testing.T) {
ctx.Req.NoError(err)
identity := ctx.AdminManagementSession.requireQuery("identities/" + enrolledSession.identityId)
identity := ctx.AdminManagementSession.requireQuery("identities/" + *enrolledSession.AuthResponse.IdentityID)
ctx.Req.Equal(expectedName, identity.Path("data.name").Data().(string))
})
@@ -178,7 +178,7 @@ func Test_CA(t *testing.T) {
ctx.Req.NoError(err)
firstIdentity := ctx.AdminManagementSession.requireQuery("identities/" + firstEnrolledSession.identityId)
firstIdentity := ctx.AdminManagementSession.requireQuery("identities/" + *firstEnrolledSession.AuthResponse.IdentityID)
ctx.Req.Equal(firstExpectedName, firstIdentity.Path("data.name").Data().(string))
//second firstIdentity that collides, becomes
@@ -189,7 +189,7 @@ func Test_CA(t *testing.T) {
ctx.Req.NoError(err)
secondIdentity := ctx.AdminManagementSession.requireQuery("identities/" + secondEnrolledSession.identityId)
secondIdentity := ctx.AdminManagementSession.requireQuery("identities/" + *secondEnrolledSession.AuthResponse.IdentityID)
ctx.Req.Equal(secondExpectedName, secondIdentity.Path("data.name").Data().(string))
})
@@ -225,8 +225,8 @@ func Test_CA(t *testing.T) {
ctx.Req.NoError(err)
identity := ctx.AdminManagementSession.requireQuery("identities/" + enrolledSession.identityId)
expectedName := fmt.Sprintf("%s - %s - %s - %s - %s", ca.name, ca.id, clientAuthenticator.cert.Subject.CommonName, requestedName, enrolledSession.identityId)
identity := ctx.AdminManagementSession.requireQuery("identities/" + *enrolledSession.AuthResponse.IdentityID)
expectedName := fmt.Sprintf("%s - %s - %s - %s - %s", ca.name, ca.id, clientAuthenticator.cert.Subject.CommonName, requestedName, *enrolledSession.AuthResponse.IdentityID)
ctx.Req.Equal(expectedName, identity.Path("data.name").Data().(string))
})
+10 -9
View File
@@ -15,7 +15,6 @@ import (
nfpem "github.com/openziti/foundation/v2/pem"
id "github.com/openziti/identity"
"github.com/openziti/sdk-golang/ziti"
sdkconfig "github.com/openziti/sdk-golang/ziti/config"
"io"
"math/big"
"net/http"
@@ -30,6 +29,8 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
ctx.RequireAdminManagementApiLogin()
ctx.CreateEnrollAndStartEdgeRouter()
time.Sleep(2 * time.Second)
t.Run("setup", func(t *testing.T) {
ctx.testContextChanged(t)
@@ -261,7 +262,7 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
go func() {
//connect client 1
client1Config := &sdkconfig.Config{
client1Config := &ziti.Config{
ZtAPI: "https://" + ctx.ApiHost + EdgeClientApiPath,
ID: id.Config{
Key: id.StoragePem + ":" + string(clientKeyPem1),
@@ -273,7 +274,9 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
},
ConfigTypes: nil,
}
client1Context := ziti.NewContextWithConfig(client1Config)
client1Context, err := ziti.NewContext(client1Config)
ctx.Req.NoError(err)
err = client1Context.Authenticate()
ctx.Req.NoError(err)
@@ -282,8 +285,6 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
close(doneClient1)
}()
time.Sleep(1 * time.Second)
conn, err := client1Context.Dial(service.Name)
ctx.Req.NoError(err)
ctx.Req.NotNil(conn)
@@ -297,7 +298,7 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
go func() {
//connect client 2
client2Config := &sdkconfig.Config{
client2Config := &ziti.Config{
ZtAPI: "https://" + ctx.ApiHost + EdgeClientApiPath,
ID: id.Config{
Key: id.StoragePem + ":" + string(clientKeyPem2),
@@ -310,7 +311,9 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
ConfigTypes: nil,
}
client2Context := ziti.NewContextWithConfig(client2Config)
client2Context, err := ziti.NewContext(client2Config)
ctx.Req.NoError(err)
err = client2Context.Authenticate()
ctx.Req.NoError(err)
@@ -319,8 +322,6 @@ func Test_CA_Auth_Two_Identities_Diff_Certs(t *testing.T) {
close(doneClient2)
}()
time.Sleep(1 * time.Second)
conn, err := client2Context.Dial(service.Name)
ctx.Req.NoError(err)
ctx.Req.NotNil(conn)
+17 -13
View File
@@ -41,7 +41,7 @@ import (
nfPem "github.com/openziti/foundation/v2/pem"
"github.com/openziti/foundation/v2/versions"
"github.com/openziti/identity/certtools"
sdkConfig "github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
sdkEnroll "github.com/openziti/sdk-golang/ziti/enroll"
"github.com/pkg/errors"
@@ -88,6 +88,10 @@ func init() {
transport.AddAddressParser(tcp.AddressParser{})
}
func ToPtr[T any](in T) *T {
return &in
}
func S(s string) *string {
return &s
}
@@ -382,7 +386,7 @@ func (ctx *TestContext) requireEnrollEdgeRouter(tunneler bool, routerId string)
enroller := enroll.NewRestEnroller()
ctx.Req.NoError(enroller.LoadConfig(configMap))
var keyAlg sdkConfig.KeyAlgVar
var keyAlg ziti.KeyAlgVar
_ = keyAlg.Set("RSA")
ctx.Req.NoError(enroller.Enroll([]byte(jwt), true, "", keyAlg))
}
@@ -404,7 +408,7 @@ func (ctx *TestContext) createAndEnrollTransitRouter() *transitRouter {
enroller := enroll.NewRestEnroller()
ctx.Req.NoError(enroller.LoadConfig(configMap))
var keyAlg sdkConfig.KeyAlgVar
var keyAlg ziti.KeyAlgVar
_ = keyAlg.Set("RSA")
ctx.Req.NoError(enroller.Enroll([]byte(jwt), true, "", keyAlg))
@@ -464,7 +468,7 @@ func (ctx *TestContext) startEdgeRouter() {
ctx.Req.NoError(ctx.router.Start())
}
func (ctx *TestContext) EnrollIdentity(identityId string) *sdkConfig.Config {
func (ctx *TestContext) EnrollIdentity(identityId string) *ziti.Config {
jwt := ctx.AdminManagementSession.getIdentityJwt(identityId)
tkn, _, err := sdkEnroll.ParseToken(jwt)
ctx.Req.NoError(err)
@@ -840,28 +844,28 @@ func (ctx *TestContext) requireNListener(count int, l edge.Listener, timeout tim
}
}
func (ctx *TestContext) WrapNetConn(conn edge.Conn, err error) *testConn {
func (ctx *TestContext) WrapNetConn(conn edge.Conn, err error) *TestConn {
ctx.Req.NoError(err)
return &testConn{
return &TestConn{
Conn: conn,
ctx: ctx,
}
}
func (ctx *TestContext) WrapConn(conn edge.Conn, err error) *testConn {
func (ctx *TestContext) WrapConn(conn edge.Conn, err error) *TestConn {
ctx.Req.NoError(err)
return &testConn{
return &TestConn{
Conn: conn,
ctx: ctx,
}
}
type testConn struct {
type TestConn struct {
edge.Conn
ctx *TestContext
}
func (conn *testConn) WriteString(val string, timeout time.Duration) {
func (conn *TestConn) WriteString(val string, timeout time.Duration) {
conn.ctx.Req.NoError(conn.SetWriteDeadline(time.Now().Add(timeout)))
defer func() { _ = conn.SetWriteDeadline(time.Time{}) }()
@@ -871,7 +875,7 @@ func (conn *testConn) WriteString(val string, timeout time.Duration) {
conn.ctx.Req.Equal(n, len(buf))
}
func (conn *testConn) ReadString(maxSize int, timeout time.Duration) string {
func (conn *TestConn) ReadString(maxSize int, timeout time.Duration) string {
conn.ctx.Req.NoError(conn.SetReadDeadline(time.Now().Add(timeout)))
defer func() { _ = conn.SetReadDeadline(time.Time{}) }()
@@ -881,12 +885,12 @@ func (conn *testConn) ReadString(maxSize int, timeout time.Duration) string {
return string(buf[:n])
}
func (conn *testConn) ReadExpected(expected string, timeout time.Duration) {
func (conn *TestConn) ReadExpected(expected string, timeout time.Duration) {
val := conn.ReadString(len(expected)+1, timeout)
conn.ctx.Req.Equal(expected, val, "read failure on connId=%v", conn.Id())
}
func (conn *testConn) RequireClose() {
func (conn *TestConn) RequireClose() {
conn.ctx.Req.NoError(conn.Close())
}
+8 -7
View File
@@ -1,3 +1,4 @@
//go:build dataflow
// +build dataflow
/*
@@ -68,7 +69,7 @@ func Test_ServerConnClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
defer conn.Close()
@@ -133,7 +134,7 @@ func Test_ServerContextClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
defer conn.Close()
@@ -201,7 +202,7 @@ func Test_ServerCloseListenerPropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
defer conn.Close()
@@ -233,7 +234,7 @@ func Test_ClientConnClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
errC := make(chan error, 1)
@@ -295,7 +296,7 @@ func Test_ClientContextClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
errC := make(chan error, 1)
@@ -358,7 +359,7 @@ func Test_ServerConnCloseWritePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
errC := make(chan error, 1)
@@ -452,7 +453,7 @@ func Test_ClientConnCloseWritePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
name := eid.New()
+2 -2
View File
@@ -122,7 +122,7 @@ func testClientFirstWithStrategy(t *testing.T, strategy string) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
logger := pfxlog.Logger()
@@ -265,7 +265,7 @@ func testServerFirstWithStrategy(t *testing.T, strategy string) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
+2 -1
View File
@@ -1,3 +1,4 @@
//go:build dataflow
// +build dataflow
/*
@@ -75,7 +76,7 @@ func Test_HSDataflow(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
clientContext := ziti.NewContextWithConfig(clientConfig)
clientContext := ziti.NewContext(clientConfig)
for i := 0; i < 100; i++ {
conn := ctx.WrapConn(clientContext.Dial(service.Name))
+1 -1
View File
@@ -130,7 +130,7 @@ func Test_EnrollmetnCaAuto(t *testing.T) {
identityGet := &rest_model.DetailIdentityEnvelope{}
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().SetResult(identityGet).Get("/identities/" + apiSession.identityId)
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().SetResult(identityGet).Get("/identities/" + *apiSession.AuthResponse.IdentityID)
ctx.NoError(err)
ctx.Equal(http.StatusOK, resp.StatusCode())
ctx.NotNil(identityGet)
+3 -3
View File
@@ -29,10 +29,10 @@ import (
"encoding/pem"
"fmt"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/controller/env"
"github.com/openziti/edge/eid"
nfpem "github.com/openziti/foundation/v2/pem"
"github.com/openziti/identity/certtools"
"github.com/openziti/sdk-golang/ziti/constants"
"gopkg.in/resty.v1"
"net/http"
"testing"
@@ -216,7 +216,7 @@ func Test_EnrollmentIdentityExtend(t *testing.T) {
client := resty.New().SetTLSClientConfig(&tls.Config{
InsecureSkipVerify: true,
})
extendResp, err := client.R().SetHeader(constants.ZitiSession, identityApiSession.token).SetBody(csrRequest).Post(resolvedUrl)
extendResp, err := client.R().SetHeader(env.ZitiSession, *identityApiSession.AuthResponse.Token).SetBody(csrRequest).Post(resolvedUrl)
ctx.Req.NoError(err)
ctx.Req.Equal(401, extendResp.StatusCode())
})
@@ -261,7 +261,7 @@ func Test_EnrollmentIdentityExtend(t *testing.T) {
url := fmt.Sprintf("/current-identity/authenticators/%s/extend", *currentAuthenticator.ID)
//use second identity http client w/ first identity's API Session
extendResp, err := secondIdentityApiSession.NewRequest().SetHeader(constants.ZitiSession, identityApiSession.token).SetBody(csrRequest).Post(url)
extendResp, err := secondIdentityApiSession.NewRequest().SetHeader(env.ZitiSession, *identityApiSession.AuthResponse.Token).SetBody(csrRequest).Post(url)
ctx.Req.NoError(err)
ctx.Req.Equal(401, extendResp.StatusCode())
})
+1 -1
View File
@@ -117,7 +117,7 @@ func Test_EnrollmentUpdb(t *testing.T) {
updbApiSession, err := updbAuth.AuthenticateClientApi(ctx)
ctx.Req.NoError(err)
ctx.Req.NotEmpty(updbApiSession)
ctx.Req.NotEmpty(updbApiSession.token)
ctx.Req.NotEmpty(updbApiSession.AuthResponse.Token)
t.Run("authenticated updb api session can query current api session", func(t *testing.T) {
ctx.testContextChanged(t)
+2 -2
View File
@@ -26,7 +26,7 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"github.com/openziti/edge/eid"
"github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti"
"math/big"
"sort"
"time"
@@ -261,7 +261,7 @@ type identity struct {
defaultHostingCost int
serviceHostingPrecedences map[string]interface{}
serviceHostingCosts map[string]uint16
config *config.Config
config *ziti.Config
authPolicyId string
}
-39
View File
@@ -20,17 +20,10 @@
package tests
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"github.com/google/uuid"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/controller/persistence"
nfpem "github.com/openziti/foundation/v2/pem"
"math/big"
"net/http"
"testing"
"time"
@@ -724,35 +717,3 @@ func Test_ExternalJWTSigner(t *testing.T) {
})
})
}
func newSelfSignedCert(commonName string) (*x509.Certificate, crypto.PrivateKey) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: commonName,
Organization: []string{"API Test Co"},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 180),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
der, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
panic(err)
}
cert, err := x509.ParseCertificate(der)
if err != nil {
panic(err)
}
return cert, priv
}
+1 -1
View File
@@ -586,7 +586,7 @@ func Test_Identity(t *testing.T) {
apiSession, err := certAuthenticator.AuthenticateClientApi(ctx)
ctx.Req.NoError(err)
ctx.Req.NotNil(apiSession)
ctx.Req.NotEmpty(apiSession.token)
ctx.Req.NotEmpty(apiSession.AuthResponse.Token)
t.Run("identity can be disabled", func(t *testing.T) {
ctx.testContextChanged(t)
+8 -8
View File
@@ -461,7 +461,7 @@ func Test_MFA(t *testing.T) {
t.Run("api session should have posture data with MFA passed", func(t *testing.T) {
ctx.testContextChanged(t)
postureDataContainer := ctx.AdminManagementSession.requireQuery(fmt.Sprintf("/identities/%s/posture-data", mfaValidatedIdentityId))
mfaPath := fmt.Sprintf("data.apiSessionPostureData.%s.mfa.passedMfa", mfaValidatedSession.id)
mfaPath := fmt.Sprintf("data.apiSessionPostureData.%s.mfa.passedMfa", *mfaValidatedSession.AuthResponse.ID)
postureDataContainer.ExistsP(mfaPath)
isMfaPassed, ok := postureDataContainer.Path(mfaPath).Data().(bool)
ctx.Req.True(ok, "should be a bool")
@@ -687,8 +687,8 @@ func Test_MFA(t *testing.T) {
t.Run("api session should have posture data with MFA passed", func(t *testing.T) {
ctx.testContextChanged(t)
postureDataContainer := ctx.AdminManagementSession.requireQuery(fmt.Sprintf("/identities/%s/posture-data", newValidatedSession.identityId))
mfaPath := fmt.Sprintf("data.apiSessionPostureData.%s.mfa.passedMfa", newValidatedSession.id)
postureDataContainer := ctx.AdminManagementSession.requireQuery(fmt.Sprintf("/identities/%s/posture-data", *newValidatedSession.AuthResponse.IdentityID))
mfaPath := fmt.Sprintf("data.apiSessionPostureData.%s.mfa.passedMfa", *newValidatedSession.AuthResponse.ID)
postureDataContainer.ExistsP(mfaPath)
isMfaPassed, ok := postureDataContainer.Path(mfaPath).Data().(bool)
ctx.Req.True(ok, "should be a bool")
@@ -800,8 +800,8 @@ func Test_MFA(t *testing.T) {
t.Run("api session should have posture data with MFA passed", func(t *testing.T) {
ctx.testContextChanged(t)
postureDataContainer := ctx.AdminManagementSession.requireQuery(fmt.Sprintf("/identities/%s/posture-data", newValidatedSession.identityId))
mfaPath := fmt.Sprintf("data.apiSessionPostureData.%s.mfa.passedMfa", newValidatedSession.id)
postureDataContainer := ctx.AdminManagementSession.requireQuery(fmt.Sprintf("/identities/%s/posture-data", *newValidatedSession.AuthResponse.IdentityID))
mfaPath := fmt.Sprintf("data.apiSessionPostureData.%s.mfa.passedMfa", *newValidatedSession.AuthResponse.ID)
postureDataContainer.ExistsP(mfaPath)
isMfaPassed, ok := postureDataContainer.Path(mfaPath).Data().(bool)
ctx.Req.True(ok, "should be a bool")
@@ -1048,7 +1048,7 @@ func Test_MFA(t *testing.T) {
t.Run("with an empty code it should fail", func(s *testing.T) {
ctx.testContextChanged(t)
resp, err := mfa02DeleteSession.newAuthenticatedRequest().SetBody(newMfaCodeBody("")).Delete("/current-identity/mfa")
resp, err := mfa02DeleteSession.newAuthenticatedRequest().Delete("/current-identity/mfa")
ctx.Req.NoError(err)
standardErrorJsonResponseTests(resp, apierror.MfaInvalidTokenCode, http.StatusBadRequest, t)
@@ -1056,7 +1056,7 @@ func Test_MFA(t *testing.T) {
t.Run("with an invalid code it should fail", func(s *testing.T) {
ctx.testContextChanged(t)
resp, err := mfa02DeleteSession.newAuthenticatedRequest().SetBody(newMfaCodeBody("456456465")).Delete("/current-identity/mfa")
resp, err := mfa02DeleteSession.newAuthenticatedRequest().SetHeader("mfa-validation-code", "44444").Delete("/current-identity/mfa")
ctx.Req.NoError(err)
standardErrorJsonResponseTests(resp, apierror.MfaInvalidTokenCode, http.StatusBadRequest, t)
@@ -1067,7 +1067,7 @@ func Test_MFA(t *testing.T) {
code := computeMFACode(mfa02DeleteSecret)
resp, err := mfa02DeleteSession.newAuthenticatedRequest().SetBody(newMfaCodeBody(code)).Delete("/current-identity/mfa")
resp, err := mfa02DeleteSession.newAuthenticatedRequest().SetHeader("mfa-validation-code", code).Delete("/current-identity/mfa")
ctx.Req.NoError(err)
standardJsonResponseTests(resp, http.StatusOK, t)
+40 -25
View File
@@ -7,16 +7,18 @@ import (
"fmt"
"github.com/google/uuid"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/edge-api/rest_client_api_client/current_api_session"
service2 "github.com/openziti/edge-api/rest_client_api_client/service"
apiClientSession "github.com/openziti/edge-api/rest_client_api_client/session"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/controller/model"
"github.com/openziti/edge/controller/persistence"
"github.com/openziti/edge/eid"
"github.com/openziti/fabric/controller/models"
"github.com/openziti/foundation/v2/errorz"
idloader "github.com/openziti/identity"
"github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/openziti/sdk-golang/ziti/edge/api"
"github.com/openziti/sdk-golang/ziti/sdkinfo"
edge_apis "github.com/openziti/sdk-golang/edge-apis"
"github.com/openziti/sdk-golang/ziti"
"github.com/rcrowley/go-metrics"
"io"
"net/url"
@@ -141,7 +143,7 @@ type perfScenarioSpec struct {
identities []*model.Identity
edgeRouters []*model.EdgeRouter
config *config.Config
config *ziti.Config
}
func (spec *perfScenarioSpec) generateAllRoleAttributes() {
@@ -200,10 +202,10 @@ func (ctx *modelPerf) runScenario(spec *perfScenarioSpec) {
ctx.createScenario(spec)
stats := newPerfStats(ctx.TestContext, spec.config, spec.name, spec.services[0].Id, edge.SessionDial)
stats := newPerfStats(ctx.TestContext, spec.config, spec.name, spec.services[0].Id, rest_model.DialBindDial)
stats.collectStats(10)
stats = newPerfStats(ctx.TestContext, spec.config, spec.name, spec.services[0].Id, edge.SessionDial)
stats = newPerfStats(ctx.TestContext, spec.config, spec.name, spec.services[0].Id, rest_model.DialBindBind)
stats.collectStats(10)
ctx.Teardown()
@@ -428,22 +430,29 @@ func newHistogram() metrics.Histogram {
return metrics.NewHistogram(metrics.NewExpDecaySample(128, 0.015))
}
func newPerfStats(ctx *TestContext, config *config.Config, description string, serviceId string, sessionType edge.SessionType) *perfStats {
func newPerfStats(ctx *TestContext, config *ziti.Config, description string, serviceId string, sessionType rest_model.DialBind) *perfStats {
zitiUrl, err := url.Parse(config.ZtAPI)
ctx.Req.NoError(err)
id, err := idloader.LoadIdentity(config.ID)
ctx.Req.NoError(err)
client, err := api.NewClient(zitiUrl, id.ClientTLSConfig(), s("all"))
creds := edge_apis.NewIdentityCredentials(id)
creds.ConfigTypes = []string{"all"}
caPool, err := ziti.GetControllerWellKnownCaPool(config.ZtAPI)
ctx.Req.NoError(err)
client := edge_apis.NewClientApiClient(zitiUrl, caPool)
return &perfStats{
TestContext: ctx,
client: client,
description: description,
serviceId: serviceId,
sessionType: sessionType,
credentials: creds,
createApiSession: newHistogram(),
refreshApiSession: newHistogram(),
getServices: newHistogram(),
@@ -456,14 +465,15 @@ type perfStats struct {
*TestContext
description string
serviceId string
client api.RestClient
sessionType edge.SessionType
client *edge_apis.ClientApiClient
sessionType rest_model.DialBind
sessionId string
createApiSession metrics.Histogram
refreshApiSession metrics.Histogram
getServices metrics.Histogram
createSession metrics.Histogram
refreshSession metrics.Histogram
credentials *edge_apis.IdentityCredentials
}
func (s *perfStats) dumpStatsToStdOut() {
@@ -497,7 +507,6 @@ func (s *perfStats) collectStats(iterations int) {
s.repeat(iterations, s.timeRefreshApiSession)
s.repeat(iterations, s.timeGetServices)
s.repeat(iterations, s.timeCreateSession)
s.repeat(iterations, s.timeRefreshSession)
}
func (s *perfStats) repeat(n int, f func()) {
@@ -514,38 +523,44 @@ func (s *perfStats) time(h metrics.Histogram, f func()) {
func (s *perfStats) timeCreateApiSession() {
s.time(s.createApiSession, func() {
info := sdkinfo.GetSdkInfo()
_, err := s.client.Login(info)
_, err := s.client.Authenticate(s.credentials)
s.Req.NoError(err)
})
}
func (s *perfStats) timeRefreshApiSession() {
s.time(s.createApiSession, func() {
_, err := s.client.Refresh()
params := current_api_session.NewGetCurrentAPISessionParams()
_, err := s.client.API.CurrentAPISession.GetCurrentAPISession(params, nil)
s.Req.NoError(err)
})
}
func (s *perfStats) timeGetServices() {
s.time(s.getServices, func() {
_, err := s.client.GetServices()
params := service2.NewListServicesParams()
params.Limit = I(500)
_, err := s.client.API.Service.ListServices(params, nil)
s.Req.NoError(err)
})
}
func (s *perfStats) timeCreateSession() {
s.time(s.createSession, func() {
session, err := s.client.CreateSession(s.serviceId, s.sessionType)
s.Req.NoError(err)
s.sessionId = session.Id
})
}
//session, err := s.client.CreateSession(s.serviceId, s.sessionType)
func (s *perfStats) timeRefreshSession() {
s.time(s.createSession, func() {
_, err := s.client.RefreshSession(s.sessionId)
s.Req.NoError(err)
params := apiClientSession.NewCreateSessionParams()
params.Session = &rest_model.SessionCreate{}
params.Session.Type = s.sessionType
params.Session.ServiceID = s.serviceId
sessionDetail, err := s.client.API.Session.CreateSession(params, nil)
if err != nil {
s.Req.NoError(err)
}
s.sessionId = *sessionDetail.Payload.Data.ID
})
}
+3 -3
View File
@@ -144,7 +144,7 @@ func Test_PostureChecks_MFA(t *testing.T) {
t.Run("failed service request exist", func(t *testing.T) {
ctx.testContextChanged(t)
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().Get("/identities/" + enrolledIdentitySession.identityId + "/failed-service-requests")
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().Get("/identities/" + *enrolledIdentitySession.AuthResponse.IdentityID + "/failed-service-requests")
ctx.Req.NoError(err)
listEnvelop := rest_model.FailedServiceRequestEnvelope{}
@@ -284,7 +284,7 @@ func Test_PostureChecks_MFA(t *testing.T) {
t.Run("removing MFA while the service requires MFA", func(t *testing.T) {
ctx.testContextChanged(t)
resp, err := newSession.newAuthenticatedRequest().SetBody(newMfaCodeBody(computeMFACode(mfaSecret))).Delete("/current-identity/mfa")
resp, err := newSession.newAuthenticatedRequest().SetHeader("mfa-validation-code", computeMFACode(mfaSecret)).Delete("/current-identity/mfa")
ctx.Req.NoError(err)
ctx.Req.Equal(http.StatusOK, resp.StatusCode())
@@ -416,7 +416,7 @@ func Test_PostureChecks_MFA(t *testing.T) {
t.Run("failed service request exist", func(t *testing.T) {
ctx.testContextChanged(t)
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().Get("/identities/" + enrolledIdentitySession.identityId + "/failed-service-requests")
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().Get("/identities/" + *enrolledIdentitySession.AuthResponse.IdentityID + "/failed-service-requests")
ctx.Req.NoError(err)
listEnvelop := &rest_model.FailedServiceRequestEnvelope{}
+7 -7
View File
@@ -56,7 +56,7 @@ func Test_PostureChecks_Sessions(t *testing.T) {
listener, err := hostContext.Listen(service.Name)
ctx.Req.NoError(err)
defer listener.Close()
defer func() { _ = listener.Close() }()
testServer := newTestServer(listener, func(conn *testServerConn) error {
for {
@@ -79,14 +79,14 @@ func Test_PostureChecks_Sessions(t *testing.T) {
t.Run("a client sdk", func(t *testing.T) {
ctx.testContextChanged(t)
var clientContext *ziti.ContextImplTest
var clientContext *ziti.ContextImpl
t.Run("can be created", func(t *testing.T) {
ctx.testContextChanged(t)
_, ztx := ctx.AdminManagementSession.RequireCreateSdkContext(dialIdentityRole)
clientContext = &ziti.ContextImplTest{
Context: ztx,
}
var ok bool
clientContext, ok = ztx.(*ziti.ContextImpl)
ctx.Req.True(ok)
})
defer clientContext.Close()
@@ -99,7 +99,7 @@ func Test_PostureChecks_Sessions(t *testing.T) {
t.Run("can provide valid posture data and dial the service", func(t *testing.T) {
ctx.testContextChanged(t)
postureCache, err := clientContext.GetPostureCache()
postureCache := clientContext.CtrlClt.PostureCache
ctx.Req.NoError(err)
currentPostureDomain := dialDomain
@@ -108,7 +108,7 @@ func Test_PostureChecks_Sessions(t *testing.T) {
}
clientConn := ctx.WrapConn(clientContext.Dial(service.Name))
defer clientConn.Close()
defer func() { _ = clientConn.Close() }()
t.Run("the dialed service can be sent data", func(t *testing.T) {
ctx.testContextChanged(t)
+278
View File
@@ -0,0 +1,278 @@
package tests
import (
"crypto/x509"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
"github.com/openziti/edge-api/rest_management_api_client/auth_policy"
"github.com/openziti/edge-api/rest_management_api_client/external_jwt_signer"
identity2 "github.com/openziti/edge-api/rest_management_api_client/identity"
"github.com/openziti/edge-api/rest_model"
nfpem "github.com/openziti/foundation/v2/pem"
edge_apis "github.com/openziti/sdk-golang/edge-apis"
"net/url"
"testing"
"time"
)
func TestSdkAuth(t *testing.T) {
ctx := NewTestContext(t)
defer ctx.Teardown()
ctx.StartServer()
ctx.RequireAdminManagementApiLogin()
testId := ctx.AdminManagementSession.RequireNewIdentityWithOtt(true)
testIdCerts := ctx.completeOttEnrollment(testId.Id)
clientApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeClientApiPath)
ctx.Req.NoError(err)
managementApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeManagementApiPath)
ctx.Req.NoError(err)
adminCreds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password)
adminClient := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA())
apiSession, err := adminClient.Authenticate(adminCreds)
t.Run("management updb", func(t *testing.T) {
ctx.testContextChanged(t)
ctx.Req.NoError(err)
ctx.Req.NotNil(adminClient)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("client updb, ca pool on client", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password)
client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA())
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("client updb, ca pool on cert", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password)
creds.CaPool = ctx.ControllerConfig.Id.CA()
client := edge_apis.NewClientApiClient(clientApiUrl, nil)
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("management cert, ca pool on client", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key)
client := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA())
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("management cert, ca pool on cert", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key)
creds.CaPool = ctx.ControllerConfig.Id.CA()
client := edge_apis.NewManagementApiClient(managementApiUrl, nil)
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("client cert, ca pool on client", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key)
client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA())
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("client cert, ca pool on creds", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key)
creds.CaPool = ctx.ControllerConfig.Id.CA()
client := edge_apis.NewClientApiClient(clientApiUrl, nil)
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("ext jwt signer", func(t *testing.T) {
ctx.testContextChanged(t)
//valid signer with issuer and audience
validJwtSignerCert, validJwtSignerPrivateKey := newSelfSignedCert("valid signer")
validJwtSignerCertPem := nfpem.EncodeToString(validJwtSignerCert)
validJwtSigner := &rest_model.ExternalJWTSignerCreate{
CertPem: &validJwtSignerCertPem,
Enabled: B(true),
Name: S("Test JWT Signer - Enabled"),
Kid: S(uuid.NewString()),
Issuer: S("the-very-best-iss"),
Audience: S("the-very-best-aud"),
UseExternalID: B(true),
}
//valid signed jwt
subjectId := uuid.NewString()
jwtToken := jwt.New(jwt.SigningMethodES256)
jwtToken.Claims = jwt.StandardClaims{
Audience: *validJwtSigner.Audience,
ExpiresAt: time.Now().Add(2 * time.Hour).Unix(),
Id: time.Now().String(),
IssuedAt: time.Now().Unix(),
Issuer: *validJwtSigner.Issuer,
NotBefore: time.Now().Unix(),
Subject: subjectId,
}
jwtToken.Header["kid"] = *validJwtSigner.Kid
jwtStrSigned, err := jwtToken.SignedString(validJwtSignerPrivateKey)
ctx.Req.NoError(err)
ctx.Req.NotEmpty(jwtStrSigned)
// ext jwt
createExtJwtParams := external_jwt_signer.NewCreateExternalJWTSignerParams()
createExtJwtParams.ExternalJWTSigner = validJwtSigner
createExtJwtSignerResp, err := adminClient.API.ExternalJWTSigner.CreateExternalJWTSigner(createExtJwtParams, nil)
ctx.Req.NoError(err)
ctx.Req.NotNil(createExtJwtSignerResp)
ctx.Req.NotEmpty(createExtJwtSignerResp.Payload.Data.ID)
//auth policy
authPolicyCreate := &rest_model.AuthPolicyCreate{
Name: S(uuid.NewString()),
Primary: &rest_model.AuthPolicyPrimary{
Cert: &rest_model.AuthPolicyPrimaryCert{Allowed: B(false), AllowExpiredCerts: B(false)},
ExtJWT: &rest_model.AuthPolicyPrimaryExtJWT{Allowed: B(true), AllowedSigners: []string{createExtJwtSignerResp.Payload.Data.ID}},
Updb: &rest_model.AuthPolicyPrimaryUpdb{
Allowed: B(false),
LockoutDurationMinutes: I(0),
MaxAttempts: I(0),
MinPasswordLength: I(5),
RequireMixedCase: B(true),
RequireNumberChar: B(true),
RequireSpecialChar: B(true),
},
},
Secondary: &rest_model.AuthPolicySecondary{
RequireExtJWTSigner: nil,
RequireTotp: B(false),
},
Tags: &rest_model.Tags{SubTags: rest_model.SubTags{}},
}
authPolicyCreateParams := auth_policy.NewCreateAuthPolicyParams()
authPolicyCreateParams.AuthPolicy = authPolicyCreate
createAuthPolicyResp, err := adminClient.API.AuthPolicy.CreateAuthPolicy(authPolicyCreateParams, nil)
ctx.Req.NoError(err)
ctx.Req.NotNil(createAuthPolicyResp)
ctx.Req.NotEmpty(createAuthPolicyResp.Payload.Data.ID)
//identity
identityType := rest_model.IdentityTypeUser
idCreate := &rest_model.IdentityCreate{
AuthPolicyID: S(createAuthPolicyResp.Payload.Data.ID),
ExternalID: S(subjectId),
IsAdmin: B(false),
Name: S(uuid.NewString()),
Type: &identityType,
}
identityCreateParams := identity2.NewCreateIdentityParams()
identityCreateParams.Identity = idCreate
idCreateResp, err := adminClient.API.Identity.CreateIdentity(identityCreateParams, nil)
ctx.Req.NoError(err)
ctx.Req.NotNil(idCreateResp)
ctx.Req.NotEmpty(idCreateResp.Payload.Data.ID)
t.Run("client jwt, ca pool on client", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewJwtCredentials(jwtStrSigned)
client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA())
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("client jwt, ca pool on creds", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewJwtCredentials(jwtStrSigned)
creds.CaPool = ctx.ControllerConfig.Id.CA()
client := edge_apis.NewClientApiClient(clientApiUrl, nil)
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("management jwt, ca pool on client", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewJwtCredentials(jwtStrSigned)
client := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA())
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
t.Run("management jwt, ca pool on creds", func(t *testing.T) {
ctx.testContextChanged(t)
creds := edge_apis.NewJwtCredentials(jwtStrSigned)
creds.CaPool = ctx.ControllerConfig.Id.CA()
client := edge_apis.NewManagementApiClient(managementApiUrl, nil)
apiSession, err := client.Authenticate(creds)
ctx.Req.NoError(err)
ctx.Req.NotNil(client)
ctx.Req.NotNil(apiSession)
ctx.Req.NotNil(apiSession.Token)
})
})
}
+1 -1
View File
@@ -16,7 +16,7 @@ func setupServiceListRefreshTest(ctx *TestContext) (string, *identity, *session)
ctx.Req.NoError(err)
lastUpdate := nonAdminUserSession.getServiceUpdateTime()
ctx.Req.Equal(nonAdminUserSession.createdAt, lastUpdate)
ctx.Req.Equal(time.Time(*nonAdminUserSession.AuthResponse.CreatedAt), lastUpdate)
nonAdminUserSession.requireServiceUpdateTimeUnchanged()
+8 -8
View File
@@ -268,14 +268,14 @@ func Test_ServiceListWithConfigs(t *testing.T) {
}
configs1 := []serviceConfig{{ServiceId: service4.Id, ConfigId: config1.Id}, {ServiceId: service4.Id, ConfigId: config5.Id}}
ctx.AdminManagementSession.requireAssignIdentityServiceConfigs(session.identityId, configs1...)
ctx.AdminManagementSession.requireAssignIdentityServiceConfigs(*session.AuthResponse.IdentityID, configs1...)
configs1 = []serviceConfig{{ServiceId: service4.Id, ConfigId: config1.Id}, {ServiceId: service4.Id, ConfigId: config5.Id}}
sort.Sort(sortableServiceConfigSlice(configs1))
currentConfigs := ctx.AdminManagementSession.listIdentityServiceConfigs(session.identityId)
currentConfigs := ctx.AdminManagementSession.listIdentityServiceConfigs(*session.AuthResponse.IdentityID)
ctx.Req.Equal(configs1, currentConfigs)
configs2 := []serviceConfig{{ServiceId: service1.Id, ConfigId: config5.Id}, {ServiceId: service3.Id, ConfigId: config1.Id}, {ServiceId: service3.Id, ConfigId: config4.Id}}
ctx.AdminManagementSession.requireAssignIdentityServiceConfigs(session.identityId, configs2...)
ctx.AdminManagementSession.requireAssignIdentityServiceConfigs(*session.AuthResponse.IdentityID, configs2...)
checkConfigs := []serviceConfig{
{ServiceId: service4.Id, ConfigId: config1.Id},
{ServiceId: service4.Id, ConfigId: config5.Id},
@@ -284,7 +284,7 @@ func Test_ServiceListWithConfigs(t *testing.T) {
{ServiceId: service3.Id, ConfigId: config4.Id},
}
sort.Sort(sortableServiceConfigSlice(checkConfigs))
currentConfigs = ctx.AdminManagementSession.listIdentityServiceConfigs(session.identityId)
currentConfigs = ctx.AdminManagementSession.listIdentityServiceConfigs(*session.AuthResponse.IdentityID)
ctx.Req.Equal(checkConfigs, currentConfigs)
service1V.configs[configType3.Name] = config5
@@ -297,8 +297,8 @@ func Test_ServiceListWithConfigs(t *testing.T) {
service.configs = map[string]*Config{}
}
ctx.AdminManagementSession.requireRemoveIdentityServiceConfigs(session.identityId, serviceConfig{ServiceId: service1.Id, ConfigId: config5.Id}, serviceConfig{ServiceId: service3.Id, ConfigId: config1.Id})
currentConfigs = ctx.AdminManagementSession.listIdentityServiceConfigs(session.identityId)
ctx.AdminManagementSession.requireRemoveIdentityServiceConfigs(*session.AuthResponse.IdentityID, serviceConfig{ServiceId: service1.Id, ConfigId: config5.Id}, serviceConfig{ServiceId: service3.Id, ConfigId: config1.Id})
currentConfigs = ctx.AdminManagementSession.listIdentityServiceConfigs(*session.AuthResponse.IdentityID)
checkConfigs = []serviceConfig{
{ServiceId: service4.Id, ConfigId: config1.Id},
{ServiceId: service4.Id, ConfigId: config5.Id},
@@ -317,8 +317,8 @@ func Test_ServiceListWithConfigs(t *testing.T) {
service.configs = map[string]*Config{}
}
ctx.AdminManagementSession.requireRemoveIdentityServiceConfigs(session.identityId)
currentConfigs = ctx.AdminManagementSession.listIdentityServiceConfigs(session.identityId)
ctx.AdminManagementSession.requireRemoveIdentityServiceConfigs(*session.AuthResponse.IdentityID)
currentConfigs = ctx.AdminManagementSession.listIdentityServiceConfigs(*session.AuthResponse.IdentityID)
ctx.Req.Equal(0, len(currentConfigs))
service2V.configs[configType1.Name] = config1
+21 -3
View File
@@ -3,11 +3,12 @@ package entities
import (
"fmt"
"github.com/michaelquigley/pfxlog"
"github.com/mitchellh/mapstructure"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/health"
"github.com/openziti/edge/tunnel"
"github.com/openziti/edge/tunnel/utils"
"github.com/openziti/foundation/v2/stringz"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/pkg/errors"
"net"
"reflect"
@@ -358,7 +359,7 @@ type TemplateFunc func(sourceAddr net.Addr, destAddr net.Addr) string
type Service struct {
FabricProvider tunnel.FabricProvider
edge.Service
rest_model.ServiceDetail
InterceptV1Config *InterceptV1Config
DialTimeout time.Duration
@@ -369,6 +370,23 @@ type Service struct {
lock sync.Mutex
}
func (self *Service) GetConfigOfType(configType string, target interface{}) (bool, error) {
if self.Configs == nil {
pfxlog.Logger().Debugf("no service configs defined for service %v", self.Name)
return false, nil
}
configMap, found := self.Config[configType]
if !found {
pfxlog.Logger().Debugf("no service config of type %v defined for service %v", configType, self.Name)
return false, nil
}
if err := mapstructure.Decode(configMap, target); err != nil {
pfxlog.Logger().WithError(err).Debugf("unable to decode service configuration for of type %v defined for service %v", configType, self.Name)
return true, fmt.Errorf("unable to decode service config structure: %w", err)
}
return true, nil
}
func (self *Service) GetFabricProvider() tunnel.FabricProvider {
return self.FabricProvider
}
@@ -398,7 +416,7 @@ func (self *Service) GetSourceAddr(sourceAddr net.Addr, destAddr net.Addr) strin
}
func (self *Service) GetName() string {
return self.Name
return *self.ServiceDetail.Name
}
func (self *Service) GetDialTimeout() time.Duration {
+12 -16
View File
@@ -18,13 +18,13 @@ package intercept
import (
"github.com/michaelquigley/pfxlog"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/health"
"github.com/openziti/edge/tunnel"
"github.com/openziti/edge/tunnel/entities"
"github.com/openziti/edge/tunnel/router"
"github.com/openziti/edge/tunnel/utils"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/pkg/errors"
"net"
"strconv"
@@ -37,7 +37,7 @@ type healthChecksProvider interface {
GetHttpChecks() []*health.HttpCheckDefinition
}
func createHostingContexts(service *entities.Service, identity *edge.CurrentIdentity, tracker AddressTracker) []tunnel.HostingContext {
func createHostingContexts(service *entities.Service, identity *rest_model.IdentityDetail, tracker AddressTracker) []tunnel.HostingContext {
var result []tunnel.HostingContext
for _, t := range service.HostV2Config.Terminators {
context := newDefaultHostingContext(identity, service, t, tracker)
@@ -52,7 +52,7 @@ func createHostingContexts(service *entities.Service, identity *edge.CurrentIden
return result
}
func newDefaultHostingContext(identity *edge.CurrentIdentity, service *entities.Service, config *entities.HostV2Terminator, tracker AddressTracker) *hostingContext {
func newDefaultHostingContext(identity *rest_model.IdentityDetail, service *entities.Service, config *entities.HostV2Terminator, tracker AddressTracker) *hostingContext {
log := pfxlog.Logger().WithField("service", service.Name)
if config.ForwardProtocol && len(config.AllowedProtocols) < 1 {
@@ -111,7 +111,7 @@ type hostingContext struct {
}
func (self *hostingContext) ServiceName() string {
return self.service.Name
return *self.service.Name
}
func (self *hostingContext) ListenOptions() *ziti.ListenOptions {
@@ -229,11 +229,11 @@ func (self *hostingContext) Dial(options map[string]interface{}) (net.Conn, bool
return self.dialAddress(options, protocol, address+":"+port)
}
func getDefaultOptions(service *entities.Service, identity *edge.CurrentIdentity, config *entities.HostV2Terminator) (*ziti.ListenOptions, error) {
func getDefaultOptions(service *entities.Service, identity *rest_model.IdentityDetail, config *entities.HostV2Terminator) (*ziti.ListenOptions, error) {
options := ziti.DefaultListenOptions()
options.ManualStart = true
options.Precedence = ziti.GetPrecedenceForLabel(identity.DefaultHostingPrecedence)
options.Cost = identity.DefaultHostingCost
options.Precedence = ziti.GetPrecedenceForLabel(string(identity.DefaultHostingPrecedence))
options.Cost = uint16(*identity.DefaultHostingCost)
if config.ListenOptions != nil {
if config.ListenOptions.Cost != nil {
@@ -244,21 +244,17 @@ func getDefaultOptions(service *entities.Service, identity *edge.CurrentIdentity
}
}
if val, ok := identity.ServiceHostingPrecedences[service.Id]; ok {
if strVal, ok := val.(string); ok {
options.Precedence = ziti.GetPrecedenceForLabel(strVal)
}
if val, ok := identity.ServiceHostingPrecedences[*service.ID]; ok {
options.Precedence = ziti.GetPrecedenceForLabel(string(val))
}
if val, ok := identity.ServiceHostingCosts[service.Id]; ok {
if floatVal, ok := val.(float64); ok {
options.Cost = uint16(floatVal)
}
if val, ok := identity.ServiceHostingCosts[*service.ID]; ok {
options.Cost = uint16(*val)
}
if config.ListenOptions != nil {
if config.ListenOptions.BindUsingEdgeIdentity {
options.Identity = identity.Name
options.Identity = *identity.Name
} else if config.ListenOptions.Identity != "" {
result, err := replaceTemplatized(config.ListenOptions.Identity, identity)
if err != nil {
+2 -2
View File
@@ -106,7 +106,7 @@ func New(ip net.IP, serviceList []string) (intercept.Interceptor, error) {
func (p *interceptor) Intercept(service *entities.Service, _ dns.Resolver, _ intercept.AddressTracker) error {
log := pfxlog.Logger().WithField("service", service.Name)
proxiedService, ok := p.services[service.Name]
proxiedService, ok := p.services[*service.Name]
if !ok {
log.Debugf("service %v was not specified at initialization. not intercepting", service.Name)
return nil
@@ -115,7 +115,7 @@ func (p *interceptor) Intercept(service *entities.Service, _ dns.Resolver, _ int
proxiedService.TunnelService = service
// pre-fetch network session todo move this to service poller?
service.FabricProvider.PrepForUse(service.Id)
service.FabricProvider.PrepForUse(*service.ID)
go p.runServiceListener(proxiedService)
return nil
+22 -9
View File
@@ -1,9 +1,11 @@
package intercept
import (
"github.com/google/uuid"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/tunnel"
"github.com/openziti/edge/tunnel/entities"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/openziti/foundation/v2/util"
"github.com/stretchr/testify/require"
"net"
"testing"
@@ -15,13 +17,17 @@ type testProvider struct {
func (self *testProvider) PrepForUse(serviceId string) {
}
func (self *testProvider) GetCurrentIdentity() (*edge.CurrentIdentity, error) {
return &edge.CurrentIdentity{
Name: "foo.bar",
AppData: map[string]interface{}{
"srcip": "123.456.789.10:5555",
"sourceIp": "15.14.13.12",
"sourcePort": 1999,
func (self *testProvider) GetCurrentIdentity() (*rest_model.IdentityDetail, error) {
cost := rest_model.TerminatorCost(0)
return &rest_model.IdentityDetail{
Name: util.Ptr("foo.bar"),
DefaultHostingCost: &cost,
AppData: &rest_model.Tags{
SubTags: map[string]interface{}{
"srcip": "123.456.789.10:5555",
"sourceIp": "15.14.13.12",
"sourcePort": 1999,
},
},
}, nil
}
@@ -69,7 +75,14 @@ func Test_SourceIp(t *testing.T) {
}
func Test_TemplateIdentity(t *testing.T) {
svc := &entities.Service{}
serviceId := uuid.NewString()
svc := &entities.Service{
ServiceDetail: rest_model.ServiceDetail{
BaseEntity: rest_model.BaseEntity{
ID: &serviceId,
},
},
}
hostTerminator := &entities.HostV2Terminator{ListenOptions: &entities.HostV2ListenOptions{}}
provider := &testProvider{}
currentIdentity, err := provider.GetCurrentIdentity()
+30 -24
View File
@@ -19,13 +19,13 @@ package intercept
import (
"fmt"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/health"
"github.com/openziti/edge/tunnel"
"github.com/openziti/edge/tunnel/dns"
"github.com/openziti/edge/tunnel/entities"
"github.com/openziti/foundation/v2/stringz"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/pkg/errors"
logrus "github.com/sirupsen/logrus"
"net"
@@ -139,16 +139,16 @@ func (self *ServiceListener) HandleProviderReady(provider tunnel.FabricProvider)
self.provider = provider
}
func (self *ServiceListener) HandleServicesChange(eventType ziti.ServiceEventType, service *edge.Service) {
func (self *ServiceListener) HandleServicesChange(eventType ziti.ServiceEventType, service *rest_model.ServiceDetail) {
self.Lock()
defer self.Unlock()
tunnelerService := &entities.Service{
FabricProvider: self.provider,
Service: *service,
ServiceDetail: *service,
}
log := logrus.WithField("service", service.Name)
log := logrus.WithField("service", *service.Name)
switch eventType {
case ziti.ServiceAdded:
@@ -169,11 +169,17 @@ func (self *ServiceListener) HandleServicesChange(eventType ziti.ServiceEventTyp
}
func (self *ServiceListener) addService(svc *entities.Service) {
log := pfxlog.Logger().WithField("serviceId", svc.Id).WithField("serviceName", svc.Name)
log := pfxlog.Logger().WithField("serviceId", *svc.ID).WithField("serviceName", *svc.Name)
svc.DialTimeout = 5 * time.Second
if stringz.Contains(svc.Permissions, "Dial") {
var perms []string
for _, perm := range svc.Permissions {
perms = append(perms, string(perm))
}
if stringz.Contains(perms, "Dial") {
interceptV1Config := &entities.InterceptV1Config{}
found, err := svc.GetConfigOfType(entities.InterceptV1, interceptV1Config)
if found {
@@ -184,7 +190,7 @@ func (self *ServiceListener) addService(svc *entities.Service) {
}
if err != nil {
logrus.WithError(err).Errorf("error decoding service config of type %v for service %v", entities.InterceptV1, svc.Name)
logrus.WithError(err).Errorf("error decoding service config of type %v for service %v", entities.InterceptV1, *svc.Name)
}
if !found {
@@ -196,7 +202,7 @@ func (self *ServiceListener) addService(svc *entities.Service) {
}
if err != nil {
logrus.WithError(err).Errorf("error decoding service config of type %v for service %v", entities.ClientConfigV1, svc.Name)
logrus.WithError(err).Errorf("error decoding service config of type %v for service %v", entities.ClientConfigV1, *svc.Name)
}
}
@@ -208,13 +214,13 @@ func (self *ServiceListener) addService(svc *entities.Service) {
}
// not all interceptors need a config, specifically proxy doesn't need one
log.Infof("starting tunnel for newly available service %s", svc.Name)
log.Infof("starting tunnel for newly available service %s", *svc.Name)
if err := self.interceptor.Intercept(svc, self.resolver, self.addrTracker); err != nil {
log.Errorf("failed to intercept service: %v", err)
}
}
if stringz.Contains(svc.Permissions, "Bind") {
if stringz.Contains(perms, "Bind") {
configType := entities.HostConfigV2
hostV2config := &entities.HostV2Config{}
found, err := svc.GetConfigOfType(configType, hostV2config)
@@ -250,31 +256,31 @@ func (self *ServiceListener) addService(svc *entities.Service) {
}
if svc.InterceptV1Config != nil || svc.HostV2Config != nil {
self.services[svc.Id] = svc
self.services[*svc.ID] = svc
}
}
func (self *ServiceListener) removeService(svc *entities.Service) {
log := pfxlog.Logger()
previousService := self.services[svc.Id]
previousService := self.services[*svc.ID]
if previousService != nil {
if previousService.InterceptV1Config != nil {
log.Infof("stopping tunnel for unavailable service: %s", previousService.Name)
err := self.interceptor.StopIntercepting(previousService.Name, self.addrTracker)
log.Infof("stopping tunnel for unavailable service: %s", *previousService.Name)
err := self.interceptor.StopIntercepting(*previousService.Name, self.addrTracker)
if err != nil {
log.WithError(err).Errorf("failed to stop intercepting service: %v", previousService.Name)
log.WithError(err).Errorf("failed to stop intercepting service: %v", *previousService.Name)
}
}
previousService.RunCleanupActions()
delete(self.services, svc.Id)
delete(self.services, *svc.ID)
}
}
func (self *ServiceListener) host(svc *entities.Service, tracker AddressTracker) {
logger := pfxlog.Logger().WithField("service", svc.Name)
logger := pfxlog.Logger().WithField("service", *svc.Name)
currentIdentity, err := self.provider.GetCurrentIdentity()
if err != nil {
@@ -290,27 +296,27 @@ func (self *ServiceListener) host(svc *entities.Service, tracker AddressTracker)
for _, hostControl := range hostControls {
_ = hostControl.Close()
}
self.healthCheckMgr.UnregisterServiceChecks(svc.Id)
self.healthCheckMgr.UnregisterServiceChecks(*svc.ID)
}
svc.AddCleanupAction(stopHook)
for idx, hostContext := range hostContexts {
hostControl, err := self.provider.HostService(hostContext)
if err != nil {
logger.WithError(err).WithField("service", svc.Name).Errorf("error listening for service")
logger.WithError(err).WithField("service", *svc.Name).Errorf("error listening for service")
return
}
context := strconv.Itoa(idx)
hostContext.SetCloseCallback(func() {
self.healthCheckMgr.UnregisterServiceContextChecks(svc.Name, context)
self.healthCheckMgr.UnregisterServiceContextChecks(*svc.Name, context)
})
hostControls = append(hostControls, hostControl)
precedence, cost := hostContext.GetInitialHealthState()
serviceState := health.NewServiceStateWithContext(svc.Name, context, precedence, cost, hostControl)
serviceState := health.NewServiceStateWithContext(*svc.Name, context, precedence, cost, hostControl)
if err := self.healthCheckMgr.RegisterServiceChecks(serviceState, hostContext.GetHealthChecks()); err != nil {
logger.WithError(err).Error("error setting up health checks")
@@ -369,8 +375,8 @@ func (self *ServiceListener) getTemplatingProvider(template string) (entities.Te
}, nil
}
func replaceTemplatized(input string, currentIdentity *edge.CurrentIdentity) (string, error) {
input = strings.ReplaceAll(input, "$tunneler_id.name", currentIdentity.Name)
func replaceTemplatized(input string, currentIdentity *rest_model.IdentityDetail) (string, error) {
input = strings.ReplaceAll(input, "$tunneler_id.name", *currentIdentity.Name)
start := "$tunneler_id.appData["
for {
index := strings.Index(input, start)
@@ -387,7 +393,7 @@ func replaceTemplatized(input string, currentIdentity *edge.CurrentIdentity) (st
tagValue := ""
logrus.Infof("appData: %v", currentIdentity.AppData)
if currentIdentity.AppData != nil {
val, found := currentIdentity.AppData[tagName]
val, found := currentIdentity.AppData.SubTags[tagName]
if found {
tagValue = fmt.Sprintf("%v", val)
}
+23 -23
View File
@@ -30,7 +30,7 @@ import (
"github.com/openziti/foundation/v2/info"
"github.com/openziti/foundation/v2/mempool"
"github.com/openziti/foundation/v2/stringz"
"github.com/openziti/sdk-golang/ziti/edge/impl"
"github.com/openziti/sdk-golang/ziti/edge/network"
cmap "github.com/orcaman/concurrent-map/v2"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -147,7 +147,7 @@ func (self *interceptor) Intercept(service *entities.Service, resolver dns.Resol
if err != nil {
return err
}
self.serviceProxies.Set(service.Name, tproxy)
self.serviceProxies.Set(*service.Name, tproxy)
return nil
}
@@ -182,13 +182,13 @@ func (self *interceptor) newTproxy(service *entities.Service, resolver dns.Resol
config := service.InterceptV1Config
if config == nil {
return nil, errors.Errorf("service %v has no intercept information", service.Name)
return nil, errors.Errorf("service %v has no intercept information", *service.Name)
}
if stringz.Contains(config.Protocols, "tcp") {
tcpLn, err := listenConfig.Listen(context.Background(), "tcp", "127.0.0.1:")
if err != nil {
return nil, errors.Wrapf(err, "failed to create TCP listener for service: %v", service.Name)
return nil, errors.Wrapf(err, "failed to create TCP listener for service: %v", *service.Name)
}
logrus.Infof("tproxy listening on tcp:%s", tcpLn.Addr().String())
t.tcpLn = tcpLn
@@ -197,7 +197,7 @@ func (self *interceptor) newTproxy(service *entities.Service, resolver dns.Resol
if stringz.Contains(config.Protocols, "udp") {
packetLn, err := listenConfig.ListenPacket(context.Background(), "udp", "127.0.0.1:")
if err != nil {
return nil, errors.Wrapf(err, "failed to create UDP listener for service: %v", service.Name)
return nil, errors.Wrapf(err, "failed to create UDP listener for service: %v", *service.Name)
}
udpLn, ok := packetLn.(*net.UDPConn)
if !ok {
@@ -208,7 +208,7 @@ func (self *interceptor) newTproxy(service *entities.Service, resolver dns.Resol
}
if t.tcpLn == nil && t.udpLn == nil {
return nil, errors.Errorf("service %v has no supported protocols (tcp, udp). Serivce protocols: %+v", service.Name, config.Protocols)
return nil, errors.Errorf("service %v has no supported protocols (tcp, udp). Serivce protocols: %+v", *service.Name, config.Protocols)
}
if t.tcpLn != nil {
@@ -385,7 +385,7 @@ func deleteIptablesChain(ipt *iptables.IPTables, table, srcChain, dstChain strin
}
func (self *tProxy) Stop(tracker intercept.AddressTracker) {
log := pfxlog.Logger().WithField("service", self.service.Name)
log := pfxlog.Logger().WithField("service", *self.service.Name)
if self.tcpLn != nil {
if err := self.tcpLn.Close(); err != nil {
log.WithError(err).Error("failed to close TCP listener")
@@ -408,7 +408,7 @@ func (self *tProxy) tcpPort() IPPortAddr {
if self.tcpLn != nil {
return (*TCPIPPortAddr)(self.tcpLn.Addr().(*net.TCPAddr))
}
logrus.Errorf("invalid state: no tcp listener for tproxy[%s]", self.service.Name)
logrus.Errorf("invalid state: no tcp listener for tproxy[%s]", *self.service.Name)
return nil
}
@@ -417,25 +417,25 @@ func (self *tProxy) udpPort() IPPortAddr {
return (*UDPIPPortAddr)(self.udpLn.LocalAddr().(*net.UDPAddr))
}
logrus.Errorf("invalid state: no udp listener for tproxy[%s]", self.service.Name)
logrus.Errorf("invalid state: no udp listener for tproxy[%s]", *self.service.Name)
return nil
}
func (self *tProxy) Intercept(resolver dns.Resolver, tracker intercept.AddressTracker) error {
service := self.service
if service.InterceptV1Config == nil {
return errors.Errorf("no client configuration for service %v", service.Name)
return errors.Errorf("no client configuration for service %v", *service.Name)
}
config := service.InterceptV1Config
logrus.Debugf("service %v using intercept.v1", service.Name)
logrus.Debugf("service %v using intercept.v1", *service.Name)
var ports []IPPortAddr
for _, p := range config.Protocols {
if p == "tcp" {
logrus.Debugf("service %v intercepting tcp", service.Name)
logrus.Debugf("service %v intercepting tcp", *service.Name)
ports = append(ports, self.tcpPort())
} else if p == "udp" {
logrus.Debugf("service %v intercepting udp", service.Name)
logrus.Debugf("service %v intercepting udp", *service.Name)
ports = append(ports, self.udpPort())
}
}
@@ -444,7 +444,7 @@ func (self *tProxy) Intercept(resolver dns.Resolver, tracker intercept.AddressTr
}
func (self *tProxy) Apply(addr *intercept.InterceptAddress) {
logrus.Debugf("for service %v, intercepting proto: %v, cidr: %v, ports: %v:%v", self.service.Name, addr.Proto(), addr.IpNet(), addr.LowPort(), addr.HighPort())
logrus.Debugf("for service %v, intercepting proto: %v, cidr: %v, ports: %v:%v", *self.service.Name, addr.Proto(), addr.IpNet(), addr.LowPort(), addr.HighPort())
var port IPPortAddr
switch addr.Proto() {
@@ -453,11 +453,11 @@ func (self *tProxy) Apply(addr *intercept.InterceptAddress) {
case "udp":
port = self.udpPort()
default:
logrus.Errorf("unknown proto[%s] for tproxy[%s]", addr.Proto(), self.service.Name)
logrus.Errorf("unknown proto[%s] for tproxy[%s]", addr.Proto(), *self.service.Name)
return
}
if err := self.addInterceptAddr(addr, self.service, port, self.tracker); err != nil {
logrus.Debugf("failed for service %v, intercepting proto: %v, cidr: %v, ports: %v:%v", self.service.Name, addr.Proto(), addr.IpNet(), addr.LowPort(), addr.HighPort())
logrus.Debugf("failed for service %v, intercepting proto: %v, cidr: %v, ports: %v:%v", *self.service.Name, addr.Proto(), addr.IpNet(), addr.LowPort(), addr.HighPort())
// do we undo the previous succesful ones?
// only fail at end and return all that failed?
@@ -505,7 +505,7 @@ func (self *tProxy) addInterceptAddr(interceptAddr *intercept.InterceptAddress,
}
} else {
interceptAddr.TproxySpec = []string{
"-m", "comment", "--comment", service.Name,
"-m", "comment", "--comment", *service.Name,
"-d", ipNet.String(),
"-p", interceptAddr.Proto(),
"--dport", fmt.Sprintf("%v:%v", interceptAddr.LowPort(), interceptAddr.HighPort()),
@@ -523,7 +523,7 @@ func (self *tProxy) addInterceptAddr(interceptAddr *intercept.InterceptAddress,
if self.interceptor.lanIf != "" {
interceptAddr.AcceptSpec = []string{
"-i", self.interceptor.lanIf,
"-m", "comment", "--comment", service.Name,
"-m", "comment", "--comment", *service.Name,
"-d", ipNet.String(),
"-p", interceptAddr.Proto(),
"--dport", fmt.Sprintf("%v:%v", interceptAddr.LowPort(), interceptAddr.HighPort()),
@@ -542,7 +542,7 @@ func (self *tProxy) addInterceptAddr(interceptAddr *intercept.InterceptAddress,
func (self *tProxy) StopIntercepting(tracker intercept.AddressTracker) error {
var errorList []error
log := pfxlog.Logger().WithField("service", self.service.Name)
log := pfxlog.Logger().WithField("service", *self.service.Name)
for _, addr := range self.addresses {
log := log.WithField("route", addr.IpNet())
@@ -570,14 +570,14 @@ func (self *tProxy) StopIntercepting(tracker intercept.AddressTracker) error {
err := self.interceptor.ipt.Delete(mangleTable, dstChain, addr.TproxySpec...)
if err != nil {
errorList = append(errorList, err)
log.WithError(err).Errorf("failed to remove iptables rule for service %s", self.service.Name)
log.WithError(err).Errorf("failed to remove iptables rule for service %s", *self.service.Name)
}
if self.interceptor.lanIf != "" {
pfxlog.Logger().Infof("Removing rule iptables -t %v -A %v %v", filterTable, dstChain, addr.TproxySpec)
err = self.interceptor.ipt.Delete(filterTable, dstChain, addr.AcceptSpec...)
if err != nil {
errorList = append(errorList, err)
log.WithError(err).Errorf("failed to remove iptables rule for service %s", self.service.Name)
log.WithError(err).Errorf("failed to remove iptables rule for service %s", *self.service.Name)
}
}
}
@@ -587,7 +587,7 @@ func (self *tProxy) StopIntercepting(tracker intercept.AddressTracker) error {
err := router.RemoveLocalAddress(ipNet, "lo")
if err != nil {
errorList = append(errorList, err)
log.WithError(err).Errorf("failed to remove route %v for service %s", ipNet, self.service.Name)
log.WithError(err).Errorf("failed to remove route %v for service %s", ipNet, *self.service.Name)
}
}
}
@@ -598,7 +598,7 @@ func (self *tProxy) StopIntercepting(tracker intercept.AddressTracker) error {
if len(errorList) == 1 {
return errorList[0]
}
return impl.MultipleErrors(errorList)
return network.MultipleErrors(errorList)
}
type IPPortAddr interface {
+2 -1
View File
@@ -2,6 +2,7 @@ package tunnel
import (
"encoding/json"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge/health"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
@@ -30,7 +31,7 @@ type HostControl interface {
type FabricProvider interface {
PrepForUse(serviceId string)
GetCurrentIdentity() (*edge.CurrentIdentity, error)
GetCurrentIdentity() (*rest_model.IdentityDetail, error)
TunnelService(service Service, identity string, conn net.Conn, halfClose bool, appInfo []byte) error
HostService(hostCtx HostingContext) (HostControl, error)
}
+1 -1
View File
@@ -91,7 +91,7 @@ func (manager *manager) CreateWriteQueue(targetAddr *net.UDPAddr, srcAddr net.Ad
conn := &udpConn{
readC: make(chan mempool.PooledBuffer, 4),
closeNotify: make(chan struct{}),
service: service.Name,
service: *service.Name,
srcAddr: srcAddr,
manager: manager,
writeConn: writeConn,