Skip to content

Commit

Permalink
fix RoleBinding with multiple subjects
Browse files Browse the repository at this point in the history
  • Loading branch information
debsmita1 committed Dec 9, 2020
1 parent 0a0880c commit 3161484
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 54 deletions.
Expand Up @@ -17,6 +17,8 @@ import {
sendRoleBindingRequest,
getNewRoles,
getRemovedRoles,
sendK8sRequest,
getGroupedRole,
} from './project-access-form-submit-utils';
import { validationSchema } from './project-access-form-validation-utils';
import ProjectAccessForm from './ProjectAccessForm';
Expand All @@ -33,7 +35,7 @@ const ProjectAccess: React.FC<ProjectAccessProps> = ({ formName, namespace, role
return <LoadingBox />;
}

const filteredRoleBindings = filterRoleBindings(roleBindings, Roles);
const filteredRoleBindings = filterRoleBindings(roleBindings.data, Roles);

const userRoleBindings: UserRoleBinding[] = getUserRoleBindings(filteredRoleBindings);

Expand All @@ -60,6 +62,15 @@ const ProjectAccess: React.FC<ProjectAccessProps> = ({ formName, namespace, role
const roleBindingRequests = [];
roleBinding.metadata.namespace = namespace;

removeRoles = _.filter(removeRoles, (removeRole) => {
const groupedRole = getGroupedRole(removeRole, roleBindings.data);
if (groupedRole) {
roleBindingRequests.push(sendK8sRequest(Verb.Patch, groupedRole));
return false;
}
return true;
});

actions.setSubmitting(true);
if (!_.isEmpty(updateRoles)) {
roleBindingRequests.push(...sendRoleBindingRequest(Verb.Patch, updateRoles, roleBinding));
Expand Down
Expand Up @@ -142,6 +142,11 @@ export const roleBindingsWithRequiredRoles = [
kind: 'User',
name: 'abc',
},
{
apiGroup: 'rbac.authorization.k8s.io',
kind: 'User',
name: 'mno',
},
],
},
];
Expand All @@ -157,6 +162,11 @@ export const roleBindingsWithRequiredAttributes = [
user: 'abc',
role: 'view',
},
{
roleBindingName: 'check-view',
user: 'mno',
role: 'view',
},
];

export const roleBindingsToBeCreated1: UserRoleBinding[] = [
Expand Down Expand Up @@ -332,3 +342,22 @@ export const displayRoleBindings: UserRoleBinding[] = [
role: 'admin',
},
];

export const getGroupedRoleResult = {
metadata: {
name: 'check-view',
namespace: 'xyz',
},
roleRef: {
apiGroup: 'rbac.authorization.k8s.io',
kind: 'ClusterRole',
name: 'view',
},
subjects: [
{
apiGroup: 'rbac.authorization.k8s.io',
kind: 'User',
name: 'abc',
},
],
};
Expand Up @@ -2,6 +2,7 @@ import {
getRolesWithNameChange,
getNewRoles,
getRemovedRoles,
getGroupedRole,
} from '../project-access-form-submit-utils';
import {
roleBindingsToBeCreated1,
Expand All @@ -12,7 +13,10 @@ import {
rolesBindingsToBeRemoved,
formValues2,
roleBindingsToBeCreated2,
roleBindingsWithRequiredRoles,
getGroupedRoleResult,
} from './project-access-form-data';
import { UserRoleBinding } from '../project-access-form-utils-types';

describe('Project Access handleSubmit Utils', () => {
it('should get roles removed by the user', async () => {
Expand All @@ -32,4 +36,14 @@ describe('Project Access handleSubmit Utils', () => {
);
expect(rolesWithNameChange).toEqual(rolesWithNameChangeResult);
});

it('should remove user belonging to grouped subjects in a Role Binding', async () => {
const role: UserRoleBinding = {
role: 'admin',
roleBindingName: 'check-view',
user: 'mno',
};
const groupedRole = getGroupedRole(role, roleBindingsWithRequiredRoles);
expect(groupedRole).toEqual(getGroupedRoleResult);
});
});

This file was deleted.

Expand Up @@ -2,7 +2,7 @@ import * as _ from 'lodash';
import { k8sCreate, k8sKill, k8sPatch, K8sResourceKind } from '@console/internal/module/k8s';
import { RoleBindingModel } from '@console/internal/models';
import { generateSecret } from '../import/import-submit-utils';
import { Verb, UserRoleBinding } from './project-access-form-utils-types';
import { Verb, UserRoleBinding, RoleBinding } from './project-access-form-utils-types';

export const getRolesWithNameChange = (
newRoles: UserRoleBinding[],
Expand All @@ -21,15 +21,18 @@ export const getRolesWithNameChange = (
return rolesWithNameChange;
};

export const sendK8sRequest = (verb: string, roleBinding): Promise<K8sResourceKind> => {
export const sendK8sRequest = (
verb: string,
roleBinding: RoleBinding,
): Promise<K8sResourceKind> => {
switch (verb) {
case Verb.Create:
return k8sCreate(RoleBindingModel, roleBinding);
case Verb.Remove:
return k8sKill(RoleBindingModel, roleBinding);
case Verb.Patch:
return k8sPatch(RoleBindingModel, { metadata: roleBinding.metadata }, [
{ op: 'replace', path: `/subjects/0`, value: roleBinding.subjects[0] },
{ op: 'replace', path: `/subjects`, value: roleBinding.subjects },
]);
default:
return null;
Expand Down Expand Up @@ -73,3 +76,14 @@ export const sendRoleBindingRequest = (verb: string, roles: UserRoleBinding[], r
});
return finalArray;
};

export const getGroupedRole = (role: UserRoleBinding, roleBindings: RoleBinding[]) => {
let groupedRole: RoleBinding;
_.forEach(roleBindings, (roleBinding: RoleBinding) => {
if (roleBinding.metadata.name === role.roleBindingName && roleBinding.subjects.length > 1) {
_.remove(roleBinding.subjects, (subject) => subject.name === role.user);
groupedRole = roleBinding;
}
});
return groupedRole;
};
@@ -1,3 +1,5 @@
import { K8sResourceCommon } from '@console/internal/module/k8s';

export enum Verb {
Create = 'Create',
Remove = 'Remove',
Expand All @@ -10,27 +12,24 @@ export enum Roles {
edit = 'edit',
}

export interface UserRole {
metadata: {
name: string;
};
roleRef: {
name: string;
};
subjects: [
{
name: string;
},
];
}

export interface UserRoleBinding {
roleBindingName?: string;
user: string;
role: string;
}

export const roleBinding = {
type ApiGroupType = {
apiGroup: string;
kind: string;
name: string;
};

export type RoleBinding = K8sResourceCommon & {
roleRef: ApiGroupType;
subjects: ApiGroupType[];
};

export const roleBinding: RoleBinding = {
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'RoleBinding',
metadata: {
Expand Down
@@ -1,24 +1,27 @@
import * as _ from 'lodash';
import { UserRoleBinding, UserRole } from './project-access-form-utils-types';
import { UserRoleBinding, RoleBinding } from './project-access-form-utils-types';

export const filterRoleBindings = (roleBindings, roles) => {
return _.filter(roleBindings.data, (user: UserRole) => _.keys(roles).includes(user.roleRef.name));
export const filterRoleBindings = (roleBindings: RoleBinding[], roles) => {
return _.filter(roleBindings, (user: RoleBinding) => _.keys(roles).includes(user.roleRef.name));
};

export const getUserRoleBindings = (roleBindings) => {
export const getUsersFromSubject = (user: RoleBinding) => {
const users: UserRoleBinding[] = user.subjects?.reduce((acc, obj) => {
acc.push({
roleBindingName: user.metadata.name,
user: obj.name,
role: user.roleRef.name,
});
return acc;
}, []);

return users;
};

export const getUserRoleBindings = (roleBindings: RoleBinding[]) => {
let userRoleBindings: UserRoleBinding[] = [];
roleBindings.map(
(user: UserRole) =>
(userRoleBindings = [
...userRoleBindings,
...[
{
roleBindingName: user.metadata.name,
user: user.subjects[0].name,
role: user.roleRef.name,
},
],
]),
(user: RoleBinding) => (userRoleBindings = [...userRoleBindings, ...getUsersFromSubject(user)]),
);
return userRoleBindings;
};

0 comments on commit 3161484

Please sign in to comment.