step4_controller.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. require('controllers/wizard/step7_controller');
  20. App.KerberosWizardStep4Controller = App.WizardStep7Controller.extend(App.AddSecurityConfigs, App.ToggleIsRequiredMixin, App.KDCCredentialsControllerMixin, {
  21. name: 'kerberosWizardStep4Controller',
  22. isWithinAddService: Em.computed.equal('wizardController.name', 'addServiceController'),
  23. adminPropertyNames: [{name: 'admin_principal', displayName: 'Admin principal'}, {name: 'admin_password', displayName: 'Admin password'}],
  24. clearStep: function() {
  25. this.set('isRecommendedLoaded', false);
  26. this.set('selectedService', null);
  27. this.set('stepConfigs', []);
  28. },
  29. loadStep: function() {
  30. if (this.get('wizardController.skipConfigureIdentitiesStep')) {
  31. App.router.send('next');
  32. return;
  33. }
  34. var self = this;
  35. this.clearStep();
  36. this.getDescriptorConfigs().then(function (properties) {
  37. self.setStepConfigs(properties);
  38. }).always(function() {
  39. self.set('isRecommendedLoaded', true);
  40. });
  41. },
  42. /**
  43. * Create service config object for Kerberos service.
  44. *
  45. * @param {App.ServiceConfigProperty[]} configs
  46. * @returns {Em.Object}
  47. */
  48. createServiceConfig: function(configs) {
  49. // Identity configs related to user principal
  50. var clusterConfigs = configs.filterProperty('serviceName','Cluster');
  51. // storm user principal is not required for ambari operation
  52. var userConfigs = configs.filterProperty('identityType','user');
  53. var generalConfigs = clusterConfigs.concat(userConfigs).uniq('name');
  54. var advancedConfigs = configs.filter(function(element){
  55. return !generalConfigs.findProperty('name', element.get('name'));
  56. });
  57. var categoryForGeneralConfigs = [
  58. App.ServiceConfigCategory.create({ name: 'Global', displayName: 'Global'}),
  59. App.ServiceConfigCategory.create({ name: 'Ambari Principals', displayName: 'Ambari Principals'})
  60. ];
  61. var categoryForAdvancedConfigs = this.createCategoryForServices();
  62. return [
  63. App.ServiceConfig.create({
  64. displayName: 'General',
  65. name: 'GENERAL',
  66. serviceName: 'KERBEROS_GENERAL',
  67. configCategories: categoryForGeneralConfigs,
  68. configs: generalConfigs,
  69. showConfig: true
  70. }),
  71. App.ServiceConfig.create({
  72. displayName: 'Advanced',
  73. name: 'ADVANCED',
  74. serviceName: 'KERBEROS_ADVANCED',
  75. configCategories: categoryForAdvancedConfigs,
  76. configs: advancedConfigs,
  77. showConfig: true
  78. })
  79. ];
  80. },
  81. /**
  82. * creates categories for advanced secure configs
  83. * @returns {[App.ServiceConfigCategory]}
  84. */
  85. createCategoryForServices: function() {
  86. var services = [];
  87. if (this.get('wizardController.name') == 'addServiceController') {
  88. services = App.StackService.find().filter(function(item) {
  89. return item.get('isInstalled') || item.get('isSelected');
  90. });
  91. } else {
  92. services = App.Service.find();
  93. }
  94. return services.map(function(item) {
  95. return App.ServiceConfigCategory.create({ name: item.get('serviceName'), displayName: item.get('displayName'), collapsedByDefault: true});
  96. });
  97. },
  98. /**
  99. * Prepare step configs using stack descriptor properties.
  100. *
  101. * @param {App.ServiceConfigProperty[]} configs
  102. * @param {App.ServiceConfigProperty[]} stackConfigs
  103. */
  104. setStepConfigs: function(configs, stackConfigs) {
  105. var configProperties = this.prepareConfigProperties(configs),
  106. stackConfigProperties = stackConfigs ? this.prepareConfigProperties(stackConfigs) : [],
  107. alterProperties = ['value','initialValue', 'defaultValue'];
  108. if (this.get('wizardController.name') == 'addServiceController') {
  109. // config properties for installed services should be disabled on Add Service Wizard
  110. configProperties.forEach(function(item) {
  111. if (this.get('adminPropertyNames').mapProperty('name').contains(item.get('name'))
  112. || item.get('name') === 'persist_credentials') return;
  113. if (this.get('installedServiceNames').contains(item.get('serviceName')) || item.get('serviceName') == 'Cluster') {
  114. item.set('isEditable', false);
  115. } else if (stackConfigs) {
  116. var stackConfigProperty = stackConfigProperties.filterProperty('filename', item.get('filename')).findProperty('name', item.get('name'));
  117. if (stackConfigProperty) {
  118. alterProperties.forEach(function (alterProperty) {
  119. item.set(alterProperty, stackConfigProperty.get(alterProperty));
  120. });
  121. }
  122. }
  123. }, this);
  124. // Concat properties that are present in the stack's kerberos descriptor but not in the cluster kerberos descriptor
  125. stackConfigProperties.forEach(function(_stackConfigProperty){
  126. var isPropertyInClusterDescriptor = configProperties.filterProperty('filename', _stackConfigProperty.get('filename')).someProperty('name', _stackConfigProperty.get('name'));
  127. if (!isPropertyInClusterDescriptor) {
  128. if (this.get('installedServiceNames').contains(_stackConfigProperty.get('serviceName')) || _stackConfigProperty.get('serviceName') == 'Cluster') {
  129. _stackConfigProperty.set('isEditable', false);
  130. }
  131. configProperties.pushObject(_stackConfigProperty);
  132. }
  133. }, this);
  134. }
  135. configProperties = App.config.sortConfigs(configProperties);
  136. this.get('stepConfigs').pushObjects(this.createServiceConfig(configProperties));
  137. this.set('selectedService', this.get('stepConfigs')[0]);
  138. },
  139. /**
  140. * Filter configs by installed services for Kerberos Wizard or by installed + selected services
  141. * for Add Service Wizard.
  142. * Set property value observer.
  143. * Set realm property with value from previous configuration step.
  144. * Set appropriate category for all configs.
  145. * Hide KDC related credentials properties if kerberos was manually enabled.
  146. *
  147. * @param {App.ServiceConfigProperty[]} configs
  148. * @returns {App.ServiceConfigProperty[]}
  149. */
  150. prepareConfigProperties: function(configs) {
  151. var self = this;
  152. // stored configs from previous steps (Configure Kerberos or Customize Services for ASW)
  153. var storedServiceConfigs = this.get('wizardController').getDBProperty('serviceConfigProperties');
  154. var installedServiceNames = ['Cluster'].concat(App.Service.find().mapProperty('serviceName'));
  155. var adminProps = [];
  156. var configProperties = configs.slice(0);
  157. var siteProperties = App.configsCollection.getAll();
  158. // override stored values
  159. App.config.mergeStoredValue(configProperties, this.get('wizardController').loadCachedStepConfigValues(this));
  160. // show admin properties in add service wizard
  161. if (this.get('isWithinAddService')) {
  162. installedServiceNames = installedServiceNames.concat(this.get('selectedServiceNames'));
  163. adminProps = this.createAdminCredentialsProperties(configProperties);
  164. }
  165. configProperties = adminProps.concat(configProperties);
  166. configProperties = configProperties.filter(function(item) {
  167. return installedServiceNames.contains(item.get('serviceName'));
  168. });
  169. if (this.get('wizardController.name') != 'addServiceController') {
  170. var realmValue = storedServiceConfigs.findProperty('name', 'realm').value;
  171. configProperties.findProperty('name', 'realm').set('value', realmValue);
  172. configProperties.findProperty('name', 'realm').set('savedValue', realmValue);
  173. configProperties.findProperty('name', 'realm').set('recommendedValue', realmValue);
  174. }
  175. configProperties.setEach('isSecureConfig', false);
  176. configProperties.forEach(function(property, item, allConfigs) {
  177. if (['spnego_keytab', 'spnego_principal'].contains(property.get('name'))) {
  178. property.addObserver('value', self, 'spnegoPropertiesObserver');
  179. }
  180. if (property.get('observesValueFrom')) {
  181. var observedValue = allConfigs.findProperty('name', property.get('observesValueFrom')).get('value');
  182. property.set('value', observedValue);
  183. property.set('recommendedValue', observedValue);
  184. }
  185. if (property.get('serviceName') == 'Cluster') {
  186. property.set('category', 'Global');
  187. }
  188. else {
  189. property.set('category', property.get('serviceName'));
  190. }
  191. // All user identity except storm should be grouped under "Ambari Principals" category
  192. if (property.get('identityType') == 'user') property.set('category', 'Ambari Principals');
  193. var siteProperty = siteProperties.findProperty('name', property.get('name'));
  194. if (siteProperty) {
  195. if (siteProperty.category === property.get('category')) {
  196. property.set('displayName',siteProperty.displayName);
  197. if (siteProperty.index) {
  198. property.set('index', siteProperty.index);
  199. }
  200. }
  201. if (siteProperty.displayType) {
  202. property.set('displayType', siteProperty.displayType);
  203. }
  204. }
  205. this.tweakConfigProperty(property);
  206. },this);
  207. return configProperties;
  208. },
  209. /**
  210. * Function to override kerberos descriptor's property values
  211. */
  212. tweakConfigProperty: function(config) {
  213. if (config.name === 'templeton.hive.properties') {
  214. var defaultHiveMsPort = "9083";
  215. var hiveMSHosts = App.HostComponent.find().filterProperty('componentName', 'HIVE_METASTORE');
  216. if (hiveMSHosts.length > 1) {
  217. var hiveMSHostNames = hiveMSHosts.mapProperty('hostName');
  218. var port = config.value.match(/:[0-9]{2,4}/);
  219. port = port ? port[0].slice(1) : defaultHiveMsPort;
  220. for (var i = 0; i < hiveMSHostNames.length; i++) {
  221. hiveMSHostNames[i] = "thrift://" + hiveMSHostNames[i] + ":" + port;
  222. }
  223. var configValue = config.value.replace(/thrift.+[0-9]{2,},/i, hiveMSHostNames.join('\\,') + ",");
  224. config.set('value', configValue);
  225. config.set('recommendedValue', configValue);
  226. }
  227. }
  228. },
  229. /**
  230. * Sync up values between inherited property and its reference.
  231. *
  232. * @param {App.ServiceConfigProperty} configProperty
  233. */
  234. spnegoPropertiesObserver: function(configProperty) {
  235. var self = this;
  236. var stepConfig = this.get('stepConfigs').findProperty('name', 'ADVANCED');
  237. stepConfig.get('configs').forEach(function(config) {
  238. if (config.get('observesValueFrom') == configProperty.get('name')) {
  239. Em.run.once(self, function() {
  240. config.set('value', configProperty.get('value'));
  241. config.set('recommendedValue', configProperty.get('value'));
  242. });
  243. }
  244. });
  245. },
  246. submit: function() {
  247. this.saveConfigurations();
  248. App.router.send('next');
  249. },
  250. saveConfigurations: function() {
  251. var kerberosDescriptor = this.get('kerberosDescriptor');
  252. var configs = [];
  253. this.get('stepConfigs').forEach(function(_stepConfig){
  254. configs = configs.concat(_stepConfig.get('configs'));
  255. });
  256. this.updateKerberosDescriptor(kerberosDescriptor, configs);
  257. App.get('router.kerberosWizardController').saveKerberosDescriptorConfigs(kerberosDescriptor);
  258. },
  259. /**
  260. * Generate App.ServiceConfigProperty instances for 'admin_principal' and 'admin_password' properties
  261. * Used for Add Service Wizard only on Configure Identities step.
  262. *
  263. * @param {object[]} loadedProperties list of already loaded config properties
  264. * @returns {App.ServiceConfigProperty[]}
  265. */
  266. createAdminCredentialsProperties: function(loadedProperties) {
  267. if (App.router.get('mainAdminKerberosController.isManualKerberos')) {
  268. return [];
  269. }
  270. var fileName = 'krb5-conf.xml';
  271. var krbProperties = loadedProperties.filterProperty('filename', fileName);
  272. var siteProperties = App.config.get('preDefinedSiteProperties');
  273. var credentialProperties = this.get('adminPropertyNames').map(function(prop, index) {
  274. var existingProperty = krbProperties.findProperty('name', prop.name);
  275. var coreObject = {
  276. serviceName: 'Cluster',
  277. displayName: prop.displayName,
  278. isRequired: false,
  279. isRequiredByAgent: false,
  280. supportsFinal: false,
  281. isFinal: false,
  282. isSecureConfig: true,
  283. index: index,
  284. value: '',
  285. isVisible: true,
  286. isUserProperty: false
  287. };
  288. var propTpl = App.config.createDefaultConfig(prop.name, fileName, false, coreObject);
  289. var siteProperty = siteProperties.filterProperty('filename', fileName).findProperty('name', prop.name);
  290. if (!Em.isNone(siteProperty)) {
  291. propTpl = $.extend(true, {}, siteProperty, propTpl);
  292. }
  293. if (!Em.isNone(existingProperty)) {
  294. propTpl = $.extend(true, {}, propTpl, existingProperty);
  295. }
  296. return App.ServiceConfigProperty.create(propTpl);
  297. });
  298. if (App.get('supports.storeKDCCredentials')) {
  299. var storeProps = [];
  300. this.initilizeKDCStoreProperties(storeProps);
  301. var persistCredentialsProp = storeProps.findProperty('name', 'persist_credentials');
  302. if (!Em.isNone(persistCredentialsProp)) {
  303. Em.setProperties(persistCredentialsProp, {
  304. index: credentialProperties.length,
  305. serviceName: 'Cluster',
  306. category: 'Global'
  307. });
  308. credentialProperties.pushObject(App.ServiceConfigProperty.create(persistCredentialsProp));
  309. }
  310. }
  311. return credentialProperties;
  312. }
  313. });