diff --git a/controller/internal/routes/service_api_model.go b/controller/internal/routes/service_api_model.go index e78ef74d2..75210da8f 100644 --- a/controller/internal/routes/service_api_model.go +++ b/controller/internal/routes/service_api_model.go @@ -194,6 +194,13 @@ func MapServiceToRestModel(ae *env.AppEnv, rc *response.RequestContext, service timeout := postureCheck.TimeoutSeconds() timeoutRemaining := postureCheck.TimeoutRemainingSeconds(rc.ApiSession.Id, ae.Handlers.PostureResponse.PostureData(rc.Identity.Id)) + //determine if updatedAt is provided by the source posture check or the posture state + if lastUpdatedAt := postureCheck.LastUpdatedAt(rc.ApiSession.Id, ae.Handlers.PostureResponse.PostureData(rc.Identity.Id)); lastUpdatedAt != nil { + if lastUpdatedAt.After(postureCheck.UpdatedAt) { + query.UpdatedAt = DateTimePtrOrNil(lastUpdatedAt) + } + + } query.IsPassing = &isCheckPassing query.TimeoutRemaining = &timeoutRemaining query.Timeout = &timeout diff --git a/controller/model/posture_check_model.go b/controller/model/posture_check_model.go index 32a06240f..0be6db06c 100644 --- a/controller/model/posture_check_model.go +++ b/controller/model/posture_check_model.go @@ -24,6 +24,7 @@ import ( "github.com/pkg/errors" "go.etcd.io/bbolt" "reflect" + "time" ) type PostureCheck struct { @@ -44,6 +45,9 @@ type PostureCheckSubType interface { FailureValues(_ string, pd *PostureData) PostureCheckFailureValues GetTimeoutSeconds() int64 GetTimeoutRemainingSeconds(apiSessionId string, pd *PostureData) int64 + + // LastUpdatedAt returns the last time the posture state changed or nil if not supported. + LastUpdatedAt(id string, pd *PostureData) *time.Time } type PostureCheckFailureValues interface { @@ -149,3 +153,9 @@ func (entity *PostureCheck) TimeoutSeconds() int64 { func (entity *PostureCheck) TimeoutRemainingSeconds(apiSessionId string, pd *PostureData) int64 { return entity.SubType.GetTimeoutRemainingSeconds(apiSessionId, pd) } + +// LastUpdatedAt returns the last time posture state changed for a specific posture check. +// If the posture state does not report changes, nil is returned. +func (entity *PostureCheck) LastUpdatedAt(apiSessionId string, pd *PostureData) *time.Time { + return entity.SubType.LastUpdatedAt(apiSessionId, pd) +} diff --git a/controller/model/posture_check_model_mac.go b/controller/model/posture_check_model_mac.go index 2e1de8d9c..f09ee6641 100644 --- a/controller/model/posture_check_model_mac.go +++ b/controller/model/posture_check_model_mac.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/openziti/edge/controller/persistence" "go.etcd.io/bbolt" + "time" ) var _ PostureCheckSubType = &PostureCheckMacAddresses{} @@ -27,6 +28,11 @@ var _ PostureCheckSubType = &PostureCheckMacAddresses{} type PostureCheckMacAddresses struct { MacAddresses []string } + +func (p *PostureCheckMacAddresses) LastUpdatedAt(apiSessionId string, pd *PostureData) *time.Time { + return nil +} + func (p *PostureCheckMacAddresses) GetTimeoutRemainingSeconds(_ string, _ *PostureData) int64 { return PostureCheckNoTimeout } @@ -37,8 +43,8 @@ func (p *PostureCheckMacAddresses) GetTimeoutSeconds() int64 { func (p *PostureCheckMacAddresses) FailureValues(_ string, pd *PostureData) PostureCheckFailureValues { return &PostureCheckFailureValuesMac{ - ActualValue: pd.Mac.Addresses, - ExpectedValue: p.MacAddresses, + ActualValue: pd.Mac.Addresses, + ExpectedValue: p.MacAddresses, } } @@ -105,4 +111,4 @@ func (p PostureCheckFailureValuesMac) Expected() interface{} { func (p PostureCheckFailureValuesMac) Actual() interface{} { return p.ActualValue -} \ No newline at end of file +} diff --git a/controller/model/posture_check_model_mfa.go b/controller/model/posture_check_model_mfa.go index 7223641ef..3bdca8a2d 100644 --- a/controller/model/posture_check_model_mfa.go +++ b/controller/model/posture_check_model_mfa.go @@ -41,6 +41,29 @@ type PostureCheckMfa struct { IgnoreLegacyEndpoints bool } +func (p *PostureCheckMfa) LastUpdatedAt(apiSessionId string, pd *PostureData) *time.Time { + apiSessionData := pd.ApiSessions[apiSessionId] + + //not enough data yet + if apiSessionData == nil || apiSessionData.Mfa == nil || apiSessionData.EndpointState == nil { + return nil + } + + var ret *time.Time = nil + + if p.PromptOnWake && apiSessionData.EndpointState.WokenAt != nil { + ret = apiSessionData.EndpointState.WokenAt + } + + if p.PromptOnUnlock && apiSessionData.EndpointState.UnlockedAt != nil { + if ret == nil || apiSessionData.EndpointState.UnlockedAt.After(*ret) { + ret = apiSessionData.EndpointState.UnlockedAt + } + } + + return ret +} + func (p *PostureCheckMfa) IsLegacyClient(apiSessionData *ApiSessionPostureData) bool { if apiSessionData.SdkInfo == nil { return true // don't know what it is @@ -154,7 +177,7 @@ func (p *PostureCheckMfa) FailureValues(apiSessionId string, pd *PostureData) Po } ret.Criteria.TimeoutSeconds = p.GetTimeoutSeconds() - + if apiSessionData, ok := pd.ApiSessions[apiSessionId]; ok { if apiSessionData.Mfa != nil { ret.ActualValue.TimedOutSeconds = apiSessionData.Mfa.TimedOut diff --git a/controller/model/posture_check_model_os.go b/controller/model/posture_check_model_os.go index 5b982ec81..839ae2243 100644 --- a/controller/model/posture_check_model_os.go +++ b/controller/model/posture_check_model_os.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/foundation/util/errorz" "go.etcd.io/bbolt" "strings" + "time" ) var _ PostureCheckSubType = &PostureCheckOperatingSystem{} @@ -32,6 +33,10 @@ type PostureCheckOperatingSystem struct { OperatingSystems []OperatingSystem } +func (p *PostureCheckOperatingSystem) LastUpdatedAt(id string, pd *PostureData) *time.Time { + return nil +} + func (p *PostureCheckOperatingSystem) GetTimeoutRemainingSeconds(_ string, _ *PostureData) int64 { return PostureCheckNoTimeout } @@ -42,7 +47,7 @@ func (p *PostureCheckOperatingSystem) GetTimeoutSeconds() int64 { func (p *PostureCheckOperatingSystem) FailureValues(_ string, pd *PostureData) PostureCheckFailureValues { return &PostureCheckFailureValuesOperatingSystem{ - ActualValue: pd.Os, + ActualValue: pd.Os, ExpectedValue: p.OperatingSystems, } } diff --git a/controller/model/posture_check_model_process.go b/controller/model/posture_check_model_process.go index 9484c3ca0..ea7b119b0 100644 --- a/controller/model/posture_check_model_process.go +++ b/controller/model/posture_check_model_process.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge/controller/persistence" "go.etcd.io/bbolt" "strings" + "time" ) var _ PostureCheckSubType = &PostureCheckProcess{} @@ -33,6 +34,10 @@ type PostureCheckProcess struct { Fingerprint string } +func (p *PostureCheckProcess) LastUpdatedAt(id string, pd *PostureData) *time.Time { + return nil +} + func (p *PostureCheckProcess) GetTimeoutSeconds() int64 { return PostureCheckNoTimeout } @@ -159,4 +164,4 @@ func (p PostureCheckFailureValuesProcess) Expected() interface{} { func (p PostureCheckFailureValuesProcess) Actual() interface{} { return p.ActualValue -} \ No newline at end of file +} diff --git a/controller/model/posture_check_model_process_,multi.go b/controller/model/posture_check_model_process_,multi.go index 617cf3327..162761260 100644 --- a/controller/model/posture_check_model_process_,multi.go +++ b/controller/model/posture_check_model_process_,multi.go @@ -22,6 +22,7 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" "go.etcd.io/bbolt" + "time" ) var _ PostureCheckSubType = &PostureCheckProcessMulti{} @@ -32,6 +33,10 @@ type PostureCheckProcessMulti struct { Processes []*ProcessMulti } +func (p *PostureCheckProcessMulti) LastUpdatedAt(id string, pd *PostureData) *time.Time { + return nil +} + func (p *PostureCheckProcessMulti) GetTimeoutSeconds() int64 { return PostureCheckNoTimeout } diff --git a/controller/model/posture_check_model_windows_domain.go b/controller/model/posture_check_model_windows_domain.go index fc3002a5e..bd9539b25 100644 --- a/controller/model/posture_check_model_windows_domain.go +++ b/controller/model/posture_check_model_windows_domain.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge/controller/persistence" "go.etcd.io/bbolt" "strings" + "time" ) var _ PostureCheckSubType = &PostureCheckDomains{} @@ -29,6 +30,10 @@ type PostureCheckDomains struct { Domains []string } +func (p *PostureCheckDomains) LastUpdatedAt(id string, pd *PostureData) *time.Time { + return nil +} + func (p *PostureCheckDomains) GetTimeoutSeconds() int64 { return PostureCheckNoTimeout } diff --git a/controller/model/posture_response_model_mfa.go b/controller/model/posture_response_model_mfa.go index 5a5352131..add9632b8 100644 --- a/controller/model/posture_response_model_mfa.go +++ b/controller/model/posture_response_model_mfa.go @@ -24,7 +24,7 @@ const ( type PostureResponseMfa struct { *PostureResponse - ApiSessionId string `json:"-"` + ApiSessionId string `json:"-"` PassedMfaAt *time.Time `json:"passedMfaAt"` } diff --git a/rest_client_api_server/embedded_spec.go b/rest_client_api_server/embedded_spec.go index 960ac79fb..2e44d0c1b 100644 --- a/rest_client_api_server/embedded_spec.go +++ b/rest_client_api_server/embedded_spec.go @@ -4293,10 +4293,10 @@ func init() { "type": "object", "required": [ "meta", - "error" + "data" ], "properties": { - "error": { + "data": { "$ref": "#/definitions/detailMfa" }, "meta": { @@ -10006,10 +10006,10 @@ func init() { "type": "object", "required": [ "meta", - "error" + "data" ], "properties": { - "error": { + "data": { "$ref": "#/definitions/detailMfa" }, "meta": { diff --git a/rest_management_api_server/embedded_spec.go b/rest_management_api_server/embedded_spec.go index 0d9596128..ece492656 100644 --- a/rest_management_api_server/embedded_spec.go +++ b/rest_management_api_server/embedded_spec.go @@ -16445,10 +16445,10 @@ func init() { "type": "object", "required": [ "meta", - "error" + "data" ], "properties": { - "error": { + "data": { "$ref": "#/definitions/detailMfa" }, "meta": { @@ -37024,10 +37024,10 @@ func init() { "type": "object", "required": [ "meta", - "error" + "data" ], "properties": { - "error": { + "data": { "$ref": "#/definitions/detailMfa" }, "meta": { diff --git a/rest_model/detail_mfa_envelope.go b/rest_model/detail_mfa_envelope.go index feb8f6948..dc4287ba6 100644 --- a/rest_model/detail_mfa_envelope.go +++ b/rest_model/detail_mfa_envelope.go @@ -43,9 +43,9 @@ import ( // swagger:model detailMfaEnvelope type DetailMfaEnvelope struct { - // error + // data // Required: true - Error *DetailMfa `json:"error"` + Data *DetailMfa `json:"data"` // meta // Required: true @@ -56,7 +56,7 @@ type DetailMfaEnvelope struct { func (m *DetailMfaEnvelope) Validate(formats strfmt.Registry) error { var res []error - if err := m.validateError(formats); err != nil { + if err := m.validateData(formats); err != nil { res = append(res, err) } @@ -70,18 +70,18 @@ func (m *DetailMfaEnvelope) Validate(formats strfmt.Registry) error { return nil } -func (m *DetailMfaEnvelope) validateError(formats strfmt.Registry) error { +func (m *DetailMfaEnvelope) validateData(formats strfmt.Registry) error { - if err := validate.Required("error", "body", m.Error); err != nil { + if err := validate.Required("data", "body", m.Data); err != nil { return err } - if m.Error != nil { - if err := m.Error.Validate(formats); err != nil { + if m.Data != nil { + if err := m.Data.Validate(formats); err != nil { if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("error") + return ve.ValidateName("data") } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("error") + return ce.ValidateName("data") } return err } @@ -114,7 +114,7 @@ func (m *DetailMfaEnvelope) validateMeta(formats strfmt.Registry) error { func (m *DetailMfaEnvelope) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error - if err := m.contextValidateError(ctx, formats); err != nil { + if err := m.contextValidateData(ctx, formats); err != nil { res = append(res, err) } @@ -128,14 +128,14 @@ func (m *DetailMfaEnvelope) ContextValidate(ctx context.Context, formats strfmt. return nil } -func (m *DetailMfaEnvelope) contextValidateError(ctx context.Context, formats strfmt.Registry) error { +func (m *DetailMfaEnvelope) contextValidateData(ctx context.Context, formats strfmt.Registry) error { - if m.Error != nil { - if err := m.Error.ContextValidate(ctx, formats); err != nil { + if m.Data != nil { + if err := m.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("error") + return ve.ValidateName("data") } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("error") + return ce.ValidateName("data") } return err } diff --git a/rest_model/dial_bind.go b/rest_model/dial_bind.go index ddcf4dc1d..f9c105598 100644 --- a/rest_model/dial_bind.go +++ b/rest_model/dial_bind.go @@ -44,8 +44,12 @@ import ( type DialBind string func NewDialBind(value DialBind) *DialBind { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated DialBind. +func (m DialBind) Pointer() *DialBind { + return &m } const ( diff --git a/rest_model/identity_type.go b/rest_model/identity_type.go index b61999dc3..ccc7ec1f9 100644 --- a/rest_model/identity_type.go +++ b/rest_model/identity_type.go @@ -44,8 +44,12 @@ import ( type IdentityType string func NewIdentityType(value IdentityType) *IdentityType { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated IdentityType. +func (m IdentityType) Pointer() *IdentityType { + return &m } const ( diff --git a/rest_model/links.go b/rest_model/links.go index 84a6d2251..cc09e97e6 100644 --- a/rest_model/links.go +++ b/rest_model/links.go @@ -53,6 +53,11 @@ func (m Links) Validate(formats strfmt.Registry) error { } if val, ok := m[k]; ok { if err := val.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName(k) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName(k) + } return err } } diff --git a/rest_model/list_protocols.go b/rest_model/list_protocols.go index f41b95bc4..e8b5638f5 100644 --- a/rest_model/list_protocols.go +++ b/rest_model/list_protocols.go @@ -53,6 +53,11 @@ func (m ListProtocols) Validate(formats strfmt.Registry) error { } if val, ok := m[k]; ok { if err := val.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName(k) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName(k) + } return err } } diff --git a/rest_model/mfa_formats.go b/rest_model/mfa_formats.go index eb43a6f82..c2a79a2ab 100644 --- a/rest_model/mfa_formats.go +++ b/rest_model/mfa_formats.go @@ -44,8 +44,12 @@ import ( type MfaFormats string func NewMfaFormats(value MfaFormats) *MfaFormats { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated MfaFormats. +func (m MfaFormats) Pointer() *MfaFormats { + return &m } const ( diff --git a/rest_model/mfa_providers.go b/rest_model/mfa_providers.go index 8b97d0ceb..060b1464b 100644 --- a/rest_model/mfa_providers.go +++ b/rest_model/mfa_providers.go @@ -44,8 +44,12 @@ import ( type MfaProviders string func NewMfaProviders(value MfaProviders) *MfaProviders { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated MfaProviders. +func (m MfaProviders) Pointer() *MfaProviders { + return &m } const ( diff --git a/rest_model/os_type.go b/rest_model/os_type.go index f633e1c7a..9c999a265 100644 --- a/rest_model/os_type.go +++ b/rest_model/os_type.go @@ -44,8 +44,12 @@ import ( type OsType string func NewOsType(value OsType) *OsType { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated OsType. +func (m OsType) Pointer() *OsType { + return &m } const ( diff --git a/rest_model/posture_check_type.go b/rest_model/posture_check_type.go index 17e712a3e..af6241945 100644 --- a/rest_model/posture_check_type.go +++ b/rest_model/posture_check_type.go @@ -44,8 +44,12 @@ import ( type PostureCheckType string func NewPostureCheckType(value PostureCheckType) *PostureCheckType { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated PostureCheckType. +func (m PostureCheckType) Pointer() *PostureCheckType { + return &m } const ( diff --git a/rest_model/posture_data.go b/rest_model/posture_data.go index 8dba8fb3f..44753db64 100644 --- a/rest_model/posture_data.go +++ b/rest_model/posture_data.go @@ -108,6 +108,11 @@ func (m *PostureData) validateAPISessionPostureData(formats strfmt.Registry) err } if val, ok := m.APISessionPostureData[k]; ok { if err := val.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("apiSessionPostureData" + "." + k) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("apiSessionPostureData" + "." + k) + } return err } } diff --git a/rest_model/semantic.go b/rest_model/semantic.go index 00b4ce704..76e68cea8 100644 --- a/rest_model/semantic.go +++ b/rest_model/semantic.go @@ -44,8 +44,12 @@ import ( type Semantic string func NewSemantic(value Semantic) *Semantic { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated Semantic. +func (m Semantic) Pointer() *Semantic { + return &m } const ( diff --git a/rest_model/terminator_cost_map.go b/rest_model/terminator_cost_map.go index 279384270..96dc641c6 100644 --- a/rest_model/terminator_cost_map.go +++ b/rest_model/terminator_cost_map.go @@ -53,6 +53,11 @@ func (m TerminatorCostMap) Validate(formats strfmt.Registry) error { } if val, ok := m[k]; ok { if err := val.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName(k) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName(k) + } return err } } diff --git a/rest_model/terminator_precedence.go b/rest_model/terminator_precedence.go index 37ad50267..20ed96bd0 100644 --- a/rest_model/terminator_precedence.go +++ b/rest_model/terminator_precedence.go @@ -44,8 +44,12 @@ import ( type TerminatorPrecedence string func NewTerminatorPrecedence(value TerminatorPrecedence) *TerminatorPrecedence { - v := value - return &v + return &value +} + +// Pointer returns a pointer to a freshly-allocated TerminatorPrecedence. +func (m TerminatorPrecedence) Pointer() *TerminatorPrecedence { + return &m } const ( diff --git a/rest_model/terminator_precedence_map.go b/rest_model/terminator_precedence_map.go index 4595ded07..ae9e45ff7 100644 --- a/rest_model/terminator_precedence_map.go +++ b/rest_model/terminator_precedence_map.go @@ -49,6 +49,11 @@ func (m TerminatorPrecedenceMap) Validate(formats strfmt.Registry) error { if val, ok := m[k]; ok { if err := val.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName(k) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName(k) + } return err } } diff --git a/rest_model/version.go b/rest_model/version.go index 9f06497f7..dab10144d 100644 --- a/rest_model/version.go +++ b/rest_model/version.go @@ -91,6 +91,11 @@ func (m *Version) validateAPIVersions(formats strfmt.Registry) error { } if val, ok := m.APIVersions[k][kk]; ok { if err := val.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("apiVersions" + "." + k + "." + kk) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("apiVersions" + "." + k + "." + kk) + } return err } } diff --git a/specs/client.yml b/specs/client.yml index dfa3f5379..4179fd24b 100644 --- a/specs/client.yml +++ b/specs/client.yml @@ -3128,9 +3128,9 @@ definitions: type: object required: - meta - - error + - data properties: - error: + data: $ref: '#/definitions/detailMfa' meta: $ref: '#/definitions/meta' diff --git a/specs/management.yml b/specs/management.yml index e15573af0..4f93c1633 100644 --- a/specs/management.yml +++ b/specs/management.yml @@ -11870,9 +11870,9 @@ definitions: type: object required: - meta - - error + - data properties: - error: + data: $ref: '#/definitions/detailMfa' meta: $ref: '#/definitions/meta' diff --git a/specs/source/shared/current-identity-mfa.yml b/specs/source/shared/current-identity-mfa.yml index 020cfdeec..0f704bc8a 100644 --- a/specs/source/shared/current-identity-mfa.yml +++ b/specs/source/shared/current-identity-mfa.yml @@ -228,11 +228,11 @@ definitions: type: object required: - meta - - error + - data properties: meta: $ref: 'standard-responses.yml#/definitions/meta' - error: + data: $ref: '#/definitions/detailMfa' detailMfa: type: object diff --git a/tests/context_json.go b/tests/context_json.go index 2a6da29ae..bc003d022 100644 --- a/tests/context_json.go +++ b/tests/context_json.go @@ -20,14 +20,13 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/Jeffail/gabs" + "github.com/michaelquigley/pfxlog" "github.com/openziti/foundation/util/errorz" "github.com/openziti/foundation/util/stringz" "net/http" "reflect" "strings" - - "github.com/Jeffail/gabs" - "github.com/michaelquigley/pfxlog" ) func (ctx *TestContext) setJsonValue(container *gabs.Container, value interface{}, path ...string) { diff --git a/tests/posture_check_mfa_test.go b/tests/posture_check_mfa_test.go index e0bb55991..4182875d0 100644 --- a/tests/posture_check_mfa_test.go +++ b/tests/posture_check_mfa_test.go @@ -20,9 +20,7 @@ package tests import ( - "encoding/json" "fmt" - "github.com/Jeffail/gabs" "github.com/google/uuid" "github.com/openziti/edge/eid" "github.com/openziti/edge/rest_model" @@ -72,11 +70,21 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().SetBody(postureCheckJson).Post("/posture-checks") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) postureCheckId := ctx.getEntityId(resp.Body()) ctx.Req.NotEmpty(postureCheckId) + resp, err = ctx.AdminManagementSession.newAuthenticatedRequest().Get("/posture-checks/" + postureCheckId) + ctx.Req.NoError(err) + + responseEnvelope := rest_model.DetailPostureCheckEnvelope{} + + err = responseEnvelope.UnmarshalJSON(resp.Body()) + ctx.Req.NoError(err) + + postureCheckDetail := responseEnvelope.Data().(*rest_model.PostureCheckMfaDetail) + ctx.AdminManagementSession.requireNewServicePolicyWithSemantic("Dial", "AllOf", s("#"+serviceRole), s("#"+identityRole), s("#"+postureCheckRole)) ctx.AdminManagementSession.requireNewEdgeRouterPolicy(s("#all"), s("#"+identityRole)) @@ -94,25 +102,36 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.testContextChanged(t) code, body := enrolledIdentitySession.query("/services/" + service.Id) ctx.Req.Equal(http.StatusOK, code) - entityService, err := gabs.ParseJSON(body) + + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err := serviceEnvelope.UnmarshalBinary(body) ctx.Req.NoError(err) - querySet, err := entityService.Path("data.postureQueries").Children() - ctx.Req.NoError(err) + querySet := serviceEnvelope.Data.PostureQueries + ctx.Req.NotNil(querySet) + ctx.Req.NotEmpty(querySet) ctx.Req.Len(querySet, 1) - postureQueries, err := querySet[0].Path("postureQueries").Children() + postureQueries := querySet[0].PostureQueries ctx.Req.NoError(err) ctx.Req.Len(postureQueries, 1) - ctx.Req.Equal(postureCheckId, postureQueries[0].Path("id").Data().(string)) - ctx.Req.Equal(string(postureCheck.TypeID()), postureQueries[0].Path("queryType").Data().(string)) + ctx.Req.Equal(postureCheckId, *postureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *postureQueries[0].QueryType) t.Run("query is currently failing", func(t *testing.T) { ctx.testContextChanged(t) - ctx.Req.False(querySet[0].Path("isPassing").Data().(bool)) - ctx.Req.False(postureQueries[0].Path("isPassing").Data().(bool)) - ctx.Req.Equal(-1, int(postureQueries[0].Path("timeout").Data().(float64))) + ctx.Req.False(*querySet[0].IsPassing) + ctx.Req.False(*postureQueries[0].IsPassing) + ctx.Req.Equal(int64(-1), *postureQueries[0].Timeout) + }) + + t.Run("updatedAt equals posture check createdAt", func(t *testing.T) { + //fix this + ctx.testContextChanged(t) + ctx.Req.NotNil(postureCheckDetail) + ctx.Req.NotEmpty(postureCheckDetail.CreatedAt()) + postureCheckDetail.CreatedAt().Equal(*postureQueries[0].CreatedAt) }) }) @@ -130,7 +149,7 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) listEnvelop := rest_model.FailedServiceRequestEnvelope{} - ctx.Req.NoError(json.Unmarshal(resp.Body(), &listEnvelop)) + ctx.Req.NoError(listEnvelop.UnmarshalBinary(resp.Body())) ctx.Req.NotEmpty(listEnvelop.Data) }) @@ -147,7 +166,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := enrolledIdentitySession.newAuthenticatedRequest().Post("/current-identity/mfa") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) t.Run("does not allow service session creation", func(t *testing.T) { ctx.testContextChanged(t) @@ -161,16 +180,20 @@ func Test_PostureChecks_MFA(t *testing.T) { t.Run("by finishing enrollment in MFA", func(t *testing.T) { resp, err := enrolledIdentitySession.newAuthenticatedRequest().Get("/current-identity/mfa") ctx.Req.NoError(err) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) - standardJsonResponseTests(resp, http.StatusOK, t) + mfaEnvelope := &rest_model.DetailMfaEnvelope{} - mfa, err := gabs.ParseJSON(resp.Body()) + err = mfaEnvelope.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) + ctx.Req.NotNil(mfaEnvelope) + ctx.Req.NotNil(mfaEnvelope.Data) - rawUrl := mfa.Path("data.provisioningUrl").Data().(string) - ctx.Req.NotEmpty(rawUrl) + mfa := mfaEnvelope.Data + ctx.Req.NotNil(mfa.ID) + ctx.Req.NotEmpty(mfa.ProvisioningURL) - parsedUrl, err := url.Parse(rawUrl) + parsedUrl, err := url.Parse(mfa.ProvisioningURL) ctx.Req.NoError(err) queryParams, err := url.ParseQuery(parsedUrl.RawQuery) @@ -190,7 +213,7 @@ func Test_PostureChecks_MFA(t *testing.T) { Post("/current-identity/mfa/verify") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusOK, t) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) t.Run("allows service session creation", func(t *testing.T) { ctx.testContextChanged(t) @@ -204,25 +227,34 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.testContextChanged(t) code, body := enrolledIdentitySession.query("/services/" + service.Id) ctx.Req.Equal(http.StatusOK, code) - entityService, err := gabs.ParseJSON(body) + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err = serviceEnvelope.UnmarshalBinary(body) ctx.Req.NoError(err) - querySet, err := entityService.Path("data.postureQueries").Children() - ctx.Req.NoError(err) + entityService := serviceEnvelope.Data + + querySet := entityService.PostureQueries ctx.Req.Len(querySet, 1) - postureQueries, err := querySet[0].Path("postureQueries").Children() - ctx.Req.NoError(err) + postureQueries := querySet[0].PostureQueries ctx.Req.Len(postureQueries, 1) - ctx.Req.Equal(postureCheckId, postureQueries[0].Path("id").Data().(string)) - ctx.Req.Equal(string(postureCheck.TypeID()), postureQueries[0].Path("queryType").Data().(string)) + ctx.Req.Equal(postureCheckId, *postureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *postureQueries[0].QueryType) t.Run("query is currently passing", func(t *testing.T) { ctx.testContextChanged(t) - ctx.Req.True(querySet[0].Path("isPassing").Data().(bool)) - ctx.Req.True(postureQueries[0].Path("isPassing").Data().(bool)) - ctx.Req.Equal(-1, int(postureQueries[0].Path("timeout").Data().(float64))) + ctx.Req.True(*querySet[0].IsPassing) + ctx.Req.True(*postureQueries[0].IsPassing) + ctx.Req.Equal(int64(-1), *postureQueries[0].Timeout) + }) + + t.Run("updatedAt equals posture check createdAt", func(t *testing.T) { + //fix this + ctx.testContextChanged(t) + ctx.Req.NotNil(postureCheckDetail) + ctx.Req.NotEmpty(postureCheckDetail.CreatedAt()) + postureCheckDetail.CreatedAt().Equal(*postureQueries[0].CreatedAt) }) }) }) @@ -242,12 +274,13 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) - sessionContainer, err := gabs.ParseJSON(resp.Body()) + sessionEnvelope := &rest_model.SessionCreateEnvelope{} + err = sessionEnvelope.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) - ctx.Req.True(sessionContainer.ExistsP("data.id")) - sessionId, ok := sessionContainer.Path("data.id").Data().(string) - ctx.Req.True(ok) + ctx.Req.NotNil(sessionEnvelope.Data.ID) + + sessionId := *sessionEnvelope.Data.ID ctx.Req.NotEmpty(sessionId) t.Run("removing MFA while the service requires MFA", func(t *testing.T) { @@ -317,10 +350,20 @@ func Test_PostureChecks_MFA(t *testing.T) { resp := ctx.AdminManagementSession.createEntityOfType("posture-checks", postureCheckBody) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) postureCheckId := ctx.getEntityId(resp.Body()) ctx.Req.NotEmpty(postureCheckId) + resp, err = ctx.AdminManagementSession.newAuthenticatedRequest().Get("/posture-checks/" + postureCheckId) + ctx.Req.NoError(err) + + responseEnvelope := rest_model.DetailPostureCheckEnvelope{} + + err = responseEnvelope.UnmarshalJSON(resp.Body()) + ctx.Req.NoError(err) + + postureCheckDetail := responseEnvelope.Data().(*rest_model.PostureCheckMfaDetail) + t.Run("identity can see service via policies", func(t *testing.T) { ctx.testContextChanged(t) ctx.Req.True(enrolledIdentitySession.isServiceVisibleToUser(service.Id)) @@ -330,25 +373,37 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.testContextChanged(t) code, body := enrolledIdentitySession.query("/services/" + service.Id) ctx.Req.Equal(http.StatusOK, code) - entityService, err := gabs.ParseJSON(body) + + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err = serviceEnvelope.UnmarshalBinary(body) ctx.Req.NoError(err) - querySet, err := entityService.Path("data.postureQueries").Children() - ctx.Req.NoError(err) + entityService := serviceEnvelope.Data + ctx.Req.NotNil(entityService) + ctx.Req.NotNil(entityService.ID) + + querySet := entityService.PostureQueries ctx.Req.Len(querySet, 1) - postureQueries, err := querySet[0].Path("postureQueries").Children() - ctx.Req.NoError(err) + postureQueries := querySet[0].PostureQueries ctx.Req.Len(postureQueries, 1) - ctx.Req.Equal(postureCheckId, postureQueries[0].Path("id").Data().(string)) - ctx.Req.Equal(string(postureCheck.TypeID()), postureQueries[0].Path("queryType").Data().(string)) + ctx.Req.Equal(postureCheckId, *postureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *postureQueries[0].QueryType) t.Run("query is currently failing", func(t *testing.T) { ctx.testContextChanged(t) - ctx.Req.False(querySet[0].Path("isPassing").Data().(bool)) - ctx.Req.False(postureQueries[0].Path("isPassing").Data().(bool)) - ctx.Req.Equal(0, int(postureQueries[0].Path("timeoutRemaining").Data().(float64))) + ctx.Req.False(*querySet[0].IsPassing) + ctx.Req.False(*postureQueries[0].IsPassing) + ctx.Req.Equal(int64(0), *postureQueries[0].TimeoutRemaining) + }) + + t.Run("updatedAt equals posture check createdAt", func(t *testing.T) { + //fix this + ctx.testContextChanged(t) + ctx.Req.NotNil(postureCheckDetail) + ctx.Req.NotEmpty(postureCheckDetail.CreatedAt()) + postureCheckDetail.CreatedAt().Equal(*postureQueries[0].CreatedAt) }) }) @@ -365,9 +420,8 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().Get("/identities/" + enrolledIdentitySession.identityId + "/failed-service-requests") ctx.Req.NoError(err) - listEnvelop := rest_model.FailedServiceRequestEnvelope{} - ctx.Req.NoError(json.Unmarshal(resp.Body(), &listEnvelop)) - + listEnvelop := &rest_model.FailedServiceRequestEnvelope{} + ctx.Req.NoError(listEnvelop.UnmarshalBinary(resp.Body())) ctx.Req.NotEmpty(listEnvelop.Data) }) }) @@ -383,7 +437,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := enrolledIdentitySession.newAuthenticatedRequest().Post("/current-identity/mfa") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) t.Run("does not allow service session creation", func(t *testing.T) { ctx.testContextChanged(t) @@ -397,16 +451,19 @@ func Test_PostureChecks_MFA(t *testing.T) { t.Run("by finishing enrollment in MFA", func(t *testing.T) { resp, err := enrolledIdentitySession.newAuthenticatedRequest().Get("/current-identity/mfa") ctx.Req.NoError(err) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) - standardJsonResponseTests(resp, http.StatusOK, t) - - mfa, err := gabs.ParseJSON(resp.Body()) + mfaEnvelope := &rest_model.DetailMfaEnvelope{} + err = mfaEnvelope.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) + ctx.Req.NotNil(mfaEnvelope) + ctx.Req.NotNil(mfaEnvelope.Data) - rawUrl := mfa.Path("data.provisioningUrl").Data().(string) - ctx.Req.NotEmpty(rawUrl) + mfa := mfaEnvelope.Data + ctx.Req.NotNil(mfa.ID) + ctx.Req.NotEmpty(mfa.ProvisioningURL) - parsedUrl, err := url.Parse(rawUrl) + parsedUrl, err := url.Parse(mfa.ProvisioningURL) ctx.Req.NoError(err) queryParams, err := url.ParseQuery(parsedUrl.RawQuery) @@ -426,7 +483,7 @@ func Test_PostureChecks_MFA(t *testing.T) { Post("/current-identity/mfa/verify") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusOK, t) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) t.Run("allows service session creation", func(t *testing.T) { ctx.testContextChanged(t) @@ -440,25 +497,28 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.testContextChanged(t) code, body := enrolledIdentitySession.query("/services/" + service.Id) ctx.Req.Equal(http.StatusOK, code) - entityService, err := gabs.ParseJSON(body) + + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err := serviceEnvelope.UnmarshalBinary(body) ctx.Req.NoError(err) - querySet, err := entityService.Path("data.postureQueries").Children() - ctx.Req.NoError(err) + querySet := serviceEnvelope.Data.PostureQueries + ctx.Req.NotNil(querySet) + ctx.Req.NotEmpty(querySet) ctx.Req.Len(querySet, 1) - postureQueries, err := querySet[0].Path("postureQueries").Children() + postureQueries := querySet[0].PostureQueries ctx.Req.NoError(err) ctx.Req.Len(postureQueries, 1) - ctx.Req.Equal(postureCheckId, postureQueries[0].Path("id").Data().(string)) - ctx.Req.Equal(string(postureCheck.TypeID()), postureQueries[0].Path("queryType").Data().(string)) + ctx.Req.Equal(postureCheckId, *postureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *postureQueries[0].QueryType) t.Run("query is currently passing", func(t *testing.T) { ctx.testContextChanged(t) - ctx.Req.True(querySet[0].Path("isPassing").Data().(bool)) - ctx.Req.True(postureQueries[0].Path("isPassing").Data().(bool)) - ctx.Req.Greater(int(postureQueries[0].Path("timeout").Data().(float64)), 0) + ctx.Req.True(*querySet[0].IsPassing) + ctx.Req.True(*postureQueries[0].IsPassing) + ctx.Req.Greater(*postureQueries[0].Timeout, int64(0)) }) }) @@ -473,7 +533,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := enrolledIdentitySession.NewRequest().SetBody(wokeState).Post("posture-response") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) t.Run("woke posture response should include service timeout change event", func(t *testing.T) { ctx.testContextChanged(t) @@ -496,26 +556,71 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.testContextChanged(t) code, body := enrolledIdentitySession.query("/services/" + service.Id) ctx.Req.Equal(http.StatusOK, code) - entityService, err := gabs.ParseJSON(body) + + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err := serviceEnvelope.UnmarshalBinary(body) ctx.Req.NoError(err) - querySet, err := entityService.Path("data.postureQueries").Children() - ctx.Req.NoError(err) + querySet := serviceEnvelope.Data.PostureQueries + ctx.Req.NotNil(querySet) + ctx.Req.NotEmpty(querySet) ctx.Req.Len(querySet, 1) - postureQueries, err := querySet[0].Path("postureQueries").Children() + postureQueries := querySet[0].PostureQueries ctx.Req.NoError(err) ctx.Req.Len(postureQueries, 1) - ctx.Req.Equal(postureCheckId, postureQueries[0].Path("id").Data().(string)) - ctx.Req.Equal(string(postureCheck.TypeID()), postureQueries[0].Path("queryType").Data().(string)) + ctx.Req.Equal(postureCheckId, *postureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *postureQueries[0].QueryType) t.Run("query has a lower timeout", func(t *testing.T) { ctx.testContextChanged(t) - ctx.Req.True(querySet[0].Path("isPassing").Data().(bool)) - ctx.Req.True(postureQueries[0].Path("isPassing").Data().(bool)) - ctx.Req.Greater(int(postureQueries[0].Path("timeoutRemaining").Data().(float64)), 0) - ctx.Req.LessOrEqual(int(postureQueries[0].Path("timeoutRemaining").Data().(float64)), 300) + ctx.Req.True(*querySet[0].IsPassing) + ctx.Req.True(*postureQueries[0].IsPassing) + ctx.Req.Greater(*postureQueries[0].TimeoutRemaining, int64(0)) + ctx.Req.LessOrEqual(*postureQueries[0].TimeoutRemaining, int64(300)) + }) + + t.Run("query has a new updatedAt value", func(t *testing.T) { + ctx.testContextChanged(t) + ctx.Req.True(time.Time(*postureQueries[0].UpdatedAt).After(time.Time(*postureCheckDetail.UpdatedAt())), "posture query updated at [%s] should now be after original time [%s]", postureQueries[0].UpdatedAt.String(), postureCheckDetail.UpdatedAt().String()) + }) + + t.Run("updating the posture check further advances updatedAt", func(t *testing.T) { + ctx.testContextChanged(t) + + newTimeout := int64(600) + mfaPatch := &rest_model.PostureCheckMfaPatch{} + mfaPatch.TimeoutSeconds = &newTimeout + + body, err := mfaPatch.MarshalJSON() + ctx.Req.NoError(err) + + resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().SetBody(body).Patch("/posture-checks/" + postureCheckId) + ctx.Req.NoError(err) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) + + resp, err = enrolledIdentitySession.newAuthenticatedRequest().Get("/services/" + service.Id) + ctx.Req.NoError(err) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) + + patchedServiceEnv := &rest_model.DetailServiceEnvelope{} + err = patchedServiceEnv.UnmarshalBinary(resp.Body()) + ctx.Req.NoError(err) + + patchedQuerySet := patchedServiceEnv.Data.PostureQueries + ctx.Req.NotNil(patchedQuerySet) + ctx.Req.NotEmpty(patchedQuerySet) + ctx.Req.Len(patchedQuerySet, 1) + + patchedPostureQueries := patchedQuerySet[0].PostureQueries + ctx.Req.NoError(err) + ctx.Req.Len(patchedPostureQueries, 1) + + ctx.Req.Equal(postureCheckId, *patchedPostureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *patchedPostureQueries[0].QueryType) + + ctx.Req.True(time.Time(*patchedPostureQueries[0].UpdatedAt).After(time.Time(*postureQueries[0].UpdatedAt)), "posture query updated at [%s] should now be after state change time [%s]", patchedPostureQueries[0].UpdatedAt.String(), postureCheckDetail.UpdatedAt().String()) }) }) }) @@ -536,12 +641,15 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) - sessionContainer, err := gabs.ParseJSON(resp.Body()) + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err = serviceEnvelope.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) - ctx.Req.True(sessionContainer.ExistsP("data.id")) - sessionId, ok := sessionContainer.Path("data.id").Data().(string) - ctx.Req.True(ok) + entityService := serviceEnvelope.Data + ctx.Req.NotNil(entityService) + ctx.Req.NotNil(entityService.ID) + + sessionId := *entityService.ID ctx.Req.NotEmpty(sessionId) }) @@ -640,7 +748,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp := ctx.AdminManagementSession.createEntityOfType("posture-checks", postureCheckBody) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) postureCheckId := ctx.getEntityId(resp.Body()) ctx.Req.NotEmpty(postureCheckId) @@ -663,7 +771,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := enrolledIdentitySession.newAuthenticatedRequest().Post("/current-identity/mfa") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) t.Run("does not allow service session creation", func(t *testing.T) { ctx.testContextChanged(t) @@ -677,16 +785,20 @@ func Test_PostureChecks_MFA(t *testing.T) { t.Run("by finishing enrollment in MFA", func(t *testing.T) { resp, err := enrolledIdentitySession.newAuthenticatedRequest().Get("/current-identity/mfa") ctx.Req.NoError(err) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) - standardJsonResponseTests(resp, http.StatusOK, t) + mfaEnvelope := &rest_model.DetailMfaEnvelope{} - mfa, err := gabs.ParseJSON(resp.Body()) + err = mfaEnvelope.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) + ctx.Req.NotNil(mfaEnvelope) + ctx.Req.NotNil(mfaEnvelope.Data) - rawUrl := mfa.Path("data.provisioningUrl").Data().(string) - ctx.Req.NotEmpty(rawUrl) + mfa := mfaEnvelope.Data + ctx.Req.NotNil(mfa.ID) + ctx.Req.NotEmpty(mfa.ProvisioningURL) - parsedUrl, err := url.Parse(rawUrl) + parsedUrl, err := url.Parse(mfa.ProvisioningURL) ctx.Req.NoError(err) queryParams, err := url.ParseQuery(parsedUrl.RawQuery) @@ -706,7 +818,7 @@ func Test_PostureChecks_MFA(t *testing.T) { Post("/current-identity/mfa/verify") ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusOK, t) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) t.Run("allows service session creation", func(t *testing.T) { ctx.testContextChanged(t) @@ -720,25 +832,28 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.testContextChanged(t) code, body := enrolledIdentitySession.query("/services/" + service.Id) ctx.Req.Equal(http.StatusOK, code) - entityService, err := gabs.ParseJSON(body) + + serviceEnvelope := &rest_model.DetailServiceEnvelope{} + err := serviceEnvelope.UnmarshalBinary(body) ctx.Req.NoError(err) - querySet, err := entityService.Path("data.postureQueries").Children() - ctx.Req.NoError(err) + querySet := serviceEnvelope.Data.PostureQueries + ctx.Req.NotNil(querySet) + ctx.Req.NotEmpty(querySet) ctx.Req.Len(querySet, 1) - postureQueries, err := querySet[0].Path("postureQueries").Children() + postureQueries := querySet[0].PostureQueries ctx.Req.NoError(err) ctx.Req.Len(postureQueries, 1) - ctx.Req.Equal(postureCheckId, postureQueries[0].Path("id").Data().(string)) - ctx.Req.Equal(string(postureCheck.TypeID()), postureQueries[0].Path("queryType").Data().(string)) + ctx.Req.Equal(postureCheckId, *postureQueries[0].ID) + ctx.Req.Equal(postureCheck.TypeID(), *postureQueries[0].QueryType) t.Run("query is currently passing", func(t *testing.T) { ctx.testContextChanged(t) - ctx.Req.True(querySet[0].Path("isPassing").Data().(bool)) - ctx.Req.True(postureQueries[0].Path("isPassing").Data().(bool)) - ctx.Req.Greater(int(postureQueries[0].Path("timeout").Data().(float64)), 0) + ctx.Req.True(*querySet[0].IsPassing) + ctx.Req.True(*postureQueries[0].IsPassing) + ctx.Req.Greater(*postureQueries[0].Timeout, int64(0)) }) }) }) @@ -759,30 +874,37 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) - sessionContainer, err := gabs.ParseJSON(resp.Body()) + sessionCreateEnvelope := &rest_model.SessionCreateEnvelope{} + err = sessionCreateEnvelope.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) + ctx.Req.NotNil(sessionCreateEnvelope.Data) + ctx.Req.NotNil(sessionCreateEnvelope.Data.ID) - ctx.Req.True(sessionContainer.ExistsP("data.id")) - sessionId, ok := sessionContainer.Path("data.id").Data().(string) - ctx.Req.True(ok) + sessionId := *sessionCreateEnvelope.Data.ID ctx.Req.NotEmpty(sessionId) resp, err = ctx.AdminManagementSession.NewRequest().Get("/sessions/" + sessionId) - ctx.Req.NoError(err) ctx.Req.Equal(http.StatusOK, resp.StatusCode()) + ctx.Req.NoError(err) + + sessionDetailEnvelope := &rest_model.DetailSessionEnvelope{} + err = sessionDetailEnvelope.UnmarshalBinary(resp.Body()) + ctx.Req.NoError(err) + ctx.Req.NotNil(sessionDetailEnvelope.Data) + ctx.Req.NotNil(sessionDetailEnvelope.Data.ID) resp, err = newSession.NewRequest().Get("/current-api-session/service-updates") ctx.Req.NoError(err) ctx.Req.Equal(http.StatusOK, resp.StatusCode()) - serviceUpdateContainer, err := gabs.ParseJSON(resp.Body()) + serviceUpdatesEnvelop := &rest_model.ListCurrentAPISessionServiceUpdatesEnvelope{} + err = serviceUpdatesEnvelop.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) + ctx.Req.NotNil(serviceUpdatesEnvelop.Data) + ctx.Req.NotNil(serviceUpdatesEnvelop.Data.LastChangeAt) + ctx.Req.False(time.Time(*serviceUpdatesEnvelop.Data.LastChangeAt).IsZero()) - ctx.Req.True(serviceUpdateContainer.ExistsP("data.lastChangeAt")) - - lastChangeAt, ok := serviceUpdateContainer.Path("data.lastChangeAt").Data().(string) - ctx.Req.True(ok) - ctx.Req.NotEmpty(lastChangeAt) + originalLastChangedAt := *serviceUpdatesEnvelop.Data.LastChangeAt t.Run("after the MFA posture check timeout", func(t *testing.T) { ctx.testContextChanged(t) @@ -799,16 +921,16 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) ctx.Req.Equal(http.StatusOK, resp.StatusCode()) - serviceUpdateContainer, err := gabs.ParseJSON(resp.Body()) + serviceUpdatesEnvelop := &rest_model.ListCurrentAPISessionServiceUpdatesEnvelope{} + err = serviceUpdatesEnvelop.UnmarshalBinary(resp.Body()) ctx.Req.NoError(err) + ctx.Req.NotNil(serviceUpdatesEnvelop.Data) + ctx.Req.NotNil(serviceUpdatesEnvelop.Data.LastChangeAt) + ctx.Req.False(time.Time(*serviceUpdatesEnvelop.Data.LastChangeAt).IsZero()) - ctx.Req.True(serviceUpdateContainer.ExistsP("data.lastChangeAt")) + newLastChangeAt := *serviceUpdatesEnvelop.Data.LastChangeAt - newLastChangeAt, ok := serviceUpdateContainer.Path("data.lastChangeAt").Data().(string) - ctx.Req.True(ok) - ctx.Req.NotEmpty(newLastChangeAt) - - ctx.Req.NotEqual(newLastChangeAt, lastChangeAt) + ctx.Req.False(originalLastChangedAt.Equal(newLastChangeAt)) }) t.Run("the existing session was removed", func(t *testing.T) { @@ -860,7 +982,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp := ctx.AdminManagementSession.createEntityOfType("posture-checks", postureCheckBody) - standardJsonResponseTests(resp, http.StatusCreated, t) + ctx.Req.Equal(http.StatusCreated, resp.StatusCode()) id := ctx.getEntityId(resp.Body()) ctx.Req.NotEmpty(id) @@ -870,7 +992,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := ctx.AdminManagementSession.NewRequest().Get("posture-checks/" + id) ctx.Req.NoError(err) ctx.Req.NotNil(resp) - standardJsonResponseTests(resp, http.StatusOK, t) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) envelope := rest_model.DetailPostureCheckEnvelope{} @@ -915,7 +1037,7 @@ func Test_PostureChecks_MFA(t *testing.T) { ctx.Req.NoError(err) - standardJsonResponseTests(resp, http.StatusOK, t) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) t.Run("can be retrieved", func(t *testing.T) { ctx.testContextChanged(t) @@ -923,7 +1045,7 @@ func Test_PostureChecks_MFA(t *testing.T) { resp, err := ctx.AdminManagementSession.NewRequest().Get("posture-checks/" + id) ctx.Req.NoError(err) ctx.Req.NotNil(resp) - standardJsonResponseTests(resp, http.StatusOK, t) + ctx.Req.Equal(http.StatusOK, resp.StatusCode()) envelope := rest_model.DetailPostureCheckEnvelope{}