SNMP Capabilities (#13289)

* SNMP Capabilities
Allow all available auth algorithms to be set in global settings
cleanup other usages

* fix style
This commit is contained in:
Tony Murray
2021-09-28 18:35:59 -05:00
committed by GitHub
parent add06be809
commit 66dddbaa66
11 changed files with 200 additions and 73 deletions

View File

@@ -0,0 +1,105 @@
<?php
/*
* SNMP.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2021 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS;
use Illuminate\Support\Str;
use Symfony\Component\Process\Process;
class SNMPCapabilities
{
/**
* @var bool
*/
private static $sha2;
/**
* @var bool
*/
private static $aes256;
public static function supportsSHA2(): bool
{
if (self::$sha2 === null) {
self::detectCapabilities();
}
return self::$sha2;
}
public static function supportsAES256(): bool
{
if (self::$aes256 === null) {
self::detectCapabilities();
}
return self::$aes256;
}
public static function supportedAuthAlgorithms(): array
{
return array_keys(array_filter(self::authAlgorithms()));
}
public static function supportedCryptoAlgorithms(): array
{
return array_keys(array_filter(self::cryptoAlgoritms()));
}
public static function authAlgorithms(): array
{
$sha2 = self::supportsSHA2();
return [
'SHA' => true,
'SHA-224' => $sha2,
'SHA-256' => $sha2,
'SHA-384' => $sha2,
'SHA-512' => $sha2,
'MD5' => true,
];
}
public static function cryptoAlgoritms(): array
{
$aes256 = self::supportsAES256();
return [
'AES' => true,
'AES-192' => $aes256,
'AES-256' => $aes256,
'AES-256-C' => $aes256,
'DES' => true,
];
}
private static function detectCapabilities(): void
{
$process = new Process([Config::get('snmpget', 'snmpget'), '--help']);
$process->run();
self::$sha2 = Str::contains($process->getErrorOutput(), 'SHA-512');
self::$aes256 = Str::contains($process->getErrorOutput(), 'AES-256');
}
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* SnmpCapabilities.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2021 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Ajax;
use Illuminate\Http\JsonResponse;
class SnmpCapabilities
{
public function __invoke(): JsonResponse
{
return new JsonResponse([
'auth' => \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms(),
'crypto' => \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms(),
]);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,11 @@
{ {
"/js/app.js": "/js/app.js?id=5fb72abe404b2429231c", "/js/app.js": "/js/app.js?id=cc34801c36c263f094da",
"/js/manifest.js": "/js/manifest.js?id=8d61162bb0caf92f60ff", "/js/manifest.js": "/js/manifest.js?id=8d61162bb0caf92f60ff",
"/css/vendor.css": "/css/vendor.css?id=8d7b2ecb46047fe813e4", "/css/vendor.css": "/css/vendor.css?id=8d7b2ecb46047fe813e4",
"/css/app.css": "/css/app.css?id=cff4bdc70b4433113ccc", "/css/app.css": "/css/app.css?id=54a173acc7d587a9afa4",
"/js/vendor.js": "/js/vendor.js?id=294cef17a3cf43045d61", "/js/vendor.js": "/js/vendor.js?id=294cef17a3cf43045d61",
"/js/lang/de.js": "/js/lang/de.js?id=8959e785f5790d6b6836", "/js/lang/de.js": "/js/lang/de.js?id=8959e785f5790d6b6836",
"/js/lang/en.js": "/js/lang/en.js?id=cad37e39e9721bd08fdd", "/js/lang/en.js": "/js/lang/en.js?id=bd7598fcfc462394f0de",
"/js/lang/fr.js": "/js/lang/fr.js?id=707149152bde5b5e2b8d", "/js/lang/fr.js": "/js/lang/fr.js?id=707149152bde5b5e2b8d",
"/js/lang/it.js": "/js/lang/it.js?id=4e3b200da489000822dd", "/js/lang/it.js": "/js/lang/it.js?id=4e3b200da489000822dd",
"/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c", "/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c",

View File

@@ -670,23 +670,6 @@ function version_info($remote = false)
return $output; return $output;
}//end version_info() }//end version_info()
/**
* Checks SNMPv3 capabilities
*
* SHA2 for Auth Algorithms (SHA-224,SHA-256,SHA-384,SHA-512)
* AES-192, AES-256 for Privacy Algorithms
*/
function snmpv3_capabilities(): array
{
$process = new Process([Config::get('snmpget', 'snmpget'), '--help']);
$process->run();
$ret['sha2'] = Str::contains($process->getErrorOutput(), 'SHA-512');
$ret['aes256'] = Str::contains($process->getErrorOutput(), 'AES-256');
return $ret;
}
/** /**
* Convert a MySQL binary v4 (4-byte) or v6 (16-byte) IP address to a printable string. * Convert a MySQL binary v4 (4-byte) or v6 (16-byte) IP address to a printable string.
* *

View File

@@ -190,7 +190,6 @@ foreach (get_port_assoc_modes() as $mode) {
echo " <option value=\"$mode\" $selected>$mode</option>\n"; echo " <option value=\"$mode\" $selected>$mode</option>\n";
} }
['sha2' => $snmpv3_sha2, 'aes256' => $snmpv3_aes256] = snmpv3_capabilities();
?> ?>
</select> </select>
</div> </div>
@@ -240,14 +239,13 @@ foreach (get_port_assoc_modes() as $mode) {
<label for="authalgo" class="col-sm-3 control-label">Auth Algorithm</label> <label for="authalgo" class="col-sm-3 control-label">Auth Algorithm</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select name="authalgo" id="authalgo" class="form-control input-sm"> <select name="authalgo" id="authalgo" class="form-control input-sm">
<option value="MD5" selected>MD5</option> <?php
<option value="SHA">SHA</option> foreach (\LibreNMS\SNMPCapabilities::authAlgorithms() as $algo => $enabled) {
<option value="SHA-224"<?= $snmpv3_sha2 ?: ' disabled'?>>SHA-224</option> echo "<option value=\"$algo\"" . ($enabled ?: ' disabled') . ">$algo</option>";
<option value="SHA-256"<?= $snmpv3_sha2 ?: ' disabled'?>>SHA-256</option> }
<option value="SHA-384"<?= $snmpv3_sha2 ?: ' disabled'?>>SHA-384</option> ?>
<option value="SHA-512"<?= $snmpv3_sha2 ?: ' disabled'?>>SHA-512</option>
</select> </select>
<?php if (! $snmpv3_sha2) {?> <?php if (! \LibreNMS\SNMPCapabilities::supportsSHA2()) {?>
<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label> <label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>
<?php } ?> <?php } ?>
</div> </div>
@@ -262,13 +260,13 @@ foreach (get_port_assoc_modes() as $mode) {
<label for="cryptoalgo" class="col-sm-3 control-label">Crypto Algorithm</label> <label for="cryptoalgo" class="col-sm-3 control-label">Crypto Algorithm</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select name="cryptoalgo" id="cryptoalgo" class="form-control input-sm"> <select name="cryptoalgo" id="cryptoalgo" class="form-control input-sm">
<option value="AES" selected>AES</option> <?php
<option value="AES-192"<?= $snmpv3_aes256 ?: ' disabled'?>>AES-192</option> foreach (\LibreNMS\SNMPCapabilities::cryptoAlgoritms() as $algo => $enabled) {
<option value="AES-256"<?= $snmpv3_aes256 ?: ' disabled'?>>AES-256</option> echo "<option value=\"$algo\"" . ($enabled ?: ' disabled') . ">$algo</option>";
<option value="AES-256-C"<?= $snmpv3_aes256 ?: ' disabled'?>>AES-256-C</option> }
<option value="DES">DES</option> ?>
</select> </select>
<?php if (! $snmpv3_aes256) {?> <?php if (! \LibreNMS\SNMPCapabilities::supportsAES256()) {?>
<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label> <label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>
<?php } ?> <?php } ?>
</div> </div>
@@ -277,7 +275,7 @@ foreach (get_port_assoc_modes() as $mode) {
</div> </div>
<?php <?php
if (Config::get('distributed_poller') === true) { if (Config::get('distributed_poller') === true) {
echo ' echo '
<div class="form-group"> <div class="form-group">
<label for="poller_group" class="col-sm-3 control-label">Poller Group</label> <label for="poller_group" class="col-sm-3 control-label">Poller Group</label>
<div class="col-sm-9"> <div class="col-sm-9">
@@ -285,16 +283,16 @@ if (Config::get('distributed_poller') === true) {
<option value="0"> Default poller group</option> <option value="0"> Default poller group</option>
'; ';
foreach (dbFetchRows('SELECT `id`,`group_name` FROM `poller_groups` ORDER BY `group_name`') as $group) { foreach (dbFetchRows('SELECT `id`,`group_name` FROM `poller_groups` ORDER BY `group_name`') as $group) {
echo '<option value="' . $group['id'] . '">' . $group['group_name'] . '</option>'; echo '<option value="' . $group['id'] . '">' . $group['group_name'] . '</option>';
} }
echo ' echo '
</select> </select>
</div> </div>
</div> </div>
'; ';
}//endif }//endif
?> ?>
<div class="form-group"> <div class="form-group">
<label for="force_add" class="col-sm-3 control-label">Force add<br><small>(No ICMP or SNMP checks performed)</small></label> <label for="force_add" class="col-sm-3 control-label">Force add<br><small>(No ICMP or SNMP checks performed)</small></label>

View File

@@ -301,7 +301,6 @@ foreach (get_port_assoc_modes() as $pam_id => $pam) {
echo ">$pam</option>\n"; echo ">$pam</option>\n";
} }
['sha2' => $snmpv3_sha2, 'aes256' => $snmpv3_aes256] = snmpv3_capabilities();
echo " </select> echo " </select>
</div> </div>
</div> </div>
@@ -357,19 +356,16 @@ echo " </select>
<div class='form-group'> <div class='form-group'>
<label for='authalgo' class='col-sm-2 control-label'>Auth Algorithm</label> <label for='authalgo' class='col-sm-2 control-label'>Auth Algorithm</label>
<div class='col-sm-4'> <div class='col-sm-4'>
<select id='authalgo' name='authalgo' class='form-control'> <select id='authalgo' name='authalgo' class='form-control'>";
<option value='MD5'>MD5</option> foreach (\LibreNMS\SNMPCapabilities::authAlgorithms() as $algo => $enabled) {
<option value='SHA' " . ($device['authalgo'] === 'SHA' ? 'selected' : '') . ">SHA</option> echo "<option value='$algo' " . ($device['authalgo'] === $algo ? 'selected' : '') . ($enabled ? '' : ' disabled') . ">$algo</option>\n";
<option value='SHA-224' " . ($device['authalgo'] === 'SHA-224' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . ">SHA-224</option> }
<option value='SHA-256' " . ($device['authalgo'] === 'SHA-256' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . ">SHA-256</option> echo '</select>';
<option value='SHA-384' " . ($device['authalgo'] === 'SHA-384' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . ">SHA-384</option>
<option value='SHA-512' " . ($device['authalgo'] === 'SHA-512' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . '>SHA-512</option> if (! \LibreNMS\SNMPCapabilities::supportsSHA2()) {
</select>
';
if (! $snmpv3_sha2) {
echo '<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>'; echo '<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>';
} }
echo " echo "
</div> </div>
</div> </div>
<div class='form-group'> <div class='form-group'>
@@ -381,15 +377,14 @@ if (! $snmpv3_sha2) {
<div class='form-group'> <div class='form-group'>
<label for='cryptoalgo' class='col-sm-2 control-label'>Crypto Algorithm</label> <label for='cryptoalgo' class='col-sm-2 control-label'>Crypto Algorithm</label>
<div class='col-sm-4'> <div class='col-sm-4'>
<select id='cryptoalgo' name='cryptoalgo' class='form-control'> <select id='cryptoalgo' name='cryptoalgo' class='form-control'>";
<option value='AES' " . ($device['cryptoalgo'] === 'AES' ? 'selected' : '') . ">AES</option>
<option value='AES-192' " . ($device['cryptoalgo'] === 'AES-192' ? 'selected' : '') . ($snmpv3_aes256 ? '' : ' disabled') . ">AES-192</option> foreach (\LibreNMS\SNMPCapabilities::cryptoAlgoritms() as $algo => $enabled) {
<option value='AES-256' " . ($device['cryptoalgo'] === 'AES-256' ? 'selected' : '') . ($snmpv3_aes256 ? '' : ' disabled') . ">AES-256</option> echo "<option value='$algo' " . ($device['cryptoalgo'] === $algo ? 'selected' : '') . ($enabled ? '' : ' disabled') . ">$algo</option>\n";
<option value='AES-256-C' " . ($device['cryptoalgo'] === 'AES-256-C' ? 'selected' : '') . ($snmpv3_aes256 ? '' : ' disabled') . ">AES-256 Cisco</option> }
<option value='DES' " . ($device['cryptoalgo'] === 'DES' ? 'selected' : '') . '>DES</option> echo '</select>
</select>
'; ';
if (! $snmpv3_aes256) { if (! \LibreNMS\SNMPCapabilities::supportsAES256()) {
echo '<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>'; echo '<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>';
} }
echo ' echo '

View File

@@ -49,8 +49,7 @@
<label for="authalgo" class="col-sm-3 control-label" v-text="$t('settings.settings.snmp.v3.fields.authalgo')"></label> <label for="authalgo" class="col-sm-3 control-label" v-text="$t('settings.settings.snmp.v3.fields.authalgo')"></label>
<div class="col-sm-9"> <div class="col-sm-9">
<select class="form-control" id="authalgo" name="authalgo" v-model="item.authalgo" @change="updateItem(id, $event.target.id, $event.target.value)"> <select class="form-control" id="authalgo" name="authalgo" v-model="item.authalgo" @change="updateItem(id, $event.target.id, $event.target.value)">
<option value="MD5">MD5</option> <option v-for="name in authAlgorithms" :value="name" v-text="name"></option>
<option value="SHA">SHA</option>
</select> </select>
</div> </div>
</div> </div>
@@ -74,8 +73,7 @@
<label for="cryptoalgo" class="col-sm-3 control-label">Cryptoalgo</label> <label for="cryptoalgo" class="col-sm-3 control-label">Cryptoalgo</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select class="form-control" id="cryptoalgo" v-model="item.cryptoalgo" @change="updateItem(id, $event.target.id, $event.target.value)"> <select class="form-control" id="cryptoalgo" v-model="item.cryptoalgo" @change="updateItem(id, $event.target.id, $event.target.value)">
<option value="AES">AES</option> <option v-for="name in cryptoAlgorithms" :value="name" v-text="name"></option>
<option value="DES">DES</option>
</select> </select>
</div> </div>
@@ -101,16 +99,24 @@
</template> </template>
<script> <script>
import BaseSetting from "./BaseSetting"; import BaseSetting from "./BaseSetting";
export default { export default {
name: "SettingSnmp3auth", name: "SettingSnmp3auth",
mixins: [BaseSetting], mixins: [BaseSetting],
data() { data() {
return { return {
localList: this.value localList: this.value,
authAlgorithms: ['MD5', 'AES'],
cryptoAlgorithms: ['AES', 'DES'],
} }
}, },
mounted() {
axios.get(route('snmp.capabilities')).then((res) => {
this.authAlgorithms = res.data.auth;
this.cryptoAlgorithms = res.data.crypto;
})
},
methods: { methods: {
addItem() { addItem() {
this.localList.push({ this.localList.push({

View File

@@ -42,8 +42,8 @@ Artisan::command('device:add
{--r|port=161 : ' . __('SNMP transport port') . '} {--r|port=161 : ' . __('SNMP transport port') . '}
{--u|security-name=root : ' . __('SNMPv3 security username') . '} {--u|security-name=root : ' . __('SNMPv3 security username') . '}
{--A|auth-password= : ' . __('SNMPv3 authentication password') . '} {--A|auth-password= : ' . __('SNMPv3 authentication password') . '}
{--a|auth-protocol=md5 : ' . __('SNMPv3 authentication protocol') . ' [md5, sha, sha-512, sha-384, sha-256, sha-224]} {--a|auth-protocol=md5 : ' . __('SNMPv3 authentication protocol') . ' [' . implode(', ', \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms()) . ']}
{--x|privacy-protocol=aes : ' . __('SNMPv3 privacy protocol') . ' [des, aes]} {--x|privacy-protocol=aes : ' . __('SNMPv3 privacy protocol') . ' [' . implode(', ', \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms()) . ']}
{--X|privacy-password= : ' . __('SNMPv3 privacy password') . '} {--X|privacy-password= : ' . __('SNMPv3 privacy password') . '}
{--P|ping-only : ' . __('Add a ping only device') . '} {--P|ping-only : ' . __('Add a ping only device') . '}
{--o|os=ping : ' . __('Ping only: specify OS') . '} {--o|os=ping : ' . __('Ping only: specify OS') . '}
@@ -60,11 +60,11 @@ Artisan::command('device:add
$this->error(__('Invalid SNMP transport')); $this->error(__('Invalid SNMP transport'));
} }
if (! in_array($this->option('auth-protocol'), ['md5', 'sha', 'sha-512', 'sha-384', 'sha-256', 'sha-224'])) { if (! in_array($this->option('auth-protocol'), \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms())) {
$this->error(__('Invalid authentication protocol')); $this->error(__('Invalid authentication protocol'));
} }
if (! in_array($this->option('privacy-protocol'), ['des', 'aes'])) { if (! in_array($this->option('privacy-protocol'), \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms())) {
$this->error(__('Invalid privacy protocol')); $this->error(__('Invalid privacy protocol'));
} }

View File

@@ -91,6 +91,7 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
Route::post('set_resolution', 'ResolutionController@set'); Route::post('set_resolution', 'ResolutionController@set');
Route::get('netcmd', 'NetCommand@run'); Route::get('netcmd', 'NetCommand@run');
Route::post('ripe/raw', 'RipeNccApiController@raw'); Route::post('ripe/raw', 'RipeNccApiController@raw');
Route::get('snmp/capabilities', 'SnmpCapabilities')->name('snmp.capabilities');
}); });
Route::get('settings/list', 'SettingsController@listAll')->name('settings.list'); Route::get('settings/list', 'SettingsController@listAll')->name('settings.list');