fix(k8s/resource-pool): unusable RP access management (#4810)

pull/4816/head
LP B 2021-02-03 06:38:56 +01:00 committed by GitHub
parent d2d7f6fdb9
commit e401724d43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 8 deletions

View File

@ -1,10 +1,32 @@
import _ from 'lodash-es';
import { KubernetesConfigMap } from 'Kubernetes/models/config-map/models';
import { KubernetesConfigMap, KubernetesPortainerAccessConfigMap } from 'Kubernetes/models/config-map/models';
import { KubernetesConfigMapCreatePayload, KubernetesConfigMapUpdatePayload } from 'Kubernetes/models/config-map/payloads';
import { KubernetesPortainerConfigurationOwnerLabel } from 'Kubernetes/models/configuration/models';
import { KubernetesConfigurationFormValuesEntry } from 'Kubernetes/models/configuration/formvalues';
class KubernetesConfigMapConverter {
static apiToPortainerAccessConfigMap(data) {
const res = new KubernetesPortainerAccessConfigMap();
res.Id = data.metadata.uid;
res.Data = data.data;
return res;
}
static createAccessPayload(data) {
const res = new KubernetesConfigMapCreatePayload();
_.unset(res, 'binaryData');
res.metadata.name = data.Name;
res.metadata.namespace = data.Namespace;
res.data = data.Data;
return res;
}
static updateAccessPayload(data) {
const res = KubernetesConfigMapConverter.createAccessPayload(data);
res.metadata.uid = data.Id;
return res;
}
/**
* API ConfigMap to front ConfigMap
*/

View File

@ -2,6 +2,15 @@ export const KubernetesPortainerConfigMapNamespace = 'portainer';
export const KubernetesPortainerConfigMapConfigName = 'portainer-config';
export const KubernetesPortainerConfigMapAccessKey = 'NamespaceAccessPolicies';
export function KubernetesPortainerAccessConfigMap() {
return {
Id: 0,
Name: KubernetesPortainerConfigMapConfigName,
Namespace: KubernetesPortainerConfigMapNamespace,
Data: {},
};
}
/**
* ConfigMap Model
*/

View File

@ -3,6 +3,7 @@ import _ from 'lodash-es';
import PortainerError from 'Portainer/error';
import KubernetesConfigMapConverter from 'Kubernetes/converters/configMap';
import { KubernetesCommonParams } from 'Kubernetes/models/common/params';
import { KubernetesPortainerAccessConfigMap } from 'Kubernetes/models/config-map/models';
class KubernetesConfigMapService {
/* @ngInject */
@ -17,6 +18,54 @@ class KubernetesConfigMapService {
this.deleteAsync = this.deleteAsync.bind(this);
}
getAccess(namespace, name) {
return this.$async(async () => {
try {
const params = new KubernetesCommonParams();
params.id = name;
const raw = await this.KubernetesConfigMaps(namespace).get(params).$promise;
return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(raw);
} catch (err) {
if (err.status === 404) {
return new KubernetesPortainerAccessConfigMap();
}
throw new PortainerError('Unable to retrieve Portainer accesses', err);
}
});
}
createAccess(config) {
return this.$async(async () => {
try {
const payload = KubernetesConfigMapConverter.createAccessPayload(config);
const params = {};
const namespace = payload.metadata.namespace;
const data = await this.KubernetesConfigMaps(namespace).create(params, payload).$promise;
return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(data);
} catch (err) {
throw new PortainerError('Unable to create Portainer accesses', err);
}
});
}
updateAccess(config) {
return this.$async(async () => {
try {
if (!config.Id) {
return await this.createAccess(config);
}
const payload = KubernetesConfigMapConverter.updateAccessPayload(config);
const params = new KubernetesCommonParams();
params.id = payload.metadata.name;
const namespace = payload.metadata.namespace;
const data = await this.KubernetesConfigMaps(namespace).update(params, payload).$promise;
return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(data);
} catch (err) {
throw new PortainerError('Unable to update Portainer accesses', err);
}
});
}
/**
* GET
*/
@ -29,12 +78,12 @@ class KubernetesConfigMapService {
this.KubernetesConfigMaps(namespace).getYaml(params).$promise,
]);
if (_.get(rawPromise, 'reason.status') == 404 && _.get(yamlPromise, 'reason.status') == 404) {
if (_.get(rawPromise, 'reason.status') === 404 && _.get(yamlPromise, 'reason.status') === 404) {
return KubernetesConfigMapConverter.defaultConfigMap(namespace, name);
}
// Saving binary data to 'data' field in configMap Object is not allowed by kubernetes and getYaml() may get
// an error. We should keep binary data to 'binaryData' field instead of 'data'. Before that, we
// Saving binary data to 'data' field in configMap Object is not allowed by kubernetes and getYaml() may get
// an error. We should keep binary data to 'binaryData' field instead of 'data'. Before that, we
// use response from get() and ignore 500 error as a workaround.
if (rawPromise.value) {
return KubernetesConfigMapConverter.apiToConfigMap(rawPromise.value, yamlPromise.value);

View File

@ -52,7 +52,7 @@ class KubernetesResourcePoolAccessController {
let [endpoint, pool, configMap] = await Promise.all([
this.EndpointService.endpoint(this.endpointId),
this.KubernetesResourcePoolService.get(name),
this.KubernetesConfigMapService.get(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName),
this.KubernetesConfigMapService.getAccess(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName),
]);
const group = await this.GroupService.group(endpoint.GroupId);
const roles = [];
@ -96,7 +96,7 @@ class KubernetesResourcePoolAccessController {
this.state.actionInProgress = true;
const newAccesses = _.concat(this.authorizedUsersAndTeams, this.formValues.multiselectOutput);
const accessConfigMap = KubernetesConfigMapHelper.modifiyNamespaceAccesses(angular.copy(this.accessConfigMap), this.pool.Namespace.Name, newAccesses);
await this.KubernetesConfigMapService.update(accessConfigMap);
await this.KubernetesConfigMapService.updateAccess(accessConfigMap);
this.Notifications.success('Access successfully created');
this.$state.reload();
} catch (err) {
@ -116,7 +116,7 @@ class KubernetesResourcePoolAccessController {
this.state.actionInProgress = true;
const newAccesses = _.without(this.authorizedUsersAndTeams, ...selectedItems);
const accessConfigMap = KubernetesConfigMapHelper.modifiyNamespaceAccesses(angular.copy(this.accessConfigMap), this.pool.Namespace.Name, newAccesses);
await this.KubernetesConfigMapService.update(accessConfigMap);
await this.KubernetesConfigMapService.updateAccess(accessConfigMap);
this.Notifications.success('Access successfully removed');
this.$state.reload();
} catch (err) {

View File

@ -167,7 +167,6 @@ angular
async function initView() {
var endpointMode = $scope.applicationState.endpoint.mode;
const endpointId = +$state.params.endpointId;
$scope.state.StackType = 2;
if (endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER') {
$scope.state.StackType = 1;