Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120825147
PolicyTest.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
17 KB
Referenced Files
None
Subscribers
None
PolicyTest.php
View Options
<?php
namespace
Tests\Feature\Controller
;
use
App\Domain
;
use
App\IP4Net
;
use
App\Policy\Greylist
;
use
App\Policy\Mailfilter
;
use
Carbon\Carbon
;
use
Tests\TestCase
;
class
PolicyTest
extends
TestCase
{
private
$clientAddress
;
private
$net
;
private
$testUser
;
private
$testDomain
;
protected
function
setUp
():
void
{
parent
::
setUp
();
$this
->
clientAddress
=
'128.0.0.100'
;
$this
->
net
=
IP4Net
::
create
([
'net_number'
=>
'128.0.0.0'
,
'net_broadcast'
=>
'128.255.255.255'
,
'net_mask'
=>
8
,
'country'
=>
'US'
,
'rir_name'
=>
'test'
,
'serial'
=>
1
,
]);
$this
->
testDomain
=
$this
->
getTestDomain
(
'test.domain'
,
[
'type'
=>
Domain
::
TYPE_EXTERNAL
,
'status'
=>
Domain
::
STATUS_ACTIVE
|
Domain
::
STATUS_CONFIRMED
|
Domain
::
STATUS_VERIFIED
,
]);
$this
->
testUser
=
$this
->
getTestUser
(
'john@test.domain'
);
Greylist\Connect
::
where
(
'sender_domain'
,
'sender.domain'
)->
delete
();
Greylist\Whitelist
::
where
(
'sender_domain'
,
'sender.domain'
)->
delete
();
$this
->
useServicesUrl
();
}
protected
function
tearDown
():
void
{
$this
->
deleteTestGroup
(
'group-test@kolab.org'
);
$this
->
deleteTestUser
(
$this
->
testUser
->
email
);
$this
->
deleteTestDomain
(
$this
->
testDomain
->
namespace
);
$this
->
net
->
delete
();
Greylist\Connect
::
where
(
'sender_domain'
,
'sender.domain'
)->
delete
();
Greylist\Whitelist
::
where
(
'sender_domain'
,
'sender.domain'
)->
delete
();
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
$john
->
settings
()
->
whereIn
(
'key'
,
[
'password_policy'
,
'max_password_age'
,
'itip_policy'
,
'externalsender_policy'
])->
delete
();
parent
::
tearDown
();
}
/**
* Test password policy check
*/
public
function
testCheckPassword
():
void
{
$this
->
useRegularUrl
();
$jack
=
$this
->
getTestUser
(
'jack@kolab.org'
);
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
$john
->
setSetting
(
'password_policy'
,
'min:8,max:100,upper,digit'
);
// Empty password
$post
=
[
'user'
=>
$john
->
id
];
$response
=
$this
->
post
(
'/api/auth/password-policy-check'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertCount
(
3
,
$json
);
$this
->
assertSame
(
'error'
,
$json
[
'status'
]);
$this
->
assertSame
(
4
,
$json
[
'count'
]);
$this
->
assertFalse
(
$json
[
'list'
][
0
][
'status'
]);
$this
->
assertSame
(
'min'
,
$json
[
'list'
][
0
][
'label'
]);
$this
->
assertFalse
(
$json
[
'list'
][
1
][
'status'
]);
$this
->
assertSame
(
'max'
,
$json
[
'list'
][
1
][
'label'
]);
$this
->
assertFalse
(
$json
[
'list'
][
2
][
'status'
]);
$this
->
assertSame
(
'upper'
,
$json
[
'list'
][
2
][
'label'
]);
$this
->
assertFalse
(
$json
[
'list'
][
3
][
'status'
]);
$this
->
assertSame
(
'digit'
,
$json
[
'list'
][
3
][
'label'
]);
// Test acting as Jack, password non-compliant
$post
=
[
'password'
=>
'9999999'
,
'user'
=>
$jack
->
id
];
$response
=
$this
->
post
(
'/api/auth/password-policy-check'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertCount
(
3
,
$json
);
$this
->
assertSame
(
'error'
,
$json
[
'status'
]);
$this
->
assertSame
(
4
,
$json
[
'count'
]);
$this
->
assertFalse
(
$json
[
'list'
][
0
][
'status'
]);
// min
$this
->
assertTrue
(
$json
[
'list'
][
1
][
'status'
]);
// max
$this
->
assertFalse
(
$json
[
'list'
][
2
][
'status'
]);
// upper
$this
->
assertTrue
(
$json
[
'list'
][
3
][
'status'
]);
// digit
// Test with no user context, expect use of the default policy
$post
=
[
'password'
=>
'9'
];
$response
=
$this
->
post
(
'/api/auth/password-policy-check'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertCount
(
3
,
$json
);
$this
->
assertSame
(
'error'
,
$json
[
'status'
]);
$this
->
assertSame
(
2
,
$json
[
'count'
]);
$this
->
assertFalse
(
$json
[
'list'
][
0
][
'status'
]);
$this
->
assertSame
(
'min'
,
$json
[
'list'
][
0
][
'label'
]);
$this
->
assertTrue
(
$json
[
'list'
][
1
][
'status'
]);
$this
->
assertSame
(
'max'
,
$json
[
'list'
][
1
][
'label'
]);
}
/**
* Test greylist policy webhook
*/
public
function
testGreylist
()
{
// Note: Only basic tests here. More detailed policy handler tests are in another place
// Test 403 response
$post
=
[
'sender'
=>
'someone@sender.domain'
,
'recipient'
=>
$this
->
testUser
->
email
,
'client_address'
=>
$this
->
clientAddress
,
'client_name'
=>
'some.mx'
,
];
$response
=
$this
->
post
(
'/api/webhooks/policy/greylist'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DEFER_IF_PERMIT'
,
$json
[
'response'
]);
$this
->
assertSame
(
"Greylisted for 5 minutes. Try again later."
,
$json
[
'reason'
]);
// Test 200 response
$connect
=
Greylist\Connect
::
where
(
'sender_domain'
,
'sender.domain'
)->
first
();
$connect
->
created_at
=
Carbon
::
now
()->
subMinutes
(
6
);
$connect
->
save
();
$response
=
$this
->
post
(
'/api/webhooks/policy/greylist'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DUNNO'
,
$json
[
'response'
]);
$this
->
assertMatchesRegularExpression
(
'/^Received-Greylist: greylisted from/'
,
$json
[
'prepend'
][
0
]);
}
/**
* Test fetching account 'password' policies
*/
public
function
testIndexPassword
():
void
{
$this
->
useRegularUrl
();
$jack
=
$this
->
getTestUser
(
'jack@kolab.org'
);
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
$john
->
setSetting
(
'password_policy'
,
'min:8,max:255,special'
);
$john
->
setSetting
(
'max_password_age'
,
6
);
// Unauth access not allowed
$response
=
$this
->
get
(
'/api/v4/policies'
);
$response
->
assertStatus
(
401
);
// Test acting as non-controller
$response
=
$this
->
actingAs
(
$jack
)->
get
(
'/api/v4/policies'
);
$response
->
assertStatus
(
403
);
// Get available policy rules
$response
=
$this
->
actingAs
(
$john
)->
get
(
'/api/v4/policies'
);
$json
=
$response
->
json
();
$response
->
assertStatus
(
200
);
$this
->
assertCount
(
7
,
$json
[
'password'
]);
$this
->
assertSame
(
'6'
,
$json
[
'config'
][
'max_password_age'
]);
$this
->
assertSame
(
'Minimum password length: 8 characters'
,
$json
[
'password'
][
0
][
'name'
]);
$this
->
assertSame
(
'min'
,
$json
[
'password'
][
0
][
'label'
]);
$this
->
assertSame
(
'8'
,
$json
[
'password'
][
0
][
'param'
]);
$this
->
assertTrue
(
$json
[
'password'
][
0
][
'enabled'
]);
$this
->
assertSame
(
'Maximum password length: 255 characters'
,
$json
[
'password'
][
1
][
'name'
]);
$this
->
assertSame
(
'max'
,
$json
[
'password'
][
1
][
'label'
]);
$this
->
assertSame
(
'255'
,
$json
[
'password'
][
1
][
'param'
]);
$this
->
assertTrue
(
$json
[
'password'
][
1
][
'enabled'
]);
$this
->
assertSame
(
'lower'
,
$json
[
'password'
][
2
][
'label'
]);
$this
->
assertFalse
(
$json
[
'password'
][
2
][
'enabled'
]);
$this
->
assertSame
(
'upper'
,
$json
[
'password'
][
3
][
'label'
]);
$this
->
assertFalse
(
$json
[
'password'
][
3
][
'enabled'
]);
$this
->
assertSame
(
'digit'
,
$json
[
'password'
][
4
][
'label'
]);
$this
->
assertFalse
(
$json
[
'password'
][
4
][
'enabled'
]);
$this
->
assertSame
(
'special'
,
$json
[
'password'
][
5
][
'label'
]);
$this
->
assertTrue
(
$json
[
'password'
][
5
][
'enabled'
]);
$this
->
assertSame
(
'last'
,
$json
[
'password'
][
6
][
'label'
]);
$this
->
assertFalse
(
$json
[
'password'
][
6
][
'enabled'
]);
}
/**
* Test fetching account 'mailDelivery' policies
*/
public
function
testIndexMailDelivery
():
void
{
$this
->
useRegularUrl
();
$keys
=
[
'greylist_policy'
,
'itip_policy'
,
'externalsender_policy'
,
'externalsender_policy_domains'
];
$jack
=
$this
->
getTestUser
(
'jack@kolab.org'
);
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
$john
->
settings
()->
whereIn
(
'key'
,
$keys
)->
delete
();
// Unauth access not allowed
$response
=
$this
->
get
(
'/api/v4/policies'
);
$response
->
assertStatus
(
401
);
// Test acting as non-controller
$response
=
$this
->
actingAs
(
$jack
)->
get
(
'/api/v4/policies'
);
$response
->
assertStatus
(
403
);
// Get polcies when mailfilter is disabled
\config
([
'app.with_mailfilter'
=>
false
]);
$response
=
$this
->
actingAs
(
$john
)->
get
(
'/api/v4/policies'
);
$json
=
$response
->
json
();
$response
->
assertStatus
(
200
);
$this
->
assertSame
([
'greylist_policy'
],
$json
[
'mailDelivery'
]);
$this
->
assertTrue
(
$json
[
'config'
][
'greylist_policy'
]);
// Get polcies when mailfilter is enabled
\config
([
'app.with_mailfilter'
=>
true
]);
$john
->
setConfig
([
'externalsender_policy'
=>
true
]);
$response
=
$this
->
actingAs
(
$john
)->
get
(
'/api/v4/policies'
);
$json
=
$response
->
json
();
$response
->
assertStatus
(
200
);
$this
->
assertSame
(
$keys
,
$json
[
'mailDelivery'
]);
$this
->
assertFalse
(
$json
[
'config'
][
'itip_policy'
]);
$this
->
assertTrue
(
$json
[
'config'
][
'greylist_policy'
]);
$this
->
assertTrue
(
$json
[
'config'
][
'externalsender_policy'
]);
$this
->
assertSame
([],
$json
[
'config'
][
'externalsender_policy_domains'
]);
}
/**
* Test mail filter (POST /api/webhooks/policy/mail/filter)
*/
public
function
testMailfilter
()
{
// Note: Only basic tests here. More detailed policy handler tests are in another place
$headers
=
[
'CONTENT_TYPE'
=>
'message/rfc822'
];
$post
=
file_get_contents
(
self
::
BASE_DIR
.
'/data/mail/1.eml'
);
$post
=
str_replace
(
"
\n
"
,
"
\r\n
"
,
$post
);
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
// Basic test, no changes to the mail content
$url
=
'/api/webhooks/policy/mail/filter?recipient=john@kolab.org&sender=jack@kolab.org'
;
$response
=
$this
->
call
(
'POST'
,
$url
,
[],
[],
[],
$headers
,
$post
)
->
assertNoContent
(
200
)
->
assertHeader
(
Mailfilter
::
HEADER
,
Mailfilter
::
HEADER_ACTION_ACCEPT_EMPTY
);
// Test returning (modified) mail content
$john
->
setConfig
([
'externalsender_policy'
=>
true
,
'itip_policy'
=>
true
]);
$url
=
'/api/webhooks/policy/mail/filter?recipient=john@kolab.org&sender=jack@external.tld'
;
$content
=
$this
->
call
(
'POST'
,
$url
,
[],
[],
[],
$headers
,
$post
)
->
assertStatus
(
200
)
->
assertHeader
(
'Content-Type'
,
'message/rfc822'
)
->
streamedContent
();
$this
->
assertStringContainsString
(
'Subject: [EXTERNAL] test sync'
,
$content
);
}
/**
* Test mail reception policy webhook
*/
public
function
testReception
()
{
// Note: Only basic tests here. More detailed policy handler tests are in another place
// Test 403 response
$post
=
[
'sender'
=>
'someone@sender.domain'
,
'recipient'
=>
$this
->
testUser
->
email
,
'client_address'
=>
$this
->
clientAddress
,
'client_name'
=>
'some.mx'
,
];
$response
=
$this
->
post
(
'/api/webhooks/policy/reception'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DEFER_IF_PERMIT'
,
$json
[
'response'
]);
$this
->
assertSame
(
"Greylisted for 5 minutes. Try again later."
,
$json
[
'reason'
]);
// Test 200 response
$connect
=
Greylist\Connect
::
where
(
'sender_domain'
,
'sender.domain'
)->
first
();
$connect
->
created_at
=
Carbon
::
now
()->
subMinutes
(
6
);
$connect
->
save
();
$response
=
$this
->
post
(
'/api/webhooks/policy/reception'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DUNNO'
,
$json
[
'response'
]);
$this
->
assertMatchesRegularExpression
(
'/^Received-Greylist: greylisted from/'
,
$json
[
'prepend'
][
0
]);
// Test sender access check (403)
$group
=
$this
->
getTestGroup
(
'group-test@kolab.org'
);
$group
->
setConfig
([
'sender_policy'
=>
[
'aaa.pl'
]]);
$post
[
'recipient'
]
=
$group
->
email
;
$response
=
$this
->
post
(
'/api/webhooks/policy/reception'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertCount
(
2
,
$json
);
$this
->
assertSame
(
'REJECT'
,
$json
[
'response'
]);
$this
->
assertSame
(
'Invalid recipient'
,
$json
[
'reason'
]);
}
/**
* Test submission policy webhook
*/
public
function
testSubmission
()
{
// Note: Only basic tests here. More detailed policy handler tests are in another place
// Test invalid sender
$post
=
[
'sender'
=>
'sender'
,
'recipients'
=>
[
'recipient@gmail.com'
],
];
$response
=
$this
->
post
(
'/api/webhooks/policy/submission'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'REJECT'
,
$json
[
'response'
]);
$this
->
assertSame
(
"Invalid sender"
,
$json
[
'reason'
]);
// Test invalid user
$post
=
[
'user'
=>
'unknown'
,
'sender'
=>
$this
->
testUser
->
email
,
'recipients'
=>
[
'recipient@gmail.com'
],
];
$response
=
$this
->
post
(
'/api/webhooks/policy/submission'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'REJECT'
,
$json
[
'response'
]);
$this
->
assertSame
(
"Invalid user"
,
$json
[
'reason'
]);
// Test unknown user
$post
=
[
'user'
=>
'unknown@domain.tld'
,
'sender'
=>
'john+test@test.domain'
,
'recipients'
=>
[
'recipient@gmail.com'
],
];
$response
=
$this
->
post
(
'/api/webhooks/policy/submission'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'REJECT'
,
$json
[
'response'
]);
$this
->
assertSame
(
"Could not find user {$post['user']}"
,
$json
[
'reason'
]);
// Test existing user and an invalid sender address
$post
=
[
'user'
=>
'john@test.domain'
,
'sender'
=>
'john1@test.domain'
,
'recipients'
=>
[
'recipient@gmail.com'
],
];
$response
=
$this
->
post
(
'/api/webhooks/policy/submission'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'REJECT'
,
$json
[
'response'
]);
$this
->
assertSame
(
"john@test.domain is unauthorized to send mail as john1@test.domain"
,
$json
[
'reason'
]);
// Test existing user with a valid sender address
$post
=
[
'user'
=>
'john@test.domain'
,
'sender'
=>
'john+test@test.domain'
,
'recipients'
=>
[
'recipient@gmail.com'
],
];
$response
=
$this
->
post
(
'/api/webhooks/policy/submission'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DUNNO'
,
$json
[
'response'
]);
}
/**
* Test ratelimit policy webhook
*/
public
function
testRatelimit
()
{
// Note: Only basic tests here. More detailed policy handler tests are in another place
// Test a valid user
$post
=
[
'sender'
=>
$this
->
testUser
->
email
,
'recipients'
=>
'someone@sender.domain'
,
];
$response
=
$this
->
post
(
'/api/webhooks/policy/ratelimit'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DUNNO'
,
$json
[
'response'
]);
// Test invalid sender
$post
[
'sender'
]
=
'non-existing'
;
$response
=
$this
->
post
(
'/api/webhooks/policy/ratelimit'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'HOLD'
,
$json
[
'response'
]);
$this
->
assertSame
(
'Invalid sender email'
,
$json
[
'reason'
]);
// Test unknown sender
$post
[
'sender'
]
=
'non-existing@example.com'
;
$response
=
$this
->
post
(
'/api/webhooks/policy/ratelimit'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DUNNO'
,
$json
[
'response'
]);
// Test alias sender
$this
->
testUser
->
suspend
();
$this
->
testUser
->
aliases
()->
create
([
'alias'
=>
'alias@test.domain'
]);
$post
[
'sender'
]
=
'alias@test.domain'
;
$response
=
$this
->
post
(
'/api/webhooks/policy/ratelimit'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'HOLD'
,
$json
[
'response'
]);
$this
->
assertSame
(
'Sender deleted or suspended'
,
$json
[
'reason'
]);
// Test app.ratelimit_whitelist
\config
([
'app.ratelimit_whitelist'
=>
[
'alias@test.domain'
]]);
$response
=
$this
->
post
(
'/api/webhooks/policy/ratelimit'
,
$post
);
$response
->
assertStatus
(
200
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'DUNNO'
,
$json
[
'response'
]);
}
/**
* Test SPF webhook
*
* @group data
* @group skipci
*/
public
function
testSenderPolicyFramework
():
void
{
// Note: Only basic tests here. More detailed policy handler tests are in another place
// TODO: Make a test that does not depend on data/dns (remove skipci)
// Test a valid user
$post
=
[
'instance'
=>
'test.local.instance'
,
'protocol_state'
=>
'RCPT'
,
'sender'
=>
'sender@spf-fail.kolab.org'
,
'client_name'
=>
'mx.kolabnow.com'
,
'client_address'
=>
'212.103.80.148'
,
'recipient'
=>
$this
->
testUser
->
email
,
];
$response
=
$this
->
post
(
'/api/webhooks/policy/spf'
,
$post
);
$response
->
assertStatus
(
403
);
$json
=
$response
->
json
();
$this
->
assertSame
(
'REJECT'
,
$json
[
'response'
]);
$this
->
assertSame
(
'Prohibited by Sender Policy Framework'
,
$json
[
'reason'
]);
$this
->
assertSame
([
'Received-SPF: Fail identity=mailfrom; client-ip=212.103.80.148;'
.
' helo=mx.kolabnow.com; envelope-from=sender@spf-fail.kolab.org;'
],
$json
[
'prepend'
]);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Apr 24, 10:33 AM (13 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18857566
Default Alt Text
PolicyTest.php (17 KB)
Attached To
Mode
rK kolab
Attached
Detach File
Event Timeline