Commit 277df1f9 authored by Geoff Simmons's avatar Geoff Simmons

a TTL > 0 is required in the policy constructor when the type is TOKEN,

but may be left out for the other types
parent f2dded65
Pipeline #115 skipped
......@@ -26,7 +26,7 @@ import hoailona [from "path"] ;
::
new OBJECT = hoailona.policy(ENUM type, DURATION ttl
new OBJECT = hoailona.policy(ENUM type [, DURATION ttl]
[, STRING description] [, BLOB secret]
[, INT start_offset])
......@@ -81,9 +81,10 @@ of Hawaiian about the choice of the name.
Defining policies
-----------------
Policies are defined by means of ``policy`` objects that are constructed
in ``vcl_init``. A policy is defined by its type (TOKEN, OPEN or DENY),
a TTL, and possibly a shared secret used for authorization. For example::
Policies are defined by means of ``policy`` objects that are
constructed in ``vcl_init``. A policy is defined by its type (TOKEN,
OPEN or DENY), a TTL for the TOKEN type, and possibly a shared secret
used for authorization. For example::
import hoailona;
import blobcode;
......@@ -96,10 +97,10 @@ a TTL, and possibly a shared secret used for authorization. For example::
blobcode.decode(encoded="secret"));
# Define a policy for open access (authorization not required)
new open_policy = hoailona.policy(OPEN, 1h);
new open_policy = hoailona.policy(OPEN);
# Define an "access denied" policy
new deny_policy = hoailona.policy(DENY, 1h);
new deny_policy = hoailona.policy(DENY);
}
Policy objects have no methods; they become useful when they are
......@@ -239,15 +240,18 @@ policy
::
new OBJ = policy(PRIV_TASK, ENUM {OPEN,DENY,TOKEN} type, DURATION ttl, STRING description=0, BLOB secret=0, INT start_offset=0)
new OBJ = policy(PRIV_TASK, ENUM {OPEN,DENY,TOKEN} type, DURATION ttl=0, STRING description=0, BLOB secret=0, INT start_offset=0)
Create a policy. The ``type`` enum classifies the policy as ``OPEN``,
``DENY`` or ``TOKEN``, and ``ttl`` determines the length of time for
which token authorization is valid by default. Unless the TTL is
overriden, strings generated by the ``hosts.token()`` method contain
parameters (epoch times) that define the duration of the authorization
to correspond with ``ttl``. The ``type`` and ``ttl`` parameters are
required.
Create a policy. The ``type`` enum is required, to classify the policy
as ``OPEN``, ``DENY`` or ``TOKEN``.
When ``TOKEN`` is specified, then a ``ttl`` greater than 0 MUST be
specified; the TTL has no effect for the ``OPEN`` and ``DENY`` types
and may be left out. The TTL determines the length of time for which
token authorization is valid by default. Unless the TTL is overriden,
strings generated by the ``hosts.token()`` method contain parameters
(epoch times) that define the duration of the authorization to
correspond with ``ttl``.
The optional ``secret`` parameter may contain a shared secret for
authorization, which serves as the key for an HMAC. The data type for
......@@ -275,7 +279,7 @@ unsynchronized clocks).
Examples::
# Open policy, no authorization required
new open = hoailona.policy(OPEN, 1h);
new open = hoailona.policy(OPEN);
# Token authorization required, where authorization lasts 2 hours,
# using the given shared secret, and setting the start offset to
......@@ -289,7 +293,7 @@ Examples::
"717569636B2062726F776E20666F7879"));
# A policy for "access denied"
new forbid = hoailona.policy(DENY, 1h, description="access denied");
new forbid = hoailona.policy(DENY, description="access denied");
.. _obj_hosts:
......@@ -411,11 +415,11 @@ description is set.
Examples::
sub vcl_init {
new p1 = hoailona.policy(OPEN, 1h);
new p1 = hoailona.policy(OPEN);
new p2 = hoailona.policy(TOKEN, 1h);
new p3 = hoailona.policy(TOKEN, 2h);
new p4 = hoailona.policy(TOKEN, 3h);
new deny = hoailona.policy(DENY, 1h);
new deny = hoailona.policy(DENY);
new h = hoailona.hosts();
......
......@@ -7,9 +7,9 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new r = hoailona.policy(DENY, 3h);
new r = hoailona.policy(DENY);
new h = hoailona.hosts();
h.add("example.com", "q", "/*/...");
h.add(host="example.org", policy="p");
......@@ -23,7 +23,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
}
......@@ -48,7 +48,7 @@ varnish v1 -errvcl {vmod hoailona error: host is empty in h.add()} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("", "p", "/foo/bar");
}
......@@ -59,7 +59,7 @@ varnish v1 -errvcl {vmod hoailona error: policy is empty in h.add()} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "", "/foo/bar");
}
......@@ -70,7 +70,7 @@ varnish v1 -errvcl {vmod hoailona error: path is set but empty in h.add()} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p", "");
}
......@@ -81,7 +81,7 @@ varnish v1 -errvcl {vmod hoailona error: path ""<>?\^`| in h.add(): invalid char
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p", {"""<>?\^`|"});
}
......@@ -92,7 +92,7 @@ varnish v1 -errvcl {vmod hoailona error: path /x... in h.add(): ... must only be
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p", "/x...");
}
......@@ -103,7 +103,7 @@ varnish v1 -errvcl {vmod hoailona error: path /.../...x in h.add(): ... must onl
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p", "/.../...x");
}
......@@ -114,7 +114,7 @@ varnish v1 -errvcl {vmod hoailona error: path /x/**/y in h.add(): more than one
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p", "/x/**/y");
}
......@@ -135,7 +135,7 @@ varnish v1 -errvcl {vmod hoailona error: Policy object q not found in h.add()} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "q", "/x/y");
}
......@@ -146,7 +146,7 @@ varnish v1 -errvcl {vmod hoailona error: Policy p already set globally for host
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p");
......@@ -159,7 +159,7 @@ varnish v1 -errvcl {vmod hoailona error: Path-specific policies already set for
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -172,7 +172,7 @@ varnish v1 -errvcl {vmod hoailona error: Policy p already assigned for host exam
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -187,7 +187,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -200,7 +200,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -226,7 +226,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -239,7 +239,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", ".../bar");
......@@ -252,7 +252,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -265,7 +265,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -279,7 +279,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("*example.com", "p");
h.add("EXAMPLE-EXAMPLE.EXAMPLE.COM", "p");
......@@ -292,7 +292,7 @@ varnish v1 -errvcl {invalid hostname -example.com: may not begin with - or .} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("-example.com", "p");
}
......@@ -303,7 +303,7 @@ varnish v1 -errvcl {invalid hostname .example.com: may not begin with - or .} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add(".example.com", "p");
}
......@@ -314,7 +314,7 @@ varnish v1 -errvcl {invalid hostname *.*.example.com: illegal characters} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("*.*.example.com", "p");
}
......@@ -325,7 +325,7 @@ varnish v1 -errvcl {invalid hostname example-%.com: illegal characters} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example-%.com", "p");
}
......@@ -336,7 +336,7 @@ varnish v1 -errvcl {invalid hostname example-ä.com: illegal characters} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example-ä.com", "p");
}
......
......@@ -8,7 +8,7 @@ varnish v1 -vcl {
sub vcl_init {
new p1 = hoailona.policy(TOKEN, 1h);
new p2 = hoailona.policy(OPEN, 1h, description="open");
new p2 = hoailona.policy(OPEN, description="open");
new h = hoailona.hosts();
h.add("example.com", "p1");
h.add("example.org", "p2");
......
......@@ -7,9 +7,9 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new r = hoailona.policy(DENY, 3h);
new r = hoailona.policy(DENY);
new h = hoailona.hosts();
h.add("example.com", "q", "/foo/bar");
h.add(host="example.org", policy="p");
......@@ -42,7 +42,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/z/...");
......@@ -83,7 +83,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p");
......@@ -119,7 +119,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar");
......@@ -153,7 +153,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/bar/...");
......@@ -187,7 +187,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/*/bar");
......@@ -229,7 +229,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/*/bar/...");
......@@ -273,7 +273,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", ".../foo/bar");
......@@ -307,7 +307,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/.../bar");
......@@ -347,7 +347,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new q = hoailona.policy(TOKEN, 2h);
new h = hoailona.hosts();
h.add("example.com", "p", "/foo/./bar");
......@@ -384,7 +384,7 @@ varnish v1 -errvcl {h.policy() may not be called in vcl_init} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p");
if (h.policy("example.com", "/foo") != 1) {
......@@ -398,7 +398,7 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p");
}
......
......@@ -11,12 +11,12 @@ varnish v1 -vcl {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p1 = hoailona.policy(OPEN, 1h);
new p1 = hoailona.policy(OPEN);
new p2 = hoailona.policy(TOKEN, 2h);
new p3 = hoailona.policy(DENY, 3h);
new p3 = hoailona.policy(DENY);
new p4 = hoailona.policy(TOKEN, 1h, description="policy p4");
new p5 = hoailona.policy(OPEN, 1h, start_offset= 0-10);
new p6 = hoailona.policy(DENY, 1h,
new p5 = hoailona.policy(OPEN, start_offset= 0-10);
new p6 = hoailona.policy(DENY,
secret=blobcode.decode(encoded="foo"));
new p7 = hoailona.policy(TOKEN, 1h, "p7",
blobcode.decode(encoded="bar"), 0-30);
......@@ -27,3 +27,12 @@ varnish v1 -vcl { backend b { .host = "${bad_ip}"; } }
# Runs fini
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -errvcl {ttl must be >= 0 when type is TOKEN in p constructor} {
import hoailona from "${vmod_topbuild}/src/.libs/libvmod_hoailona.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(TOKEN);
}
}
......@@ -41,7 +41,7 @@ varnish v1 -errvcl {h.secret() may not be called in vcl_init} {
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = hoailona.policy(OPEN, 1h);
new p = hoailona.policy(OPEN);
new h = hoailona.hosts();
if (blobcode.encode(blob=h.secret()) == "foo") {
return(fail);
......
......@@ -174,7 +174,7 @@ varnish v1 -vcl {
sub vcl_init {
new p = hoailona.policy(TOKEN, 1h);
new q = hoailona.policy(OPEN, 1h);
new q = hoailona.policy(OPEN);
new h = hoailona.hosts();
h.add("example.com", "p");
h.add("example.org", "q");
......
......@@ -170,8 +170,6 @@ vmod_policy__init(VRT_CTX, struct vmod_hoailona_policy **policyp,
vcl_name);
return;
}
item->policy = policy;
VSLIST_INSERT_HEAD(policyhead, item, list);
if (strcmp(policys, "DENY") == 0)
policy->type = DENY;
......@@ -181,6 +179,15 @@ vmod_policy__init(VRT_CTX, struct vmod_hoailona_policy **policyp,
policy->type = TOKEN;
else
WRONG("illegal policy enum");
if (policy->type == TOKEN && ttl <= 0.) {
VERR(ctx, "ttl must be >= 0 when type is TOKEN "
"in %s constructor", vcl_name);
return;
}
item->policy = policy;
VSLIST_INSERT_HEAD(policyhead, item, list);
policy->vcl_name = strdup(vcl_name);
AN(policy->vcl_name);
if (description != NULL)
......
......@@ -9,7 +9,7 @@ $Module hoailona 3 Akamai SecureHD Token Authorization VMOD
::
new OBJECT = hoailona.policy(ENUM type, DURATION ttl
new OBJECT = hoailona.policy(ENUM type [, DURATION ttl]
[, STRING description] [, BLOB secret]
[, INT start_offset])
......@@ -64,9 +64,10 @@ of Hawaiian about the choice of the name.
Defining policies
-----------------
Policies are defined by means of ``policy`` objects that are constructed
in ``vcl_init``. A policy is defined by its type (TOKEN, OPEN or DENY),
a TTL, and possibly a shared secret used for authorization. For example::
Policies are defined by means of ``policy`` objects that are
constructed in ``vcl_init``. A policy is defined by its type (TOKEN,
OPEN or DENY), a TTL for the TOKEN type, and possibly a shared secret
used for authorization. For example::
import hoailona;
import blobcode;
......@@ -79,10 +80,10 @@ a TTL, and possibly a shared secret used for authorization. For example::
blobcode.decode(encoded="secret"));
# Define a policy for open access (authorization not required)
new open_policy = hoailona.policy(OPEN, 1h);
new open_policy = hoailona.policy(OPEN);
# Define an "access denied" policy
new deny_policy = hoailona.policy(DENY, 1h);
new deny_policy = hoailona.policy(DENY);
}
Policy objects have no methods; they become useful when they are
......@@ -208,16 +209,19 @@ subroutines, subsequent calls to ``.token()`` and ``.secret()`` in the
same backend transaction are based on the policy that was determined
by that call.
$Object policy(PRIV_TASK, ENUM {OPEN, DENY, TOKEN} type, DURATION ttl,
$Object policy(PRIV_TASK, ENUM {OPEN, DENY, TOKEN} type, DURATION ttl=0,
STRING description=0, BLOB secret=0, INT start_offset=0)
Create a policy. The ``type`` enum classifies the policy as ``OPEN``,
``DENY`` or ``TOKEN``, and ``ttl`` determines the length of time for
which token authorization is valid by default. Unless the TTL is
overriden, strings generated by the ``hosts.token()`` method contain
parameters (epoch times) that define the duration of the authorization
to correspond with ``ttl``. The ``type`` and ``ttl`` parameters are
required.
Create a policy. The ``type`` enum is required, to classify the policy
as ``OPEN``, ``DENY`` or ``TOKEN``.
When ``TOKEN`` is specified, then a ``ttl`` greater than 0 MUST be
specified; the TTL has no effect for the ``OPEN`` and ``DENY`` types
and may be left out. The TTL determines the length of time for which
token authorization is valid by default. Unless the TTL is overriden,
strings generated by the ``hosts.token()`` method contain parameters
(epoch times) that define the duration of the authorization to
correspond with ``ttl``.
The optional ``secret`` parameter may contain a shared secret for
authorization, which serves as the key for an HMAC. The data type for
......@@ -245,7 +249,7 @@ unsynchronized clocks).
Examples::
# Open policy, no authorization required
new open = hoailona.policy(OPEN, 1h);
new open = hoailona.policy(OPEN);
# Token authorization required, where authorization lasts 2 hours,
# using the given shared secret, and setting the start offset to
......@@ -259,7 +263,7 @@ Examples::
"717569636B2062726F776E20666F7879"));
# A policy for "access denied"
new forbid = hoailona.policy(DENY, 1h, description="access denied");
new forbid = hoailona.policy(DENY, description="access denied");
$Object hosts()
......@@ -368,11 +372,11 @@ description is set.
Examples::
sub vcl_init {
new p1 = hoailona.policy(OPEN, 1h);
new p1 = hoailona.policy(OPEN);
new p2 = hoailona.policy(TOKEN, 1h);
new p3 = hoailona.policy(TOKEN, 2h);
new p4 = hoailona.policy(TOKEN, 3h);
new deny = hoailona.policy(DENY, 1h);
new deny = hoailona.policy(DENY);
new h = hoailona.hosts();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment