feat(kompose): hide kompose [EE-4562] (#8084)

pull/8143/head
Ali 2 years ago committed by GitHub
parent 8fd0efa34f
commit 9cdc0da615
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -640,6 +640,7 @@
"Scopes": "", "Scopes": "",
"UserIdentifier": "" "UserIdentifier": ""
}, },
"ShowKomposeBuildOption": false,
"SnapshotInterval": "5m", "SnapshotInterval": "5m",
"TemplatesURL": "https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json", "TemplatesURL": "https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json",
"TrustOnFirstConnect": false, "TrustOnFirstConnect": false,

@ -16,6 +16,8 @@ type publicSettingsResponse struct {
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod" example:"1"` AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod" example:"1"`
// The minimum required length for a password of any user when using internal auth mode // The minimum required length for a password of any user when using internal auth mode
RequiredPasswordLength int `json:"RequiredPasswordLength" example:"1"` RequiredPasswordLength int `json:"RequiredPasswordLength" example:"1"`
// Show the Kompose build option (discontinued in 2.18)
ShowKomposeBuildOption bool `json:"ShowKomposeBuildOption" example:"false"`
// Whether edge compute features are enabled // Whether edge compute features are enabled
EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures" example:"true"` EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures" example:"true"`
// Supported feature flags // Supported feature flags
@ -70,6 +72,7 @@ func generatePublicSettings(appSettings *portainer.Settings) *publicSettingsResp
AuthenticationMethod: appSettings.AuthenticationMethod, AuthenticationMethod: appSettings.AuthenticationMethod,
RequiredPasswordLength: appSettings.InternalAuthSettings.RequiredPasswordLength, RequiredPasswordLength: appSettings.InternalAuthSettings.RequiredPasswordLength,
EnableEdgeComputeFeatures: appSettings.EnableEdgeComputeFeatures, EnableEdgeComputeFeatures: appSettings.EnableEdgeComputeFeatures,
ShowKomposeBuildOption: appSettings.ShowKomposeBuildOption,
EnableTelemetry: appSettings.EnableTelemetry, EnableTelemetry: appSettings.EnableTelemetry,
KubeconfigExpiry: appSettings.KubeconfigExpiry, KubeconfigExpiry: appSettings.KubeconfigExpiry,
Features: appSettings.FeatureFlagSettings, Features: appSettings.FeatureFlagSettings,

@ -32,6 +32,8 @@ type settingsUpdatePayload struct {
TemplatesURL *string `example:"https://raw.githubusercontent.com/portainer/templates/master/templates.json"` TemplatesURL *string `example:"https://raw.githubusercontent.com/portainer/templates/master/templates.json"`
// The default check in interval for edge agent (in seconds) // The default check in interval for edge agent (in seconds)
EdgeAgentCheckinInterval *int `example:"5"` EdgeAgentCheckinInterval *int `example:"5"`
// Show the Kompose build option (discontinued in 2.18)
ShowKomposeBuildOption *bool `json:"ShowKomposeBuildOption" example:"false"`
// Whether edge compute features are enabled // Whether edge compute features are enabled
EnableEdgeComputeFeatures *bool `example:"true"` EnableEdgeComputeFeatures *bool `example:"true"`
// The duration of a user session // The duration of a user session
@ -131,6 +133,10 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *
settings.TemplatesURL = *payload.TemplatesURL settings.TemplatesURL = *payload.TemplatesURL
} }
if payload.ShowKomposeBuildOption != nil {
settings.ShowKomposeBuildOption = *payload.ShowKomposeBuildOption
}
if payload.HelmRepositoryURL != nil { if payload.HelmRepositoryURL != nil {
if *payload.HelmRepositoryURL != "" { if *payload.HelmRepositoryURL != "" {

@ -857,6 +857,8 @@ type (
TemplatesURL string `json:"TemplatesURL" example:"https://raw.githubusercontent.com/portainer/templates/master/templates.json"` TemplatesURL string `json:"TemplatesURL" example:"https://raw.githubusercontent.com/portainer/templates/master/templates.json"`
// The default check in interval for edge agent (in seconds) // The default check in interval for edge agent (in seconds)
EdgeAgentCheckinInterval int `json:"EdgeAgentCheckinInterval" example:"5"` EdgeAgentCheckinInterval int `json:"EdgeAgentCheckinInterval" example:"5"`
// Show the Kompose build option (discontinued in 2.18)
ShowKomposeBuildOption bool `json:"ShowKomposeBuildOption" example:"false"`
// Whether edge compute features are enabled // Whether edge compute features are enabled
EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures"` EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures"`
// The duration of a user session // The duration of a user session

@ -108,6 +108,14 @@
You can get more information about Compose file format in the You can get more information about Compose file format in the
<a href="https://docs.docker.com/compose/compose-file/" target="_blank">official documentation</a>. <a href="https://docs.docker.com/compose/compose-file/" target="_blank">official documentation</a>.
</p> </p>
<p
>In a forthcoming Portainer release, we plan to remove support for docker-compose format manifests for Kubernetes deployments, and the Kompose conversion tool
which enables this. The reason for this is because Kompose now poses a security risk, since it has a number of Common Vulnerabilities and Exposures (CVEs).</p
>
<p
>Unfortunately, while the Kompose project has a maintainer and is part of the CNCF, it is not being actively maintained. Releases are very infrequent and new
pull requests to the project (including ones we've submitted) are taking months to be merged, with new CVEs arising in the meantime.</p
>
</span> </span>
<span class="text-muted small" ng-show="!ctrl.stack.IsComposeFormat"> <span class="text-muted small" ng-show="!ctrl.stack.IsComposeFormat">
<p class="vertical-center"> <p class="vertical-center">

@ -9,6 +9,7 @@ import { renderTemplate } from '@/react/portainer/custom-templates/components/ut
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service'; import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
import { compose, kubernetes } from '@@/BoxSelector/common-options/deployment-methods'; import { compose, kubernetes } from '@@/BoxSelector/common-options/deployment-methods';
import { editor, git, template, url } from '@@/BoxSelector/common-options/build-methods'; import { editor, git, template, url } from '@@/BoxSelector/common-options/build-methods';
import { getPublicSettings } from '@/react/portainer/settings/settings.service';
class KubernetesDeployController { class KubernetesDeployController {
/* @ngInject */ /* @ngInject */
@ -27,10 +28,7 @@ class KubernetesDeployController {
this.isTemplateVariablesEnabled = isBE; this.isTemplateVariablesEnabled = isBE;
this.deployOptions = [ this.deployOptions = [{ ...kubernetes, value: KubernetesDeployManifestTypes.KUBERNETES }];
{ ...kubernetes, value: KubernetesDeployManifestTypes.KUBERNETES },
{ ...compose, value: KubernetesDeployManifestTypes.COMPOSE },
];
this.methodOptions = [ this.methodOptions = [
{ ...git, value: KubernetesDeployBuildMethods.GIT }, { ...git, value: KubernetesDeployBuildMethods.GIT },
@ -341,6 +339,16 @@ class KubernetesDeployController {
} }
} }
try {
const publicSettings = await getPublicSettings();
this.showKomposeBuildOption = publicSettings.ShowKomposeBuildOption;
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to get public settings');
}
if (this.showKomposeBuildOption) {
this.deployOptions = [...this.deployOptions, { ...compose, value: KubernetesDeployManifestTypes.COMPOSE }];
}
this.state.viewReady = true; this.state.viewReady = true;
this.$window.onbeforeunload = () => { this.$window.onbeforeunload = () => {

@ -20,6 +20,7 @@ export function SettingsViewModel(data) {
this.EnforceEdgeID = data.EnforceEdgeID; this.EnforceEdgeID = data.EnforceEdgeID;
this.AgentSecret = data.AgentSecret; this.AgentSecret = data.AgentSecret;
this.EdgePortainerUrl = data.EdgePortainerUrl; this.EdgePortainerUrl = data.EdgePortainerUrl;
this.ShowKomposeBuildOption = data.ShowKomposeBuildOption;
} }
export function PublicSettingsViewModel(settings) { export function PublicSettingsViewModel(settings) {
@ -36,6 +37,7 @@ export function PublicSettingsViewModel(settings) {
this.Features = settings.Features; this.Features = settings.Features;
this.Edge = new EdgeSettingsViewModel(settings.Edge); this.Edge = new EdgeSettingsViewModel(settings.Edge);
this.DefaultRegistry = settings.DefaultRegistry; this.DefaultRegistry = settings.DefaultRegistry;
this.ShowKomposeBuildOption = settings.ShowKomposeBuildOption;
} }
export function InternalAuthSettingsViewModel(data) { export function InternalAuthSettingsViewModel(data) {

@ -184,6 +184,16 @@
tooltip="'Hides the \'Add with form\' buttons and prevents adding/editing of resources via forms'" tooltip="'Hides the \'Add with form\' buttons and prevents adding/editing of resources via forms'"
></por-switch-field> ></por-switch-field>
</div> </div>
<div class="form-group">
<por-switch-field
label="'Allow docker-compose format Kubernetes manifests'"
checked="formValues.ShowKomposeBuildOption"
name="'toggle_showKomposeBuildOption'"
on-change="(onToggleShowKompose)"
field-class="'col-sm-12'"
label-class="'col-sm-3 col-lg-2'"
></por-switch-field>
</div>
<!-- !deployment options --> <!-- !deployment options -->
<!-- actions --> <!-- actions -->
<div class="form-group"> <div class="form-group">

@ -1,18 +1,22 @@
import angular from 'angular'; import angular from 'angular';
import { FeatureId } from '@/react/portainer/feature-flags/enums'; import { FeatureId } from '@/react/portainer/feature-flags/enums';
// import trackEvent directly because the event only fires once with $analytics.trackEvent
import { trackEvent } from '@/angulartics.matomo/analytics-services';
import { options } from './options'; import { options } from './options';
angular.module('portainer.app').controller('SettingsController', [ angular.module('portainer.app').controller('SettingsController', [
'$scope', '$scope',
'$analytics',
'$state', '$state',
'Notifications', 'Notifications',
'SettingsService', 'SettingsService',
'ModalService',
'StateManager', 'StateManager',
'BackupService', 'BackupService',
'FileSaver', 'FileSaver',
'Blob', 'Blob',
function ($scope, $state, Notifications, SettingsService, StateManager, BackupService, FileSaver) { function ($scope, $analytics, $state, Notifications, SettingsService, ModalService, StateManager, BackupService, FileSaver) {
$scope.customBannerFeatureId = FeatureId.CUSTOM_LOGIN_BANNER; $scope.customBannerFeatureId = FeatureId.CUSTOM_LOGIN_BANNER;
$scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING; $scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING;
$scope.enforceDeploymentOptions = FeatureId.ENFORCE_DEPLOYMENT_OPTIONS; $scope.enforceDeploymentOptions = FeatureId.ENFORCE_DEPLOYMENT_OPTIONS;
@ -53,6 +57,7 @@ angular.module('portainer.app').controller('SettingsController', [
$scope.formValues = { $scope.formValues = {
customLogo: false, customLogo: false,
ShowKomposeBuildOption: false,
KubeconfigExpiry: undefined, KubeconfigExpiry: undefined,
HelmRepositoryURL: undefined, HelmRepositoryURL: undefined,
BlackListedLabels: [], BlackListedLabels: [],
@ -64,6 +69,8 @@ angular.module('portainer.app').controller('SettingsController', [
backupFormType: $scope.BACKUP_FORM_TYPES.FILE, backupFormType: $scope.BACKUP_FORM_TYPES.FILE,
}; };
$scope.initialFormValues = {};
$scope.onToggleEnableTelemetry = function onToggleEnableTelemetry(checked) { $scope.onToggleEnableTelemetry = function onToggleEnableTelemetry(checked) {
$scope.$evalAsync(() => { $scope.$evalAsync(() => {
$scope.formValues.enableTelemetry = checked; $scope.formValues.enableTelemetry = checked;
@ -76,6 +83,33 @@ angular.module('portainer.app').controller('SettingsController', [
}); });
}; };
$scope.onToggleShowKompose = async function onToggleShowKompose(checked) {
if (checked) {
ModalService.confirmWarn({
title: 'Are you sure?',
message: `<p>In a forthcoming Portainer release, we plan to remove support for docker-compose format manifests for Kubernetes deployments, and the Kompose conversion tool which enables this. The reason for this is because Kompose now poses a security risk, since it has a number of Common Vulnerabilities and Exposures (CVEs).</p>
<p>Unfortunately, while the Kompose project has a maintainer and is part of the CNCF, it is not being actively maintained. Releases are very infrequent and new pull requests to the project (including ones we've submitted) are taking months to be merged, with new CVEs arising in the meantime.</p>`,
buttons: {
confirm: {
label: 'Ok',
className: 'btn-warning',
},
},
callback: function (confirmed) {
$scope.setShowCompose(confirmed);
},
});
return;
}
$scope.setShowCompose(checked);
};
$scope.setShowCompose = function setShowCompose(checked) {
return $scope.$evalAsync(() => {
$scope.formValues.ShowKomposeBuildOption = checked;
});
};
$scope.onToggleAutoBackups = function onToggleAutoBackups(checked) { $scope.onToggleAutoBackups = function onToggleAutoBackups(checked) {
$scope.$evalAsync(() => { $scope.$evalAsync(() => {
$scope.formValues.scheduleAutomaticBackups = checked; $scope.formValues.scheduleAutomaticBackups = checked;
@ -152,8 +186,13 @@ angular.module('portainer.app').controller('SettingsController', [
KubeconfigExpiry: $scope.formValues.KubeconfigExpiry, KubeconfigExpiry: $scope.formValues.KubeconfigExpiry,
HelmRepositoryURL: $scope.formValues.HelmRepositoryURL, HelmRepositoryURL: $scope.formValues.HelmRepositoryURL,
GlobalDeploymentOptions: $scope.formValues.GlobalDeploymentOptions, GlobalDeploymentOptions: $scope.formValues.GlobalDeploymentOptions,
ShowKomposeBuildOption: $scope.formValues.ShowKomposeBuildOption,
}; };
if (kubeSettingsPayload.ShowKomposeBuildOption !== $scope.initialFormValues.ShowKomposeBuildOption && $scope.initialFormValues.enableTelemetry) {
trackEvent('kubernetes-allow-compose', { category: 'kubernetes', metadata: { 'kubernetes-allow-compose': kubeSettingsPayload.ShowKomposeBuildOption } });
}
$scope.state.kubeSettingsActionInProgress = true; $scope.state.kubeSettingsActionInProgress = true;
updateSettings(kubeSettingsPayload, 'Kubernetes settings updated'); updateSettings(kubeSettingsPayload, 'Kubernetes settings updated');
}; };
@ -165,6 +204,8 @@ angular.module('portainer.app').controller('SettingsController', [
StateManager.updateLogo(settings.LogoURL); StateManager.updateLogo(settings.LogoURL);
StateManager.updateSnapshotInterval(settings.SnapshotInterval); StateManager.updateSnapshotInterval(settings.SnapshotInterval);
StateManager.updateEnableTelemetry(settings.EnableTelemetry); StateManager.updateEnableTelemetry(settings.EnableTelemetry);
$scope.initialFormValues.ShowKomposeBuildOption = response.ShowKomposeBuildOption;
$scope.initialFormValues.enableTelemetry = response.EnableTelemetry;
$scope.formValues.BlackListedLabels = response.BlackListedLabels; $scope.formValues.BlackListedLabels = response.BlackListedLabels;
}) })
.catch(function error(err) { .catch(function error(err) {
@ -193,6 +234,12 @@ angular.module('portainer.app').controller('SettingsController', [
$scope.formValues.KubeconfigExpiry = settings.KubeconfigExpiry; $scope.formValues.KubeconfigExpiry = settings.KubeconfigExpiry;
$scope.formValues.HelmRepositoryURL = settings.HelmRepositoryURL; $scope.formValues.HelmRepositoryURL = settings.HelmRepositoryURL;
$scope.formValues.BlackListedLabels = settings.BlackListedLabels; $scope.formValues.BlackListedLabels = settings.BlackListedLabels;
if (settings.ShowKomposeBuildOption) {
$scope.formValues.ShowKomposeBuildOption = settings.ShowKomposeBuildOption;
}
$scope.initialFormValues.ShowKomposeBuildOption = settings.ShowKomposeBuildOption;
$scope.initialFormValues.enableTelemetry = settings.EnableTelemetry;
}) })
.catch(function error(err) { .catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings'); Notifications.error('Failure', err, 'Unable to retrieve application settings');

Loading…
Cancel
Save