summaryrefslogtreecommitdiffstats
path: root/src/tests/modules/rest
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/modules/rest')
-rw-r--r--src/tests/modules/rest/all.mk6
-rw-r--r--src/tests/modules/rest/module.conf46
-rw-r--r--src/tests/modules/rest/rest_module.attrs14
-rw-r--r--src/tests/modules/rest/rest_module.unlang111
-rw-r--r--src/tests/modules/rest/rest_xlat.attrs18
-rw-r--r--src/tests/modules/rest/rest_xlat.unlang208
6 files changed, 403 insertions, 0 deletions
diff --git a/src/tests/modules/rest/all.mk b/src/tests/modules/rest/all.mk
new file mode 100644
index 0000000..e2a6133
--- /dev/null
+++ b/src/tests/modules/rest/all.mk
@@ -0,0 +1,6 @@
+#
+# Test the "rest" module
+#
+
+# Don't test smtp if REST_TEST_SERVER ENV is not set
+rest_require_test_server := 1
diff --git a/src/tests/modules/rest/module.conf b/src/tests/modules/rest/module.conf
new file mode 100644
index 0000000..ecfaa53
--- /dev/null
+++ b/src/tests/modules/rest/module.conf
@@ -0,0 +1,46 @@
+#rest unit test config
+json {
+}
+
+rest {
+ tls {
+ ca_info_file = "$ENV{top_srcdir}raddb/restcerts/ca.pem"
+
+ private_key_password = "whatever"
+
+ random_file = /dev/urandom
+
+ check_cert_cn = no
+ }
+
+ connect_uri = "http://$ENV{REST_TEST_SERVER}:$ENV{REST_TEST_SERVER_PORT}/"
+
+ xlat {
+ body_uri_encode = no
+ timeout = 0.5
+ tls = ${..tls}
+ }
+
+ authorize {
+ uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?section=authorize"
+ method = "GET"
+ tls = ${..tls}
+ }
+
+ authenticate {
+ uri = "https://$ENV{REST_TEST_SERVER}:$ENV{REST_TEST_SERVER_SSL_PORT}/auth?section=authenticate"
+ method = "POST"
+ tls = ${..tls}
+ body = 'post'
+ data = 'user=%{User-Name}'
+ auth = 'basic'
+ }
+
+ accounting {
+ uri = "https://$ENV{REST_TEST_SERVER}:$ENV{REST_TEST_SERVER_SSL_PORT}/user/%{User-Name}/mac/%{Called-Station-ID}?action=post-auth&section=accounting"
+ method = 'POST'
+ body = 'json'
+ data = '{"NAS": "%{NAS-IP-Address}", "Password": "%{User-Password}", "Verify": true}'
+ tls = ${..tls}
+ }
+}
diff --git a/src/tests/modules/rest/rest_module.attrs b/src/tests/modules/rest/rest_module.attrs
new file mode 100644
index 0000000..3ecf895
--- /dev/null
+++ b/src/tests/modules/rest/rest_module.attrs
@@ -0,0 +1,14 @@
+#
+# Input packet
+#
+Packet-Type = Access-Request
+User-Name = 'Bob'
+User-Password = 'Saget'
+Called-Station-Id = 'aa:bb:cc:dd:ee:ff'
+NAS-IP-Address = '192.168.1.1'
+
+#
+# Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/rest/rest_module.unlang b/src/tests/modules/rest/rest_module.unlang
new file mode 100644
index 0000000..c78c380
--- /dev/null
+++ b/src/tests/modules/rest/rest_module.unlang
@@ -0,0 +1,111 @@
+# Pre-set Tmp-String-2 to check correct operator behaviour
+update {
+ &control:Tmp-String-2 := "foo"
+}
+
+# Test "authorize" rest call. Uses http to a GET end point
+rest
+
+debug_control
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-0 == "authorize")) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-1 == "GET")) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-1[*] == "/user/<username>/mac/<client>")) {
+ test_fail
+}
+
+if (!(&control:User-Name == "Bob")) {
+ test_fail
+}
+
+# The "op" for setting Tmp-String-2 is ^=
+if (!(&control:Tmp-String-2[0] == "Bob") || !(&control:Tmp-String-2[1] == "foo")) {
+ test_fail
+}
+
+# Reset control attributes
+update control {
+ &Tmp-String-0[*] !* ANY
+ &Tmp-String-1[*] !* ANY
+ &User-Name[*] !* ANY
+}
+
+# Pre-fill NAS-IP-Address to check operator behaviour
+update {
+ &control:NAS-IP-Address := "10.0.0.10"
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# Test "accounting" rest call. Uses https to a POST end point
+rest.accounting
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-0 == "accounting")) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-1 == "POST")) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-1[*] == "/user/<username>/mac/<client>")) {
+ test_fail
+}
+
+if (!(&control:User-Name == "Bob")) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-2[0] == "Bob") || !(&control:Tmp-String-2[1] == "Bob") || !(&control:Tmp-String-2[2] == "foo")) {
+ test_fail
+}
+
+# NAS IP Address is passed in body data
+if (!(&control:NAS-IP-Address[0] == "10.0.0.10") || !(&control:NAS-IP-Address[1] == "192.168.1.1")) {
+ test_fail
+}
+
+debug_control
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# Test "authenticate" rest call. Uses http basic authentication
+rest.authenticate
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&reply:REST-HTTP-Body == "Section: authenticate, User: Bob, Authenticated: true\n")) {
+ test_fail
+}
+
+# Clear up reply
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+test_pass
diff --git a/src/tests/modules/rest/rest_xlat.attrs b/src/tests/modules/rest/rest_xlat.attrs
new file mode 100644
index 0000000..6370197
--- /dev/null
+++ b/src/tests/modules/rest/rest_xlat.attrs
@@ -0,0 +1,18 @@
+#
+# Input packet
+#
+Packet-Type = Access-Request
+User-Name = 'Bob'
+User-Password = 'Saget'
+Called-Station-Id = 'aa:bb:cc:dd:ee:ff'
+NAS-IP-Address = '192.168.1.1'
+Login-IP-Host = 127.0.0.1
+NAS-Port = 8080
+Calling-Station-Id = 'dummy&unsafe=escaped'
+Tmp-String-9 = ''
+
+#
+# Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/rest/rest_xlat.unlang b/src/tests/modules/rest/rest_xlat.unlang
new file mode 100644
index 0000000..52eb597
--- /dev/null
+++ b/src/tests/modules/rest/rest_xlat.unlang
@@ -0,0 +1,208 @@
+#
+# PRE rest_module eval
+#
+# Largely a back port of the rlm_rest tests from v4, with v4 specific functionality removed.
+#
+
+update {
+ &Tmp-String-0 := "$ENV{REST_TEST_SERVER}"
+ &Tmp-Integer-0 := "$ENV{REST_TEST_SERVER_PORT}"
+ &Tmp-Integer-1 := "$ENV{REST_TEST_SERVER_SSL_PORT}"
+ &Tmp-String-1 := "notfound"
+}
+
+# Retrieve a plain text file
+update {
+ &control:Tmp-String-1 := "%{rest:GET http://%{Tmp-String-0}:%{Tmp-Integer-0}/test.txt}"
+}
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&control:Tmp-String-1 == "Sample text response\n")) {
+ test_fail
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# Take host from incomming packet
+update {
+ &control:Tmp-String-1 := "%{rest:http://%{Login-IP-Host}:%{Tmp-Integer-0}/test.txt}"
+}
+
+if (!(&reply:REST-HTTP-Status-Code == 200) || !(&control:Tmp-String-1 == "Sample text response\n")) {
+ test_fail
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# Check a "not found" gives a 404 status code
+update {
+ &control:Tmp-String-1 := "%{rest:GET http://%{Tmp-String-0}:%{Tmp-Integer-0}/%{Tmp-String-1}}"
+}
+
+if (!(&reply:REST-HTTP-Status-Code == 404)) {
+ test_fail
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# GET with URL parameters
+update {
+ &Tmp-String-2 := "%{rest:GET http://%{Tmp-String-0}:%{Tmp-Integer-0}/user/%{User-Name}/mac/%{Called-Station-Id}}"
+}
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&Tmp-String-2 =~ /"control:Tmp-String-1":\["GET","\\\/user\\\/<username>\\\/mac\\\/<client>"\]/)) {
+ test_fail
+}
+
+if (&Tmp-String-2 =~ /"control:User-Name":\{([^}]+)\}/) {
+ if (!("%{1}" =~ /"value":"Bob"/)) {
+ test_fail
+ }
+} else {
+ test_fail
+}
+
+update {
+ &control:Tmp-String-3 := 'dummy'
+}
+
+update {
+ &control:Tmp-String-2 = "%{json_encode:&NAS-IP-Address}"
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# POST to https with JSON body data
+update {
+ &Tmp-String-2 := "%{rest:POST https://%{Tmp-String-0}:%{Tmp-Integer-1}/user/%{User-Name}/mac/%{Called-Station-Id}?section=accounting %{control:Tmp-String-2}}"
+}
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&Tmp-String-2 =~ /"control:Tmp-String-1":\["POST","\\\/user\\\/<username>\\\/mac\\\/<client>"\]/)) {
+ test_fail
+}
+
+if (&Tmp-String-2 =~ /"control:User-Name":\{([^}]+)\}/) {
+ if (!("%{1}" =~ /"value":"Bob"/)) {
+ test_fail
+ }
+} else {
+ test_fail
+}
+
+update {
+ &control:Tmp-String-2 := "NAS=%{NAS-IP-Address}&user=%{User-Name}"
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# POST to https with POST body data
+update {
+ &Tmp-String-2 := "%{rest:POST https://%{Tmp-String-0}:%{Tmp-Integer-1}/post/test?section=dummy %{control:Tmp-String-2}}"
+}
+
+if (!(&reply:REST-HTTP-Status-Code == 200)) {
+ test_fail
+}
+
+if (!(&Tmp-String-2 == "Section: dummy, User: Bob\n")) {
+ test_fail
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# URI with tainted values in the arguments - input argument includes URI argument
+# separator - make sure this doesn't end up generating extra arguments, but gets escaped.
+update {
+ &Tmp-String-2 := "%{rest:GET http://%{Tmp-String-0}:%{Tmp-Integer-0}/user/%{User-Name}/reflect/?station=%{Calling-Station-Id}}"
+}
+
+if (!(&Tmp-String-2 == "{\"station\":\"dummy&unsafe=escaped\"}\n" )) {
+ test_fail
+}
+
+# Zero length untainted value - check parsing doesn't break on zero length string
+update {
+ &Tmp-String-8 := ""
+}
+update {
+ &Tmp-String-2 := "%{rest:http://%{Tmp-String-0}:%{Tmp-Integer-0}/user/%{User-Name}/reflect/%{Tmp-String-8}?station=%{User-Name}}"
+}
+
+if (!(&Tmp-String-2 == "{\"station\":\"Bob\"}\n" )) {
+ test_fail
+}
+
+# Clear previous status code and body
+update reply {
+ &REST-HTTP-Status-Code !* ANY
+ &REST-HTTP-Body !* ANY
+}
+
+# Zero length tainted value - check escaping doesn't break on zero length string
+update {
+ &Tmp-String-2 := "%{rest:http://%{Tmp-String-0}:%{Tmp-Integer-0}/user/%{User-Name}/reflect/%{Tmp-String-9}?station=%{Called-Station-Id}}"
+}
+
+if (!(&Tmp-String-2 == "{\"station\":\"aa:bb:cc:dd:ee:ff\"}\n" )) {
+ test_fail
+}
+
+# Clear previous status code and body
+update reply {
+ REST-HTTP-Status-Code !* ANY
+ REST-HTTP-Body !* ANY
+}
+
+# A request which will take longer than the timeout set for xlats
+update {
+ &Tmp-String-2 := "%{rest:http://%{Tmp-String-0}:%{Tmp-Integer-0}/delay}"
+}
+
+if (&reply:REST-HTTP-Status-Code) {
+ test_fail
+}
+
+if (!(&Tmp-String-2 == "")) {
+ test_fail
+}
+
+if (!(&Module-Failure-Message[*] == 'Request failed: 28 - Timeout was reached')) {
+ test_fail
+}
+
+test_pass