mirror of https://github.com/rancher/dashboard.git
211 lines
6.2 KiB
Vue
211 lines
6.2 KiB
Vue
<script>
|
|
import CruResource from '@/components/CruResource';
|
|
import LabeledSelect from '@/components/form/LabeledSelect';
|
|
import LabeledInput from '@/components/form/LabeledInput';
|
|
import Banner from '@/components/Banner';
|
|
import Loading from '@/components/Loading';
|
|
import { CIS, CONFIG_MAP, ENDPOINTS } from '@/config/types';
|
|
import { mapGetters } from 'vuex';
|
|
import createEditView from '@/mixins/create-edit-view';
|
|
import { allHash } from '@/utils/promise';
|
|
import Checkbox from '@/components/form/Checkbox';
|
|
import RadioGroup from '@/components/form/RadioGroup';
|
|
import cronstrue from 'cronstrue';
|
|
|
|
const semver = require('semver');
|
|
|
|
export default {
|
|
components: {
|
|
CruResource, LabeledSelect, Banner, Loading, Checkbox, LabeledInput, RadioGroup
|
|
},
|
|
|
|
mixins: [createEditView],
|
|
|
|
props: {
|
|
value: {
|
|
type: Object,
|
|
default: () => {
|
|
return {};
|
|
}
|
|
},
|
|
mode: {
|
|
type: String,
|
|
default: 'create'
|
|
}
|
|
},
|
|
|
|
async fetch() {
|
|
const hash = await allHash({
|
|
profiles: this.$store.dispatch('cluster/findAll', { type: CIS.CLUSTER_SCAN_PROFILE }),
|
|
benchmarks: this.$store.dispatch('cluster/findAll', { type: CIS.BENCHMARK }),
|
|
defaultConfigMap: this.$store.dispatch('cluster/find', { type: CONFIG_MAP, id: 'cis-operator-system/default-clusterscanprofiles' }),
|
|
});
|
|
|
|
try {
|
|
await this.$store.dispatch('cluster/find', { type: ENDPOINTS, id: 'cattle-monitoring-system/rancher-monitoring-alertmanager' });
|
|
|
|
this.hasAlertManager = true;
|
|
} catch {
|
|
this.hasAlertManager = false;
|
|
}
|
|
|
|
this.allProfiles = hash.profiles;
|
|
this.defaultConfigMap = hash.defaultConfigMap;
|
|
},
|
|
|
|
data() {
|
|
if (!this.value.metadata.name) {
|
|
this.value.metadata.generateName = 'scan-';
|
|
}
|
|
|
|
return {
|
|
allProfiles: [], defaultConfigMap: null, scanAlertRule: this.value.spec.scanAlertRule, hasAlertManager: false
|
|
};
|
|
},
|
|
|
|
computed: {
|
|
...mapGetters({ currentCluster: 'currentCluster', t: 'i18n/t' }),
|
|
|
|
cronLabel() {
|
|
const { cronSchedule } = this.value.spec;
|
|
|
|
if (!cronSchedule) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const hint = cronstrue.toString(cronSchedule);
|
|
|
|
return hint;
|
|
} catch (e) {
|
|
return 'invalid cron expression';
|
|
}
|
|
},
|
|
|
|
validProfiles() {
|
|
const profileNames = this.allProfiles.filter((profile) => {
|
|
const benchmarkVersion = profile?.spec?.benchmarkVersion;
|
|
const benchmark = this.$store.getters['cluster/byId'](CIS.BENCHMARK, benchmarkVersion);
|
|
|
|
return this.validateBenchmark(benchmark, this.currentCluster );
|
|
}).map((profile) => {
|
|
return { label: profile.id, value: profile.id };
|
|
});
|
|
|
|
return profileNames;
|
|
},
|
|
|
|
defaultProfile() {
|
|
if (this.defaultConfigMap) {
|
|
const profiles = this.defaultConfigMap.data;
|
|
const provider = this.currentCluster.status.provider;
|
|
|
|
const name = profiles[provider] || profiles.default;
|
|
|
|
if (name) {
|
|
return this.allProfiles.find(profile => profile.id === name);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
},
|
|
|
|
monitoringUrl() {
|
|
return this.$router.resolve({
|
|
name: 'c-cluster-monitoring',
|
|
params: { cluster: this.$route.params.cluster }
|
|
}).href;
|
|
},
|
|
},
|
|
|
|
watch: {
|
|
defaultProfile(neu) {
|
|
if (neu && !this.value.spec.scanProfileName) {
|
|
this.value.spec.scanProfileName = neu?.id;
|
|
}
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
validateBenchmark(benchmark, currentCluster) {
|
|
const clusterVersion = currentCluster.kubernetesVersion;
|
|
|
|
if (!!benchmark?.spec?.clusterProvider) {
|
|
return benchmark?.spec?.clusterProvider === currentCluster.status.provider;
|
|
}
|
|
if (benchmark?.spec?.minKubernetesVersion) {
|
|
if (semver.gt(benchmark?.spec?.minKubernetesVersion, clusterVersion)) {
|
|
return false;
|
|
}
|
|
}
|
|
if (benchmark?.spec?.maxKubernetesVersion) {
|
|
if (semver.gt(clusterVersion, benchmark?.spec?.maxKubernetesVersion)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
},
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<Loading v-if="$fetchState.pending" />
|
|
|
|
<CruResource
|
|
v-else
|
|
:validation-passed="!!value.spec.scanProfileName"
|
|
:done-route="doneRoute"
|
|
:resource="value"
|
|
:mode="mode"
|
|
:errors="errors"
|
|
@finish="save"
|
|
@error="e=>errors = e"
|
|
>
|
|
<template>
|
|
<Banner v-if="!validProfiles.length" color="warning" :label="t('cis.noProfiles')" />
|
|
|
|
<div v-else class="row mb-20">
|
|
<div class="col span-6">
|
|
<LabeledSelect
|
|
v-model="value.spec.scanProfileName"
|
|
:mode="mode"
|
|
:label="t('cis.profile')"
|
|
:options="validProfiles"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<h3>Scheduling</h3>
|
|
<div class="row mb-20">
|
|
<div class="col span-6">
|
|
<LabeledInput v-model="value.spec.cronSchedule" :mode="mode" :label="t('cis.cronSchedule.label')" :placeholder="t('cis.cronSchedule.placeholder')" />
|
|
<span class="text-muted">{{ cronLabel }}</span>
|
|
</div>
|
|
<div class="col span-6">
|
|
<LabeledInput v-model.number="value.spec.retention" type="number" :mode="mode" :label="t('cis.retention')" />
|
|
</div>
|
|
</div>
|
|
<h3>
|
|
Alerting
|
|
</h3>
|
|
<div class="row mb-20">
|
|
<div class="col span-12">
|
|
<Banner v-if="scanAlertRule.alertOnFailure || scanAlertRule.alertOnComplete" class="mt-0" :color="hasAlertManager ? 'info' : 'warning'">
|
|
<span v-if="!hasAlertManager" v-html="t('cis.alertNotFound')" />
|
|
<span v-html="t('cis.alertNeeded', {link: monitoringUrl}, true)" />
|
|
</banner>
|
|
<Checkbox v-model="scanAlertRule.alertOnComplete" :label="t('cis.alertOnComplete')" />
|
|
<Checkbox v-model="scanAlertRule.alertOnFailure" :label="t('cis.alertOnFailure')" />
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col">
|
|
<span>{{ t('cis.scoreWarning.label') }}</span> <i v-tooltip="t('cis.scoreWarning.protip')" class="icon icon-info" />
|
|
<RadioGroup v-model="value.spec.scoreWarning" name="scoreWarning" :options="['pass', 'fail']" :labels="[t('cis.scan.pass'), t('cis.scan.fail')]" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</CruResource>
|
|
</template>
|