forked from openshift/origin-web-console
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroleBindings.js
131 lines (117 loc) · 4.54 KB
/
roleBindings.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
'use strict';
angular
.module('openshiftConsole')
.factory('RoleBindingsService', function($q, DataService) {
// some API constraints worth nothing:
// ServiceAccountUsernamePrefix = "system:serviceaccount:"
// ServiceAccountUsernameSeparator = ":"
// ServiceAccountGroupPrefix = "system:serviceaccounts:"
// AllServiceAccountsGroup = "system:serviceaccounts"
var cache = {};
// recurse until we get a unique binding name compared to what is cached
var qualifyBindingName = function(name, suffix) {
var search = suffix ?
name + suffix :
name;
return _.some(cache, _.matchesProperty('metadata.name', search)) ?
qualifyBindingName(name, _.uniqueId()) :
search;
};
var bindingTPL = function(role, projectNamespace) {
var roleName = _.get(role, 'metadata.name');
var bindingName = roleName ? qualifyBindingName(roleName) : null;
return {
kind: 'RoleBinding',
apiVersion: 'v1',
metadata: {
name: bindingName,
namespace: projectNamespace,
},
roleRef: {
name: _.get(role, 'metadata.name'),
// Roles have a namespace, clusterRoles do not
namespace: _.get(role, 'metadata.namespace'),
},
subjects: []
// userNames & groupNames are legacy, do not use!
// we literally must null them out when we receive them
};
};
var qualifySubject = function(subject, namespace) {
// NOTE: so far, SAs are the only ones that need tweaking
if(_.isEqual(subject.kind, 'ServiceAccount')) {
subject.namespace = subject.namespace || namespace;
} else if(_.isEqual(subject.kind, 'SystemUser') || _.isEqual(subject.kind, 'SystemGroup')) {
if(!_.startsWith(subject.name, 'system:')) {
subject.name = 'system:'+subject.name;
}
}
return subject;
};
var cleanBinding = function(binding) {
// These generated lists must be removed to be regenerated
binding.userNames = null;
binding.groupNames = null;
};
var create = function(role, subject, namespace, context) {
var binding = bindingTPL(role, namespace);
subject = qualifySubject(subject, namespace);
binding.subjects.push(angular.copy(subject));
return DataService.create('rolebindings', null, binding, context);
};
var addSubject = function(rb, subject, namespace, context) {
var tpl = bindingTPL();
var binding = _.extend(tpl, rb);
if(!subject) {
return binding;
}
subject = qualifySubject(subject, namespace);
if(_.isArray(binding.subjects)) {
if(_.includes(binding.subjects, subject)) {
return; // nothing to see here, folks.
}
binding.subjects.push(subject);
} else {
binding.subjects = [subject];
}
cleanBinding(binding);
return DataService.update('rolebindings', binding.metadata.name, binding, context);
};
// has to handle multiple bindings or multiple reference to a subject within a single binding
var removeSubject = function(subjectName, role, namespace, roleBindings, context) {
var matchingBindings = _.filter(roleBindings, {roleRef: {name: role}});
return $q.all(
_.map(matchingBindings, function(binding) {
var tpl = bindingTPL();
binding = _.extend(tpl, binding);
cleanBinding(binding);
var toMatch = { name: subjectName };
if(namespace) {
toMatch.namespace = namespace;
}
binding.subjects = _.reject(binding.subjects, toMatch);
return binding.subjects.length ?
DataService.update('rolebindings', binding.metadata.name, binding, context) :
DataService.delete('rolebindings', binding.metadata.name, context)
// For a delete, resp is simply a 201 or less useful object.
// Instead, this intercepts the response & returns the binding object
// with the empty .subjects[] list.
.then(function() {
return binding;
});
}));
};
var list = function(context, fn, opts) {
return DataService
.list('rolebindings', context, function(resp) {
cache = resp.by('metadata.name');
fn(resp);
}, opts);
};
return {
list: list,
create: create,
addSubject: addSubject,
removeSubject: removeSubject
};
});