I am attempting to write a query to audit a table of IP addresses against a table of overlapping net blocks. Individual net blocks can be marked active or inactive via a BOOLEAN. The audit query should return a BOOLEAN as active
depending upon the active column in the netblock
table. If any net block has the active
column set to FALSE, then the IP addresses contained within the netblock should report as active
set to FALSE.
The following is the definition of the ip
table:
CREATE TABLE IF NOT EXISTS ip
(
address INET NOT NULL UNIQUE,
modified timestamp WITH TIME ZONE NOT NULL
DEFAULT TIMESTAMP 'epoch',
username VARCHAR(64),
acctSession VARCHAR(32),
nasId INTEGER,
PRIMARY KEY ( address ),
FOREIGN KEY ( nasId )
REFERENCES nas
( id )
);
The following are example entries in ip
:
radius_ippool=> SELECT * FROM ip ORDER BY address;
address | modified | username | acctsession | nasid
--------------+-------------------------------+--------------------+-------------------------+-------
209.193.4.0 | 1970-01-01 00:00:00-10 | | |
209.193.4.1 | 1970-01-01 00:00:00-10 | | |
209.193.4.2 | 1970-01-01 00:00:00-10 | | |
209.193.4.3 | 1970-01-01 00:00:00-10 | | |
209.193.4.4 | 1970-01-01 00:00:00-10 | | |
209.193.4.5 | 1970-01-01 00:00:00-10 | | |
209.193.4.6 | 1970-01-01 00:00:00-10 | | |
209.193.4.7 | 1970-01-01 00:00:00-10 | | |
209.193.4.8 | 2019-05-09 11:55:20.456856-08 | jdoe8@example.net | aqaqqaasdqweaasdqa8 | 3
209.193.4.9 | 2019-05-09 11:55:20.638136-08 | jdoe9@aexample.net | qweadszcxqweasdzcx9 | 3
209.193.4.10 | 2019-05-09 11:55:20.85176-08 | jdoe10@example.net | user:jdoe10@example.net | 3
209.193.4.11 | 2019-05-09 11:55:20.872469-08 | jdoe11@example.net | user:jdoe11@example.net | 3
209.193.4.12 | 2019-05-09 11:55:20.894765-08 | jdoe12@example.net | user:jdoe12@example.net | 3
209.193.4.13 | 2019-05-09 11:55:21.02472-08 | jdoe13@example.net | user:jdoe13@example.net | 3
209.193.4.14 | 1970-01-01 00:00:00-10 | | |
209.193.4.15 | 1970-01-01 00:00:00-10 | | |
(16 rows)
The following is the definition of the netblock
table:
CREATE TABLE IF NOT EXISTS netblock
(
id SERIAL,
network CIDR NOT NULL UNIQUE,
poolId INTEGER NOT NULL,
regionId INTEGER,
active BOOLEAN NOT NULL DEFAULT TRUE,
description VARCHAR(256),
PRIMARY KEY ( id ),
FOREIGN KEY ( poolId )
REFERENCES pool
( id ),
FOREIGN KEY ( regionId )
REFERENCES region
( id )
);
The following are example entries in the netblock
table:
radius_ippool=> SELECT * FROM netblock ORDER BY network;
id | network | poolid | regionid | active | description
----+----------------+--------+----------+--------+----------------------------------------
1 | 209.193.4.0/28 | 1 | 2 | t |
2 | 209.193.4.0/29 | 1 | 2 | f | Reserved for engineering test accounts
4 | 209.193.4.4/30 | 1 | 2 | t |
(3 rows)
I have figure out a query to list all “active” and “inactive” IP addresses in separate queries:
-- query to return "inactive" IP addresses
SELECT DISTINCT netblock.regionId AS regionId,
ip.address AS ipAddress,
netblock.active AS active
FROM ip
INNER JOIN netblock
ON ip.address <<= netblock.network
WHERE netblock.active = FALSE
ORDER BY ipAddress;
-- query to return "active" IP addresses
SELECT DISTINCT netblock.regionId AS regionId,
ip.address AS ipAddress,
netblock.active AS active
FROM ip
INNER JOIN netblock
ON ip.address <<= netblock.network
WHERE netblock.active = TRUE
AND ip.address NOT IN
(
SELECT address AS ipAddress
FROM ip
INNER JOIN netblock
ON ip.address <<= netblock.network
AND netblock.active = FALSE
)
ORDER BY ipAddress;
Results of above query:
regionid | ipaddress | active
----------+-------------+--------
2 | 209.193.4.0 | f
2 | 209.193.4.1 | f
2 | 209.193.4.2 | f
2 | 209.193.4.3 | f
2 | 209.193.4.4 | f
2 | 209.193.4.5 | f
2 | 209.193.4.6 | f
2 | 209.193.4.7 | f
(8 rows)
regionid | ipaddress | active
----------+--------------+--------
2 | 209.193.4.8 | t
2 | 209.193.4.9 | t
2 | 209.193.4.10 | t
2 | 209.193.4.11 | t
2 | 209.193.4.12 | t
2 | 209.193.4.13 | t
2 | 209.193.4.14 | t
2 | 209.193.4.15 | t
(8 rows)
How do I replace the static value of unknown
for the active
column in the following table by queuing the netblock table for inactvie/active net blocks?
SELECT DISTINCT netblock.regionId AS regionId,
ip.address AS address,
'unknown' AS active,
(
nasId IS NOT NULL
OR
acctSession IS NOT NULL
) AS assigned,
ip.modified AS modified,
ip.nasid AS nasId,
ip.username AS username,
ip.acctSession AS acctSession
FROM ip
INNER JOIN netblock
ON ip.address <<= netblock.network
ORDER BY address;
Results from above query:
regionid | address | active | assigned | modified | nasid | username | acctsession
----------+--------------+---------+----------+-------------------------------+-------+--------------------+-------------------------
2 | 209.193.4.0 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.1 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.2 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.3 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.4 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.5 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.6 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.7 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.8 | unknown | t | 2019-05-09 11:55:20.456856-08 | 3 | jdoe8@example.net | aqaqqaasdqweaasdqa8
2 | 209.193.4.9 | unknown | t | 2019-05-09 11:55:20.638136-08 | 3 | jdoe9@aexample.net | qweadszcxqweasdzcx9
2 | 209.193.4.10 | unknown | t | 2019-05-09 11:55:20.85176-08 | 3 | jdoe10@example.net | user:jdoe10@example.net
2 | 209.193.4.11 | unknown | t | 2019-05-09 11:55:20.872469-08 | 3 | jdoe11@example.net | user:jdoe11@example.net
2 | 209.193.4.12 | unknown | t | 2019-05-09 11:55:20.894765-08 | 3 | jdoe12@example.net | user:jdoe12@example.net
2 | 209.193.4.13 | unknown | t | 2019-05-09 11:55:21.02472-08 | 3 | jdoe13@example.net | user:jdoe13@example.net
2 | 209.193.4.14 | unknown | f | 1970-01-01 00:00:00-10 | | |
2 | 209.193.4.15 | unknown | f | 1970-01-01 00:00:00-10 | | |
(16 rows)
Advertisement
Answer
You can use ALL
and a subquery to check if all the net blocks the IP is in are active.
SELECT
true = ALL (SELECT nb2.active
FROM netblock nb2
WHERE ip.address <<= nb2.network) active,
Alternatively you can use NOT EXISTS
:
SELECT
NOT EXISTS (SELECT *
FROM netblock nb2
WHERE ip.address <<= nb2.network
AND NOT nb2.active) active,