feat: mask client ip in audit log
This commit is contained in:
@@ -26,7 +26,7 @@ return static function (): void {
|
|||||||
];
|
];
|
||||||
|
|
||||||
$clientIp = ClientIp::resolve($_SERVER, $settings);
|
$clientIp = ClientIp::resolve($_SERVER, $settings);
|
||||||
$auditBase['client_ip'] = $clientIp;
|
$auditBase['client_ip'] = $settings->auditClientIp($clientIp);
|
||||||
$createdAt = time();
|
$createdAt = time();
|
||||||
$correlation = KeyName::build($ctx->serverName(), $ctx->username(), $createdAt);
|
$correlation = KeyName::build($ctx->serverName(), $ctx->username(), $createdAt);
|
||||||
$auditBase['correlation'] = $correlation;
|
$auditBase['correlation'] = $correlation;
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ final class Settings
|
|||||||
'MAIL_LOGIN_REDIRECT_URL' => '/',
|
'MAIL_LOGIN_REDIRECT_URL' => '/',
|
||||||
'LOGIN_KEY_TTL' => '30',
|
'LOGIN_KEY_TTL' => '30',
|
||||||
'USER_IP_BOUND' => '1',
|
'USER_IP_BOUND' => '1',
|
||||||
|
'IP_MASK' => '1',
|
||||||
'MAIL_LOGIN_SOURCE_SERVER_NAME' => '',
|
'MAIL_LOGIN_SOURCE_SERVER_NAME' => '',
|
||||||
'MAIL_LOGIN_CLIENT_IP_MODE' => 'direct',
|
'MAIL_LOGIN_CLIENT_IP_MODE' => 'direct',
|
||||||
'MAIL_LOGIN_TRUSTED_PROXIES' => '',
|
'MAIL_LOGIN_TRUSTED_PROXIES' => '',
|
||||||
@@ -135,6 +136,16 @@ final class Settings
|
|||||||
return $this->getString('USER_IP_BOUND', '1') === '1';
|
return $this->getString('USER_IP_BOUND', '1') === '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ipMask(): bool
|
||||||
|
{
|
||||||
|
return $this->getString('IP_MASK', '1') === '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function auditClientIp(string $clientIp): string
|
||||||
|
{
|
||||||
|
return $this->ipMask() ? 'MASLED' : $clientIp;
|
||||||
|
}
|
||||||
|
|
||||||
public function sourceServerName(): string
|
public function sourceServerName(): string
|
||||||
{
|
{
|
||||||
return $this->sanitizeServerName($this->getString('MAIL_LOGIN_SOURCE_SERVER_NAME', ''));
|
return $this->sanitizeServerName($this->getString('MAIL_LOGIN_SOURCE_SERVER_NAME', ''));
|
||||||
@@ -247,6 +258,9 @@ final class Settings
|
|||||||
if (!in_array($this->getString('USER_IP_BOUND', ''), ['0', '1'], true)) {
|
if (!in_array($this->getString('USER_IP_BOUND', ''), ['0', '1'], true)) {
|
||||||
throw new InvalidArgumentException('USER_IP_BOUND must be 0 or 1');
|
throw new InvalidArgumentException('USER_IP_BOUND must be 0 or 1');
|
||||||
}
|
}
|
||||||
|
if (!in_array($this->getString('IP_MASK', ''), ['0', '1'], true)) {
|
||||||
|
throw new InvalidArgumentException('IP_MASK must be 0 or 1');
|
||||||
|
}
|
||||||
if (!in_array(strtolower($this->getString('DEFAULT_ENABLE', 'true')), ['0', '1', 'true', 'false', 'yes', 'no', 'on', 'off'], true)) {
|
if (!in_array(strtolower($this->getString('DEFAULT_ENABLE', 'true')), ['0', '1', 'true', 'false', 'yes', 'no', 'on', 'off'], true)) {
|
||||||
throw new InvalidArgumentException('DEFAULT_ENABLE must be a boolean value');
|
throw new InvalidArgumentException('DEFAULT_ENABLE must be a boolean value');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ LOGIN_KEY_TTL=30
|
|||||||
# 1 = przypnij URL do IP przeglądarki użytkownika, 0 = nie przypinaj do IP.
|
# 1 = przypnij URL do IP przeglądarki użytkownika, 0 = nie przypinaj do IP.
|
||||||
USER_IP_BOUND=1
|
USER_IP_BOUND=1
|
||||||
|
|
||||||
|
# 1 = maskuj IP użytkownika w audit.log jako MASLED, 0 = zapisuj rzeczywiste IP.
|
||||||
|
# To ustawienie nie zmienia IP przekazywanego do DirectAdmin przez --ip.
|
||||||
|
IP_MASK=1
|
||||||
|
|
||||||
# Opcjonalna jawna nazwa źródłowego serwera. Puste = pierwsza etykieta SERVER_NAME.
|
# Opcjonalna jawna nazwa źródłowego serwera. Puste = pierwsza etykieta SERVER_NAME.
|
||||||
MAIL_LOGIN_SOURCE_SERVER_NAME=
|
MAIL_LOGIN_SOURCE_SERVER_NAME=
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ name=mail-login
|
|||||||
id=mail-login
|
id=mail-login
|
||||||
type=user
|
type=user
|
||||||
author=HITME.PL
|
author=HITME.PL
|
||||||
version=1.0.7
|
version=1.0.8
|
||||||
active=no
|
active=no
|
||||||
installed=no
|
installed=no
|
||||||
user_run_as=root
|
user_run_as=root
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ test('plugin metadata and packaging docs match project rules', function (): void
|
|||||||
assert_contains('name=mail-login', $conf);
|
assert_contains('name=mail-login', $conf);
|
||||||
assert_contains('id=mail-login', $conf);
|
assert_contains('id=mail-login', $conf);
|
||||||
assert_contains('type=user', $conf);
|
assert_contains('type=user', $conf);
|
||||||
assert_contains('version=1.0.7', $conf);
|
assert_contains('version=1.0.8', $conf);
|
||||||
assert_contains('user_run_as=root', $conf);
|
assert_contains('user_run_as=root', $conf);
|
||||||
assert_contains('/Users/marek/GPT/ChatGPT/da_plugins/mail-login/src', $packing);
|
assert_contains('/Users/marek/GPT/ChatGPT/da_plugins/mail-login/src', $packing);
|
||||||
assert_contains('/Users/marek/GPT/ChatGPT/da_plugins/mail-login/archives/X.Y.Z/mail-login.tar.gz', $packing);
|
assert_contains('/Users/marek/GPT/ChatGPT/da_plugins/mail-login/archives/X.Y.Z/mail-login.tar.gz', $packing);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ test('settings expose secure defaults from plugin-settings.conf', function (): v
|
|||||||
|
|
||||||
assert_same(30, $settings->loginKeyTtl());
|
assert_same(30, $settings->loginKeyTtl());
|
||||||
assert_true($settings->userIpBound());
|
assert_true($settings->userIpBound());
|
||||||
|
assert_true($settings->ipMask());
|
||||||
|
assert_same('MASLED', $settings->auditClientIp('198.51.100.10'));
|
||||||
assert_true($settings->defaultEnable());
|
assert_true($settings->defaultEnable());
|
||||||
assert_same('login_url', $settings->method());
|
assert_same('login_url', $settings->method());
|
||||||
assert_same(1, $settings->mxLoginMode());
|
assert_same(1, $settings->mxLoginMode());
|
||||||
@@ -34,14 +36,28 @@ test('settings accept explicit ttl and user ip binding toggle', function (): voi
|
|||||||
$settings = Settings::fromArray([
|
$settings = Settings::fromArray([
|
||||||
'LOGIN_KEY_TTL' => '5',
|
'LOGIN_KEY_TTL' => '5',
|
||||||
'USER_IP_BOUND' => '0',
|
'USER_IP_BOUND' => '0',
|
||||||
|
'IP_MASK' => '0',
|
||||||
'MX_LOGIN_MODE' => '2',
|
'MX_LOGIN_MODE' => '2',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert_same(5, $settings->loginKeyTtl());
|
assert_same(5, $settings->loginKeyTtl());
|
||||||
assert_false($settings->userIpBound());
|
assert_false($settings->userIpBound());
|
||||||
|
assert_false($settings->ipMask());
|
||||||
|
assert_same('198.51.100.10', $settings->auditClientIp('198.51.100.10'));
|
||||||
assert_same(2, $settings->mxLoginMode());
|
assert_same(2, $settings->mxLoginMode());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('settings reject unsupported ip mask values', function (): void {
|
||||||
|
foreach (['yes', '2', ''] as $mask) {
|
||||||
|
try {
|
||||||
|
Settings::fromArray(['IP_MASK' => $mask]);
|
||||||
|
throw new RuntimeException('Expected invalid IP_MASK to fail: ' . $mask);
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
assert_contains('IP_MASK', $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('settings reject unsupported mx login mode values', function (): void {
|
test('settings reject unsupported mx login mode values', function (): void {
|
||||||
foreach (['0', '3', 'helper', ''] as $mode) {
|
foreach (['0', '3', 'helper', ''] as $mode) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user