@rancher/shell 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/translations/en-us.yaml +13 -0
- package/components/auth/AuthBanner.vue +6 -0
- package/edit/auth/ldap/config.vue +21 -1
- package/edit/auth/saml.vue +132 -37
- package/package.json +1 -1
- package/scripts/extension/publish +1 -1
- package/utils/gc/gc.ts +1 -1
|
@@ -455,7 +455,13 @@ authConfig:
|
|
|
455
455
|
objectClass: Object Class
|
|
456
456
|
password: Password
|
|
457
457
|
port: Port
|
|
458
|
+
protocol: Protocol
|
|
459
|
+
protocols:
|
|
460
|
+
starttls: Start TLS
|
|
461
|
+
ldap: LDAP
|
|
462
|
+
tls: LDAPS (TLS)
|
|
458
463
|
customizeSchema: Customize Schema
|
|
464
|
+
oktaSchema: 'The defaults below are for a generic OpenLDAP server. For more information on the values to use when using the Okta LDAP interface, see: <a target="_blank" rel="noopener noreferrer nofollow" href="https://help.okta.com/en-us/Content/Topics/Directory/LDAP-interface-connection-settings.htm">Okta LDAP Interface connection settings</a>'
|
|
459
465
|
users: Users
|
|
460
466
|
groups: Groups
|
|
461
467
|
searchAttribute: Search Attribute
|
|
@@ -500,6 +506,13 @@ authConfig:
|
|
|
500
506
|
shibboleth: Configure a Shibboleth account
|
|
501
507
|
showLdap: Configure an OpenLDAP Server
|
|
502
508
|
userName: User Name Field
|
|
509
|
+
search:
|
|
510
|
+
title: User and Group Search
|
|
511
|
+
message: The SAML Protocol does not support search or lookup for users or groups. In order to enabled search, an OpenLDAP server must be configured.
|
|
512
|
+
on: LDAP User and Group search has been configured
|
|
513
|
+
off: LDAP User and Group search is not configured
|
|
514
|
+
show: Show details
|
|
515
|
+
hide: Hide details
|
|
503
516
|
azuread:
|
|
504
517
|
tenantId: Tenant ID
|
|
505
518
|
applicationId: Application ID
|
|
@@ -5,6 +5,7 @@ import { Checkbox } from '@components/Form/Checkbox';
|
|
|
5
5
|
import UnitInput from '@shell/components/form/UnitInput';
|
|
6
6
|
import { Banner } from '@components/Banner';
|
|
7
7
|
import FileSelector from '@shell/components/form/FileSelector';
|
|
8
|
+
import { OKTA, SHIBBOLETH } from '../saml';
|
|
8
9
|
|
|
9
10
|
const DEFAULT_NON_TLS_PORT = 389;
|
|
10
11
|
const DEFAULT_TLS_PORT = 636;
|
|
@@ -33,6 +34,11 @@ export default {
|
|
|
33
34
|
type: {
|
|
34
35
|
type: String,
|
|
35
36
|
required: true
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
isCreate: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
},
|
|
@@ -46,9 +52,17 @@ export default {
|
|
|
46
52
|
model: this.value,
|
|
47
53
|
hostname: this.value.servers.join(','),
|
|
48
54
|
serverSetting: null,
|
|
55
|
+
OKTA
|
|
49
56
|
};
|
|
50
57
|
},
|
|
51
58
|
|
|
59
|
+
computed: {
|
|
60
|
+
// Does the auth provider support LDAP for search in addition to SAML?
|
|
61
|
+
isSamlProvider() {
|
|
62
|
+
return this.type === SHIBBOLETH || this.type === OKTA;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
52
66
|
watch: {
|
|
53
67
|
hostname(neu, old) {
|
|
54
68
|
this.value.servers = neu.split(',');
|
|
@@ -232,6 +246,12 @@ export default {
|
|
|
232
246
|
<div class="row">
|
|
233
247
|
<h3> {{ t('authConfig.ldap.customizeSchema') }}</h3>
|
|
234
248
|
</div>
|
|
249
|
+
<Banner
|
|
250
|
+
v-if="type === OKTA && isCreate"
|
|
251
|
+
class="row"
|
|
252
|
+
color="info"
|
|
253
|
+
label-key="authConfig.ldap.oktaSchema"
|
|
254
|
+
/>
|
|
235
255
|
<div class="row">
|
|
236
256
|
<div class="col span-6">
|
|
237
257
|
<h4>{{ t('authConfig.ldap.users') }}</h4>
|
|
@@ -361,7 +381,7 @@ export default {
|
|
|
361
381
|
/>
|
|
362
382
|
</div>
|
|
363
383
|
<div
|
|
364
|
-
v-if="
|
|
384
|
+
v-if="!isSamlProvider"
|
|
365
385
|
class=" col span-6"
|
|
366
386
|
>
|
|
367
387
|
<RadioGroup
|
package/edit/auth/saml.vue
CHANGED
|
@@ -11,6 +11,31 @@ import FileSelector from '@shell/components/form/FileSelector';
|
|
|
11
11
|
import AuthBanner from '@shell/components/auth/AuthBanner';
|
|
12
12
|
import config from '@shell/edit/auth/ldap/config';
|
|
13
13
|
|
|
14
|
+
export const SHIBBOLETH = 'shibboleth';
|
|
15
|
+
export const OKTA = 'okta';
|
|
16
|
+
|
|
17
|
+
// Standard LDAP defaults
|
|
18
|
+
const LDAP_DEFAULTS = {
|
|
19
|
+
connectionTimeout: 5000,
|
|
20
|
+
groupDNAttribute: 'entryDN',
|
|
21
|
+
groupMemberMappingAttribute: 'member',
|
|
22
|
+
groupMemberUserAttribute: 'entryDN',
|
|
23
|
+
groupNameAttribute: 'cn',
|
|
24
|
+
groupObjectClass: 'groupOfNames',
|
|
25
|
+
groupSearchAttribute: 'cn',
|
|
26
|
+
nestedGroupMembershipEnabled: false,
|
|
27
|
+
port: 389,
|
|
28
|
+
servers: [],
|
|
29
|
+
starttls: false,
|
|
30
|
+
tls: false,
|
|
31
|
+
disabledStatusBitmask: 0,
|
|
32
|
+
userLoginAttribute: 'uid',
|
|
33
|
+
userMemberAttribute: 'memberOf',
|
|
34
|
+
userNameAttribute: 'cn',
|
|
35
|
+
userObjectClass: 'inetOrgPerson',
|
|
36
|
+
userSearchAttribute: 'uid|sn|givenName'
|
|
37
|
+
};
|
|
38
|
+
|
|
14
39
|
export default {
|
|
15
40
|
components: {
|
|
16
41
|
Loading,
|
|
@@ -26,7 +51,10 @@ export default {
|
|
|
26
51
|
|
|
27
52
|
mixins: [CreateEditView, AuthConfig],
|
|
28
53
|
data() {
|
|
29
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
showLdap: false,
|
|
56
|
+
showLdapDetails: false,
|
|
57
|
+
};
|
|
30
58
|
},
|
|
31
59
|
|
|
32
60
|
computed: {
|
|
@@ -42,32 +70,32 @@ export default {
|
|
|
42
70
|
return { enabled: true, ...this.model };
|
|
43
71
|
},
|
|
44
72
|
|
|
73
|
+
// Does the auth provider support LDAP for search in addition to SAML?
|
|
74
|
+
supportsLDAPSearch() {
|
|
75
|
+
return this.NAME === SHIBBOLETH || this.NAME === OKTA;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
ldapHosts() {
|
|
79
|
+
const hosts = this.model?.openLdapConfig.servers || [];
|
|
80
|
+
|
|
81
|
+
return hosts.join(',');
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
ldapProtocol() {
|
|
85
|
+
if (this.model?.openLdapConfig?.starttls) {
|
|
86
|
+
return this.t('authConfig.ldap.protocols.starttls');
|
|
87
|
+
} else if (this.model?.openLdapConfig?.tls) {
|
|
88
|
+
return this.t('authConfig.ldap.protocols.tls');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return this.t('authConfig.ldap.protocols.ldap');
|
|
92
|
+
}
|
|
45
93
|
},
|
|
46
94
|
watch: {
|
|
47
95
|
showLdap(neu, old) {
|
|
48
96
|
if (neu && !this.model.openLdapConfig) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
groupDNAttribute: 'entryDN',
|
|
52
|
-
groupMemberMappingAttribute: 'member',
|
|
53
|
-
groupMemberUserAttribute: 'entryDN',
|
|
54
|
-
groupNameAttribute: 'cn',
|
|
55
|
-
groupObjectClass: 'groupOfNames',
|
|
56
|
-
groupSearchAttribute: 'cn',
|
|
57
|
-
nestedGroupMembershipEnabled: false,
|
|
58
|
-
port: 389,
|
|
59
|
-
servers: [],
|
|
60
|
-
starttls: false,
|
|
61
|
-
tls: false,
|
|
62
|
-
disabledStatusBitmask: 0,
|
|
63
|
-
userLoginAttribute: 'uid',
|
|
64
|
-
userMemberAttribute: 'memberOf',
|
|
65
|
-
userNameAttribute: 'cn',
|
|
66
|
-
userObjectClass: 'inetOrgPerson',
|
|
67
|
-
userSearchAttribute: 'uid|sn|givenName'
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
this.$set(this.model, 'openLdapConfig', config);
|
|
97
|
+
// Use a spread of config, so that if don't make changes to the defaults if the user edits them
|
|
98
|
+
this.$set(this.model, 'openLdapConfig', { ...LDAP_DEFAULTS });
|
|
71
99
|
}
|
|
72
100
|
}
|
|
73
101
|
}
|
|
@@ -98,7 +126,9 @@ export default {
|
|
|
98
126
|
:disable="disable"
|
|
99
127
|
:edit="goToEdit"
|
|
100
128
|
>
|
|
101
|
-
<template
|
|
129
|
+
<template
|
|
130
|
+
slot="rows"
|
|
131
|
+
>
|
|
102
132
|
<tr><td>{{ t(`authConfig.saml.displayName`) }}: </td><td>{{ model.displayNameField }}</td></tr>
|
|
103
133
|
<tr><td>{{ t(`authConfig.saml.userName`) }}: </td><td>{{ model.userNameField }}</td></tr>
|
|
104
134
|
<tr><td>{{ t(`authConfig.saml.UID`) }}: </td><td>{{ model.uidField }}</td></tr>
|
|
@@ -106,6 +136,47 @@ export default {
|
|
|
106
136
|
<tr><td>{{ t(`authConfig.saml.api`) }}: </td><td>{{ model.rancherApiHost }}</td></tr>
|
|
107
137
|
<tr><td>{{ t(`authConfig.saml.groups`) }}: </td><td>{{ model.groupsField }}</td></tr>
|
|
108
138
|
</template>
|
|
139
|
+
|
|
140
|
+
<template
|
|
141
|
+
v-if="supportsLDAPSearch"
|
|
142
|
+
slot="footer"
|
|
143
|
+
>
|
|
144
|
+
<Banner
|
|
145
|
+
v-if="showLdap"
|
|
146
|
+
color="success"
|
|
147
|
+
class="banner"
|
|
148
|
+
>
|
|
149
|
+
<div
|
|
150
|
+
class="advanced-ldap-banner"
|
|
151
|
+
>
|
|
152
|
+
<div>{{ t('authConfig.saml.search.on') }}</div>
|
|
153
|
+
<div>
|
|
154
|
+
<a
|
|
155
|
+
class="toggle-btn"
|
|
156
|
+
@click="showLdapDetails = !showLdapDetails"
|
|
157
|
+
>
|
|
158
|
+
<template v-if="showLdapDetails">{{ t('authConfig.saml.search.hide') }}</template>
|
|
159
|
+
<template v-else>{{ t('authConfig.saml.search.show') }}</template>
|
|
160
|
+
</a>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</Banner>
|
|
164
|
+
<Banner
|
|
165
|
+
v-else
|
|
166
|
+
color="info"
|
|
167
|
+
>
|
|
168
|
+
{{ t('authConfig.saml.search.off') }}
|
|
169
|
+
</Banner>
|
|
170
|
+
|
|
171
|
+
<table v-if="showLdapDetails && model.openLdapConfig">
|
|
172
|
+
<tr><td>{{ t('authConfig.ldap.hostname.label') }}:</td><td>{{ ldapHosts }}</td></tr>
|
|
173
|
+
<tr><td>{{ t('authConfig.ldap.port') }}:</td><td>{{ model.openLdapConfig.port }}</td></tr>
|
|
174
|
+
<tr><td>{{ t('authConfig.ldap.protocol') }}:</td><td>{{ ldapProtocol }}</td></tr>
|
|
175
|
+
<tr><td>{{ t('authConfig.ldap.serviceAccountDN') }}:</td><td>{{ model.openLdapConfig.serviceAccountDistinguishedName }}</td></tr>
|
|
176
|
+
<tr><td>{{ t('authConfig.ldap.userSearchBase.label') }}:</td><td>{{ model.openLdapConfig.userSearchBase }}</td></tr>
|
|
177
|
+
<tr><td>{{ t('authConfig.ldap.groupSearchBase.label') }}:</td><td>{{ model.openLdapConfig.groupSearchBase }}</td></tr>
|
|
178
|
+
</table>
|
|
179
|
+
</template>
|
|
109
180
|
</AuthBanner>
|
|
110
181
|
|
|
111
182
|
<hr>
|
|
@@ -233,7 +304,26 @@ export default {
|
|
|
233
304
|
/>
|
|
234
305
|
</div>
|
|
235
306
|
</div>
|
|
236
|
-
<div
|
|
307
|
+
<div
|
|
308
|
+
v-if="!model.enabled"
|
|
309
|
+
class="row"
|
|
310
|
+
>
|
|
311
|
+
<div class="col span-12">
|
|
312
|
+
<Banner color="info">
|
|
313
|
+
<div v-clean-html="t('authConfig.associatedWarning', tArgs, true)" />
|
|
314
|
+
</Banner>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
<div v-if="supportsLDAPSearch">
|
|
318
|
+
<div class="row">
|
|
319
|
+
<h2>{{ t('authConfig.saml.search.title') }}</h2>
|
|
320
|
+
</div>
|
|
321
|
+
<div class="row">
|
|
322
|
+
<Banner
|
|
323
|
+
label-key="authConfig.saml.search.message"
|
|
324
|
+
color="info"
|
|
325
|
+
/>
|
|
326
|
+
</div>
|
|
237
327
|
<div class="row">
|
|
238
328
|
<Checkbox
|
|
239
329
|
v-model="showLdap"
|
|
@@ -243,25 +333,15 @@ export default {
|
|
|
243
333
|
</div>
|
|
244
334
|
<div class="row mt-20 mb-20">
|
|
245
335
|
<config
|
|
246
|
-
v-if="showLdap"
|
|
336
|
+
v-if="showLdap && model.openLdapConfig"
|
|
247
337
|
v-model="model.openLdapConfig"
|
|
248
338
|
:type="NAME"
|
|
249
339
|
:mode="mode"
|
|
340
|
+
:is-create="!model.enabled"
|
|
250
341
|
/>
|
|
251
342
|
</div>
|
|
252
343
|
</div>
|
|
253
344
|
</template>
|
|
254
|
-
<div
|
|
255
|
-
v-if="!model.enabled"
|
|
256
|
-
class="row"
|
|
257
|
-
>
|
|
258
|
-
<div class="col span-12">
|
|
259
|
-
<Banner
|
|
260
|
-
v-clean-html="t('authConfig.associatedWarning', tArgs, true)"
|
|
261
|
-
color="info"
|
|
262
|
-
/>
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
345
|
</CruResource>
|
|
266
346
|
</div>
|
|
267
347
|
</template>
|
|
@@ -274,4 +354,19 @@ export default {
|
|
|
274
354
|
margin: 0 3px;
|
|
275
355
|
}
|
|
276
356
|
}
|
|
357
|
+
|
|
358
|
+
// Banner shows message and link formatted right aligned
|
|
359
|
+
.advanced-ldap-banner {
|
|
360
|
+
display: flex;
|
|
361
|
+
flex: 1;
|
|
362
|
+
|
|
363
|
+
> :first-child {
|
|
364
|
+
flex: 1;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.toggle-btn {
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
user-select: none;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
277
372
|
</style>
|
package/package.json
CHANGED
|
@@ -82,7 +82,7 @@ pushd ${BASE_DIR} > /dev/null
|
|
|
82
82
|
|
|
83
83
|
if [ "${GITHUB_BUILD}" == "true" ]; then
|
|
84
84
|
# Determine if gh-pages build is possible
|
|
85
|
-
if [[ "${GITHUB_BRANCH}" == "gh-pages" ]] && ! git show-ref -q
|
|
85
|
+
if [[ "${GITHUB_BRANCH}" == "gh-pages" ]] && ! git show-ref -q gh-pages; then
|
|
86
86
|
echo -e "${YELLOW}'gh-pages' branch not found, this branch must exist before running this script${RESET}"
|
|
87
87
|
exit 1
|
|
88
88
|
fi
|
package/utils/gc/gc.ts
CHANGED
|
@@ -29,7 +29,7 @@ class GarbageCollect {
|
|
|
29
29
|
* To avoid JSON.parse on the `ui-performance` setting keep a local cache
|
|
30
30
|
*/
|
|
31
31
|
private getUiPerfGarbageCollection = (rootState: any) => {
|
|
32
|
-
const uiPerfSetting = rootState.management.types[MANAGEMENT.SETTING]
|
|
32
|
+
const uiPerfSetting = rootState.management.types[MANAGEMENT.SETTING]?.list.find((s: any) => s.id === SETTING.UI_PERFORMANCE);
|
|
33
33
|
|
|
34
34
|
if (!uiPerfSetting || !uiPerfSetting.value) {
|
|
35
35
|
// Could be in the process of logging out
|