@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.
@@ -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
@@ -73,6 +73,12 @@ export default {
73
73
  >
74
74
  <slot name="rows" />
75
75
  </table>
76
+
77
+ <slot
78
+ v-if="$slots.footer"
79
+ name="footer"
80
+ />
81
+
76
82
  <DisableAuthProviderModal
77
83
  ref="disableAuthProviderModal"
78
84
  @disable="disable"
@@ -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="type!=='shibboleth'"
384
+ v-if="!isSamlProvider"
365
385
  class=" col span-6"
366
386
  >
367
387
  <RadioGroup
@@ -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 { showLdap: false };
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
- const config = {
50
- connectionTimeout: 5000,
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 slot="rows">
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 v-if="NAME === 'shibboleth'">
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -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 --heads gh-pages; then
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].list.find((s: any) => s.id === SETTING.UI_PERFORMANCE);
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