diff options
Diffstat (limited to 'src/tests/modules/rest')
-rw-r--r-- | src/tests/modules/rest/all.mk | 6 | ||||
-rw-r--r-- | src/tests/modules/rest/module.conf | 46 | ||||
-rw-r--r-- | src/tests/modules/rest/rest_module.attrs | 14 | ||||
-rw-r--r-- | src/tests/modules/rest/rest_module.unlang | 111 | ||||
-rw-r--r-- | src/tests/modules/rest/rest_xlat.attrs | 18 | ||||
-rw-r--r-- | src/tests/modules/rest/rest_xlat.unlang | 208 |
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§ion=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 |