From 69066e55ffd74274da529e9dd26ab0d4890a03dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Rodr=C3=ADguez?= Date: Thu, 14 Mar 2024 15:37:09 -0300 Subject: [PATCH] Add support for IP CIDR for Host schema ipAddress --- src/IntegrationSchema.ts | 3 ++ src/schemas/Host.json | 9 ++++ src/validateEntityWithSchema.test.ts | 81 ++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/src/IntegrationSchema.ts b/src/IntegrationSchema.ts index 4b66e9e..3e95166 100644 --- a/src/IntegrationSchema.ts +++ b/src/IntegrationSchema.ts @@ -3,6 +3,8 @@ import addFormats from 'ajv-formats'; const ipv4 = addFormats.get('ipv4') as RegExp; const ipv6 = addFormats.get('ipv6') as RegExp; +const ipv4CidrRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(3[0-2]|[12]?[0-9])$/; +const ipv6CidrRegex = /^([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^([0-9a-fA-F]{1,4}:){1,7}:\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^::\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}$/; // JSON Schema allows an object to contain properties that are not specified by // the schema. This can be disabled with `additionalProperties: false`. Ajv then @@ -24,6 +26,7 @@ export const IntegrationSchema = new Ajv({ strictSchema: false, formats: { ip: (x) => ipv4.test(x) || ipv6.test(x), + ipCidr: (x) => ipv4CidrRegex.test(x) || ipv6CidrRegex.test(x), }, }); diff --git a/src/schemas/Host.json b/src/schemas/Host.json index 26b1123..f57c0bf 100644 --- a/src/schemas/Host.json +++ b/src/schemas/Host.json @@ -28,6 +28,7 @@ "description": "A listing of all IP addresses associated with this Host", "anyOf": [ { "type": "string", "format": "ip" }, + { "type": "string", "format": "ipCidr" }, { "type": "array", "uniqueItems": true, @@ -35,6 +36,14 @@ "type": "string", "format": "ip" } + }, + { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "format": "ipCidr" + } } ] }, diff --git a/src/validateEntityWithSchema.test.ts b/src/validateEntityWithSchema.test.ts index 62fdf90..7d6ae77 100644 --- a/src/validateEntityWithSchema.test.ts +++ b/src/validateEntityWithSchema.test.ts @@ -98,6 +98,87 @@ describe('Host', () => { } as any), ).not.toThrow(); }); + + test('allows single IPv4 address in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: '192.168.1.1', + } as any), + ).not.toThrow(); + }); + + test('allows single IPv4 CIDR block in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: '192.168.1.0/24', + } as any), + ).not.toThrow(); + }); + + test('allows single IPv6 address in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: '2001:db8::1', + } as any), + ).not.toThrow(); + }); + + test('allows single IPv6 CIDR block in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: '2001:db8::/32', + } as any), + ).not.toThrow(); + }); + + test('allows array of IPv4 addresses in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: ['192.168.1.1', '10.0.0.1'], + } as any), + ).not.toThrow(); + }); + + test('allows array of IPv4 and IPv6 addresses in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: ['192.168.1.1', '2001:db8::1'], + } as any), + ).not.toThrow(); + }); + + test('allows array with IPv4 CIDR blocks in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: ['192.168.1.0/24', '10.0.0.0/16'], + } as any), + ).not.toThrow(); + }); + + test('disallows invalid IPv4 address in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: '256.256.256.256', + } as any), + ).toThrow(); + }); + + test('disallows invalid IPv4 CIDR block in ipAddress', () => { + expect(() => + validateEntityWithSchema({ + ...requiredProperties, + ipAddress: '192.168.1.0/33', // Invalid CIDR notation + } as any), + ).toThrow(); + }); }); describe('IpAddress', () => {