mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-05-14 15:01:44 +00:00
feat: add PodSecurityStandard setting (#842)
* feat: add PodSecurity Standard setting Signed-off-by: Andy Lee <andy.lee@suse.com> * refactor: unneeded change Signed-off-by: Andy Lee <andy.lee@suse.com> * refactor: filter by isSystem namespace Signed-off-by: Andy Lee <andy.lee@suse.com> * refactor: add fallback logic Signed-off-by: Andy Lee <andy.lee@suse.com> --------- Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
parent
5cc8b4c301
commit
d291a35754
@ -0,0 +1,196 @@
|
|||||||
|
<script>
|
||||||
|
import { RadioGroup } from '@components/Form/Radio';
|
||||||
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||||
|
import { NAMESPACE } from '@shell/config/types';
|
||||||
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HarvesterClusterPodSecurityStandard',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
RadioGroup,
|
||||||
|
LabeledSelect,
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [CreateEditView],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetch() {
|
||||||
|
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||||
|
|
||||||
|
await this.$store.dispatch(`${ inStore }/findAll`, { type: NAMESPACE });
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
let enabled = false;
|
||||||
|
let whitelistedNamespaces = [];
|
||||||
|
let privilegedNamespaces = [];
|
||||||
|
let restrictedNamespaces = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(this.value.value || this.value.default || '{}');
|
||||||
|
|
||||||
|
enabled = !!parsed.enabled;
|
||||||
|
whitelistedNamespaces = parsed.whitelistedNamespacesList ? parsed.whitelistedNamespacesList.split(',') : [];
|
||||||
|
privilegedNamespaces = parsed.privilegedNamespacesList ? parsed.privilegedNamespacesList.split(',') : [];
|
||||||
|
restrictedNamespaces = parsed.restrictedNamespacesList ? parsed.restrictedNamespacesList.split(',') : [];
|
||||||
|
} catch (e) {
|
||||||
|
enabled = false;
|
||||||
|
whitelistedNamespaces = [];
|
||||||
|
privilegedNamespaces = [];
|
||||||
|
restrictedNamespaces = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
enabled,
|
||||||
|
whitelistedNamespaces,
|
||||||
|
privilegedNamespaces,
|
||||||
|
restrictedNamespaces,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
enabledOptions() {
|
||||||
|
return [
|
||||||
|
{ label: this.t('generic.enabled'), value: true },
|
||||||
|
{ label: this.t('generic.disabled'), value: false },
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
allNamespaces() {
|
||||||
|
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||||
|
|
||||||
|
return this.$store.getters[`${ inStore }/all`](NAMESPACE).filter((ns) => !ns.isSystem).map((ns) => ns.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
whitelistedOptions() {
|
||||||
|
const excluded = new Set([...this.privilegedNamespaces, ...this.restrictedNamespaces]);
|
||||||
|
|
||||||
|
return this.allNamespaces.filter((ns) => !excluded.has(ns));
|
||||||
|
},
|
||||||
|
|
||||||
|
privilegedOptions() {
|
||||||
|
const excluded = new Set([...this.whitelistedNamespaces, ...this.restrictedNamespaces]);
|
||||||
|
|
||||||
|
return this.allNamespaces.filter((ns) => !excluded.has(ns));
|
||||||
|
},
|
||||||
|
|
||||||
|
restrictedOptions() {
|
||||||
|
const excluded = new Set([...this.whitelistedNamespaces, ...this.privilegedNamespaces]);
|
||||||
|
|
||||||
|
return this.allNamespaces.filter((ns) => !excluded.has(ns));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
useDefault() {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(this.value.default || '{}');
|
||||||
|
|
||||||
|
this.enabled = !!parsed.enabled;
|
||||||
|
this.whitelistedNamespaces = parsed.whitelistedNamespacesList ? parsed.whitelistedNamespacesList.split(',') : [];
|
||||||
|
this.privilegedNamespaces = parsed.privilegedNamespacesList ? parsed.privilegedNamespacesList.split(',') : [];
|
||||||
|
this.restrictedNamespaces = parsed.restrictedNamespacesList ? parsed.restrictedNamespacesList.split(',') : [];
|
||||||
|
} catch (e) {
|
||||||
|
this.enabled = false;
|
||||||
|
this.whitelistedNamespaces = [];
|
||||||
|
this.privilegedNamespaces = [];
|
||||||
|
this.restrictedNamespaces = [];
|
||||||
|
}
|
||||||
|
this.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
onUpdateEnabled() {
|
||||||
|
if (!this.enabled) {
|
||||||
|
this.whitelistedNamespaces = [];
|
||||||
|
this.privilegedNamespaces = [];
|
||||||
|
this.restrictedNamespaces = [];
|
||||||
|
}
|
||||||
|
this.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateWhitelisted(selected) {
|
||||||
|
this.whitelistedNamespaces = selected;
|
||||||
|
this.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
updatePrivileged(selected) {
|
||||||
|
this.privilegedNamespaces = selected;
|
||||||
|
this.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateRestricted(selected) {
|
||||||
|
this.restrictedNamespaces = selected;
|
||||||
|
this.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.value.value = JSON.stringify({
|
||||||
|
enabled: this.enabled,
|
||||||
|
whitelistedNamespacesList: this.whitelistedNamespaces.join(','),
|
||||||
|
privilegedNamespacesList: this.privilegedNamespaces.join(','),
|
||||||
|
restrictedNamespacesList: this.restrictedNamespaces.join(','),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="row mb-20">
|
||||||
|
<div class="col span-6">
|
||||||
|
<RadioGroup
|
||||||
|
v-model:value="enabled"
|
||||||
|
name="enabled"
|
||||||
|
:options="enabledOptions"
|
||||||
|
@update:value="onUpdateEnabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template v-if="enabled">
|
||||||
|
<div class="row mb-20">
|
||||||
|
<div class="col span-12">
|
||||||
|
<LabeledSelect
|
||||||
|
v-model:value="whitelistedNamespaces"
|
||||||
|
:label="t('harvester.setting.clusterPodSecurityStandard.whitelistedNamespaces.label')"
|
||||||
|
:options="whitelistedOptions"
|
||||||
|
:multiple="true"
|
||||||
|
:mode="mode"
|
||||||
|
@update:value="updateWhitelisted"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-20">
|
||||||
|
<div class="col span-12">
|
||||||
|
<LabeledSelect
|
||||||
|
v-model:value="privilegedNamespaces"
|
||||||
|
:label="t('harvester.setting.clusterPodSecurityStandard.privilegedNamespaces.label')"
|
||||||
|
:options="privilegedOptions"
|
||||||
|
:multiple="true"
|
||||||
|
:mode="mode"
|
||||||
|
@update:value="updatePrivileged"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-20">
|
||||||
|
<div class="col span-12">
|
||||||
|
<LabeledSelect
|
||||||
|
v-model:value="restrictedNamespaces"
|
||||||
|
:label="t('harvester.setting.clusterPodSecurityStandard.restrictedNamespaces.label')"
|
||||||
|
:options="restrictedOptions"
|
||||||
|
:multiple="true"
|
||||||
|
:mode="mode"
|
||||||
|
@update:value="updateRestricted"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -65,7 +65,8 @@ const FEATURE_FLAGS = {
|
|||||||
'vGPUAsPCIDevice',
|
'vGPUAsPCIDevice',
|
||||||
'instanceManagerResourcesSetting',
|
'instanceManagerResourcesSetting',
|
||||||
'rwxNetworkSetting',
|
'rwxNetworkSetting',
|
||||||
'createPVCWithDataVolume'
|
'createPVCWithDataVolume',
|
||||||
|
'clusterPodSecurityStandardSetting'
|
||||||
],
|
],
|
||||||
'v1.8.1': [],
|
'v1.8.1': [],
|
||||||
'v1.9.0': [],
|
'v1.9.0': [],
|
||||||
|
|||||||
@ -41,7 +41,8 @@ export const HCI_SETTING = {
|
|||||||
RANCHER_CLUSTER: 'rancher-cluster',
|
RANCHER_CLUSTER: 'rancher-cluster',
|
||||||
MAX_HOTPLUG_RATIO: 'max-hotplug-ratio',
|
MAX_HOTPLUG_RATIO: 'max-hotplug-ratio',
|
||||||
KUBEVIRT_MIGRATION: 'kubevirt-migration',
|
KUBEVIRT_MIGRATION: 'kubevirt-migration',
|
||||||
INSTANCE_MANAGER_RESOURCES: 'instance-manager-resources'
|
INSTANCE_MANAGER_RESOURCES: 'instance-manager-resources',
|
||||||
|
CLUSTER_POD_SECURITY_STANDARD: 'cluster-pod-security-standard'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HCI_ALLOWED_SETTINGS = {
|
export const HCI_ALLOWED_SETTINGS = {
|
||||||
@ -130,6 +131,9 @@ export const HCI_ALLOWED_SETTINGS = {
|
|||||||
},
|
},
|
||||||
[HCI_SETTING.INSTANCE_MANAGER_RESOURCES]: {
|
[HCI_SETTING.INSTANCE_MANAGER_RESOURCES]: {
|
||||||
kind: 'json', from: 'import', featureFlag: 'instanceManagerResourcesSetting'
|
kind: 'json', from: 'import', featureFlag: 'instanceManagerResourcesSetting'
|
||||||
|
},
|
||||||
|
[HCI_SETTING.CLUSTER_POD_SECURITY_STANDARD]: {
|
||||||
|
kind: 'json', from: 'import', canReset: true, featureFlag: 'clusterPodSecurityStandardSetting'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1286,6 +1286,13 @@ harvester:
|
|||||||
rancherCluster:
|
rancherCluster:
|
||||||
kubeConfig: Rancher KubeConfig
|
kubeConfig: Rancher KubeConfig
|
||||||
removeUpstreamClusterWhenNamespaceIsDeleted: Remove Upstream Cluster When Namespace Is Deleted
|
removeUpstreamClusterWhenNamespaceIsDeleted: Remove Upstream Cluster When Namespace Is Deleted
|
||||||
|
clusterPodSecurityStandard:
|
||||||
|
whitelistedNamespaces:
|
||||||
|
label: 'Whitelisted Namespaces'
|
||||||
|
privilegedNamespaces:
|
||||||
|
label: 'Privileged Namespaces'
|
||||||
|
restrictedNamespaces:
|
||||||
|
label: 'Restricted Namespaces'
|
||||||
storageNetwork:
|
storageNetwork:
|
||||||
range:
|
range:
|
||||||
placeholder: e.g. 172.16.0.0/24
|
placeholder: e.g. 172.16.0.0/24
|
||||||
@ -2043,6 +2050,7 @@ advancedSettings:
|
|||||||
'harv-max-hotplug-ratio': 'The ratio for kubevirt to limit the maximum CPU and memory that can be hotplugged to a VM. The value could be an integer between 1 and 20, default to 4.'
|
'harv-max-hotplug-ratio': 'The ratio for kubevirt to limit the maximum CPU and memory that can be hotplugged to a VM. The value could be an integer between 1 and 20, default to 4.'
|
||||||
'harv-kubevirt-migration': 'Configure cluster-wide KubeVirt live migration parameters.'
|
'harv-kubevirt-migration': 'Configure cluster-wide KubeVirt live migration parameters.'
|
||||||
'harv-instance-manager-resources': 'Configure resource percentage reservations for Longhorn instance manager V1 and V2. Valid instance manager CPU range between 0 - 40.'
|
'harv-instance-manager-resources': 'Configure resource percentage reservations for Longhorn instance manager V1 and V2. Valid instance manager CPU range between 0 - 40.'
|
||||||
|
'harv-cluster-pod-security-standard': 'Enforce Kubernetes Pod Security Standards (PSS) at the cluster level.'
|
||||||
|
|
||||||
typeLabel:
|
typeLabel:
|
||||||
kubevirt.io.virtualmachine: |-
|
kubevirt.io.virtualmachine: |-
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user