Skip to content

Commit

Permalink
fix: update schemas and return empty config (#103)
Browse files Browse the repository at this point in the history
* fix: do not insert empty object when config does not exist

Updating manifest and config schemas.

* fix: update schema and fixes in firewall processing
  • Loading branch information
jcbsfilho authored Feb 7, 2025
1 parent 4f595a0 commit 40d0bce
Show file tree
Hide file tree
Showing 16 changed files with 186 additions and 130 deletions.
1 change: 1 addition & 0 deletions packages/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ Type definition for the domain configuration.
- `edgeApplicationId?: number` - ID of the edge application.
- `edgeFirewallId?: number` - ID of the edge firewall.
- `digitalCertificateId?: string | number | null` - ID of the digital certificate.
- `active?: boolean` - Whether the domain is active.
- `mtls?: MTLSConfig` - Configuration for mTLS.
- `verification: 'enforce' | 'permissive'` - mTLS verification mode.
- `trustedCaCertificateId: number` - ID of the trusted CA certificate.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1832,45 +1832,38 @@ describe('convertJsonConfigToObject', () => {
describe('Domains', () => {
it('should throw error when required fields are missing', () => {
const jsonConfig = {
domains: [
{
name: 'mydomain.com',
// missing required fields
},
],
domain: {
// missing required fields
},
};

expect(() => convertJsonConfigToObject(JSON.stringify(jsonConfig))).toThrow();
});

it('should throw error for invalid digital_certificate_id value', () => {
const jsonConfig = {
domains: [
{
name: 'mydomain.com',
edge_application_id: 123,
cnames: ['www.mydomain.com'],
cname_access_only: false,
digital_certificate_id: 'invalid_value',
},
],
domain: {
name: 'mydomain.com',
edge_application_id: 123,
cnames: ['www.mydomain.com'],
cname_access_only: false,
digital_certificate_id: 'invalid_value',
},
};

expect(() => convertJsonConfigToObject(JSON.stringify(jsonConfig))).toThrow();
});

it('should throw error for invalid crl_list values', () => {
const jsonConfig = {
domains: [
{
name: 'mydomain.com',
edge_application_id: 123,
cnames: ['www.mydomain.com'],
cname_access_only: false,
digital_certificate_id: 'lets_encrypt',
crl_list: ['invalid', 'values'],
},
],
domain: {
name: 'mydomain.com',
edge_application_id: 123,
cnames: ['www.mydomain.com'],
cname_access_only: false,
digital_certificate_id: 'lets_encrypt',
crl_list: ['invalid', 'values'],
},
};

expect(() => convertJsonConfigToObject(JSON.stringify(jsonConfig))).toThrow();
Expand Down
5 changes: 3 additions & 2 deletions packages/config/src/configProcessor/helpers/behaviors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
export const requestBehaviors = {
setOrigin: {
transform: (value: any, payloadCDN: any) => {
const origin = payloadCDN.origin.find((o: any) => o.name === value.name && o.origin_type === value.type);
const origin = payloadCDN.origin?.find((o: any) => o.name === value.name && o.origin_type === value.type);

if (!origin) {
throw new Error(`Rule setOrigin name '${value.name}' not found in the origin settings`);
Expand Down Expand Up @@ -54,6 +54,7 @@ export const requestBehaviors = {
};
}
if (typeof value === 'object') {
payloadCDN.cache = payloadCDN.cache || [];
const cacheSetting = {
name: value.name,
...value,
Expand Down Expand Up @@ -266,7 +267,7 @@ export const responseBehaviors = {
export const revertRequestBehaviors = {
set_origin: {
transform: (value: any, payloadCDN: any) => {
const origin = payloadCDN.origin.find((o: any) => o.name === value);
const origin = payloadCDN.origin?.find((o: any) => o.name === value);
if (!origin) {
throw new Error(`Rule setOrigin name '${value.name}' not found in the origin settings`);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/config/src/configProcessor/helpers/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,10 @@ const azionConfigSchema = {
errorMessage:
"The 'digitalCertificateId' field must be a string, number or null. If string, it must be 'lets_encrypt'.",
},
active: {
type: 'boolean',
errorMessage: "The 'active' field must be a boolean.",
},
mtls: {
type: 'object',
properties: {
Expand Down
64 changes: 50 additions & 14 deletions packages/config/src/configProcessor/helpers/schemaManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ const schemaWafManifest = {
};

const schemaDomainsManifest = {
type: 'object',
type: ['object', 'null'],
properties: {
id: {
type: 'number',
Expand Down Expand Up @@ -253,7 +253,7 @@ const schemaDomainsManifest = {
errorMessage: "The 'crl_list' field must be an array of numbers.",
},
},
required: ['name', 'edge_application_id', 'cnames', 'cname_access_only', 'digital_certificate_id'],
required: ['name'],
dependencies: {
is_mtls_enabled: {
oneOf: [
Expand Down Expand Up @@ -309,6 +309,7 @@ const schemaFirewallRuleCriteria = {
additionalProperties: false,
errorMessage: {
required: "The 'variable', 'operator' and 'conditional' fields are required in criteria.",
additionalProperties: 'No additional properties are allowed in criteria.',
},
};

Expand Down Expand Up @@ -393,6 +394,10 @@ const schemaFirewallRuleBehavior = {
},
required: ['name'],
additionalProperties: false,
errorMessage: {
required: "The 'name' field is required in firewall behaviors.",
additionalProperties: 'No additional properties are allowed in firewall behaviors.',
},
};

const schemaFirewallRule = {
Expand All @@ -406,8 +411,20 @@ const schemaFirewallRule = {
type: 'string',
errorMessage: "The 'name' field must be a string.",
},
criteria: schemaFirewallRuleCriteria,
behavior: schemaFirewallRuleBehavior,
criteria: {
type: 'array',
items: {
type: 'array',
items: schemaFirewallRuleCriteria,
errorMessage: "The 'criteria' field must be an array of criteria objects.",
},
errorMessage: "The 'criteria' field must be an array of criteria objects.",
},
behaviors: {
type: 'array',
items: schemaFirewallRuleBehavior,
errorMessage: "The 'behaviors' field must be an array of behavior objects.",
},
description: {
type: 'string',
maxLength: 1000,
Expand All @@ -424,12 +441,17 @@ const schemaFirewallRule = {
errorMessage: "The 'order' field must be an integer.",
},
},
required: ['name', 'criteria', 'behavior'],
required: ['name', 'criteria', 'behaviors'],
additionalProperties: false,
errorMessage: {
type: "The 'firewall' field must be an object",
required: "The 'name', 'criteria' and 'behaviors' fields are required in firewall rules.",
additionalProperties: 'No additional properties are allowed in firewall rules.',
},
};

const schemaFirewallManifest = {
type: 'object',
type: ['object', 'null'],
properties: {
main_settings: {
type: 'object',
Expand All @@ -441,9 +463,9 @@ const schemaFirewallManifest = {
domains: {
type: 'array',
items: {
type: 'number',
type: 'string',
errorMessage: "Each domain in the firewall's domains list must be a string",
},
errorMessage: "The 'domains' field must be an array of numbers.",
},
is_active: {
type: 'boolean',
Expand All @@ -461,6 +483,10 @@ const schemaFirewallManifest = {
type: 'boolean',
errorMessage: "The 'waf_enabled' field must be a boolean.",
},
debug_rules: {
type: 'boolean',
errorMessage: "The 'debug_rules' field must be a boolean.",
},
},
required: ['name'],
additionalProperties: false,
Expand All @@ -469,15 +495,21 @@ const schemaFirewallManifest = {
required: "The 'name' field is required in firewall main settings.",
},
},
rules: {
rules_engine: {
type: 'array',
items: schemaFirewallRule,
errorMessage: "The 'rules' field must be an array of firewall rules.",
errorMessage: {
type: "The 'rules_engine' field must be an array",
required: "The 'rules_engine' field must be an array of firewall rules.",
additionalProperties: 'No additional properties are allowed in firewall rules.',
},
},
},
required: ['main_settings'],
additionalProperties: false,
errorMessage: {
additionalProperties: 'No additional properties are allowed in firewall object.',
required: "The 'main_settings' field is required in firewall object.",
},
};

Expand Down Expand Up @@ -789,13 +821,17 @@ const schemaManifest = {
type: "The 'waf' field must be an array",
},
},
domains: {
type: 'array',
items: schemaDomainsManifest,
errorMessage: "The 'domains' field must be an array of domain items.",
domain: {
...schemaDomainsManifest,
errorMessage: {
type: "The 'domain' field must be an object",
},
},
firewall: {
...schemaFirewallManifest,
errorMessage: {
type: "The 'firewall' field must be an object",
},
},
application: {
type: 'array',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ describe('processConfig', () => {
};

const result = processConfig(azionConfig);
expect(result.cache).toEqual([]);
expect(result.cache).toBeUndefined();
});

it('should correctly convert request rules', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class BuildProcessConfigStrategy extends ProcessConfigStrategy {
transformToManifest(config: AzionConfig) {
const build = config?.build;
if (!build) {
return {};
return;
}
const payload: AzionBuild = build;
return payload;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CacheProcessConfigStrategy extends ProcessConfigStrategy {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const payload: any[] = [];
if (!Array.isArray(config?.cache) || config?.cache.length === 0) {
return payload;
return;
}
config?.cache.forEach((cache) => {
const maxAgeSecondsBrowser = cache?.browser ? this.evaluateMathExpression(cache.browser.maxAgeSeconds) : 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import ProcessConfigStrategy from '../processConfigStrategy';
class DomainProcessConfigStrategy extends ProcessConfigStrategy {
transformToManifest(config: AzionConfig) {
const domain = config?.domain;
if (!domain) {
return {};
if (!domain || Object.keys(domain).length === 0) {
return;
}
if (
domain.digitalCertificateId &&
Expand All @@ -35,12 +35,12 @@ class DomainProcessConfigStrategy extends ProcessConfigStrategy {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const domainSetting: any = {
name: domain.name,
cname_access_only: domain.cnameAccessOnly || false,
cname_access_only: domain.cnameAccessOnly ?? false,
cnames: domain.cnames || [],
digital_certificate_id: domain.digitalCertificateId || null,
edge_application_id: domain.edgeApplicationId || null,
edge_firewall_id: domain.edgeFirewallId || null,
active: true,
is_active: domain.active === undefined ? true : domain.active,
};
if (domain.mtls) {
domainSetting.is_mtls_enabled = true;
Expand All @@ -55,14 +55,18 @@ class DomainProcessConfigStrategy extends ProcessConfigStrategy {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
transformToConfig(payload: any, transformedPayload: AzionConfig) {
const domain = payload.domain || {};
const domain = payload.domain;
if (!domain || Object.keys(domain).length === 0) {
return;
}
transformedPayload.domain = {
name: domain.name,
cnameAccessOnly: domain.cname_access_only,
cnames: domain.cnames,
digitalCertificateId: domain.digital_certificate_id,
edgeApplicationId: domain.edge_application_id,
edgeFirewallId: domain.edge_firewall_id,
active: domain.is_active === undefined ? true : domain.is_active,
mtls: domain.mtls_verification
? {
verification: domain.mtls_verification,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class OriginProcessConfigStrategy extends ProcessConfigStrategy {
transformToManifest(config: AzionConfig) {
const payload: AzionOrigin[] = [];
if (!Array.isArray(config?.origin) || config?.origin.length === 0) {
return payload;
return;
}
const originsType = ['single_origin', 'object_storage', 'load_balancer', 'live_ingest'];
config?.origin.forEach((origin) => {
Expand All @@ -32,7 +32,7 @@ class OriginProcessConfigStrategy extends ProcessConfigStrategy {
originSetting.origin_path = origin.path || '';
originSetting.origin_protocol_policy = origin.protocolPolicy || 'preserve';
originSetting.method = origin.method || 'ip_hash';
originSetting.is_origin_redirection_enabled = origin.redirection || false;
originSetting.is_origin_redirection_enabled = origin.redirection ?? false;
originSetting.connection_timeout = origin.connectionTimeout || 60;
originSetting.timeout_between_bytes = origin.timeoutBetweenBytes || 120;

Expand Down Expand Up @@ -100,7 +100,7 @@ class OriginProcessConfigStrategy extends ProcessConfigStrategy {
originSetting.path = origin.origin_path;
originSetting.protocolPolicy = origin.origin_protocol_policy;
originSetting.method = origin.method;
originSetting.redirection = origin.is_origin_redirection_enabled;
originSetting.redirection = origin.is_origin_redirection_enabled ?? false;
originSetting.connectionTimeout = origin.connection_timeout;
originSetting.timeoutBetweenBytes = origin.timeout_between_bytes;
originSetting.addresses = origin.addresses;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class PurgeProcessConfigStrategy extends ProcessConfigStrategy {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const payload: any[] = [];
if (!Array.isArray(config?.purge) || config?.purge.length === 0) {
return payload;
return;
}
config?.purge.forEach((purge) => {
purge?.urls.forEach((value) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class RulesProcessConfigStrategy extends ProcessConfigStrategy {
transformToManifest(config: AzionConfig, context: any) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const payload: any[] = [];
if (config?.rules === undefined || Object.keys(config.rules).length === 0) {
return;
}
// request
if (Array.isArray(config?.rules?.request)) {
config?.rules?.request?.forEach((rule, index) => {
Expand Down Expand Up @@ -154,7 +157,7 @@ class RulesProcessConfigStrategy extends ProcessConfigStrategy {
};

const rulesConfig = payload.rules;
if (!rulesConfig) {
if (!rulesConfig || Object.keys(rulesConfig).length === 0) {
return;
}

Expand Down
Loading

0 comments on commit 40d0bce

Please sign in to comment.