From 4e9a13528bf9700c5be3b395d7de67859cd23161 Mon Sep 17 00:00:00 2001 From: Peterson Paulo <109550332+peterpaulo-azion@users.noreply.github.com> Date: Fri, 20 Dec 2024 13:48:03 -0300 Subject: [PATCH 1/4] [UXE-5952] fix: edge firewall behavior handling with new rate limit properties and selectors (#2035) --- ...edge-firewall-rule-engine-rate-limit.cy.js | 88 +++++++++++++++++++ .../product-selectors/edge-firewall.js | 8 +- ...eate-edge-firewall-rules-engine-service.js | 19 ++-- ...edit-edge-firewall-rules-engine-service.js | 19 ++-- ...edge-firewall-rules-engine-service.test.js | 4 +- 5 files changed, 119 insertions(+), 19 deletions(-) create mode 100644 cypress/e2e/edge-firewall/create-edge-firewall-rule-engine-rate-limit.cy.js diff --git a/cypress/e2e/edge-firewall/create-edge-firewall-rule-engine-rate-limit.cy.js b/cypress/e2e/edge-firewall/create-edge-firewall-rule-engine-rate-limit.cy.js new file mode 100644 index 000000000..13774924b --- /dev/null +++ b/cypress/e2e/edge-firewall/create-edge-firewall-rule-engine-rate-limit.cy.js @@ -0,0 +1,88 @@ +/* eslint-disable cypress/no-unnecessary-waiting */ +import generateUniqueName from '../../support/utils' +import selectors from '../../support/selectors' + +let firewallName, ruleName + +describe('Edge Firewall spec', { tags: ['@dev5'] }, () => { + beforeEach(() => { + cy.login() + firewallName = generateUniqueName('EdgeFirewall') + ruleName = generateUniqueName('EdgeFirewallRule') + }) + + it('should create an Edge Firewall and set a rate limit', () => { + cy.openProduct('Edge Firewall') + + // Act - create Edge Firewall + cy.get(selectors.edgeFirewall.createButton).click() + cy.get(selectors.edgeFirewall.nameInput).clear() + cy.get(selectors.edgeFirewall.nameInput).type(firewallName) + cy.get(selectors.edgeFirewall.edgeFunctionSwitch).click() + cy.get(selectors.edgeFirewall.wafEnabledSwitch).click() + cy.get(selectors.edgeFirewall.saveButton).click() + cy.verifyToast('success', 'Your Edge Firewall has been created') + + cy.get(selectors.edgeFirewall.rulesEngineTab).click() + cy.get(selectors.edgeFirewall.createRuleButton).click() + cy.get(selectors.edgeFirewall.ruleNameInput).click() + cy.get(selectors.edgeFirewall.ruleNameInput).type(ruleName) + cy.get(selectors.edgeFirewall.ruleDescriptionInput).clear() + cy.get(selectors.edgeFirewall.ruleDescriptionInput).type('My Rule Description') + cy.get(selectors.edgeFirewall.ruleCriteriaVariableDropdown).click() + cy.get(selectors.edgeFirewall.ruleCriteriaVariableDropdownHeaderAccept).click() + cy.get(selectors.edgeFirewall.ruleCriteriaOperatorDropdown).click() + cy.get(selectors.edgeFirewall.ruleCriteriaOperatorMatches).click() + cy.get(selectors.edgeFirewall.ruleCriteriaInput).clear() + cy.get(selectors.edgeFirewall.ruleCriteriaInput).type('test') + + cy.get(selectors.edgeFirewall.ruleBehaviorDropdown).click() + cy.get(selectors.edgeFirewall.ruleBehaviorSetRateLimit).click() + cy.get(selectors.edgeFirewall.behaviorRateLimitType).click() + cy.get(selectors.edgeFirewall.behaviorRateLimitTypeFirstOption).click() + cy.get(selectors.edgeFirewall.behaviorAverageRateLimitInput).type('1') + cy.get(selectors.edgeFirewall.behaviorLimitBy).click() + cy.get(selectors.edgeFirewall.behaviorLimitByFirstOption).click() + + cy.intercept('POST', '/api/v4/edge_firewall/firewalls/*/rules*').as('addEdgeFirewallRule') + + cy.get(selectors.edgeFirewall.ruleSubmit).click() + + cy.wait('@addEdgeFirewallRule').then((interception) => { + const requestBody = interception.request.body + expect(requestBody.criteria[0][0].operator).to.equal('matches') + }) + + cy.verifyToast('success', 'Rule Engine successfully created') + + // Assert - Find the created rule + cy.get(selectors.edgeFirewall.rulesTableSearchInput).clear() + cy.get(selectors.edgeFirewall.rulesTableSearchInput).type(`${ruleName}{enter}`) + cy.get(selectors.edgeFirewall.rulesTableColumnName).should('have.text', ruleName) + cy.get(selectors.edgeFirewall.rulesTableColumnDescriptionShowMore).click() + cy.get(selectors.edgeFirewall.rulesTableColumnDescription).should( + 'have.text', + 'My Rule Description' + ) + + // Cleanup - Remove the created rule + cy.deleteEntityFromLoadedList().then(() => { + cy.verifyToast('Rules Engine successfully deleted') + }) + + // Assert - Find the created firewall + cy.get(selectors.edgeFirewall.mainSettingsTab).click() + cy.get(selectors.edgeFirewall.cancelButton).click() + cy.get(selectors.edgeFirewall.searchInput).clear() + cy.get(selectors.edgeFirewall.searchInput).type(`${firewallName}{enter}`) + cy.get(selectors.edgeFirewall.nameRow).should('have.text', firewallName) + cy.get(selectors.edgeFirewall.activeRow).should('have.text', 'Active') + }) + + afterEach(() => { + // Delete the firewall + cy.deleteEntityFromList({ entityName: firewallName, productName: 'Edge Firewall' }).then(() => { + cy.verifyToast('Edge Firewall successfully deleted') + }) + }) +}) diff --git a/cypress/support/selectors/product-selectors/edge-firewall.js b/cypress/support/selectors/product-selectors/edge-firewall.js index c1fac10f6..04132b15e 100644 --- a/cypress/support/selectors/product-selectors/edge-firewall.js +++ b/cypress/support/selectors/product-selectors/edge-firewall.js @@ -46,6 +46,7 @@ export default { '[data-testid="edge-firewall-rules-form__network-list[0]__dropdown-filter-input"]', ruleBehaviorDropdown: '[data-testid="edge-firewall-rules-form__behaviors[0]-dropdown__dropdown"]', ruleBehaviorRunFunction: '#behaviors\\[0\\]\\.name_4', + ruleBehaviorSetRateLimit: '#behaviors\\[0\\]\\.name_2', ruleBehaviorFirstOption: '#behaviors\\[0\\]\\.name_0', rulesWafDropdown: '[data-testid="edge-firewall-rule-form__behaviors[0]__waf__dropdown"] > .p-dropdown-label', @@ -69,5 +70,10 @@ export default { cancelButton: '[data-testid="form-actions-cancel-button"]', searchInput: '[data-testid="data-table-search-input"]', nameRow: '[data-testid="list-table-block__column__name__row"]', - activeRow: '[data-testid="list-table-block__column__status__row"] > .p-tag-value' + activeRow: '[data-testid="list-table-block__column__status__row"] > .p-tag-value', + behaviorRateLimitType: '#behaviors\\[0\\]\\.type > .p-dropdown-label', + behaviorRateLimitTypeFirstOption: '#behaviors\\[0\\]\\.type_1', + behaviorAverageRateLimitInput: '[data-testid="field-number__input"] > .p-inputtext', + behaviorLimitBy: '#behaviors\\[0\\]\\.limit_by > .p-dropdown-label', + behaviorLimitByFirstOption: '#behaviors\\[0\\]\\.limit_by_0', } diff --git a/src/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.js b/src/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.js index 78e74592e..f42c1eb34 100644 --- a/src/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.js +++ b/src/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.js @@ -36,16 +36,19 @@ const parseBehaviors = (behaviors) => { } case 'set_rate_limit': const typeToEnableBurstSize = 'second' - const burstSizeByType = - behavior.type === typeToEnableBurstSize ? behavior.maximum_burst_size : '' + const argument = { + type: behavior.type, + limit_by: behavior.limit_by, + average_rate_limit: Number(behavior.average_rate_limit) + } + + if (behavior.type === typeToEnableBurstSize) { + argument.maximum_burst_size = Number(behavior.maximum_burst_size) + } + return { name: behavior.name, - argument: { - type: behavior.type, - limit_by: behavior.limit_by, - average_rate_limit: `${behavior.average_rate_limit}`, - maximum_burst_size: `${burstSizeByType}` - } + argument } case 'set_custom_response': return { diff --git a/src/services/edge-firewall-rules-engine-services/v4/edit-edge-firewall-rules-engine-service.js b/src/services/edge-firewall-rules-engine-services/v4/edit-edge-firewall-rules-engine-service.js index fe9272495..1a7fcf294 100644 --- a/src/services/edge-firewall-rules-engine-services/v4/edit-edge-firewall-rules-engine-service.js +++ b/src/services/edge-firewall-rules-engine-services/v4/edit-edge-firewall-rules-engine-service.js @@ -36,16 +36,19 @@ const parseBehaviors = (behaviors) => { } case 'set_rate_limit': const typeToEnableBurstSize = 'second' - const burstSizeByType = - behavior.type === typeToEnableBurstSize ? behavior.maximum_burst_size : '' + const argument = { + type: behavior.type, + limit_by: behavior.limit_by, + average_rate_limit: Number(behavior.average_rate_limit) + } + + if (behavior.type === typeToEnableBurstSize) { + argument.maximum_burst_size = Number(behavior.maximum_burst_size) + } + return { name: behavior.name, - argument: { - type: behavior.type, - limit_by: behavior.limit_by, - average_rate_limit: `${behavior.average_rate_limit}`, - maximum_burst_size: `${burstSizeByType}` - } + argument } case 'set_custom_response': return { diff --git a/src/tests/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.test.js b/src/tests/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.test.js index 3ffc1e94d..f2033d409 100644 --- a/src/tests/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.test.js +++ b/src/tests/services/edge-firewall-rules-engine-services/v4/create-edge-firewall-rules-engine-service.test.js @@ -67,8 +67,8 @@ describe('EdgeFirewallRulesEngineService', () => { argument: { type: 'second', limit_by: 'ip', - average_rate_limit: '10', - maximum_burst_size: '20' + average_rate_limit: 10, + maximum_burst_size: 20 } }, { From 5ca1f133f471719786c5aa5e6c062a441fe07cb2 Mon Sep 17 00:00:00 2001 From: Lucas Mendes <92529166+lucasmendes21@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:49:21 -0300 Subject: [PATCH 2/4] [UXE-5966] fix: incorrect argument when saving criteria rules engine (#2038) --- .../v4/edit-rules-engine-service.js | 3 +- .../v4/helper-criteria.js | 17 ++++++ .../v4/edit-rules-engine-service.test.js | 61 ++++++++++++++++--- 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 src/services/edge-application-rules-engine-services/v4/helper-criteria.js diff --git a/src/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.js b/src/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.js index f627d38de..343b142ab 100644 --- a/src/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.js +++ b/src/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.js @@ -2,6 +2,7 @@ import { AxiosHttpClientAdapter } from '@/services/axios/AxiosHttpClientAdapter' import { makeEdgeApplicationV4BaseUrl } from '@/services/edge-application-services/v4/make-edge-application-v4-base-url' import * as Errors from '@/services/axios/errors' import { adaptBehavior } from './helper-behavior' +import { adaptCriteria } from './helper-criteria' import { extractApiError } from '@/helpers/extract-api-error' export const editRulesEngineService = async ({ id, payload, reorder = false }) => { @@ -28,7 +29,7 @@ const adapt = (payload, reorder) => { name, phase: phase.content || phase, behaviors: adaptBehavior(behaviors), - criteria, + criteria: adaptCriteria(criteria), active: isActive, description } diff --git a/src/services/edge-application-rules-engine-services/v4/helper-criteria.js b/src/services/edge-application-rules-engine-services/v4/helper-criteria.js new file mode 100644 index 000000000..4ce0ed941 --- /dev/null +++ b/src/services/edge-application-rules-engine-services/v4/helper-criteria.js @@ -0,0 +1,17 @@ +const isExistenceOperator = (operator) => ['exists', 'does_not_exist'].includes(operator) + +const processCriteria = (criteria) => { + if (!isExistenceOperator(criteria.operator)) { + return criteria + } + + // eslint-disable-next-line no-unused-vars + const { argument, ...processedCriteria } = criteria + return processedCriteria +} + +export const adaptCriteria = (criterias) => { + return criterias.map((criteriaArray) => { + return criteriaArray.map(processCriteria) + }) +} diff --git a/src/tests/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.test.js b/src/tests/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.test.js index 9634aa885..e3438ef81 100644 --- a/src/tests/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.test.js +++ b/src/tests/services/edge-application-rules-engine-services/v4/edit-rules-engine-service.test.js @@ -2,6 +2,7 @@ import { AxiosHttpClientAdapter } from '@/services/axios/AxiosHttpClientAdapter' import * as Errors from '@/services/axios/errors' import { editRulesEngineService } from '@/services/edge-application-rules-engine-services/v4' import { describe, expect, it, vi } from 'vitest' +import { adaptCriteria } from '@/services/edge-application-rules-engine-services/v4/helper-criteria' const fixtures = { ruleEngineMock: { @@ -17,15 +18,13 @@ const fixtures = { } ], criteria: [ - { - entries: [ - { - variable: 'remote_addr', - operator: 'is_equal', - value: '127.0.0.1' - } - ] - } + [ + { + variable: 'remote_addr', + operator: 'is_equal', + value: '127.0.0.1' + } + ] ], isActive: true, description: 'Test rule description' @@ -123,4 +122,48 @@ describe('EdgeApplicationRulesEngineServices', () => { expect(promise).rejects.toBe('Bad Request Error') }) + + it('should remove argument from criteria when operator is "exists" or "does_not_exist"', () => { + const criterias = [ + [ + { + variable: 'remote_addr', + operator: 'exists', + argument: '192.168.1.1' + }, + { + variable: 'remote_addr', + operator: 'is_equal', + argument: '192.168.1.1' + }, + { + variable: 'remote_addr', + operator: 'does_not_exist', + argument: '192.168.1.2' + }, + ] + ] + + const expectedCriterias = [ + [ + { + variable: 'remote_addr', + operator: 'exists' + }, + { + variable: 'remote_addr', + operator: 'is_equal', + argument: '192.168.1.1' + }, + { + variable: 'remote_addr', + operator: 'does_not_exist' + }, + ] + ] + + const result = adaptCriteria(criterias) + + expect(result).toEqual(expectedCriterias) + }) }) From f8e2c3ca82dd493269fd7e19e83895bee102d01b Mon Sep 17 00:00:00 2001 From: Lucas Mendes <92529166+lucasmendes21@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:58:14 -0300 Subject: [PATCH 3/4] [NO-ISSUE] chore: update version to 1.31.1 (#2040) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 73f57c066..40b69d091 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "azion-console-kit", - "version": "1.31.0", + "version": "1.31.1", "private": false, "type": "module", "repository": { From 27ea363ce24e771542b4f43a7fd95b52959b4350 Mon Sep 17 00:00:00 2001 From: Aloisio Bastian Date: Mon, 23 Dec 2024 17:07:45 -0300 Subject: [PATCH 4/4] test: remove unused assert (#2044) --- cypress/e2e/domains/create-domain-mtls.cy.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cypress/e2e/domains/create-domain-mtls.cy.js b/cypress/e2e/domains/create-domain-mtls.cy.js index 97ccc5440..3aa8f22b0 100644 --- a/cypress/e2e/domains/create-domain-mtls.cy.js +++ b/cypress/e2e/domains/create-domain-mtls.cy.js @@ -98,10 +98,6 @@ describe('Domains spec', { tags: ['@dev3'] }, () => { cy.verifyToast('Successfully copied!') cy.get(selectors.domains.confirmButton).click() cy.get(selectors.domains.editPageTitle).should('have.text', 'Edit Domain') - cy.get(selectors.domains.mtlsTrustedCAFieldSelectedValue).should( - 'contain', - digitalCertificateName - ) }) afterEach(() => {