diff options
author | Dixsie Wolmers <dixsie@ibm.com> | 2020-12-07 22:12:53 +0300 |
---|---|---|
committer | Derick Montague <derick.montague@ibm.com> | 2020-12-16 02:11:26 +0300 |
commit | 8f030bac11637fcd0a005907b558d7accbff68bd (patch) | |
tree | f9eb7487b4b1578e17d74e8bfdae97622ce9fc3b | |
parent | 645250b918ccc1d3965824a1c259d0367f6691b1 (diff) | |
download | webui-vue-8f030bac11637fcd0a005907b558d7accbff68bd.tar.xz |
Add security settings page
Adds ability to enable/disable:
- SSH protocol
- IPMI protocol
Signed-off-by: Dixsie Wolmers <dixsie@ibm.com>
Change-Id: I2430a46343dd8756ef75fcc3cb068df8d51dd415
-rw-r--r-- | src/components/AppNavigation/AppNavigationMixin.js | 5 | ||||
-rw-r--r-- | src/locales/en-US.json | 29 | ||||
-rw-r--r-- | src/router/routes.js | 9 | ||||
-rw-r--r-- | src/store/index.js | 2 | ||||
-rw-r--r-- | src/store/modules/Configuration/SecuritySettingsStore.js | 95 | ||||
-rw-r--r-- | src/views/Configuration/SecuritySettings/SecuritySettings.vue | 125 | ||||
-rw-r--r-- | src/views/Configuration/SecuritySettings/index.js | 2 |
7 files changed, 267 insertions, 0 deletions
diff --git a/src/components/AppNavigation/AppNavigationMixin.js b/src/components/AppNavigation/AppNavigationMixin.js index f0691a57..b163d75e 100644 --- a/src/components/AppNavigation/AppNavigationMixin.js +++ b/src/components/AppNavigation/AppNavigationMixin.js @@ -108,6 +108,11 @@ const AppNavigationMixin = { route: '/configuration/network-settings', }, { + id: 'security-settings', + label: this.$t('appNavigation.securitySettings'), + route: '/configuration/security-settings', + }, + { id: 'snmp-settings', label: this.$t('appNavigation.snmpSettings'), route: '/snmp-settings', diff --git a/src/locales/en-US.json b/src/locales/en-US.json index fb0d45a4..0e28de51 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -110,6 +110,7 @@ "overview": "@:appPageTitle.overview", "primaryNavigation": "Primary navigation", "rebootBmc": "@:appPageTitle.rebootBmc", + "securitySettings": "@:appPageTitle.securitySettings", "sensors": "@:appPageTitle.sensors", "serialOverLan": "SOL console", "serverLed": "@:appPageTitle.serverLed", @@ -134,6 +135,7 @@ "pageNotFound": "Page not found", "profileSettings": "Profile settings", "rebootBmc": "Reboot BMC", + "securitySettings": "Security settings", "sensors": "Sensors", "serialOverLan": "Serial over LAN (SOL) console", "serverLed": "Server LED", @@ -546,6 +548,33 @@ "successRebootStart": "Rebooting BMC." } }, + "pageSecuritySettings": { + "ipmi": "Network IPMI (out-of-band IPMI)", + "ipmiDescription": "Allow remote management of the platform via IPMI. Tools such as ipmitool require this setting to be enabled.", + "networkServices": "Network services", + "ssh": "SSH port 22 (BMC shell)", + "sshDescription": "SSH access to the BMC's command shell. Disabling this will disable users' ability to connect BMC shell via SSH.", + "modal": { + "disableMessage": { + "ipmi": "Are you sure you want to disable @:pageSecuritySettings.ipmi?", + "ssh": "Are you sure you want to disable @:pageSecuritySettings.ssh?" + }, + "enableMessage": { + "ipmi": "Are you sure you want to enable @:pageSecuritySettings.ipmi?", + "ssh": "Are you sure you want to enable @:pageSecuritySettings.ssh?" + } + }, + "toast": { + "errorIpmiDisabled": "Error disabling IPMI security setting.", + "errorIpmiEnabled":"Error enabling IPMI security setting.", + "errorSshDisabled":"Error disabling SSH security setting.", + "errorSshEnabled": "Error enabling SSH security setting.", + "successIpmiDisabled": "Successfully disabled IPMI security setting.", + "successIpmiEnabled": "Successfully enabled IPMI security setting.", + "successSshDisabled": "Successfully disabled SSH security setting.", + "successSshEnabled": "Successfully enabled SSH security setting." + } + }, "pageSensors": { "exportFilePrefix": "sensors_", "searchForSensors": "Search for sensors", diff --git a/src/router/routes.js b/src/router/routes.js index 3be1a1e4..a82833ad 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -17,6 +17,7 @@ import Overview from '@/views/Overview'; import PageNotFound from '@/views/PageNotFound'; import ProfileSettings from '@/views/ProfileSettings'; import RebootBmc from '@/views/Control/RebootBmc'; +import SecuritySettings from '@/views/Configuration/SecuritySettings'; import Sensors from '@/views/Health/Sensors'; import SerialOverLan from '@/views/Control/SerialOverLan'; import SerialOverLanConsole from '@/views/Control/SerialOverLan/SerialOverLanConsole'; @@ -163,6 +164,14 @@ const routes = [ }, }, { + path: '/configuration/security-settings', + name: 'security-settings', + component: SecuritySettings, + meta: { + title: i18n.t('appPageTitle.securitySettings'), + }, + }, + { path: '/control/kvm', name: 'kvm', component: Kvm, diff --git a/src/store/index.js b/src/store/index.js index e6153b1b..b4a77d82 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -21,6 +21,7 @@ import FanStore from './modules/Health/FanStore'; import ChassisStore from './modules/Health/ChassisStore'; import BmcStore from './modules/Health/BmcStore'; import ProcessorStore from './modules/Health/ProcessorStore'; +import SecuritySettingsStore from './modules/Configuration/SecuritySettingsStore'; import WebSocketPlugin from './plugins/WebSocketPlugin'; import DateTimeStore from './modules/Configuration/DateTimeSettingsStore'; @@ -55,6 +56,7 @@ export default new Vuex.Store({ bmc: BmcStore, processors: ProcessorStore, virtualMedia: VirtualMediaStore, + securitySettings: SecuritySettingsStore, }, plugins: [WebSocketPlugin], }); diff --git a/src/store/modules/Configuration/SecuritySettingsStore.js b/src/store/modules/Configuration/SecuritySettingsStore.js new file mode 100644 index 00000000..5a885425 --- /dev/null +++ b/src/store/modules/Configuration/SecuritySettingsStore.js @@ -0,0 +1,95 @@ +import api from '@/store/api'; +import i18n from '@/i18n'; + +const SecuritySettingsStore = { + namespaced: true, + state: { + sshProtocolEnabled: false, + ipmiProtocolEnabled: false, + }, + getters: { + sshProtocolEnabled: (state) => state.sshProtocolEnabled, + ipmiProtocolEnabled: (state) => state.ipmiProtocolEnabled, + }, + mutations: { + setSshProtocolEnabled: (state, sshProtocolEnabled) => + (state.sshProtocolEnabled = sshProtocolEnabled), + setIpmiProtocolEnabled: (state, ipmiProtocolEnabled) => + (state.ipmiProtocolEnabled = ipmiProtocolEnabled), + }, + actions: { + async getNetworkProtocolStatus({ commit }) { + return await api + .get('/redfish/v1/Managers/bmc/NetworkProtocol') + .then((response) => { + const sshProtocol = response.data.SSH.ProtocolEnabled; + const ipmiProtocol = response.data.IPMI.ProtocolEnabled; + commit('setSshProtocolEnabled', sshProtocol); + commit('setIpmiProtocolEnabled', ipmiProtocol); + }) + .catch((error) => console.log(error)); + }, + async saveIpmiProtocolState({ commit }, protocolEnabled) { + commit('setIpmiProtocolEnabled', protocolEnabled); + const ipmi = { + IPMI: { + ProtocolEnabled: protocolEnabled, + }, + }; + return await api + .patch('/redfish/v1/Managers/bmc/NetworkProtocol', ipmi) + .then(() => { + if (protocolEnabled) { + return i18n.t('pageSecuritySettings.toast.successIpmiEnabled'); + } else { + return i18n.t('pageSecuritySettings.toast.successIpmiDisabled'); + } + }) + .catch((error) => { + console.log(error); + commit('setIpmiProtocolEnabled', !protocolEnabled); + if (protocolEnabled) { + throw new Error( + i18n.t('pageSecuritySettings.toast.errorIpmiEnabled') + ); + } else { + throw new Error( + i18n.t('pageSecuritySettings.toast.errorIpmiDisabled') + ); + } + }); + }, + async saveSshProtocolState({ commit }, protocolEnabled) { + commit('setSshProtocolEnabled', protocolEnabled); + const ssh = { + SSH: { + ProtocolEnabled: protocolEnabled, + }, + }; + return await api + .patch('/redfish/v1/Managers/bmc/NetworkProtocol', ssh) + .then(() => { + if (protocolEnabled) { + return i18n.t('pageSecuritySettings.toast.successSshEnabled'); + } else { + return i18n.t('pageSecuritySettings.toast.successSshDisabled'); + } + }) + .catch((error) => { + console.log(error); + commit('setSshProtocolEnabled', !protocolEnabled); + if (protocolEnabled) { + throw new Error( + i18n.t('pageSecuritySettings.toast.errorSshEnabled') + ); + } else { + throw new Error( + i18n.t('pageSecuritySettings.toast.errorSshDisabled') + ); + } + }); + }, + }, +}; + +export default SecuritySettingsStore; diff --git a/src/views/Configuration/SecuritySettings/SecuritySettings.vue b/src/views/Configuration/SecuritySettings/SecuritySettings.vue new file mode 100644 index 00000000..d665a7f5 --- /dev/null +++ b/src/views/Configuration/SecuritySettings/SecuritySettings.vue @@ -0,0 +1,125 @@ +<template> + <b-container fluid="xl"> + <page-title /> + <b-row> + <b-col lg="8" md="8"> + <page-section + :section-title="$t('pageSecuritySettings.networkServices')" + > + <b-row class="setting-section"> + <b-col class="d-flex align-items-center justify-content-between"> + <dl class="mr-3 w-75"> + <dt>{{ $t('pageSecuritySettings.ssh') }}</dt> + <dd> + {{ $t('pageSecuritySettings.sshDescription') }} + </dd> + </dl> + <b-form-checkbox + id="sshSwitch" + v-model="sshProtocolState" + data-test-id="securitySettings-checkbox-switchSshProtocol" + switch + @change="changeSshProtocolState" + > + <span class="sr-only"> + {{ $t('pageSecuritySettings.ssh') }} + </span> + <span v-if="sshProtocolState"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </b-col> + </b-row> + <b-row class="setting-section"> + <b-col class="d-flex align-items-center justify-content-between"> + <dl class="mt-3 mr-3 w-75"> + <dt>{{ $t('pageSecuritySettings.ipmi') }}</dt> + <dd> + {{ $t('pageSecuritySettings.ipmiDescription') }} + </dd> + </dl> + <b-form-checkbox + id="ipmiSwitch" + v-model="ipmiProtocolState" + data-test-id="securitySettings-checkbox-switchIpmiProtocol" + switch + @change="changeIpmiProtocolState" + > + <span class="sr-only"> + {{ $t('pageSecuritySettings.ipmi') }} + </span> + <span v-if="ipmiProtocolState"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </b-col> + </b-row> + </page-section> + </b-col> + </b-row> + </b-container> +</template> + +<script> +import PageSection from '@/components/Global/PageSection'; +import PageTitle from '@/components/Global/PageTitle'; + +import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; +import BVToastMixin from '@/components/Mixins/BVToastMixin'; + +export default { + name: 'SecuritySettings', + components: { PageTitle, PageSection }, + mixins: [LoadingBarMixin, BVToastMixin], + beforeRouteLeave(to, from, next) { + this.hideLoader(); + next(); + }, + computed: { + sshProtocolState: { + get() { + return this.$store.getters['securitySettings/sshProtocolEnabled']; + }, + set(newValue) { + return newValue; + }, + }, + ipmiProtocolState: { + get() { + return this.$store.getters['securitySettings/ipmiProtocolEnabled']; + }, + set(newValue) { + return newValue; + }, + }, + }, + created() { + this.startLoader(); + this.$store + .dispatch('securitySettings/getNetworkProtocolStatus') + .finally(() => this.endLoader()); + }, + methods: { + changeIpmiProtocolState(state) { + this.$store + .dispatch('securitySettings/saveIpmiProtocolState', state) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + changeSshProtocolState(state) { + this.$store + .dispatch('securitySettings/saveSshProtocolState', state) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + }, +}; +</script> + +<style lang="scss" scoped> +.setting-section { + border-bottom: 1px solid gray('300'); +} +</style> diff --git a/src/views/Configuration/SecuritySettings/index.js b/src/views/Configuration/SecuritySettings/index.js new file mode 100644 index 00000000..5ec2b615 --- /dev/null +++ b/src/views/Configuration/SecuritySettings/index.js @@ -0,0 +1,2 @@ +import SecuritySettings from './SecuritySettings.vue'; +export default SecuritySettings; |