feat(crowdsec-dashboard): Add LAPI-only mode, enrollment key storage, improved contrast
- Add Local Protection Mode banner when CAPI unavailable (LAPI still works) - Save enrollment key to UCI config for future repairs - Improve text contrast in wizard (better readability) - Simplify LAPI repair function based on official OpenWrt approach - Never delete CAPI credentials to avoid rate-limiting - Add get_settings/save_settings RPC methods - Bump version to 0.7.0-r27 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ca562f69cd
commit
da5b88110a
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=luci-app-crowdsec-dashboard
|
PKG_NAME:=luci-app-crowdsec-dashboard
|
||||||
PKG_VERSION:=0.7.0
|
PKG_VERSION:=0.7.0
|
||||||
PKG_RELEASE:=24
|
PKG_RELEASE:=27
|
||||||
PKG_ARCH:=all
|
PKG_ARCH:=all
|
||||||
|
|
||||||
PKG_LICENSE:=Apache-2.0
|
PKG_LICENSE:=Apache-2.0
|
||||||
@ -29,6 +29,10 @@ define Package/luci-app-crowdsec-dashboard/conffiles
|
|||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/luci-app-crowdsec-dashboard/install
|
define Package/luci-app-crowdsec-dashboard/install
|
||||||
|
# UCI config file
|
||||||
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
|
$(INSTALL_CONF) ./root/etc/config/crowdsec-dashboard $(1)/etc/config/
|
||||||
|
|
||||||
# RPCD backend (MUST be 755 for ubus calls)
|
# RPCD backend (MUST be 755 for ubus calls)
|
||||||
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
|
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
|
||||||
$(INSTALL_BIN) ./root/usr/libexec/rpcd/luci.crowdsec-dashboard $(1)/usr/libexec/rpcd/
|
$(INSTALL_BIN) ./root/usr/libexec/rpcd/luci.crowdsec-dashboard $(1)/usr/libexec/rpcd/
|
||||||
|
|||||||
@ -289,6 +289,19 @@ var callRemoveHubItem = rpc.declare({
|
|||||||
expect: { }
|
expect: { }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var callGetSettings = rpc.declare({
|
||||||
|
object: 'luci.crowdsec-dashboard',
|
||||||
|
method: 'get_settings',
|
||||||
|
expect: { }
|
||||||
|
});
|
||||||
|
|
||||||
|
var callSaveSettings = rpc.declare({
|
||||||
|
object: 'luci.crowdsec-dashboard',
|
||||||
|
method: 'save_settings',
|
||||||
|
params: ['enrollment_key', 'machine_name', 'auto_enroll'],
|
||||||
|
expect: { }
|
||||||
|
});
|
||||||
|
|
||||||
function formatDuration(seconds) {
|
function formatDuration(seconds) {
|
||||||
if (!seconds) return 'N/A';
|
if (!seconds) return 'N/A';
|
||||||
if (seconds < 60) return seconds + 's';
|
if (seconds < 60) return seconds + 's';
|
||||||
@ -432,6 +445,10 @@ return baseclass.extend({
|
|||||||
installHubItem: callInstallHubItem,
|
installHubItem: callInstallHubItem,
|
||||||
removeHubItem: callRemoveHubItem,
|
removeHubItem: callRemoveHubItem,
|
||||||
|
|
||||||
|
// Settings Management
|
||||||
|
getSettings: callGetSettings,
|
||||||
|
saveSettings: callSaveSettings,
|
||||||
|
|
||||||
formatDuration: formatDuration,
|
formatDuration: formatDuration,
|
||||||
formatDate: formatDate,
|
formatDate: formatDate,
|
||||||
formatRelativeTime: formatRelativeTime,
|
formatRelativeTime: formatRelativeTime,
|
||||||
|
|||||||
@ -148,7 +148,7 @@ body > .main > .main-right,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wizard-step p {
|
.wizard-step p {
|
||||||
color: #cbd5e1;
|
color: #e2e8f0;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ body > .main > .main-right,
|
|||||||
|
|
||||||
.collection-desc {
|
.collection-desc {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #94a3b8;
|
color: #cbd5e1;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ body > .main > .main-right,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-value {
|
.status-value {
|
||||||
color: #94a3b8;
|
color: #cbd5e1;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,20 @@ return view.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
load: function() {
|
load: function() {
|
||||||
return this.runHealthCheck();
|
var self = this;
|
||||||
|
// Load saved settings first, then run health check
|
||||||
|
return API.getSettings().then(function(settings) {
|
||||||
|
if (settings && settings.enrollment_key) {
|
||||||
|
self.config.enrollmentKey = settings.enrollment_key;
|
||||||
|
}
|
||||||
|
if (settings && settings.machine_name) {
|
||||||
|
self.config.machineName = settings.machine_name;
|
||||||
|
}
|
||||||
|
return self.runHealthCheck();
|
||||||
|
}).catch(function() {
|
||||||
|
// Settings not available, continue with health check
|
||||||
|
return self.runHealthCheck();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
runHealthCheck: function() {
|
runHealthCheck: function() {
|
||||||
@ -211,6 +224,10 @@ return view.extend({
|
|||||||
renderHealthCheck: function() {
|
renderHealthCheck: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
// Determine protection mode
|
||||||
|
var lapiOnly = this.health.lapiAvailable && !this.health.capiConnected;
|
||||||
|
var fullProtection = this.health.lapiAvailable && this.health.capiConnected;
|
||||||
|
|
||||||
var checks = [
|
var checks = [
|
||||||
{
|
{
|
||||||
id: 'crowdsec',
|
id: 'crowdsec',
|
||||||
@ -224,6 +241,7 @@ return view.extend({
|
|||||||
label: _('Local API (LAPI)'),
|
label: _('Local API (LAPI)'),
|
||||||
ok: this.health.lapiAvailable,
|
ok: this.health.lapiAvailable,
|
||||||
status: this.health.lapiAvailable ? _('Available') : _('Unavailable'),
|
status: this.health.lapiAvailable ? _('Available') : _('Unavailable'),
|
||||||
|
critical: true, // LAPI is critical for protection
|
||||||
action: !this.health.lapiAvailable && this.health.crowdsecRunning ? _('Will repair') : null
|
action: !this.health.lapiAvailable && this.health.crowdsecRunning ? _('Will repair') : null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -231,7 +249,10 @@ return view.extend({
|
|||||||
label: _('Central API (CAPI)'),
|
label: _('Central API (CAPI)'),
|
||||||
ok: this.health.capiConnected,
|
ok: this.health.capiConnected,
|
||||||
status: this.health.capiConnected ? _('Connected') : (this.health.capiEnrolled ? _('Enrolled but not connected') : _('Not registered')),
|
status: this.health.capiConnected ? _('Connected') : (this.health.capiEnrolled ? _('Enrolled but not connected') : _('Not registered')),
|
||||||
action: !this.health.capiConnected ? _('Enrollment required') : null
|
// CAPI is NOT critical - local protection works without it
|
||||||
|
critical: false,
|
||||||
|
warning: !this.health.capiConnected && this.health.lapiAvailable,
|
||||||
|
action: !this.health.capiConnected ? _('Optional - enroll for community blocklists') : null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bouncer',
|
id: 'bouncer',
|
||||||
@ -240,6 +261,7 @@ return view.extend({
|
|||||||
status: this.health.bouncerRegistered ?
|
status: this.health.bouncerRegistered ?
|
||||||
(this.health.bouncerRunning ? _('Running') : _('Registered but stopped')) :
|
(this.health.bouncerRunning ? _('Running') : _('Registered but stopped')) :
|
||||||
_('Not registered'),
|
_('Not registered'),
|
||||||
|
critical: true, // Bouncer is critical for enforcement
|
||||||
action: !this.health.bouncerRegistered ? _('Will register') : (!this.health.bouncerRunning ? _('Will start') : null)
|
action: !this.health.bouncerRegistered ? _('Will register') : (!this.health.bouncerRunning ? _('Will start') : null)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -247,6 +269,7 @@ return view.extend({
|
|||||||
label: _('nftables Rules'),
|
label: _('nftables Rules'),
|
||||||
ok: this.health.nftablesActive,
|
ok: this.health.nftablesActive,
|
||||||
status: this.health.nftablesActive ? _('Active') : _('Not loaded'),
|
status: this.health.nftablesActive ? _('Active') : _('Not loaded'),
|
||||||
|
critical: true,
|
||||||
action: !this.health.nftablesActive ? _('Will configure') : null
|
action: !this.health.nftablesActive ? _('Will configure') : null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -265,16 +288,37 @@ return view.extend({
|
|||||||
this.health.checking ? E('span', { 'class': 'spinning', 'style': 'margin-left: 12px; font-size: 14px;' }, '') : E([])
|
this.health.checking ? E('span', { 'class': 'spinning', 'style': 'margin-left: 12px; font-size: 14px;' }, '') : E([])
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
// Protection Mode Banner
|
||||||
|
this.health.lapiAvailable ? E('div', {
|
||||||
|
'style': 'margin-bottom: 16px; padding: 12px 16px; border-radius: 8px; display: flex; align-items: center; ' +
|
||||||
|
(fullProtection ? 'background: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.3);' :
|
||||||
|
'background: rgba(234, 179, 8, 0.1); border: 1px solid rgba(234, 179, 8, 0.3);')
|
||||||
|
}, [
|
||||||
|
E('span', { 'style': 'font-size: 24px; margin-right: 12px;' }, fullProtection ? '🛡️' : '⚡'),
|
||||||
|
E('div', {}, [
|
||||||
|
E('strong', { 'style': 'color: ' + (fullProtection ? '#22c55e' : '#eab308') + ';' },
|
||||||
|
fullProtection ? _('Full Protection Mode') : _('Local Protection Mode')),
|
||||||
|
E('div', { 'style': 'font-size: 0.85em; color: #cbd5e1; margin-top: 2px;' },
|
||||||
|
fullProtection ?
|
||||||
|
_('Community blocklists + local detection active') :
|
||||||
|
_('Local auto-ban active. Enroll CAPI for community blocklists.'))
|
||||||
|
])
|
||||||
|
]) : E([]),
|
||||||
|
|
||||||
E('div', { 'class': 'status-checks', 'style': 'display: grid; gap: 8px;' },
|
E('div', { 'class': 'status-checks', 'style': 'display: grid; gap: 8px;' },
|
||||||
checks.map(function(check) {
|
checks.map(function(check) {
|
||||||
|
// Determine icon and color based on ok/warning/critical status
|
||||||
|
var iconColor = check.ok ? '#22c55e' : (check.warning ? '#eab308' : (check.critical ? '#ef4444' : '#eab308'));
|
||||||
|
var icon = check.ok ? '✓' : (check.warning ? '⚠' : (check.critical ? '✗' : '⚠'));
|
||||||
|
|
||||||
return E('div', {
|
return E('div', {
|
||||||
'class': 'check-item',
|
'class': 'check-item',
|
||||||
'style': 'display: flex; align-items: center; padding: 12px; background: rgba(15, 23, 42, 0.5); border-radius: 8px;'
|
'style': 'display: flex; align-items: center; padding: 12px; background: rgba(15, 23, 42, 0.5); border-radius: 8px;'
|
||||||
}, [
|
}, [
|
||||||
E('span', {
|
E('span', {
|
||||||
'class': 'check-icon',
|
'class': 'check-icon',
|
||||||
'style': 'font-size: 20px; margin-right: 12px; color: ' + (check.ok ? '#22c55e' : (check.critical ? '#ef4444' : '#eab308')) + ';'
|
'style': 'font-size: 20px; margin-right: 12px; color: ' + iconColor + ';'
|
||||||
}, check.ok ? '✓' : (check.critical ? '✗' : '⚠')),
|
}, icon),
|
||||||
E('div', { 'style': 'flex: 1;' }, [
|
E('div', { 'style': 'flex: 1;' }, [
|
||||||
E('strong', {}, check.label),
|
E('strong', {}, check.label),
|
||||||
E('div', { 'style': 'font-size: 0.85em; color: ' + (check.ok ? '#22c55e' : '#94a3b8') + ';' }, check.status)
|
E('div', { 'style': 'font-size: 0.85em; color: ' + (check.ok ? '#22c55e' : '#94a3b8') + ';' }, check.status)
|
||||||
@ -321,7 +365,7 @@ return view.extend({
|
|||||||
'style': 'margin-bottom: 20px; padding: 16px; background: rgba(15, 23, 42, 0.5); border-radius: 8px;'
|
'style': 'margin-bottom: 20px; padding: 16px; background: rgba(15, 23, 42, 0.5); border-radius: 8px;'
|
||||||
}, [
|
}, [
|
||||||
E('h4', { 'style': 'margin: 0 0 12px 0; color: #818cf8;' }, _('Console Enrollment (Optional)')),
|
E('h4', { 'style': 'margin: 0 0 12px 0; color: #818cf8;' }, _('Console Enrollment (Optional)')),
|
||||||
E('p', { 'style': 'margin: 0 0 12px 0; font-size: 0.9em; color: #94a3b8;' },
|
E('p', { 'style': 'margin: 0 0 12px 0; font-size: 0.9em; color: #cbd5e1;' },
|
||||||
_('Enroll to receive community blocklists. Leave empty to skip.')),
|
_('Enroll to receive community blocklists. Leave empty to skip.')),
|
||||||
E('input', {
|
E('input', {
|
||||||
'type': 'text',
|
'type': 'text',
|
||||||
@ -341,7 +385,7 @@ return view.extend({
|
|||||||
'value': this.config.machineName,
|
'value': this.config.machineName,
|
||||||
'input': function(ev) { self.config.machineName = ev.target.value; }
|
'input': function(ev) { self.config.machineName = ev.target.value; }
|
||||||
}),
|
}),
|
||||||
E('p', { 'style': 'margin: 8px 0 0 0; font-size: 0.85em; color: #64748b;' }, [
|
E('p', { 'style': 'margin: 8px 0 0 0; font-size: 0.85em; color: #94a3b8;' }, [
|
||||||
_('After enrollment, validate on '),
|
_('After enrollment, validate on '),
|
||||||
E('a', { 'href': 'https://app.crowdsec.net', 'target': '_blank', 'style': 'color: #818cf8;' }, 'app.crowdsec.net'),
|
E('a', { 'href': 'https://app.crowdsec.net', 'target': '_blank', 'style': 'color: #818cf8;' }, 'app.crowdsec.net'),
|
||||||
_('. Service will restart automatically.')
|
_('. Service will restart automatically.')
|
||||||
@ -371,7 +415,7 @@ return view.extend({
|
|||||||
this.renderCollectionToggle('crowdsecurity/iptables', _('Firewall log parser'), this.config.firewallEnabled),
|
this.renderCollectionToggle('crowdsecurity/iptables', _('Firewall log parser'), this.config.firewallEnabled),
|
||||||
this.renderCollectionToggle('crowdsecurity/http-cve', _('Web CVE protection'), this.config.httpEnabled),
|
this.renderCollectionToggle('crowdsecurity/http-cve', _('Web CVE protection'), this.config.httpEnabled),
|
||||||
E('div', { 'style': 'margin-top: 12px;' }, [
|
E('div', { 'style': 'margin-top: 12px;' }, [
|
||||||
E('strong', { 'style': 'font-size: 0.9em; color: #94a3b8;' }, _('OpenWrt Parsers:')),
|
E('strong', { 'style': 'font-size: 0.9em; color: #cbd5e1;' }, _('OpenWrt Parsers:')),
|
||||||
]),
|
]),
|
||||||
this.renderCollectionToggle('crowdsecurity/syslog-logs', _('Syslog parser'), true, 'parser'),
|
this.renderCollectionToggle('crowdsecurity/syslog-logs', _('Syslog parser'), true, 'parser'),
|
||||||
this.renderCollectionToggle('crowdsecurity/dropbear-logs', _('Dropbear SSH parser'), this.config.sshEnabled, 'parser')
|
this.renderCollectionToggle('crowdsecurity/dropbear-logs', _('Dropbear SSH parser'), this.config.sshEnabled, 'parser')
|
||||||
@ -437,7 +481,7 @@ return view.extend({
|
|||||||
}, checked ? '☑' : '☐'),
|
}, checked ? '☑' : '☐'),
|
||||||
E('div', { 'style': 'flex: 1;' }, [
|
E('div', { 'style': 'flex: 1;' }, [
|
||||||
E('strong', { 'style': 'display: block;' }, label),
|
E('strong', { 'style': 'display: block;' }, label),
|
||||||
E('span', { 'style': 'font-size: 0.85em; color: #64748b;' }, description)
|
E('span', { 'style': 'font-size: 0.85em; color: #94a3b8;' }, description)
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
@ -471,7 +515,7 @@ return view.extend({
|
|||||||
}, checked ? '☑' : '☐'),
|
}, checked ? '☑' : '☐'),
|
||||||
E('div', { 'style': 'flex: 1;' }, [
|
E('div', { 'style': 'flex: 1;' }, [
|
||||||
E('code', { 'style': 'font-size: 0.9em;' }, name),
|
E('code', { 'style': 'font-size: 0.9em;' }, name),
|
||||||
E('span', { 'style': 'margin-left: 8px; font-size: 0.85em; color: #64748b;' }, '— ' + description)
|
E('span', { 'style': 'margin-left: 8px; font-size: 0.85em; color: #94a3b8;' }, '— ' + description)
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
@ -482,7 +526,7 @@ return view.extend({
|
|||||||
return E('div', { 'class': 'wizard-step', 'style': 'text-align: center; padding: 48px 24px;' }, [
|
return E('div', { 'class': 'wizard-step', 'style': 'text-align: center; padding: 48px 24px;' }, [
|
||||||
E('div', { 'class': 'spinning', 'style': 'font-size: 48px; margin-bottom: 24px;' }, '⚙️'),
|
E('div', { 'class': 'spinning', 'style': 'font-size: 48px; margin-bottom: 24px;' }, '⚙️'),
|
||||||
E('h2', {}, _('Applying Configuration...')),
|
E('h2', {}, _('Applying Configuration...')),
|
||||||
E('p', { 'style': 'color: #94a3b8; margin-bottom: 24px;' }, this.config.applyStep),
|
E('p', { 'style': 'color: #cbd5e1; margin-bottom: 24px;' }, this.config.applyStep),
|
||||||
|
|
||||||
// Progress bar
|
// Progress bar
|
||||||
E('div', { 'style': 'max-width: 400px; margin: 0 auto 24px;' }, [
|
E('div', { 'style': 'max-width: 400px; margin: 0 auto 24px;' }, [
|
||||||
@ -493,7 +537,7 @@ return view.extend({
|
|||||||
'style': 'height: 100%; width: ' + progressPercent + '%; background: linear-gradient(90deg, #667eea, #764ba2); transition: width 0.3s;'
|
'style': 'height: 100%; width: ' + progressPercent + '%; background: linear-gradient(90deg, #667eea, #764ba2); transition: width 0.3s;'
|
||||||
})
|
})
|
||||||
]),
|
]),
|
||||||
E('div', { 'style': 'margin-top: 8px; font-size: 0.9em; color: #64748b;' }, progressPercent + '%')
|
E('div', { 'style': 'margin-top: 8px; font-size: 0.9em; color: #94a3b8;' }, progressPercent + '%')
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Errors if any
|
// Errors if any
|
||||||
@ -511,19 +555,37 @@ return view.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renderComplete: function() {
|
renderComplete: function() {
|
||||||
|
var fullProtection = this.health.lapiAvailable && this.health.capiConnected;
|
||||||
|
var localOnly = this.health.lapiAvailable && !this.health.capiConnected;
|
||||||
|
|
||||||
return E('div', { 'class': 'wizard-step wizard-complete', 'style': 'text-align: center;' }, [
|
return E('div', { 'class': 'wizard-step wizard-complete', 'style': 'text-align: center;' }, [
|
||||||
E('div', { 'class': 'success-hero', 'style': 'margin-bottom: 32px;' }, [
|
E('div', { 'class': 'success-hero', 'style': 'margin-bottom: 32px;' }, [
|
||||||
E('div', { 'style': 'font-size: 64px; margin-bottom: 16px;' }, '🎉'),
|
E('div', { 'style': 'font-size: 64px; margin-bottom: 16px;' }, fullProtection ? '🛡️' : '⚡'),
|
||||||
E('h2', {}, _('Setup Complete!'))
|
E('h2', {}, _('Setup Complete!'))
|
||||||
]),
|
]),
|
||||||
|
|
||||||
E('p', { 'style': 'color: #94a3b8; margin-bottom: 32px;' },
|
// Protection Mode Banner
|
||||||
|
E('div', {
|
||||||
|
'style': 'max-width: 400px; margin: 0 auto 24px; padding: 16px; border-radius: 8px; ' +
|
||||||
|
(fullProtection ? 'background: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.3);' :
|
||||||
|
'background: rgba(234, 179, 8, 0.1); border: 1px solid rgba(234, 179, 8, 0.3);')
|
||||||
|
}, [
|
||||||
|
E('strong', { 'style': 'color: ' + (fullProtection ? '#22c55e' : '#eab308') + ';' },
|
||||||
|
fullProtection ? _('Full Protection Mode') : _('Local Protection Mode')),
|
||||||
|
E('div', { 'style': 'font-size: 0.85em; color: #cbd5e1; margin-top: 4px;' },
|
||||||
|
fullProtection ?
|
||||||
|
_('Community blocklists + local detection active') :
|
||||||
|
_('Local auto-ban protects against attacks detected on your network'))
|
||||||
|
]),
|
||||||
|
|
||||||
|
E('p', { 'style': 'color: #cbd5e1; margin-bottom: 32px;' },
|
||||||
_('CrowdSec is now protecting your network.')),
|
_('CrowdSec is now protecting your network.')),
|
||||||
|
|
||||||
// Summary of what was done
|
// Summary of what was done
|
||||||
E('div', { 'style': 'max-width: 400px; margin: 0 auto 32px; text-align: left;' }, [
|
E('div', { 'style': 'max-width: 400px; margin: 0 auto 32px; text-align: left;' }, [
|
||||||
this.health.lapiAvailable ? this.renderCompletedItem(_('LAPI available')) : E([]),
|
this.health.lapiAvailable ? this.renderCompletedItem(_('LAPI available (local detection)')) : E([]),
|
||||||
this.health.capiConnected ? this.renderCompletedItem(_('CAPI connected')) : E([]),
|
this.health.capiConnected ? this.renderCompletedItem(_('CAPI connected (community blocklists)')) :
|
||||||
|
this.renderWarningItem(_('CAPI not connected (local protection only)')),
|
||||||
this.health.bouncerRegistered ? this.renderCompletedItem(_('Bouncer registered')) : E([]),
|
this.health.bouncerRegistered ? this.renderCompletedItem(_('Bouncer registered')) : E([]),
|
||||||
this.health.nftablesActive ? this.renderCompletedItem(_('nftables rules active')) : E([]),
|
this.health.nftablesActive ? this.renderCompletedItem(_('nftables rules active')) : E([]),
|
||||||
this.health.collectionsInstalled > 0 ?
|
this.health.collectionsInstalled > 0 ?
|
||||||
@ -562,6 +624,13 @@ return view.extend({
|
|||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderWarningItem: function(text) {
|
||||||
|
return E('div', { 'style': 'display: flex; align-items: center; padding: 8px 0;' }, [
|
||||||
|
E('span', { 'style': 'color: #eab308; margin-right: 12px; font-size: 18px;' }, '⚠'),
|
||||||
|
E('span', { 'style': 'color: #cbd5e1;' }, text)
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
handleApplyAll: function() {
|
handleApplyAll: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.config.applying = true;
|
this.config.applying = true;
|
||||||
@ -586,6 +655,13 @@ return view.extend({
|
|||||||
this.config.enrollmentKey = keyInput ? keyInput.value.trim() : '';
|
this.config.enrollmentKey = keyInput ? keyInput.value.trim() : '';
|
||||||
this.config.machineName = nameInput ? nameInput.value.trim() : '';
|
this.config.machineName = nameInput ? nameInput.value.trim() : '';
|
||||||
|
|
||||||
|
// Save enrollment key for future repairs (if provided)
|
||||||
|
if (this.config.enrollmentKey) {
|
||||||
|
API.saveSettings(this.config.enrollmentKey, this.config.machineName, '1').catch(function(err) {
|
||||||
|
console.log('[Wizard] Failed to save enrollment key:', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Define steps
|
// Define steps
|
||||||
var steps = [];
|
var steps = [];
|
||||||
var stepWeight = 0;
|
var stepWeight = 0;
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
config settings 'main'
|
||||||
|
option enrollment_key ''
|
||||||
|
option machine_name ''
|
||||||
|
option auto_enroll '0'
|
||||||
@ -981,182 +981,105 @@ repair_lapi() {
|
|||||||
json_init
|
json_init
|
||||||
local steps_done=""
|
local steps_done=""
|
||||||
local errors=""
|
local errors=""
|
||||||
local REPAIR_TIMEOUT=10
|
local config_file="/etc/crowdsec/config.yaml"
|
||||||
|
local creds_file="/etc/crowdsec/local_api_credentials.yaml"
|
||||||
|
local db_file="/srv/crowdsec/data/crowdsec.db"
|
||||||
|
local capi_creds="/etc/crowdsec/online_api_credentials.yaml"
|
||||||
|
|
||||||
secubox_log "Starting LAPI repair..."
|
secubox_log "Starting LAPI repair (simplified)..."
|
||||||
|
|
||||||
# Step 1: Stop CrowdSec completely
|
# Step 1: Stop CrowdSec
|
||||||
/etc/init.d/crowdsec stop >/dev/null 2>&1
|
/etc/init.d/crowdsec stop >/dev/null 2>&1
|
||||||
sleep 1
|
sleep 2
|
||||||
killall crowdsec 2>/dev/null
|
killall crowdsec 2>/dev/null
|
||||||
sleep 1
|
sleep 1
|
||||||
steps_done="${steps_done}Stopped; "
|
steps_done="Stopped; "
|
||||||
|
|
||||||
# Step 2: Create required directories
|
# Step 2: Create required directories
|
||||||
mkdir -p /srv/crowdsec/data 2>/dev/null
|
mkdir -p /srv/crowdsec/data 2>/dev/null
|
||||||
mkdir -p /etc/crowdsec/hub 2>/dev/null
|
mkdir -p /etc/crowdsec/hub 2>/dev/null
|
||||||
mkdir -p /etc/crowdsec/acquis.d 2>/dev/null
|
mkdir -p /etc/crowdsec/acquis.d 2>/dev/null
|
||||||
mkdir -p /var/etc/crowdsec 2>/dev/null
|
|
||||||
chmod 755 /srv/crowdsec/data 2>/dev/null
|
chmod 755 /srv/crowdsec/data 2>/dev/null
|
||||||
steps_done="${steps_done}Dirs; "
|
steps_done="${steps_done}Dirs; "
|
||||||
|
|
||||||
# Step 3: Fix config.yaml
|
# Step 3: Fix config paths
|
||||||
local config_file="/etc/crowdsec/config.yaml"
|
|
||||||
local var_config="/var/etc/crowdsec/config.yaml"
|
|
||||||
if [ -f "$config_file" ]; then
|
if [ -f "$config_file" ]; then
|
||||||
sed -i 's|^\(\s*\)data_dir:.*|\1data_dir: /srv/crowdsec/data/|' "$config_file" 2>/dev/null
|
sed -i 's|^\(\s*\)data_dir:.*|\1data_dir: /srv/crowdsec/data/|' "$config_file" 2>/dev/null
|
||||||
sed -i 's|^\(\s*\)db_path:.*|\1db_path: /srv/crowdsec/data/crowdsec.db|' "$config_file" 2>/dev/null
|
sed -i 's|^\(\s*\)db_path:.*|\1db_path: /srv/crowdsec/data/crowdsec.db|' "$config_file" 2>/dev/null
|
||||||
cp "$config_file" "$var_config" 2>/dev/null
|
steps_done="${steps_done}Config fixed; "
|
||||||
steps_done="${steps_done}Config; "
|
|
||||||
else
|
else
|
||||||
errors="${errors}No config; "
|
errors="${errors}No config file; "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Step 4: Remove corrupted credentials
|
# Step 4: Reset LAPI credentials (delete old ones)
|
||||||
local creds_file="/etc/crowdsec/local_api_credentials.yaml"
|
|
||||||
rm -f "$creds_file" 2>/dev/null
|
rm -f "$creds_file" 2>/dev/null
|
||||||
|
steps_done="${steps_done}Creds cleared; "
|
||||||
|
|
||||||
# Step 5: Clean up orphaned machines from database
|
# Step 5: Reset database (delete it, CrowdSec will recreate)
|
||||||
local db_file="/srv/crowdsec/data/crowdsec.db"
|
rm -f "$db_file" 2>/dev/null
|
||||||
if [ -f "$db_file" ]; then
|
steps_done="${steps_done}DB reset; "
|
||||||
if command -v sqlite3 >/dev/null 2>&1; then
|
|
||||||
# Remove all machines - we'll re-register
|
|
||||||
sqlite3 "$db_file" "DELETE FROM machines;" 2>/dev/null
|
|
||||||
steps_done="${steps_done}DB cleaned; "
|
|
||||||
else
|
|
||||||
# No sqlite3 - delete the database file, CrowdSec will recreate it
|
|
||||||
rm -f "$db_file" 2>/dev/null
|
|
||||||
steps_done="${steps_done}DB reset; "
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 6: Start CrowdSec in LAPI-only mode (no agent)
|
# Step 6: Start CrowdSec via init (will auto-create DB and register machine)
|
||||||
# This allows LAPI to start without needing valid credentials
|
|
||||||
local crowdsec_bin="/usr/bin/crowdsec"
|
|
||||||
if [ -x "$crowdsec_bin" ]; then
|
|
||||||
# Start LAPI-only mode in background
|
|
||||||
"$crowdsec_bin" -c "$var_config" -no-cs &
|
|
||||||
local cs_pid=$!
|
|
||||||
steps_done="${steps_done}LAPI-only started; "
|
|
||||||
|
|
||||||
# Wait for LAPI to be ready (max 8 seconds)
|
|
||||||
local retries=8
|
|
||||||
local lapi_ready=0
|
|
||||||
while [ $retries -gt 0 ]; do
|
|
||||||
if grep -qi ":1F90 " /proc/net/tcp 2>/dev/null; then
|
|
||||||
lapi_ready=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
retries=$((retries - 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$lapi_ready" = "1" ]; then
|
|
||||||
steps_done="${steps_done}LAPI up; "
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Step 7: Register machine while LAPI is running
|
|
||||||
if [ -x "$CSCLI" ]; then
|
|
||||||
local reg_output=""
|
|
||||||
reg_output=$("$CSCLI" -c "$var_config" machines add localhost --auto --force -f "$creds_file" 2>&1)
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
steps_done="${steps_done}Registered; "
|
|
||||||
else
|
|
||||||
errors="${errors}Reg failed: ${reg_output}; "
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
errors="${errors}LAPI timeout; "
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 8: Stop LAPI-only mode
|
|
||||||
kill $cs_pid 2>/dev/null
|
|
||||||
sleep 1
|
|
||||||
killall crowdsec 2>/dev/null
|
|
||||||
steps_done="${steps_done}LAPI stopped; "
|
|
||||||
else
|
|
||||||
errors="${errors}No crowdsec binary; "
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 9: Verify credentials were created
|
|
||||||
if [ -s "$creds_file" ] && grep -q "password:" "$creds_file"; then
|
|
||||||
steps_done="${steps_done}Creds OK; "
|
|
||||||
else
|
|
||||||
errors="${errors}No creds; "
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 10: Start CrowdSec normally via init
|
|
||||||
/etc/init.d/crowdsec start >/dev/null 2>&1
|
/etc/init.d/crowdsec start >/dev/null 2>&1
|
||||||
sleep 3
|
sleep 5
|
||||||
|
steps_done="${steps_done}Started; "
|
||||||
|
|
||||||
# Step 11: Verify everything is working
|
# Step 7: Check if CrowdSec is running
|
||||||
local lapi_ok=0
|
local lapi_ok=0
|
||||||
if pgrep crowdsec >/dev/null 2>&1; then
|
if pgrep crowdsec >/dev/null 2>&1; then
|
||||||
steps_done="${steps_done}Running; "
|
steps_done="${steps_done}Running; "
|
||||||
if [ -x "$CSCLI" ]; then
|
|
||||||
if run_with_timeout 5 "$CSCLI" lapi status >/dev/null 2>&1; then
|
# Step 8: Register machine if credentials don't exist
|
||||||
lapi_ok=1
|
if [ ! -s "$creds_file" ] || ! grep -q "password:" "$creds_file" 2>/dev/null; then
|
||||||
steps_done="${steps_done}LAPI OK; "
|
secubox_log "Registering local machine..."
|
||||||
|
if "$CSCLI" machines add -a -f "$creds_file" 2>/dev/null; then
|
||||||
|
steps_done="${steps_done}Machine registered; "
|
||||||
|
# Restart to pick up new credentials
|
||||||
|
/etc/init.d/crowdsec restart >/dev/null 2>&1
|
||||||
|
sleep 3
|
||||||
else
|
else
|
||||||
errors="${errors}LAPI check failed; "
|
errors="${errors}Machine registration failed; "
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Step 9: Verify LAPI is working
|
||||||
|
if run_with_timeout 5 "$CSCLI" lapi status >/dev/null 2>&1; then
|
||||||
|
lapi_ok=1
|
||||||
|
steps_done="${steps_done}LAPI OK; "
|
||||||
|
else
|
||||||
|
errors="${errors}LAPI check failed; "
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
errors="${errors}Not running; "
|
errors="${errors}CrowdSec not running; "
|
||||||
# Get error from log
|
|
||||||
local log_err=""
|
local log_err=""
|
||||||
log_err=$(tail -3 /var/log/crowdsec.log 2>/dev/null | grep -i "fatal\|error" | head -1)
|
log_err=$(tail -5 /var/log/crowdsec.log 2>/dev/null | grep -i "fatal\|error" | head -1)
|
||||||
[ -n "$log_err" ] && errors="${errors}${log_err}; "
|
[ -n "$log_err" ] && errors="${errors}Log: ${log_err}; "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Step 12: Update hub index (required for collections to work)
|
# Step 10: Try to connect CAPI if LAPI works (don't delete existing CAPI creds)
|
||||||
if [ "$lapi_ok" = "1" ] && [ -x "$CSCLI" ]; then
|
if [ "$lapi_ok" = "1" ]; then
|
||||||
if run_with_timeout 30 "$CSCLI" hub update >/dev/null 2>&1; then
|
local capi_ok=0
|
||||||
steps_done="${steps_done}Hub updated; "
|
# Check if CAPI is already working
|
||||||
else
|
local capi_status=""
|
||||||
errors="${errors}Hub update failed; "
|
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
|
||||||
fi
|
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
|
||||||
fi
|
capi_ok=1
|
||||||
|
steps_done="${steps_done}CAPI OK; "
|
||||||
# Step 13: Register with CAPI (required for console enrollment)
|
elif [ ! -f "$capi_creds" ]; then
|
||||||
if [ "$lapi_ok" = "1" ] && [ -x "$CSCLI" ]; then
|
# No CAPI credentials - try to register (safe)
|
||||||
local capi_creds="/etc/crowdsec/online_api_credentials.yaml"
|
|
||||||
local capi_registered=0
|
|
||||||
|
|
||||||
# First attempt: try to register with existing credentials
|
|
||||||
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
|
|
||||||
capi_registered=1
|
|
||||||
steps_done="${steps_done}CAPI registered; "
|
|
||||||
else
|
|
||||||
# Check if CAPI is already working
|
|
||||||
local capi_status=""
|
|
||||||
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
|
|
||||||
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
|
|
||||||
capi_registered=1
|
|
||||||
steps_done="${steps_done}CAPI OK; "
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If CAPI still not working, try with fresh credentials
|
|
||||||
if [ "$capi_registered" = "0" ] && [ -f "$capi_creds" ]; then
|
|
||||||
secubox_log "CAPI registration failed, removing stale credentials and retrying..."
|
|
||||||
rm -f "$capi_creds"
|
|
||||||
steps_done="${steps_done}CAPI creds reset; "
|
|
||||||
|
|
||||||
# Retry registration with clean slate
|
|
||||||
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
|
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
|
||||||
capi_registered=1
|
capi_ok=1
|
||||||
steps_done="${steps_done}CAPI re-registered; "
|
steps_done="${steps_done}CAPI registered; "
|
||||||
else
|
else
|
||||||
local capi_err=""
|
errors="${errors}CAPI registration failed (will work in local mode); "
|
||||||
capi_err=$(run_with_timeout 10 "$CSCLI" capi register 2>&1)
|
|
||||||
errors="${errors}CAPI: ${capi_err}; "
|
|
||||||
fi
|
fi
|
||||||
elif [ "$capi_registered" = "0" ]; then
|
else
|
||||||
errors="${errors}CAPI not registered; "
|
# CAPI credentials exist but not working - don't delete them!
|
||||||
|
steps_done="${steps_done}CAPI creds preserved; "
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Final result
|
||||||
if [ "$lapi_ok" = "1" ]; then
|
if [ "$lapi_ok" = "1" ]; then
|
||||||
json_add_boolean "success" 1
|
json_add_boolean "success" 1
|
||||||
json_add_string "message" "LAPI repaired successfully"
|
json_add_string "message" "LAPI repaired successfully"
|
||||||
@ -1209,24 +1132,28 @@ repair_capi() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Step 1: Backup and remove existing credentials
|
# Step 1: Check credentials and register only if needed
|
||||||
|
# IMPORTANT: Never delete existing credentials - this triggers rate limiting
|
||||||
if [ -f "$capi_creds" ]; then
|
if [ -f "$capi_creds" ]; then
|
||||||
cp "$capi_creds" "${capi_creds}.bak" 2>/dev/null
|
steps_done="${steps_done}Credentials exist (preserved); "
|
||||||
rm -f "$capi_creds"
|
secubox_log "CAPI credentials exist, trying to reconnect..."
|
||||||
steps_done="${steps_done}Removed stale credentials; "
|
# Try to reconnect with existing credentials by restarting crowdsec
|
||||||
fi
|
/etc/init.d/crowdsec restart >/dev/null 2>&1
|
||||||
|
sleep 3
|
||||||
# Step 2: Register with CAPI
|
|
||||||
local reg_output=""
|
|
||||||
reg_output=$(run_with_timeout 20 "$CSCLI" capi register 2>&1)
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
steps_done="${steps_done}CAPI registered; "
|
|
||||||
else
|
else
|
||||||
# Check if error is about already registered
|
# No credentials - safe to register
|
||||||
if echo "$reg_output" | grep -qi "already registered"; then
|
secubox_log "No CAPI credentials, registering..."
|
||||||
steps_done="${steps_done}Already registered; "
|
local reg_output=""
|
||||||
|
reg_output=$(run_with_timeout 20 "$CSCLI" capi register 2>&1)
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
steps_done="${steps_done}CAPI registered; "
|
||||||
else
|
else
|
||||||
errors="${errors}Registration failed: ${reg_output}; "
|
# Check if error is about already registered
|
||||||
|
if echo "$reg_output" | grep -qi "already registered"; then
|
||||||
|
steps_done="${steps_done}Already registered; "
|
||||||
|
else
|
||||||
|
errors="${errors}Registration failed: ${reg_output}; "
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1369,20 +1296,27 @@ console_enroll() {
|
|||||||
capi_ok=1
|
capi_ok=1
|
||||||
secubox_log "CAPI already connected"
|
secubox_log "CAPI already connected"
|
||||||
else
|
else
|
||||||
# Try to register with CAPI
|
# CAPI not connected - check if credentials exist
|
||||||
secubox_log "CAPI not connected, attempting registration..."
|
if [ -f "$capi_creds" ]; then
|
||||||
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
|
# Credentials exist but CAPI not working - try restarting CrowdSec
|
||||||
capi_ok=1
|
secubox_log "CAPI credentials exist but not connected, restarting CrowdSec..."
|
||||||
secubox_log "CAPI registration successful"
|
/etc/init.d/crowdsec restart >/dev/null 2>&1
|
||||||
|
sleep 3
|
||||||
|
# Check again after restart
|
||||||
|
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
|
||||||
|
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
|
||||||
|
capi_ok=1
|
||||||
|
secubox_log "CAPI connected after restart"
|
||||||
|
else
|
||||||
|
# Still not working but DO NOT delete credentials (rate limit protection)
|
||||||
|
secubox_log "CAPI still not connected - credentials preserved to avoid rate limit"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# If registration fails and credentials exist, try with fresh credentials
|
# No credentials - safe to register
|
||||||
if [ -f "$capi_creds" ]; then
|
secubox_log "No CAPI credentials, attempting registration..."
|
||||||
secubox_log "CAPI registration failed, removing stale credentials..."
|
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
|
||||||
rm -f "$capi_creds"
|
capi_ok=1
|
||||||
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
|
secubox_log "CAPI registration successful"
|
||||||
capi_ok=1
|
|
||||||
secubox_log "CAPI re-registration successful"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -2073,10 +2007,60 @@ remove_hub_item() {
|
|||||||
json_dump
|
json_dump
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Get dashboard settings (enrollment key, etc.)
|
||||||
|
get_settings() {
|
||||||
|
json_init
|
||||||
|
|
||||||
|
local enrollment_key=""
|
||||||
|
local machine_name=""
|
||||||
|
local auto_enroll=""
|
||||||
|
|
||||||
|
# Read from UCI config
|
||||||
|
enrollment_key=$(uci -q get crowdsec-dashboard.main.enrollment_key 2>/dev/null)
|
||||||
|
machine_name=$(uci -q get crowdsec-dashboard.main.machine_name 2>/dev/null)
|
||||||
|
auto_enroll=$(uci -q get crowdsec-dashboard.main.auto_enroll 2>/dev/null)
|
||||||
|
|
||||||
|
json_add_string "enrollment_key" "$enrollment_key"
|
||||||
|
json_add_string "machine_name" "$machine_name"
|
||||||
|
json_add_string "auto_enroll" "${auto_enroll:-0}"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Save dashboard settings
|
||||||
|
save_settings() {
|
||||||
|
local enrollment_key="$1"
|
||||||
|
local machine_name="$2"
|
||||||
|
local auto_enroll="$3"
|
||||||
|
|
||||||
|
json_init
|
||||||
|
|
||||||
|
# Ensure config section exists
|
||||||
|
uci -q get crowdsec-dashboard.main >/dev/null 2>&1 || {
|
||||||
|
uci set crowdsec-dashboard.main=settings
|
||||||
|
}
|
||||||
|
|
||||||
|
# Save settings
|
||||||
|
[ -n "$enrollment_key" ] && uci set crowdsec-dashboard.main.enrollment_key="$enrollment_key"
|
||||||
|
[ -n "$machine_name" ] && uci set crowdsec-dashboard.main.machine_name="$machine_name"
|
||||||
|
[ -n "$auto_enroll" ] && uci set crowdsec-dashboard.main.auto_enroll="$auto_enroll"
|
||||||
|
|
||||||
|
if uci commit crowdsec-dashboard 2>/dev/null; then
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Settings saved"
|
||||||
|
secubox_log "Saved enrollment settings"
|
||||||
|
else
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "error" "Failed to save settings"
|
||||||
|
fi
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
# Main dispatcher
|
# Main dispatcher
|
||||||
case "$1" in
|
case "$1" in
|
||||||
list)
|
list)
|
||||||
echo '{"decisions":{},"alerts":{"limit":"number"},"metrics":{},"bouncers":{},"machines":{},"hub":{},"status":{},"ban":{"ip":"string","duration":"string","reason":"string"},"unban":{"ip":"string"},"stats":{},"seccubox_logs":{},"collect_debug":{},"waf_status":{},"metrics_config":{},"configure_metrics":{"enable":"string"},"collections":{},"install_collection":{"collection":"string"},"remove_collection":{"collection":"string"},"update_hub":{},"register_bouncer":{"bouncer_name":"string"},"delete_bouncer":{"bouncer_name":"string"},"firewall_bouncer_status":{},"control_firewall_bouncer":{"action":"string"},"firewall_bouncer_config":{},"update_firewall_bouncer_config":{"key":"string","value":"string"},"nftables_stats":{},"check_wizard_needed":{},"wizard_state":{},"repair_lapi":{},"repair_capi":{},"reset_wizard":{},"console_status":{},"console_enroll":{"key":"string","name":"string"},"console_disable":{},"service_control":{"action":"string"},"configure_acquisition":{"syslog_enabled":"string","firewall_enabled":"string","ssh_enabled":"string","http_enabled":"string","syslog_path":"string"},"acquisition_config":{},"acquisition_metrics":{},"health_check":{},"capi_metrics":{},"hub_available":{},"install_hub_item":{"item_type":"string","item_name":"string"},"remove_hub_item":{"item_type":"string","item_name":"string"}}'
|
echo '{"decisions":{},"alerts":{"limit":"number"},"metrics":{},"bouncers":{},"machines":{},"hub":{},"status":{},"ban":{"ip":"string","duration":"string","reason":"string"},"unban":{"ip":"string"},"stats":{},"seccubox_logs":{},"collect_debug":{},"waf_status":{},"metrics_config":{},"configure_metrics":{"enable":"string"},"collections":{},"install_collection":{"collection":"string"},"remove_collection":{"collection":"string"},"update_hub":{},"register_bouncer":{"bouncer_name":"string"},"delete_bouncer":{"bouncer_name":"string"},"firewall_bouncer_status":{},"control_firewall_bouncer":{"action":"string"},"firewall_bouncer_config":{},"update_firewall_bouncer_config":{"key":"string","value":"string"},"nftables_stats":{},"check_wizard_needed":{},"wizard_state":{},"repair_lapi":{},"repair_capi":{},"reset_wizard":{},"console_status":{},"console_enroll":{"key":"string","name":"string"},"console_disable":{},"service_control":{"action":"string"},"configure_acquisition":{"syslog_enabled":"string","firewall_enabled":"string","ssh_enabled":"string","http_enabled":"string","syslog_path":"string"},"acquisition_config":{},"acquisition_metrics":{},"health_check":{},"capi_metrics":{},"hub_available":{},"install_hub_item":{"item_type":"string","item_name":"string"},"remove_hub_item":{"item_type":"string","item_name":"string"},"get_settings":{},"save_settings":{"enrollment_key":"string","machine_name":"string","auto_enroll":"string"}}'
|
||||||
;;
|
;;
|
||||||
call)
|
call)
|
||||||
case "$2" in
|
case "$2" in
|
||||||
@ -2249,6 +2233,16 @@ case "$1" in
|
|||||||
item_name=$(echo "$input" | jsonfilter -e '@.item_name' 2>/dev/null)
|
item_name=$(echo "$input" | jsonfilter -e '@.item_name' 2>/dev/null)
|
||||||
remove_hub_item "$item_type" "$item_name"
|
remove_hub_item "$item_type" "$item_name"
|
||||||
;;
|
;;
|
||||||
|
get_settings)
|
||||||
|
get_settings
|
||||||
|
;;
|
||||||
|
save_settings)
|
||||||
|
read -r input
|
||||||
|
enrollment_key=$(echo "$input" | jsonfilter -e '@.enrollment_key' 2>/dev/null)
|
||||||
|
machine_name=$(echo "$input" | jsonfilter -e '@.machine_name' 2>/dev/null)
|
||||||
|
auto_enroll=$(echo "$input" | jsonfilter -e '@.auto_enroll' 2>/dev/null)
|
||||||
|
save_settings "$enrollment_key" "$machine_name" "$auto_enroll"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo '{"error": "Unknown method"}'
|
echo '{"error": "Unknown method"}'
|
||||||
;;
|
;;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user