From: Nick Porter Date: Fri, 2 Feb 2024 14:50:19 +0000 (+0000) Subject: Add tests of rlm_sqlippool X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a39810eef55fb63d194d620d41c3661873e920d7;p=thirdparty%2Ffreeradius-server.git Add tests of rlm_sqlippool --- diff --git a/src/tests/modules/sqlippool/.gitignore b/src/tests/modules/sqlippool/.gitignore new file mode 100644 index 00000000000..405551a9439 --- /dev/null +++ b/src/tests/modules/sqlippool/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sqlippool/all.mk b/src/tests/modules/sqlippool/all.mk new file mode 100644 index 00000000000..e08c2366962 --- /dev/null +++ b/src/tests/modules/sqlippool/all.mk @@ -0,0 +1,3 @@ +# +# Test the sqlippool module using sqlite backend +# diff --git a/src/tests/modules/sqlippool/alloc.attrs b/src/tests/modules/sqlippool/alloc.attrs new file mode 100644 index 00000000000..871a106ce7c --- /dev/null +++ b/src/tests/modules/sqlippool/alloc.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = 00:11:22:33:44:55 + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/alloc.unlang b/src/tests/modules/sqlippool/alloc.unlang new file mode 100644 index 00000000000..496564557d1 --- /dev/null +++ b/src/tests/modules/sqlippool/alloc.unlang @@ -0,0 +1,93 @@ +# +# Allocate an address from an SQL IP Pool +# +uint32 expiry +&control.IP-Pool.Name := 'test_alloc' + +# +# Add IP addresses +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:10'))") + +# +# Check allocation +# +sqlippool.allocate +if (!updated) { + test_fail +} + +if !(&reply.Framed-IP-Address == 192.168.0.1) { + test_fail +} + +# +# Check Expiry +# +&expiry := %sql("SELECT strftime('%%s', expiry_time) FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") +if ((&expiry - %l) < 20) { + test_fail +} + +# +2 - Some slop for macOS +if ((&expiry - %l) > 42) { + test_fail +} + +# +# Verify the address details have been updated +# +if !(%sql("SELECT owner FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '00:11:22:33:44:55') { + test_fail +} + +if !(%sql("SELECT gateway FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '127.0.0.1') { + test_fail +} + +&Framed-IP-Address := &reply.Framed-IP-Address +&reply := {} + +# +# Add IP addresses +# +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) values ('%{control.IP-Pool.Name}', '192.168.1.1', datetime('now', '-00:10'))") + +# +# Check we get the same lease, with the same lease time +# +sqlippool.allocate +if (!updated) { + test_fail +} + +# +# Check the IP addresses are the same +# +if !(&Framed-IP-Address == &reply.Framed-IP-Address) { + test_fail +} + +&reply := {} + +# +# Now change the Calling-Station-ID and check we get a different lease +# +&Calling-Station-ID := 'another_mac' + +sqlippool.allocate +if (!updated) { + test_fail +} + +# +# Check we got the right lease +# +if !(&reply.Framed-IP-Address == 192.168.1.1) { + test_fail +} + +&reply := {} + +test_pass diff --git a/src/tests/modules/sqlippool/alloc_fail.attrs b/src/tests/modules/sqlippool/alloc_fail.attrs new file mode 100644 index 00000000000..871a106ce7c --- /dev/null +++ b/src/tests/modules/sqlippool/alloc_fail.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = 00:11:22:33:44:55 + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/alloc_fail.unlang b/src/tests/modules/sqlippool/alloc_fail.unlang new file mode 100644 index 00000000000..7e703136ee2 --- /dev/null +++ b/src/tests/modules/sqlippool/alloc_fail.unlang @@ -0,0 +1,60 @@ +# +# Allocate an address from an SQL IP Pool +# +uint32 expiry +&control.IP-Pool.Name := 'test_alloc_fail' + +# +# Ensure no matching records +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") + +# +# Check allocation failed +# +sqlippool.allocate +if (!noop) { + test_fail +} + +if (&reply.Framed-IP-Address) { + test_fail +} + +# +# Insert a record +# +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:10'))") + +# +# Check allocation +# +sqlippool.allocate +if (!updated) { + test_fail +} + +if !(&reply.Framed-IP-Address == 192.168.0.1) { + test_fail +} + +&reply := {} + +# +# Now change the Calling-Station-ID and check we don't get an address (pool full) +# +&Calling-Station-ID := 'another_mac' + +sqlippool.allocate +if (!notfound) { + test_fail +} + +# +# Check we got no address +# +if (&reply.Framed-IP-Address) { + test_fail +} + +test_pass diff --git a/src/tests/modules/sqlippool/alloc_requested.attrs b/src/tests/modules/sqlippool/alloc_requested.attrs new file mode 100644 index 00000000000..5a6325fe7b2 --- /dev/null +++ b/src/tests/modules/sqlippool/alloc_requested.attrs @@ -0,0 +1,14 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = 00:11:22:33:44:55 +Framed-IP-Address = 192.168.0.2 + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/alloc_requested.unlang b/src/tests/modules/sqlippool/alloc_requested.unlang new file mode 100644 index 00000000000..8d5ceddb035 --- /dev/null +++ b/src/tests/modules/sqlippool/alloc_requested.unlang @@ -0,0 +1,74 @@ +# +# Allocate an address from an SQL IP Pool +# +uint32 expiry +&control.IP-Pool.Name := 'test_alloc_requested' + +# +# Add IP addresses +# Based on expiry_time, the last of these would be allocated, but the second will be requested +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:10'))") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.2', datetime('now', '-00:10'))") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.3', datetime('now', '-00:20'))") + +# +# Check allocation +# +sqlippool.allocate +if (!updated) { + test_fail +} + +if !(&reply.Framed-IP-Address == 192.168.0.2) { + test_fail +} + +# +# Check Expiry +# +&expiry := %sql("SELECT strftime('%%s', expiry_time) FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") +if ((&expiry - %l) < 20) { + test_fail +} + +# +2 - Some slop for macOS +if ((&expiry - %l) > 42) { + test_fail +} + +# +# Verify the address details have been updated +# +if !(%sql("SELECT owner FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '00:11:22:33:44:55') { + test_fail +} + +if !(%sql("SELECT gateway FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '127.0.0.1') { + test_fail +} + +&reply := {} +&request -= &Framed-IP-Address + +# +# Now change the Calling-Station-ID and check we get a different lease +# +&Calling-Station-ID := 'another_mac' + +sqlippool.allocate +if (!updated) { + test_fail +} + +# +# Check we got the right lease - the oldest one by expiry_time +# +if !(&reply.Framed-IP-Address == 192.168.0.3) { + test_fail +} + +&reply := {} + +test_pass diff --git a/src/tests/modules/sqlippool/module.conf b/src/tests/modules/sqlippool/module.conf new file mode 100644 index 00000000000..0a6e621c9b1 --- /dev/null +++ b/src/tests/modules/sqlippool/module.conf @@ -0,0 +1,60 @@ +sql { + driver = "sqlite" + dialect = "sqlite" + sqlite { + # Path to the sqlite database + filename = "$ENV{MODULE_TEST_DIR}/sql_sqlite/$ENV{TEST}/rlm_sql_sqlite.db" + + # If the file above does not exist and bootstrap is set + # a new database file will be created, and the SQL statements + # contained within the file will be executed. + bootstrap = "${modconfdir}/${..:name}/main/${..dialect}/schema.sql" + bootstrap = "${modconfdir}/${..:name}/ippool/${..dialect}/schema.sql" + } + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 1 + lifetime = 1 + idle_timeout = 60 + retry_delay = 1 + } + + # The group attribute specific to this instance of rlm_sql + group_attribute = "SQL-Group" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} + +sqlippool { + sql_module_instance = "sql" + dialect = "sqlite" + ippool_table = "fr_ippool" + lease_duration = 60 + offer_duration = 30 + pool_name = &control.IP-Pool.Name + allocated_address_attr = &reply.Framed-IP-Address + owner = "%{Calling-Station-Id}" + requested_address = "%{Framed-IP-Address}" + gateway = "%{NAS-IP-Address}" + + $INCLUDE ${modconfdir}/sql/ippool/${dialect}/queries.conf +} + diff --git a/src/tests/modules/sqlippool/release.attrs b/src/tests/modules/sqlippool/release.attrs new file mode 100644 index 00000000000..871a106ce7c --- /dev/null +++ b/src/tests/modules/sqlippool/release.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = 00:11:22:33:44:55 + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/release.unlang b/src/tests/modules/sqlippool/release.unlang new file mode 100644 index 00000000000..ade5e01b6b5 --- /dev/null +++ b/src/tests/modules/sqlippool/release.unlang @@ -0,0 +1,68 @@ +# +# Test releasing IP addresses in the sqlippool module +# +uint32 expiry +&control.IP-Pool.Name := 'test_release' + +# +# Add IP addresses +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:10'))") + +# +# Check allocation +# +sqlippool.allocate +if (!updated) { + test_fail +} + +if !(&reply.Framed-IP-Address == 192.168.0.1) { + test_fail +} + +# +# Release the IP address +# +&Framed-IP-Address := &reply.Framed-IP-Address + +sqlippool.release +if !(updated) { + test_fail +} + +# +# Verify the association with the device has been removed +# +if (%sql("SELECT address FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND owner = '%{Calling-Station-Id}")) { + test_fail +} + + +# Check the expiry - releasing an address sets the exipry to now +# Allow for some time passing between packet processing and "now" +&expiry := %sql("SELECT strftime('%%s', expiry_time) FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") +if (&expiry > (%l + 5)) { + test_fail +} + +if ((%l - &expiry) > 5) { + test_fail +} + +# +# Release the IP address again +# Will return notfound as address is already released. +# +&Framed-IP-Address := &reply.Framed-IP-Address + +sqlippool.release + +if (!notfound) { + test_fail +} + +&reply := {} + +test_pass diff --git a/src/tests/modules/sqlippool/static.attrs b/src/tests/modules/sqlippool/static.attrs new file mode 100644 index 00000000000..4bb429e8b63 --- /dev/null +++ b/src/tests/modules/sqlippool/static.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = aa:bb:cc:dd:ee:ff + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/static.unlang b/src/tests/modules/sqlippool/static.unlang new file mode 100644 index 00000000000..a33777c2276 --- /dev/null +++ b/src/tests/modules/sqlippool/static.unlang @@ -0,0 +1,64 @@ +# +# Test static IP allocation using sqlippool +# +&control.IP-Pool.Name := 'test_static' + +# +# Add a dynamic IP addresses +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:20'))") + +# +# Add a static IP assigned to the calling station in the request +# with a shorter expiry time than the dynamic address - so the dynamic +# would be chosen if simply selected on expiry time. +# +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time, owner, status_id) VALUES ('%{control.IP-Pool.Name}', '192.168.0.10', datetime('now', '-00:10'), 'aa:bb:cc:dd:ee:ff', 2)") + +# +# Check allocation +# +sqlippool.allocate +if (!updated) { + test_fail +} + +if !(&reply.Framed-IP-Address == 192.168.0.10) { + test_fail +} + +# +# Check that renewal does not mess with static IP +# +&Framed-IP-Address := &reply.Framed-IP-Address + +sqlippool.renew +if !(updated) { + test_fail +} + +# +# Check that releasing does not mess with static IP +# +sqlippool.release +if !(notfound) { + test_fail +} + +# +# Verify the association with the device remains +# +if !(%sql("SELECT address FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND owner = '%{Calling-Station-Id}'") == '192.168.0.10') { + test_fail +} + +# Check the expiry - this will have been put in the future by the allocation / renewal +# and not reset by the release. +if (%sql("SELECT strftime('%%s', expiry_time) FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") <= %l) { + test_fail +} + +&reply := {} + +test_pass diff --git a/src/tests/modules/sqlippool/update.attrs b/src/tests/modules/sqlippool/update.attrs new file mode 100644 index 00000000000..871a106ce7c --- /dev/null +++ b/src/tests/modules/sqlippool/update.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = 00:11:22:33:44:55 + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/update.unlang b/src/tests/modules/sqlippool/update.unlang new file mode 100644 index 00000000000..30e93d76a4c --- /dev/null +++ b/src/tests/modules/sqlippool/update.unlang @@ -0,0 +1,103 @@ +# +# Test updates on sqlippool allocated addresses. +# +uint32 expiry +&control.IP-Pool.Name := 'test_update' + +# +# Add IP addresses +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:10'))") + +# 1. Check allocation +sqlippool.allocate +if (!updated) { + test_fail +} + +# 2. +if !(&reply.Framed-IP-Address == 192.168.0.1) { + test_fail +} + +# 3. Verify expiry time is based on offer duration +&expiry := %sql("SELECT strftime('%%s', expiry_time) FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") +if ((&expiry - %l) < 20) { + test_fail +} + +# 4. +if ((&expiry - %l) > 40) { + test_fail +} + + +# 5. Verify the gateway was set +if !(%sql("SELECT gateway FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '127.0.0.1') { + test_fail +} + +# 6. Add another IP addresses +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) values ('%{control.IP-Pool.Name}', '192.168.1.1', datetime('now', '-00:10'))") + +# 7. Verify that the lease time is extended +&Framed-IP-Address := &reply.Framed-IP-Address +&NAS-IP-Address := 127.0.0.2 + +sqlippool.renew +if (!updated) { + test_fail +} + +# 8. Check expiry reflects that +&expiry := %sql("SELECT strftime('%%s', expiry_time) FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") +if ((&expiry - %l) < 50) { + test_fail +} + +# 9. +if ((&expiry - %l) > 70) { + test_fail +} + +# 10. Verify the gateway was updated +if !(%sql("SELECT gateway FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '127.0.0.2') { + test_fail +} + +# Change the ip address to one that doesn't exist in the pool and check we *can't* update it +&Framed-IP-Address := 192.168.3.1 + +sqlippool.renew +# 11. +if (!notfound) { + test_fail +} + +# 12. This will have caused the update_free query to have run - which will have released the original address. +if (%sql("SELECT address FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND owner = '00:11:22:33:44:55'")) { + test_fail +} + +# re-issue the original allocation +&reply := {} +&Framed-IP-Address := 192.168.0.1 +sqlippool.allocate + +# 13. Now change the calling station ID and check that we *can't* update the lease +&Calling-Station-ID := 'naughty' + +sqlippool.renew +if (!notfound) { + test_fail +} + +# 14. Verify the lease is still associated with the previous device +if !(&reply.Framed-IP-Address == %sql("SELECT address FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND owner = '00:11:22:33:44:55'")) { + test_fail +} + +&reply := {} + +test_pass diff --git a/src/tests/modules/sqlippool/update_alloc.attrs b/src/tests/modules/sqlippool/update_alloc.attrs new file mode 100644 index 00000000000..871a106ce7c --- /dev/null +++ b/src/tests/modules/sqlippool/update_alloc.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'john' +User-Password = 'testing123' +NAS-IP-Address = 127.0.0.1 +Calling-Station-Id = 00:11:22:33:44:55 + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlippool/update_alloc.unlang b/src/tests/modules/sqlippool/update_alloc.unlang new file mode 100644 index 00000000000..aa4f4ea5bab --- /dev/null +++ b/src/tests/modules/sqlippool/update_alloc.unlang @@ -0,0 +1,38 @@ +# +# Allocate an address from an SQL IP Pool and update +# +&control.IP-Pool.Name := 'test_update_alloc' + +# +# Add IP addresses +# +%sql("DELETE FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}'") +%sql("INSERT INTO fr_ippool (pool_name, address, expiry_time) VALUES ('%{control.IP-Pool.Name}', '192.168.0.1', datetime('now', '-00:10'))") + +# 1. Check allocation +sqlippool.allocate +if (!updated) { + test_fail +} + +# +# Attempt to update an IP address by performing a renew +# +&Framed-IP-Address := 192.168.0.1 +&NAS-IP-Address := 127.0.0.1 + +sqlippool.renew + +# 2. Verify the gateway was set +if !(%sql("SELECT gateway FROM fr_ippool WHERE pool_name = '%{control.IP-Pool.Name}' AND address = '%{reply.Framed-IP-Address}'") == '127.0.0.1') { + test_fail +} + +# 4. Verify we got an IP +if !(&reply.Framed-IP-Address == 192.168.0.1) { + test_fail +} + +&reply := {} + +test_pass