· 9 years ago · Dec 20, 2016, 07:29 AM
1/*
2* Licensed Materials - Property of IBM Corp.
3* IBM UrbanCode Build
4* IBM UrbanCode Deploy
5* IBM UrbanCode Release
6* IBM AnthillPro
7* (c) Copyright IBM Corporation 2002, 2014. All Rights Reserved.
8*
9* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
10* GSA ADP Schedule Contract with IBM Corp.
11*/
12
13
14/*
15This script requires the Groovy scripting language. You can find Groovy at
16http://groovy.codehaus.org/. Download Groovy at http://dist.codehaus.org/groovy/distributions/.
17To install it, follow the instructions at http://groovy.codehaus.org/install.html.
18
19Automatic import packages & classes:
20 java.io/lang/net/util
21 java.math.BigDecimal/BigInteger
22 groovy.lang/util
23*/
24import java.io.UnsupportedEncodingException;
25import java.security.KeyPair
26import java.security.KeyStore
27import java.security.PrivateKey
28import java.security.PublicKey
29import java.security.cert.Certificate
30import java.security.GeneralSecurityException;
31import java.security.KeyStoreException;
32import java.security.SecureRandom;
33import java.security.NoSuchAlgorithmException;
34
35import javax.crypto.KeyGenerator;
36import javax.crypto.SecretKey;
37import javax.crypto.spec.SecretKeySpec;
38
39import org.apache.commons.lang.StringEscapeUtils
40import org.apache.tools.ant.*
41import org.apache.tools.ant.taskdefs.condition.Os
42
43import com.urbancode.air.keytool.Extension
44import com.urbancode.air.keytool.KeytoolHelper
45import com.urbancode.commons.util.IO
46import com.urbancode.commons.util.unix.Unix
47import com.urbancode.commons.util.agent.AgentVersionHelper
48import com.urbancode.commons.util.crypto.CryptStringUtil
49import com.urbancode.commons.util.crypto.SecureRandomHelper
50import com.urbancode.commons.validation.ValidationException
51import com.urbancode.commons.validation.ValidationRules
52import com.urbancode.commons.validation.format.JreHomeValidationRule
53import com.urbancode.commons.validation.format.NoSpaceValidationRule
54import com.urbancode.commons.validation.format.RequiredValueValidationRule
55import com.urbancode.commons.validation.format.SocketPortValidationRule
56import com.urbancode.commons.validation.format.YesNoValidationRule
57import com.urbancode.commons.validation.rules.NumericValueRule
58import com.urbancode.shell.Os
59
60import org.apache.commons.lang.StringUtils
61import org.apache.commons.lang.RandomStringUtils;
62import org.apache.http.client.HttpClient
63import org.apache.http.client.methods.*
64import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder
65
66class AgentInstaller {
67
68 boolean isUnix = Os.isFamily("unix")
69 boolean isWindows = Os.isFamily("windows")
70 boolean isZos = Os.isFamily("z/os")
71
72 def agentEncoding = "UTF-8"
73 def systemEncoding = getSystemEncoding()
74 def systemIn = System.in.newReader(systemEncoding)
75
76
77 def NL = System.getProperty('line.separator')
78
79 def nonInteractive = false
80 def autoUpgradeAgent = false
81 def inputAnotherHost = true
82
83 def ant = null
84
85 def productName = null
86 def productPrefix = null
87 def productCapitalName = null
88
89 def srcDir = null
90 def unpackDir = null
91 def javaHome = null
92 def currentJavaHome = null
93 def javaSystemProperties = null
94
95 def installPropertiesFile = null
96
97 def installOs = null
98 def installArch = null
99
100 def installAsService = null
101 def installServiceName = null
102 def installServiceLogin = null
103 def installServicePassword = null
104 def installServiceAutostart = null
105 def installServiceStatus = null
106 def doServiceInstall = null
107 def serviceNameValidated = false
108
109 def installAgentDir = null
110 def installAgentId = null
111 def installAgentName = null
112 def generateAgentName = false
113 def installAgentTeams = null
114
115 def installAgentRemoteHost = null
116 def installAgentRemotePort = null
117 def installAgentBrokerUrl = null
118 def installAgentProxyHost = null
119 def installAgentProxyPort = null
120 def installDisableHttpFailover = null
121
122 def installAgentRemoteHostList = []
123 def installAgentRemotePortList = []
124 def installAgentProxyHostList = []
125 def installAgentProxyPortList = []
126 def installBrokerURL = null
127
128 def installAgentMutualAuth = null
129 def disableFullEncryption = null
130 def installAgentKeystore = null
131 def installAgentKeystorePwd = null
132
133 def installAgentVerifyServerIdentity = null
134 def installAgentServerUrl = null
135
136 def installInitUser = null
137 def installInitGroup = null
138
139 def portValidator = null
140 def yesNoValidator = null
141 def jreHomeValidator = null
142 def optionalValidator = null
143 def requiredValidator = null
144 def numberValidator = null
145 def serviceNameValidator = null
146
147 def installAgentDirTokenReplacement = null
148 def javaHomeTokenReplacement = null
149
150 def hostName = null
151
152 def val = null // for groovy bug work-around
153
154 def classpath = null
155
156 def encryptionKeyStorePath = null
157 def keyStorePassword = null
158 def encryptionKeystoreAlias = null
159
160 AgentInstaller(classpath) {
161 def requiredValidationRule = new RequiredValueValidationRule()
162
163 optionalValidator = new ValidationRules()
164
165 requiredValidator = new ValidationRules()
166 requiredValidator.addRule(requiredValidationRule)
167
168 portValidator = new ValidationRules()
169 portValidator.addRule(requiredValidationRule)
170 portValidator.addRule(new SocketPortValidationRule())
171
172 yesNoValidator = new ValidationRules()
173 yesNoValidator.addRule(requiredValidationRule)
174 yesNoValidator.addRule(new YesNoValidationRule())
175
176 jreHomeValidator = new ValidationRules()
177 jreHomeValidator.addRule(requiredValidationRule)
178 jreHomeValidator.addRule(new JreHomeValidationRule());
179
180 def numericValidationRule = new NumericValueRule()
181 numericValidationRule.setLowerBound(1)
182 numericValidationRule.setUpperBound(Integer.MAX_VALUE)
183 numberValidator = new ValidationRules()
184 numberValidator.addRule(requiredValidationRule)
185 numberValidator.addRule(numericValidationRule)
186
187 serviceNameValidator = new ValidationRules();
188 serviceNameValidator.addRule(requiredValidationRule);
189 serviceNameValidator.addRule(new NoSpaceValidationRule());
190
191 this.classpath = classpath
192 }
193
194 void setAntBuilder(antBuilder) {
195 ant = new AntBuilder(antBuilder.project)
196 // have to do this, otherwise properties don't work right
197 antBuilder.project.copyInheritedProperties(ant.project)
198 antBuilder.project.copyUserProperties(ant.project)
199
200 installAgentDir = ant.project.properties.'install.agent.dir'
201 if (installAgentDir != null) {
202 installAgentDir = new File(installAgentDir).getAbsolutePath()
203 }
204
205 initNonInteractiveProperties()
206 }
207
208 void initNonInteractiveProperties() {
209 srcDir = ant.project.properties.'src.dir'
210
211 if (ant.project.properties.'locked/agent.home') {
212 installAgentDir = ant.project.properties.'locked/agent.home'
213 }
214
215 // properties used when constructing an install package (msi, etc)
216 if (ant.project.properties.'package.replacement.agent.dir') {
217 installAgentDirTokenReplacement = ant.project.properties.'package.replacement.agent.dir'
218 }
219 if (ant.project.properties.'package.replacement.java.home') {
220 javaHomeTokenReplacement = ant.project.properties.'package.replacement.java.home'
221 }
222 if (ant.project.properties.'package.java.home') {
223 javaHome = ant.project.properties.'package.java.home'
224 }
225 if (ant.project.properties.'package.os') {
226 installOs = ant.project.properties.'package.os'
227 }
228 if (ant.project.properties.'package.arch') {
229 installArch = ant.project.properties.'package.arch'
230 }
231 if (ant.project.properties.'package.generate.agent.name') {
232 generateAgentName = Boolean.valueOf(ant.project.properties.'package.generate.agent.name');
233 }
234 if (ant.project.properties.'package.init.user') {
235 installInitUser = ant.project.properties.'package.init.user'
236 }
237 if (ant.project.properties.'package.init.group') {
238 installInitGroup = ant.project.properties.'package.init.group'
239 }
240
241 if (javaHome == null) {
242 javaHome = System.getenv().'JAVA_HOME'
243 }
244 if (javaHome == null) {
245 javaHome = System.getProperty('java.home')
246 }
247
248 // Protection against invalid java paths set in the install props or JAVA_HOME
249 jreHomeValidator.validate(javaHome)
250
251 if (ant.project.properties.'install.properties.file') {
252 installPropertiesFile = ant.project.properties.'install.properties.file'
253 }
254
255 initInstalledProperties();
256 }
257
258 void initInstalledProperties() {
259
260 // always written by installer:
261 // locked/agent.brokerUrl
262 // locked/agent.home
263 // locked/ant.home
264
265 // properties from the existing agent's installed.properties
266 if (ant.project.properties.'locked/agent.id') {
267 installAgentId = ant.project.properties.'locked/agent.id'
268 }
269 if (ant.project.properties.'locked/agent.name') {
270 installAgentName = ant.project.properties.'locked/agent.name'
271 }
272 if (ant.project.properties.'locked/agent.initial.teams') {
273 installAgentTeams = ant.project.properties.'locked/agent.initial.teams'
274 }
275 if (ant.project.properties.'locked/agent.jms.remote.host') {
276 installAgentRemoteHostList.addAll(ant.project.properties.'locked/agent.jms.remote.host'.split(','))
277 }
278 if (ant.project.properties.'locked/agent.jms.remote.port') {
279 installAgentRemotePortList.addAll(ant.project.properties.'locked/agent.jms.remote.port'.split(','))
280 }
281 // validate the input for agent.jms.remote.* properties
282 if (installAgentRemoteHostList.size() != installAgentRemotePortList.size()) {
283 throw new IllegalArgumentException(
284 "You only specified " +
285 installAgentRemotePortList.size() +
286 " ports. Expected " +
287 installAgentRemoteHostList.size() + ".")
288 }
289 println("installAgentRemotePortList: " + installAgentRemotePortList)
290 for (int i = 0; i < installAgentRemotePortList.size(); i++) {
291 portValidator.validate(installAgentRemotePortList.get(i))
292 }
293 if (ant.project.properties.'locked/agent.http.proxy.host') {
294 installAgentProxyHost = ant.project.properties.'locked/agent.http.proxy.host'
295 }
296 if (ant.project.properties.'locked/agent.http.proxy.port') {
297 installAgentProxyPort = ant.project.properties.'locked/agent.http.proxy.port'
298 }
299 if (ant.project.properties.'locked/agent.mutual_auth') {
300 installAgentMutualAuth = ant.project.properties.'locked/agent.mutual_auth'
301 }
302
303 if (ant.project.properties.'agent.jms.disable_full_encryption') {
304 disableFullEncryption = ant.project.properties.'agent.jms.disable_full_encryption'
305 }
306
307 if (ant.project.properties.'locked/agent.keystore') {
308 installAgentKeystore = ant.project.properties.'locked/agent.keystore'
309 }
310 if (ant.project.properties.'locked/agent.keystore.pwd') {
311 installAgentKeystorePwd = CryptStringUtil.decrypt(ant.project.properties.'locked/agent.keystore.pwd')
312 }
313 if (ant.project.properties.'locked/agent.service') {
314 installAsService = ant.project.properties.'locked/agent.service'
315 }
316 if (ant.project.properties.'locked/agent.service.name') {
317 installServiceName = ant.project.properties.'locked/agent.service.name'
318 }
319 if (ant.project.properties.'locked/agent.service.login') {
320 installServiceLogin = ant.project.properties.'locked/agent.service.login'
321 installServiceLogin = installServiceLogin.replaceAll("(\\\\\\\\)+", "\\\\");
322 installServiceLogin = installServiceLogin.replace("\\\\", "\\")
323 }
324 if (ant.project.properties.'locked/agent.service.password') {
325 installServicePassword = CryptStringUtil.decrypt(ant.project.properties.'locked/agent.service.password')
326 }
327 if (ant.project.properties.'locked/agent.service.autostart') {
328 installServiceAutostart = ant.project.properties.'locked/agent.service.autostart'
329 }
330 if (ant.project.properties[productName + "/java.home"]) {
331 javaHome = ant.project.properties[productName + "/java.home"]
332 currentJavaHome = javaHome
333 }
334 if (ant.project.properties['agent.HttpFailoverHandler.disabled']) {
335 installDisableHttpFailover = ant.project.properties.'agent.HttpFailoverHandler.disabled'
336 }
337 if (ant.project.properties.'locked/agent.brokerUrl'){
338 installBrokerURL = ant.project.properties.'locked/agent.brokerUrl'
339 }
340 if (ant.project.properties.'verify.server.identity'){
341 installAgentVerifyServerIdentity = ant.project.properties.'verify.server.identity'
342 }
343 if (ant.project.properties.'server.url'){
344 installAgentServerUrl = ant.project.properties.'server.url'
345 }
346 if (ant.project.properties.'encryption.keystore') {
347 encryptionKeyStorePath = ant.project.properties.'encryption.keystore'
348 }
349 if (ant.project.properties.'encryption.keystore.password') {
350 keyStorePassword = CryptStringUtil.class.decrypt(ant.project.properties.'encryption.keystore.password')
351 }
352 if (ant.project.properties.'encryption.keystore.alias') {
353 encryptionKeystoreAlias = ant.project.properties.'encryption.keystore.alias'
354 }
355 }
356
357 void setNonInteractive(mode) {
358 this.nonInteractive = mode
359 }
360
361 void setAutoUpgradeAgent(mode) {
362 this.autoUpgradeAgent = mode
363 }
364
365 void unpack(src, dst) {
366 ant.unzip(src: src, dest: dst)
367 }
368
369 void init() {
370 if (ant == null) {
371 ant = new AntBuilder()
372 }
373
374 def overlayZip = srcDir + "/overlay.zip"
375 unpackDir = File.createTempFile("agent-install-", ".tmp")
376 unpackDir.delete()
377 unpackDir.mkdirs()
378 unpackDir = unpackDir.getCanonicalPath()
379 unpack(overlayZip, unpackDir)
380 }
381
382 void install(productName, productPrefix, productCapitalName) {
383 this.productName = productName
384 this.productPrefix = productPrefix
385 this.productCapitalName = productCapitalName
386 init()
387
388 try {
389 this.installAgent()
390 prompt('Installer Complete. (press return to exit installer)') // wait for user input
391 }
392 catch (Exception e) {
393 e.printStackTrace()
394 prompt('Install Failed. (press return to exit installer)') // wait for user input
395 throw e;
396 }
397 finally {
398 ant.delete(dir: unpackDir)
399 }
400 }
401
402 void installAgent() {
403 def componentInstall = "agent"
404
405 if (nonInteractive) {
406 println("\nInstalling " + productName + " Agent (non-interactive)\n")
407 } else {
408 println("\nInstalling " + productName + " Agent\n")
409 }
410
411 installAgentDir = getInstallDir(componentInstall, installAgentDir)
412
413 def doUpgrade = checkForUpgrade(installAgentDir, componentInstall, installServiceName)
414
415 if (doUpgrade) {
416 File installedVersionFile = new File(installAgentDir + "/conf/installed.version")
417 Properties props = new Properties();
418 installedVersionFile.withInputStream{
419 props.load(it)
420 }
421 def installedVersion = props['installed.version']
422
423 // We should not delete plugins if the agent version is 6.1.0.4 or newer.
424 if (!AgentVersionHelper.versionIsAtLeast(installedVersion, 6, 1, 0, 4)) {
425 File pluginDir = new File(installAgentDir + "/var/plugins")
426 println("\nDeleting existing plugins directory: " + pluginDir + "\n")
427 if (pluginDir.exists()) {
428 pluginDir.deleteDir()
429 pluginDir.mkdirs()
430 }
431 }
432 }
433
434 println("\nInstalling Agent to: " + installAgentDir + "\n")
435
436 // read existing properties
437 // file location was changed in newer versions of the agent
438 File oldPropsFile = new File(installAgentDir, "conf/agent/agent.properties");
439 File propsFile = new File(installAgentDir, "conf/agent/installed.properties");
440 if (oldPropsFile.exists()) {
441 ant.move(tofile: propsFile.absolutePath,
442 file: oldPropsFile.absolutePath);
443 }
444
445 if (propsFile.exists()) {
446 ant.property(file: propsFile.absolutePath)
447 initInstalledProperties()
448 }
449 else if (installPropertiesFile) {
450 // if we were given a properties file on input, copy it to the agent's installed.properties
451 // to preserve extra properties
452
453 def props = new Properties()
454 new File(installPropertiesFile).withInputStream {
455 props.load(it)
456 }
457
458 // Filter properties used to configure creation of install packages
459 def propsCopy = new Properties()
460 props.each {
461 if (!it.key.startsWith("package.") && !it.key.contains("agent.service.password")) {
462 propsCopy[it.key] = it.value
463 }
464 }
465
466 propsFile.parentFile.mkdirs()
467 propsFile.withOutputStream {
468 propsCopy.store(it, null)
469 }
470 }
471
472 // make sure we have the JAVA_HOME
473 final def jreDir = new File(srcDir + File.separator + 'java')
474 if (jreDir.exists()) {
475 javaHome = installAgentDir + File.separator + 'java'
476 } else {
477 javaHome = prompt(
478 currentJavaHome,
479 "Please enter the home directory of the JRE/JDK used to run this agent. " +
480 "[Default: " + javaHome + "]",
481 javaHome,
482 jreHomeValidator)
483 }
484
485 javaHome = new File(javaHome).absolutePath
486 println("JAVA_HOME: " + javaHome + "\n")
487
488 def installWithRelayFromProperty = installAgentProxyPort ? "Y" : "N"
489 def installWithRelayDefault = nonInteractive ? installWithRelayFromProperty : null
490 def installWithRelay = installAgentProxyHost ? "Y" : installWithRelayDefault
491 installWithRelay = parseBoolean(prompt(
492 installWithRelay,
493 "Will the agent connect to an agent relay instead of directly to the server? y,N [Default: N]",
494 "N",
495 yesNoValidator))
496
497 if (nonInteractive) {
498 inputAnotherHost = null
499 // add default values if needed
500 if (installAgentRemoteHostList.size() == 0) {
501 installAgentRemoteHostList.add("localhost");
502 }
503 if (installAgentRemotePortList.size() == 0) {
504 installAgentRemotePortList.add("7918");
505 }
506 }
507 while (inputAnotherHost) {
508 if (installWithRelay) {
509 installAgentRemoteHostList.add(prompt(
510 installAgentRemoteHost,
511 "Enter the hostname or address of the agent relay the agent will connect to."))
512 installAgentRemotePortList.add(prompt(
513 installAgentRemotePort,
514 "Enter the agent communication port for the agent relay. [Default: 7916]",
515 "7916",
516 portValidator))
517 inputAnotherHost = parseBoolean(prompt(
518 null,
519 "Do you want to configure another failover relay connection? y,N [Default: N]",
520 "N",
521 yesNoValidator))
522 } else {
523 installAgentRemoteHostList.add(prompt(
524 installAgentRemoteHost,
525 "Enter the hostname or address of the server the agent will connect to. [Default: localhost]",
526 "localhost"))
527 installAgentRemotePortList.add(prompt(
528 installAgentRemotePort,
529 "Enter the agent communication port for the server. [Default: 7918]",
530 "7918",
531 portValidator))
532 inputAnotherHost = parseBoolean(prompt(
533 null,
534 "Do you want to configure another failover server connection? y,N [Default: N]",
535 "N",
536 yesNoValidator))
537 }
538 }
539
540 if (installAgentRemoteHostList.isEmpty()) {
541 installAgentRemoteHostList.add(installAgentRemoteHost)
542 }
543 if (installAgentRemotePortList.isEmpty()) {
544 installAgentRemotePortList.add(installAgentRemotePort)
545 }
546
547 if (installWithRelay) {
548 installAgentProxyHost = prompt(
549 installAgentProxyHost,
550 "Enter the hostname or address of the HTTP proxy server for the agent relay. " +
551 "[Default: " + installAgentRemoteHostList.get(0) + "]",
552 installAgentRemoteHostList.get(0))
553 installAgentProxyPort = prompt(
554 installAgentProxyPort,
555 "Enter the HTTP proxy port for the agent relay. [Default: 20080]",
556 "20080",
557 portValidator)
558 installDisableHttpFailover = parseBoolean(prompt(
559 installDisableHttpFailover,
560 "Do you want to disable HTTP Failover Handling? This is necessary if the relay is behind a firewall and accessed through a load balancer. N,y [Default: N]",
561 "N",
562 yesNoValidator))
563 }
564
565 installAgentMutualAuth = parseBoolean(prompt(
566 installAgentMutualAuth,
567 "Enable mutual (two-way) authentication with SSL for server/agent JMS communication? This setting must match that of the server. y,N [Default: N]",
568 "n"))
569
570 // Prompt for whether to enable end-to-end encryption (for JMS),
571 // the default is "N" if upgrade, "Y" if new installation.
572 String promptAgentFullEncryption =
573 "Disable end-to-end encryption for server/agent JMS communication? This option enhances" +
574 " the security of UrbanCode messages sent between the agent and the server, and" +
575 " requires an initial HTTPS connection to set up keys."
576 String defaultAgentFullEncryption = "n"
577
578 promptAgentFullEncryption = promptAgentFullEncryption + " y,N [Default: N]"
579 disableFullEncryption = parseBoolean(prompt(
580 disableFullEncryption,
581 promptAgentFullEncryption, // user prompt
582 defaultAgentFullEncryption))
583
584 installAgentVerifyServerIdentity = parseBoolean(prompt(
585 installAgentVerifyServerIdentity,
586 "Enable the agent to verify the server HTTPS certificate?" +
587 " If enabled, you must import the server certificate" +
588 " to the JRE keystore on the agent. y,N [Default: N]",
589 "n"))
590
591 // If full encryption is enabled, process the required value for 'server.url'.
592 if (disableFullEncryption == null || !disableFullEncryption) {
593
594 String promptAgentServerUrl = "Enter the full web URL for the central IBM UrbanCode Deploy " +
595 "server to validate the connection. Leave empty to skip."
596
597 if (doUpgrade) {
598 // "Prompt" for server.url value if current value is null. No validation.
599 installAgentServerUrl = prompt(installAgentServerUrl, promptAgentServerUrl)
600 }
601 // Else if silent-mode and value for server.url is empty, print warning--prompt() will
602 // do that for empty values--and continue with silent installation
603 else if (nonInteractive && !StringUtils.isNotBlank(installAgentServerUrl)) {
604 installAgentServerUrl = prompt(installAgentServerUrl, promptAgentServerUrl)
605 }
606 // Else, new installation, and either interactive mode or silent w/server.url value not empty
607 else {
608 boolean serverUrlIsValid = false
609
610 // Loop while we prompt the user for the central server and Test the connection.
611 while (!serverUrlIsValid) {
612 installAgentServerUrl = prompt(installAgentServerUrl, promptAgentServerUrl, null)
613
614 // Loop until they do not enter the url or we can validate it
615 if (installAgentServerUrl == null || installAgentServerUrl.isAllWhitespace()) {
616 serverUrlIsValid = true;
617 }
618 else {
619 try {
620 // Test server with http request
621 // Display message to wait while we send a test request to the central server.
622 println("Sending a request to the central IBM UrbanCode Deploy server...")
623 def response = executeGetMethod(installAgentServerUrl)
624 serverUrlIsValid = true
625 println("Server response ok.")
626 }
627 catch (Exception e) {
628 println("Error: Server access attempt failed for URL [${installAgentServerUrl}]: " + e + ".\n")
629 }
630
631 if (!serverUrlIsValid) {
632 if (nonInteractive) { // For Non-Interactive mode, fail-out
633 throw new IllegalArgumentException(
634 "Non-Interactive Mode: problem with full web URL for central IBM UrbanCode Deploy server: '${installAgentServerUrl}' .")
635 }
636 else { // interactive mode: server url access failed, clear value and ask user again
637 installAgentServerUrl = null
638 }
639 }
640 }
641 }
642 }
643 }
644
645 try {
646 hostName = InetAddress.localHost.canonicalHostName
647 }
648 catch (UnknownHostException e) {
649 hostName = "localhost"
650 }
651
652 if (!generateAgentName) {
653 installAgentName = prompt(
654 installAgentName,
655 "Enter the name for this agent. [Default: "+hostName+"]",
656 hostName)
657 }
658
659 if (!doUpgrade) {
660 ant.echo(message: "The agent can be added to one or more teams when it first connects to the server. " +
661 "Changing this setting after initial connection to the server will not have any effect. " +
662 "You can also add a specific type associated with a team by using the format <team>:<type>")
663 installAgentTeams = prompt(
664 installAgentTeams,
665 "Enter teams (and types) to add this agent to, separated by commas. [Default: None]",
666 "")
667 }
668
669 // copy files
670 copyAgentFiles(installAgentDir, doUpgrade)
671
672 //create key if it does not exist
673 createSecretKey();
674
675 // write the installed version
676 ant.echo(file: installAgentDir + "/conf/installed.version", encoding: "UTF-8",
677 message: "installed.version=" + ant.project.properties.'version' + NL)
678 ant.echo(message: "Installed version " + ant.project.properties.'version' + NL)
679
680 //install service
681 if (Os.isFamily("windows")) {
682 doServiceInstall = false
683 if (installServiceName != null) {
684 doServiceInstall = true
685 }
686 else {
687 installAsService = parseBoolean(prompt(
688 installAsService,
689 "Do you want to install the Agent as Windows service? y,N [Default: N]",
690 "N",
691 yesNoValidator))
692 doServiceInstall = installAsService
693 }
694
695 def defaultName = productName.toLowerCase().replace(" ", "-")+"-agent"
696 def strLocalsystem = /.\localsystem/
697 def strPath = /'.\'/
698 if (doServiceInstall == true) {
699 if (installServiceName == null) {
700 installServiceName = prompt(
701 installServiceName,
702 "Enter a unique service name for the Agent. No spaces please. [Default: " + defaultName+"]",
703 defaultName,
704 serviceNameValidator)
705 }
706
707 if (installServiceLogin == null) {
708 installServiceLogin = prompt(
709 installServiceLogin,
710 "Enter the user account name including domain path to run the service as (for local use " +
711 strPath + " before login), The local system account will be used by default. [Default: " +
712 strLocalsystem + "]",
713 strLocalsystem,
714 requiredValidator)
715 }
716
717 if (installServiceLogin != strLocalsystem) {
718 installServicePassword = prompt(
719 installServicePassword,
720 "Please enter your password for desired account.",
721 "nopass",
722 requiredValidator)
723 }
724 else {
725 installServicePassword = "nopass"
726 }
727
728 installServiceAutostart = prompt(
729 installServiceAutostart,
730 "Do you want to start the '" + installServiceName + "' service automatically? y,N " +
731 "[Default: N]",
732 "N",
733 yesNoValidator)
734
735 ant.exec(dir: installAgentDir + "/bin/service", executable:"cscript.exe") {
736 arg(value:"//I")
737 arg(value:"//Nologo")
738 arg(value:installAgentDir + "/bin/service/agent_srvc_install.vbs")
739 arg(value:installServiceName)
740 arg(value:installServiceLogin)
741 arg(value:installServicePassword)
742 arg(value:installServiceAutostart)
743 }
744
745 // read service installation status properties
746 if (new File(installAgentDir + "/bin/service/srvc.properties").exists()) {
747 ant.property(file: installAgentDir + "/bin/service/srvc.properties")
748 installServiceStatus = ant.project.properties.'install.service.status'
749 if (installServiceStatus == "OK") {
750 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
751 entry(key: "install.service.name", value: installServiceName)
752 }
753 }
754 ant.delete(file: installAgentDir + "/bin/service/srvc.properties")
755
756 }
757 }
758 else {
759 println("\nYou can install service manually (see documentation).\n\n")
760 }
761 }
762 }
763
764 private void copyAgentFiles(installAgentDir, doUpgrade) {
765 // In order to run the installer the User had change the encoding of these files. Since we
766 // treat all files as UTF-8 we will convert these back to UTF-8 temporarily.
767 if (isZos) {
768 IO.transcode(systemEncoding, agentEncoding, new File(srcDir + "/opt/apache-ant-1.8.4/bin/ant"))
769 IO.transcode(systemEncoding, agentEncoding, new File(srcDir + "/opt/apache-ant-1.8.4/bin/antRun"))
770 IO.transcode(systemEncoding, agentEncoding, new File(srcDir + "/opt/groovy-1.8.8/bin/groovy"))
771 IO.transcode(systemEncoding, agentEncoding, new File(srcDir + "/opt/groovy-1.8.8/bin/startGroovy"))
772 }
773
774 ant.delete(dir: installAgentDir + "/lib", failonerror: 'false')
775
776 // clean out old unused configuration files
777 ant.delete(dir: installAgentDir + "/conf") {
778 include(name: "client/**/*.xml")
779 include(name: "spring-client/**/*")
780 }
781
782 // create directory structure
783 // ant mkdir threw a fit with cyrillic characters
784 new File(installAgentDir + "/bin").mkdirs()
785 new File(installAgentDir + "/conf/agent").mkdirs()
786 new File(installAgentDir + "/lib").mkdirs()
787 new File(installAgentDir + "/monitor").mkdirs()
788 new File(installAgentDir + "/native").mkdirs()
789 new File(installAgentDir + "/opt").mkdirs()
790 new File(installAgentDir + "/var/jobs").mkdirs()
791 new File(installAgentDir + "/var/log").mkdirs()
792 new File(installAgentDir + "/var/temp").mkdirs()
793
794 final def jreDir = new File(srcDir + '/java')
795 if (jreDir.exists()) {
796 ant.delete(dir: installAgentDir + "/java", quiet: 'true', failonerror: 'false')
797 ant.copy(todir: installAgentDir + "/java") {
798 fileset(dir: srcDir + "/java") {
799 include(name: "**/*")
800 }
801 }
802 ant.chmod(perm: "+x", type: "file", dir: installAgentDir + "/java/bin", includes: "**")
803 }
804
805 // these need to run after the embedded Java is copied so it can be used.
806 installOs = getOs(javaHome, classpath)
807 installArch = getArch(javaHome, classpath)
808
809 // copy conf files
810 if (!doUpgrade) {
811 ant.copy(todir: installAgentDir + "/conf", overwrite: 'true') {
812 fileset(dir: unpackDir + "/conf") {
813 include(name: "agent/java.security")
814 include(name: "agent/log4j.properties")
815 }
816 }
817 }
818 else {
819 ant.copy(todir: installAgentDir + "/conf", overwrite: 'true') {
820 fileset(dir: unpackDir + "/conf") {
821 include(name: "agent/java.security")
822 }
823 }
824 }
825
826 // Copy all other overlay files
827 ant.copy(todir: installAgentDir + "/properties", overwrite: 'true') {
828 fileset(dir: unpackDir + "/properties") {
829 exclude(name: "conf/**/*")
830 }
831 }
832
833
834 if (!installAgentKeystore) {
835 installAgentKeystore = "../conf/agent.keystore"
836 }
837 if (!installAgentKeystorePwd) {
838 installAgentKeystorePwd = "changeit"
839 }
840
841 //check whether or not the file path is absolute
842 File keyStoreFile = new File(installAgentKeystore);
843 if (!keyStoreFile.isAbsolute()) {
844 //if the file path is relative it must be relative from the agent's bin directory
845 keyStoreFile = new File(installAgentDir+"/bin", installAgentKeystore);
846 }
847
848 //if the keystore file does not exist we need to make a new one.
849 if (!keyStoreFile.exists()) {
850 Date from = new Date();
851 Date to = new Date(from.getTime() + (7305 * 86400000l));
852
853 KeytoolHelper keyHelper = new KeytoolHelper();
854 KeyStore ks = keyHelper.generateKeyStore(keyStoreFile, "JKS", installAgentKeystorePwd);
855 KeyPair pair = keyHelper.generateKeyPair("RSA", 2048);
856
857 PrivateKey privKey = pair.getPrivate();
858 PublicKey pubKey = pair.getPublic();
859
860 Extension extension = new Extension(pubKey, false);
861 extension.SetExtensionIdentifierAsSubjectKey();
862 List<Extension> extensions = new ArrayList<Extension>();
863 extensions.add(extension);
864
865 Certificate cert = keyHelper.buildWithExtensions("CN="+productPrefix+"_agent", from, to,
866 pair, "SHA256WithRSA", extensions);
867 Certificate[] certArray = new Object[1]
868 certArray[0] = cert
869
870 ks.setKeyEntry(productPrefix + "_agent", privKey, installAgentKeystorePwd.toCharArray(), certArray);
871 ks.store(new FileOutputStream(keyStoreFile.getAbsolutePath()), installAgentKeystorePwd.toCharArray());
872 }
873
874 if (installAgentId == null) {
875 installAgentId = ""
876 }
877
878 // so we do not get "null"
879 installAgentProxyHost = installAgentProxyHost ? installAgentProxyHost : ""
880 installAgentProxyPort = installAgentProxyPort ? installAgentProxyPort : ""
881
882 // ensure replacements are initialized
883 if (installAgentDirTokenReplacement == null) {
884 installAgentDirTokenReplacement = installAgentDir
885 }
886 if (javaHomeTokenReplacement == null) {
887 javaHomeTokenReplacement = javaHome
888 }
889
890 def brokerURL = null
891
892 // construct the broker URL if not already defined
893 if (installBrokerURL == null) {
894 // if installer is interactive and installWithRelay is true, no default is provided and
895 // no validation is done. so if user just presses enter through the prompt, null gets
896 // added to the list
897 installAgentRemoteHostList.remove(null)
898
899 brokerURL = "failover:("
900 for (int i = 0; i < installAgentRemoteHostList.size(); i++) {
901 brokerURL += "ah3://" + installAgentRemoteHostList.get(i) + ":" + installAgentRemotePortList.get(i)
902 if (i+1 != installAgentRemoteHostList.size()) {
903 brokerURL += ","
904 }
905 }
906 brokerURL += ")"
907 }
908 else {
909 brokerURL = installBrokerURL
910 }
911
912 if (!encryptionKeyStorePath) {
913 encryptionKeyStorePath = "../conf/encryption.keystore";
914 }
915 if (!keyStorePassword) {
916 //set to default
917 keyStorePassword = "changeit"
918 }
919
920 if (!encryptionKeystoreAlias) {
921 def uniquePart = RandomStringUtils.randomAlphanumeric(4)
922 def prefix = "aes128key"
923 encryptionKeystoreAlias = "${prefix}${uniquePart}".toLowerCase()
924 }
925
926 if (!doUpgrade) {
927 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
928 entry(key: "locked/agent.brokerUrl", value: brokerURL)
929 entry(key: "locked/agent.jms.remote.host", value: installAgentRemoteHostList.get(0))
930 entry(key: "locked/agent.jms.remote.port", value: installAgentRemotePortList.get(0))
931 entry(key: "locked/agent.http.proxy.host", value: installAgentProxyHost)
932 entry(key: "locked/agent.http.proxy.port", value: installAgentProxyPort)
933 entry(key: productName + "/java.home", value: javaHomeTokenReplacement)
934 entry(key: "locked/agent.home", value: installAgentDirTokenReplacement)
935 entry(key: "locked/agent.mutual_auth", value: installAgentMutualAuth)
936 entry(key: "agent.jms.full_encryption", operation:"del");
937 if (disableFullEncryption != null && disableFullEncryption) {
938 entry(key: "agent.jms.disable_full_encryption", value: disableFullEncryption)
939 }
940 entry(key: "locked/agent.keystore", value: installAgentKeystore)
941 entry(key: "locked/agent.keystore.pwd", value: CryptStringUtil.encrypt(installAgentKeystorePwd))
942 entry(key: "system.default.encoding", value: systemEncoding)
943 entry(key: "agent.HttpFailoverHandler.disabled", value: installDisableHttpFailover)
944 entry(key: "verify.server.identity", value: installAgentVerifyServerIdentity)
945 entry(key: "encryption.keystore.password", value: CryptStringUtil.encrypt(keyStorePassword))
946 entry(key: "encryption.keystore", value: encryptionKeyStorePath)
947 entry(key: "encryption.keystore.alias", value: encryptionKeystoreAlias)
948 }
949 if (installAgentServerUrl != null && !installAgentServerUrl.isAllWhitespace()) {
950 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
951 entry(key: "server.url", value: installAgentServerUrl)
952 }
953 }
954 if (installAgentId != null && !installAgentId.isAllWhitespace()) {
955 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
956 entry(key: "locked/agent.id", value: installAgentId)
957 }
958 }
959 if (installAgentName != null && !installAgentName.isAllWhitespace()) {
960 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
961 entry(key: "locked/agent.name", value: installAgentName)
962 }
963 }
964 if (installAgentTeams != null && !installAgentTeams.isAllWhitespace()) {
965 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
966 entry(key: "locked/agent.initial.teams", value: installAgentTeams)
967 }
968 }
969 if (isZos) {
970 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
971 entry(key: "com.urbancode.shell.impersonation.unix.suFormat", value: "%s -s %u -c %c")
972 }
973 }
974 }
975 else {
976 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
977 entry(key: "locked/agent.id", default: installAgentId)
978 entry(key: "locked/agent.brokerUrl", default: brokerURL)
979 entry(key: "locked/agent.jms.remote.host", default: installAgentRemoteHostList.get(0))
980 entry(key: "locked/agent.jms.remote.port", default: installAgentRemotePortList.get(0))
981 entry(key: "locked/agent.http.proxy.host", default: installAgentProxyHost)
982 entry(key: "locked/agent.http.proxy.port", default: installAgentProxyPort)
983 entry(key: productName + "/java.home", default: javaHomeTokenReplacement)
984 entry(key: "locked/agent.home", default: installAgentDirTokenReplacement)
985 entry(key: "locked/agent.mutual_auth", default: installAgentMutualAuth)
986 entry(key: "agent.jms.full_encryption", operation:"del");
987 if (disableFullEncryption != null && disableFullEncryption) {
988 entry(key: "agent.jms.disable_full_encryption", default: disableFullEncryption)
989 }
990 entry(key: "locked/agent.keystore", default: installAgentKeystore)
991 entry(key: "locked/agent.keystore.pwd", default: CryptStringUtil.encrypt(installAgentKeystorePwd))
992 entry(key: "system.default.encoding", default: systemEncoding)
993 entry(key: "agent.HttpFailoverHandler.disabled", default: installDisableHttpFailover)
994 entry(key: "verify.server.identity", default: installAgentVerifyServerIdentity)
995 entry(key: "encryption.keystore.password", default: CryptStringUtil.encrypt(keyStorePassword))
996 entry(key: "encryption.keystore", default: encryptionKeyStorePath)
997 entry(key: "encryption.keystore.alias", default: encryptionKeystoreAlias)
998 }
999 if (installAgentServerUrl != null && !installAgentServerUrl.isAllWhitespace()) {
1000 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
1001 entry(key: "server.url", default: installAgentServerUrl)
1002 }
1003 }
1004 if (installAgentId != null && !installAgentId.isAllWhitespace()) {
1005 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
1006 entry(key: "locked/agent.id", default: installAgentId)
1007 }
1008 }
1009 if (installAgentName != null && !installAgentName.isAllWhitespace()) {
1010 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
1011 entry(key: "locked/agent.name", default: installAgentName)
1012 }
1013 }
1014 if (isZos) {
1015 ant.propertyfile(file: installAgentDir + "/conf/agent/installed.properties") {
1016 entry(key: "com.urbancode.shell.impersonation.unix.suFormat", default: "%s -s %u -c %c")
1017 }
1018 }
1019 }
1020
1021 // copy lib files
1022 ant.copy(todir: installAgentDir + "/lib", overwrite: 'true') {
1023 fileset(dir: srcDir + "/lib") {
1024 include(name: "*.jar")
1025 include(name: "Validation.jar")
1026 }
1027
1028 fileset(dir: srcDir + "/lib/bsf") {
1029 include(name: "*.jar")
1030 }
1031
1032 // include external lib files (distribution project may have unpacked these)
1033 if (new File(srcDir,'../lib').exists() && new File(srcDir, 'lib/include-main-jars.conf').exists()) {
1034 fileset(dir: '../lib', includesfile:'lib/include-main-jars.conf')
1035 }
1036 }
1037
1038 // copy monitor files
1039 ant.copy(todir: installAgentDir + "/monitor", overwrite: 'true') {
1040 fileset(dir: srcDir + "/monitor") {
1041 include(name: "*.jar")
1042 }
1043 }
1044
1045 // copy native files
1046 File nativeSrcDir = new File(srcDir + "/native/" + installOs)
1047 if (nativeSrcDir.isDirectory()) {
1048 ant.copy(todir: installAgentDir + "/native", overwrite: 'true', failonerror: 'false') {
1049 fileset(dir: srcDir + "/native/" + installOs) {
1050 include(name: "**")
1051 }
1052 }
1053 }
1054
1055 // copy opt files
1056 ant.copy(todir: installAgentDir + "/opt", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1057 fileset(dir: srcDir + "/opt") {
1058 include(name: "apache-ant-*/**/*")
1059 include(name: "groovy-*/**/*")
1060 }
1061 }
1062
1063 // run platform specific install
1064 if (isUnix) {
1065 copyAgentFilesUnix(installAgentDir, doUpgrade)
1066 removeWorkingDirFromClasspathUnix(installAgentDir)
1067 }
1068 else if (isWindows) {
1069 copyAgentFilesWindows(installAgentDir, doUpgrade)
1070 removeWorkingDirFromClasspathWindows(installAgentDir)
1071 }
1072
1073 writePluginJavaOpts()
1074
1075 if (isZos) {
1076 convertFilesToSystemEncoding()
1077 }
1078
1079 // chmod opt bin files
1080 ant.chmod(perm: "+x", type: "file") {
1081 fileset(dir: installAgentDir) {
1082 include(name: "opt/*/bin/*")
1083 exclude(name: "opt/*/bin/*.bat")
1084 exclude(name: "opt/*/bin/*.cmd")
1085 }
1086 }
1087 }
1088
1089 /**
1090 * Copy the unix specific files to the agent directory. Make any necessary substitutions and file permission
1091 * alterations.
1092 */
1093 private void copyAgentFilesUnix(installAgentDir, doUpgrade) {
1094
1095 //copy udclient
1096 ant.copy(todir: installAgentDir + "/opt/udclient/", overwrite: 'true') {
1097 fileset(dir:srcDir + '/opt/udclient') {
1098 include(name:'udclient.jar')
1099 include(name:'udclient')
1100 }
1101 }
1102
1103 ant.chmod(file: installAgentDir + "/opt/udclient/udclient", perm:"+x")
1104
1105 // create a directory for the init script
1106 ant.mkdir(dir: installAgentDir + "/bin/init")
1107
1108 // ensure replacements are initialized
1109 if (installAgentDirTokenReplacement == null) {
1110 installAgentDirTokenReplacement = installAgentDir
1111 }
1112 if (javaHomeTokenReplacement == null) {
1113 javaHomeTokenReplacement = javaHome
1114 }
1115 if (installInitUser == null) {
1116 installInitUser = ""
1117 }
1118 if (installInitGroup == null) {
1119 installInitGroup = ""
1120 }
1121
1122
1123 ant.filterset(id: 'agent-unix-filterset') {
1124 filter(token: "AGENT_HOME", value: installAgentDirTokenReplacement)
1125 filter(token: "AGENT_USER", value: installInitUser)
1126 filter(token: "AGENT_GROUP", value: installInitGroup)
1127 filter(token: "product.prefix", value: productPrefix)
1128 filter(token: "product.name", value: productName)
1129 filter(token: "product.capital.name", value: productCapitalName)
1130 filter(token: "JAVA_HOME", value: javaHomeTokenReplacement)
1131 filter(token: "JAVA_DEBUG_OPTS", value: '-Xdebug -Xrunjdwp:transport=dt_socket,address=localhost:10001,server=y,suspend=n -Dcom.sun.management.jmxremote')
1132 filter(token: "JAVA_OPTS", value: "-Xmx512m")
1133 }
1134
1135 //
1136 // Copy all scripts and unix-specific files
1137 //
1138
1139 ant.copy(todir: installAgentDir + "/bin/", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1140 fileset(dir:srcDir+'/bin/agent') {
1141 include(name:'agent')
1142 include(name:'*tool')
1143 include(name:'codestation')
1144 include(name:'init/agent')
1145 include(name:'configure-agent')
1146 }
1147 filterset(refid: 'agent-unix-filterset')
1148 compositemapper {
1149 mapper(type:'glob', from:'configure-agent', to:'configure-agent')
1150 mapper(type:'glob', from:'*agent', to:'*agent')
1151 mapper(type:'glob', from:'*tool', to:'*tool')
1152 mapper(type:'glob', from:'codestation', to:'codestation')
1153 }
1154 }
1155
1156 ant.copy(todir: installAgentDir + "/bin/", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1157 fileset(dir:srcDir+'/bin/agent') {
1158 include(name:'classpath.conf.UNIX')
1159 include(name:'worker-args.conf.UNIX')
1160 }
1161 filterset(refid: 'agent-unix-filterset')
1162 mapper(type:'regexp', from:'^(.*)\\.UNIX$', to:'\\1')
1163 }
1164
1165 //
1166 // Fix line endings and permissions
1167 //
1168
1169 // locate all files that are native scripts
1170 ant.fileset(dir: installAgentDir, id: 'agentNativeScriptFileSet') {
1171 patternset(id:'agentNativeScriptFileSelector') {
1172 include(name: 'bin/agent')
1173 include(name: 'bin/init/agent')
1174 include(name: 'bin/configure-agent')
1175 include(name: 'opt/apache-ant-*/bin/ant')
1176 include(name: 'opt/groovy-*/bin/groovy')
1177 include(name: 'opt/groovy-*/bin/groovyc')
1178 }
1179 }
1180
1181 // Link old executables to the new one if upgrading.
1182 if(doUpgrade) {
1183 makeSymlinksToNewExec(installAgentDir)
1184 }
1185
1186 // fix line endings - must be done before chmod
1187 ant.fixcrlf(srcDir: installAgentDir, eol: "lf", encoding: "UTF-8", outputEncoding: "UTF-8") {
1188 include(name: "bin/classpath.conf")
1189 patternset(refid:'agentNativeScriptFileSelector')
1190 }
1191
1192 // adjust modes on scripts - must be after doing fixcrlf
1193 ant.chmod(perm: "+x", type: "file") {
1194 fileset(refid:'agentNativeScriptFileSet')
1195 }
1196
1197 ant.chmod(perm: "+x", type: "file", dir: installAgentDir + "/native", includes: "**")
1198 }
1199
1200 //
1201 // private method for linking old executable files to the new when upgrading.
1202 //
1203
1204 private void makeSymlinksToNewExec(installAgentDir) {
1205 // List of known deprecated executable file names.
1206 def oldExecNames = ["udagent", "ibm-ucdagent"]
1207
1208 // The executable name currently in use.
1209 def newExecName = "agent"
1210
1211 // Necessary for creating symlinks.
1212 Unix unix = new Unix();
1213
1214 for(String n : oldExecNames) {
1215 // File objects for an old executable and its corresponding .bak file.
1216 File oldExec = new File(installAgentDir + "/bin/" + n)
1217 File oldExecBak = new File(installAgentDir + "/bin/" + n + ".bak")
1218
1219 // Same as above, but for the executable in the init directory.
1220 File oldExecInit = new File(installAgentDir + "/bin/init/" + n)
1221 File oldExecInitBak = new File(installAgentDir + "/bin/init/" + n + ".bak")
1222
1223 if(oldExec.exists() && !oldExec.isDirectory()) {
1224 if(!oldExecBak.exists()) {
1225 IO.copy(oldExec, oldExecBak)
1226 }
1227 IO.delete(oldExec)
1228 unix.mksymlink(oldExec, installAgentDir + "/bin/" + newExecName)
1229 }
1230
1231 if(oldExecInit.exists() && !oldExecInit.isDirectory()) {
1232 if(!oldExecInitBak.exists()) {
1233 IO.copy(oldExecInit, oldExecInitBak)
1234 }
1235 IO.delete(oldExecInit)
1236 unix.mksymlink(oldExecInit, installAgentDir + "/bin/init/" + newExecName)
1237 }
1238 }
1239 }
1240
1241 private void copyAgentFilesWindows(installAgentDir, doUpgrade) {
1242
1243 //copy udclient
1244 ant.copy(todir: installAgentDir + "/opt/udclient/", overwrite: 'true') {
1245 fileset(dir:srcDir + '/opt/udclient') {
1246 include(name:'udclient.jar')
1247 include(name:'udclient.cmd')
1248 }
1249 }
1250
1251 // create a directory for the service script and exe
1252 ant.mkdir(dir: installAgentDir + "\\bin\\service")
1253
1254 def overwriteNative = doUpgrade ? 'true' : 'false'
1255
1256 // ensure replacements are initialized
1257 if (installAgentDirTokenReplacement == null) {
1258 installAgentDirTokenReplacement = installAgentDir
1259 }
1260 if (javaHomeTokenReplacement == null) {
1261 javaHomeTokenReplacement = javaHome
1262 }
1263
1264 // create a shared filter set
1265 ant.filterset(id: "agent-windows-filterset") {
1266 filter(token: "TEMPLATE", value: "agent")
1267 filter(token: "AGENT_HOME", value: installAgentDirTokenReplacement)
1268 filter(token: "JAVA_HOME", value: javaHomeTokenReplacement)
1269 filter(token: "product.prefix", value: productPrefix)
1270 filter(token: "product.name", value: productName)
1271 filter(token: "product.capital.name", value: productCapitalName)
1272 filter(token: "ARCH", value: installArch)
1273 filter(token: "JAVA_OPTS", value: "-Xmx512m")
1274 filter(token: "JAVA_DEBUG_OPTS", value: '-Xdebug -Xrunjdwp:transport=dt_socket,address=10001,server=y,suspend=n -Dcom.sun.management.jmxremote')
1275 }
1276
1277 ant.copy(toDir: installAgentDir + "\\bin", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1278 fileset(dir: srcDir+"\\bin\\agent") {
1279 include(name:'agent.cmd')
1280 include(name:'configure-agent.cmd')
1281 }
1282
1283 filterset(refid: "agent-windows-filterset")
1284 compositemapper {
1285 mapper(type:'glob', from:'agent.cmd', to:'agent.cmd')
1286 mapper(type:'glob', from:'configure-agent.cmd', to:'configure-agent.cmd')
1287 }
1288 }
1289
1290 ant.copy(toDir: installAgentDir + "\\bin", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1291 fileset(dir: srcDir+"\\bin\\agent") {
1292 include(name:'classpath.conf.WIN')
1293 include(name:'worker-args.conf.WIN')
1294 }
1295
1296 filterset(refid: "agent-windows-filterset")
1297 mapper(type:'regexp', from:'^(.*)\\.WIN$', to:'\\1')
1298 }
1299
1300 ant.copy(toDir: installAgentDir + "\\bin", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1301 fileset(dir: srcDir+'\\bin') {
1302 include(name:'TEMPLATE_run.cmd')
1303 include(name:'TEMPLATE_start.cmd')
1304 include(name:'TEMPLATE_stop.cmd')
1305 }
1306 filterset(refid: "agent-windows-filterset")
1307 mapper(type:'regexp', from:'^TEMPLATE_(.*)\\.cmd$', to:'\\1_agent.cmd')
1308 }
1309
1310 // create service install script
1311 // do NOT attempt to quote spaces in JAVA_OPTS here
1312 ant.copy(todir: installAgentDir + "\\bin\\service", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1313 fileset(dir:srcDir + "\\bin\\agent\\service\\") {
1314 include(name:'_agent.cmd')
1315 }
1316
1317 filterset { filter(token: "JAVA_OPTS", value: "") }
1318 filterset(refid: "agent-windows-filterset")
1319 compositemapper {
1320 mapper(type:'glob', from:'agent.cmd', to:'agent.cmd')
1321 mapper(type:'glob', from:'_agent.cmd', to:'_agent.cmd')
1322 }
1323 }
1324
1325
1326 ant.copy(todir: installAgentDir + "\\bin", overwrite: 'true') {
1327 fileset(dir: srcDir + "\\bin") {
1328 include(name: "Impersonater.exe") // copy Impersonater exe
1329 }
1330 }
1331
1332 // copy service exe
1333 if (new File(srcDir + "\\bin\\agentservice.exe").exists()) {
1334 ant.copy(file: srcDir + "\\bin\\agentservice.exe", todir: installAgentDir + "\\bin\\service", overwrite: 'true')
1335 }
1336
1337 // copy the service configurator vbs scripts
1338 ant.copy(todir: installAgentDir + "\\bin", overwrite: 'true', encoding: "UTF-8", outputEncoding: "UTF-8") {
1339 fileset(dir: srcDir + "\\bin\\agent") {
1340 include(name: "service\\agent_srvc_configurator.vbs")
1341 include(name: "service\\agent_srvc_stop.vbs")
1342 include(name: "service\\agent_srvc_install.vbs")
1343 }
1344
1345 filterset(refid: "agent-windows-filterset")
1346 }
1347
1348 // fix line endings - must be done before chmod
1349 ant.fixcrlf(srcDir: installAgentDir, encoding: "UTF-8", outputEncoding: "UTF-8") {
1350 include(name: "bin\\agent.cmd")
1351 include(name: "bin\\classpath.conf")
1352 include(name: "bin\\worker-args.conf")
1353 include(name: "bin\\configure-agent.cmd");
1354 include(name: "bin\\run_agent.cmd")
1355 include(name: "bin\\start_agent.cmd")
1356 include(name: "bin\\stop_agent.cmd")
1357 include(name: "bin\\service\\agent.cmd")
1358 include(name: "bin\\service\\_agent.cmd")
1359 include(name: "bin\\service\\agent_srvc_configurator.vbs")
1360 include(name: "bin\\service\\agent_srvc_stop.vbs")
1361 include(name: "bin\\service\\agent_srvc_install.vbs")
1362 }
1363 }
1364
1365 private void convertFilesToSystemEncoding() {
1366 def files = []
1367 File groovyConfDir = new File(installAgentDir + "/opt/groovy-1.8.8/conf")
1368 File groovyBinDir = new File(installAgentDir + "/opt/groovy-1.8.8/bin")
1369 File antBinDir = new File(installAgentDir + "/opt/apache-ant-1.8.4/bin")
1370
1371 groovyConfDir.eachFile { IO.transcode(agentEncoding, systemEncoding, new File(groovyConfDir, it.name)) }
1372 groovyBinDir.eachFile { IO.transcode(agentEncoding, systemEncoding, new File(groovyBinDir, it.name)) }
1373 antBinDir.eachFile { IO.transcode(agentEncoding, systemEncoding, new File(antBinDir, it.name)) }
1374 IO.transcode(agentEncoding, systemEncoding, new File(installAgentDir + "/opt/udclient/udclient"))
1375 IO.transcode(agentEncoding, systemEncoding, new File(installAgentDir + "/bin/agent"))
1376 IO.transcode(agentEncoding, systemEncoding, new File(installAgentDir + "/bin/init/agent"))
1377 IO.transcode(agentEncoding, systemEncoding, new File(installAgentDir + "/bin/configure-agent"))
1378
1379 // transcoding the files removes the execute permission from them.
1380 ant.chmod(perm: "+x", type: "file") {
1381 fileset(dir: installAgentDir) {
1382 include(name: "bin/agent")
1383 include(name: "bin/configure-agent")
1384 }
1385 }
1386
1387 // The user had to change the encoding of these files in order to run the installer. We
1388 // should return them to the system encoding now that we've copied them to the install
1389 // location.
1390 IO.transcode(agentEncoding, systemEncoding, new File(srcDir + "/opt/apache-ant-1.8.4/bin/ant"))
1391 IO.transcode(agentEncoding, systemEncoding, new File(srcDir + "/opt/apache-ant-1.8.4/bin/antRun"))
1392 IO.transcode(agentEncoding, systemEncoding, new File(srcDir + "/opt/groovy-1.8.8/bin/groovy"))
1393 IO.transcode(agentEncoding, systemEncoding, new File(srcDir + "/opt/groovy-1.8.8/bin/startGroovy"))
1394
1395 // chmod opt bin files in source directory after transcode
1396 ant.chmod(perm: "+x", type: "file") {
1397 fileset(dir: srcDir) {
1398 include(name: "opt/*/bin/*")
1399 exclude(name: "opt/*/bin/*.bat")
1400 exclude(name: "opt/*/bin/*.cmd")
1401 }
1402 }
1403 }
1404
1405 private String getInstallDir(installComponent, installDir) {
1406 String defaultDir = null
1407 if (Os.isFamily('mac')) {
1408 defaultDir = '/Library/' + productPrefix + '/'+installComponent
1409 }
1410 else if (Os.isFamily('unix')) {
1411 defaultDir = '/opt/' + productPrefix + '/' + installComponent
1412 }
1413 else if (Os.isFamily('windows')) {
1414 String progFiles = ant.project.properties.'ProgramFiles'
1415 if (progFiles != null && progFiles.length() > 0 ) {
1416 defaultDir = progFiles+'\\' + productPrefix + '\\'+installComponent
1417 }
1418 else {
1419 defaultDir = "C:\\Program Files" + File.separator + installComponent.replace('/', '\\')
1420 }
1421 }
1422
1423 installDir = prompt(
1424 installDir,
1425 'Enter the directory where ' + installComponent + ' should be installed.' +
1426 (defaultDir == null ? '' : ' [Default: '+defaultDir+']'),
1427 defaultDir,
1428 requiredValidator)
1429
1430 if (!new File(installDir).exists()) {
1431 String createDir = prompt(
1432 null,
1433 'The specified directory does not exist. Do you want to create it? Y,n [Default: Y]',
1434 'Y',
1435 yesNoValidator)
1436 if ('Y'.equalsIgnoreCase(createDir) || 'YES'.equalsIgnoreCase(createDir)) {
1437 new File(installDir).mkdirs()
1438 }
1439 else {
1440 ant.fail('Can not install without creating installation directory.')
1441 }
1442 }
1443
1444 return new File(installDir).absolutePath
1445 }
1446
1447 private boolean checkForUpgrade(installDir, componentInstall, installServiceName) {
1448 if (new File(installDir + '/conf/installed.version').exists()) {
1449 ant.property(file: installDir + '/conf/installed.version')
1450
1451 if (new File(installDir + '/var/' + productName + '-' + componentInstall + '.pid').exists()) {
1452 ant.fail('A previously installed version of ${component.name} is running. ' +
1453 'Please shutdown the running ${component.name} and start the installation again.')
1454 }
1455
1456 if (nonInteractive) {
1457 return true
1458 }
1459
1460 def doUpgrade = prompt(
1461 null,
1462 'A previous version (' + ant.project.properties.'installed.version' + ') ' +
1463 'exists in the specified directory. Do you want to upgrade the currently ' +
1464 'installed version? [Y,n]',
1465 'Y',
1466 yesNoValidator)
1467 if (doUpgrade == 'Y' || doUpgrade == 'y') {
1468
1469 //stopping service if running
1470 if (componentInstall == 'agent' && installServiceName != null && (Os.isFamily('windows'))) {
1471 println('\nYour Agent is installed as "' + installServiceName + '" service.\n\n')
1472 ant.exec(dir: './bin/agent/service', executable: 'cscript.exe') {
1473 arg(value:'//I')
1474 arg(value:'//Nologo')
1475 arg(value:'agent_srvc_stop.vbs')
1476 arg(value:installServiceName)
1477 }
1478 }
1479
1480 return true
1481 }
1482 ant.fail('Not upgrading the existing installation.')
1483 }
1484
1485 return false
1486 }
1487
1488 private String prompt(promptText) {
1489 return prompt(null, promptText, null)
1490 }
1491
1492 private String prompt(curValue, promptText) {
1493 return prompt(curValue, promptText, null)
1494 }
1495
1496 private String prompt(curValue, promptText, defaultValue) {
1497 return prompt(curValue, promptText, defaultValue, null)
1498 }
1499
1500 private String prompt(curValue, promptText, defaultValue, validator) {
1501 // use curValue if not null and not empty
1502 if (curValue != null && curValue.trim()) {
1503 return curValue
1504 }
1505
1506 if (nonInteractive) {
1507 println(promptText)
1508
1509 def warningMessage = 'Warning: Installer prompting for input in non-interactive mode.'
1510 if (defaultValue) {
1511 warningMessage += ' Returning default: ' + defaultValue
1512 }
1513 println(warningMessage)
1514
1515 if (validator != null) {
1516 try {
1517 validator.validate(defaultValue)
1518 } catch (ValidationException ve) {
1519 throw new IllegalArgumentException(
1520 "Non-Interactive Mode: problem with default value of '${defaultValue}' " +
1521 "for '${promptText}' - " + ve.getValidationMessageArray().join(' '))
1522 }
1523 }
1524 return defaultValue
1525 }
1526
1527 def userValue = null
1528 def valid = false
1529 while (!valid) {
1530 println(promptText)
1531 userValue = read(defaultValue)
1532
1533 if (validator != null) {
1534 try {
1535 validator.validate(userValue)
1536 valid = true
1537 }
1538 catch (ValidationException ve) {
1539 for (message in ve.getValidationMessageArray()) {
1540 println(message)
1541 }
1542 }
1543 }
1544 else {
1545 valid = true
1546 }
1547 }
1548
1549 return userValue
1550 }
1551
1552 private String read(defaultValue) {
1553 def line = systemIn.readLine()?.trim()
1554 return line ?: defaultValue
1555 }
1556
1557 private void println(displayText) {
1558 if (displayText != null) {
1559 ant.echo(displayText)
1560 }
1561 }
1562
1563 private def getAllIPs(){
1564 def ips = []
1565 for (interfaz in java.net.NetworkInterface.getNetworkInterfaces()) {
1566 for (inet in interfaz.getInetAddresses()) {
1567 ips.add(inet.getHostAddress())
1568 }
1569 }
1570 // filter self-assinged ips
1571 return ips.findAll{!(it.startsWith('169.254') || it.startsWith('fe80:'))}
1572 }
1573
1574
1575
1576 private def getAllIPv4s(){
1577 return getAllIPs().findAll{it.split('\\.') == 4}
1578 }
1579
1580 private def getPrimaryIPv4(){
1581 // only use localhost as primary ip if no other public ips are present
1582 def result = getAllIPs().find{it != "localhost" && it != '127.0.0.1'}
1583 return result == null ? 'localhost' : result
1584 }
1585
1586 private def getAllIPv6s(){
1587 return getAllIPs().findAll{it.split(':') > 2}
1588 }
1589
1590 // command is a string or string array
1591 private Map runCommand(command) {
1592 def proc = command.execute()
1593 proc.waitFor()
1594 def result = [:] // empty map
1595 result["out"] = proc.in.text // std output of the process
1596 result["err"] = proc.err.text
1597 result["exit"] = proc.exitValue()
1598 return result
1599 }
1600
1601 /**
1602 * runs the specified script with the given arguments
1603 * @param script the path to the script ot run, given as relative to the src dir
1604 * @param args the arguments to provide to the script
1605 */
1606 private void runGroovyScript(script, args) {
1607 def extclasspath = ant.path() {
1608 fileset(dir: srcDir + '/lib/ext')
1609 pathelement(path: classpath)
1610 }
1611
1612 // need groovy-all-*.jar and commons-cli.jar (and driver-class) on classpath
1613 ant.java(
1614 classname:'groovy.lang.GroovyShell',
1615 fork:'yes',
1616 failonerror: true,
1617 dir: srcDir,
1618 classpath: extclasspath
1619 ) {
1620 arg(value: new File(srcDir+'/'+script).canonicalPath)
1621
1622 for (argument in args) {
1623 arg(value: argument)
1624 }
1625 }
1626 }
1627
1628 private Map getSystemPropertiesForRuntime(javaHome, classpath) {
1629 def result = [:]
1630 try {
1631 def process = ["${javaHome}" + File.separator + "bin" + File.separator + "java",
1632 "-Xmx64m", "-Xms64m", "-classpath", classpath,
1633 "com.urbancode.commons.detection.GetSystemProperties"].execute()
1634 process.consumeProcessErrorStream(System.err)
1635 process.in.eachLine {
1636 def prop = it.split("=", 2)
1637 result[prop[0]] = StringEscapeUtils.unescapeJava(prop[1])
1638 }
1639 }
1640 catch (Exception e) {
1641 result = null
1642 }
1643 return result
1644 }
1645
1646 private String getSSLKeyManagerFactoryDefaultAlgorithmForRuntime(javaHome, classpath) {
1647 def result = null
1648 try {
1649 def process = ["${javaHome}" + File.separator + "bin" + File.separator + "java",
1650 "-Xmx64m", "-Xms64m", "-classpath", classpath,
1651 "com.urbancode.commons.detection.GetSSLKeyManagerFactoryDefaultAlgorithm"].execute()
1652 process.consumeProcessErrorStream(System.err)
1653 result = process.text.trim()
1654 }
1655 catch (Exception e) {
1656 }
1657
1658 if (result == null || result.size() == 0) {
1659 result = 'SunX509'
1660 }
1661 return result
1662 }
1663
1664 private String getOs(javaHome, classpath) {
1665 if (installOs == null) {
1666 try {
1667 def process = ["${javaHome}" + File.separator + "bin" + File.separator + "java",
1668 "-Xmx64m", "-Xms64m", "-classpath", classpath,
1669 "com.urbancode.commons.detection.GetOs"].execute()
1670 process.consumeProcessErrorStream(System.err)
1671 installOs = process.text.trim()
1672 }
1673 catch (Exception e) {
1674 println "Error retrieving OS. Installation may not complete correctly. Error: ${e.message}"
1675 }
1676 }
1677 return installOs
1678 }
1679
1680 private String getArch(javaHome, classpath) {
1681 if (installArch == null) {
1682 try {
1683 def process = ["${javaHome}" + File.separator + "bin" + File.separator + "java",
1684 "-Xmx64m", "-Xms64m", "-classpath", classpath,
1685 "com.urbancode.commons.detection.GetArch"].execute()
1686 process.consumeProcessErrorStream(System.err)
1687 installArch = process.text.trim()
1688 }
1689 catch (Exception e) {
1690 println "Error retrieving system architecture. Installation may not complete correctly. Error: ${e.message}"
1691 }
1692 }
1693 return installArch
1694 }
1695
1696 // Get the system encoding. Use console.encoding (ibm jdk) if set, otherwise use file.encoding
1697 private String getSystemEncoding() {
1698 def systemEncoding = System.properties.'console.encoding'
1699 if (systemEncoding == null) {
1700 systemEncoding = System.properties.'file.encoding'
1701 }
1702 return systemEncoding
1703 }
1704
1705 private void writePluginJavaOpts() {
1706 File pluginJavaOpts = new File(installAgentDir + "/conf/plugin-javaopts.conf")
1707 if (!pluginJavaOpts.exists()) {
1708 pluginJavaOpts.createNewFile();
1709 pluginJavaOpts.withWriter("UTF-8") { out ->
1710 out.writeLine('-Dfile.encoding=${system.default.encoding}')
1711 out.writeLine('-Dconsole.encoding=${system.default.encoding}')
1712 }
1713 }
1714 else {
1715 // At one point, java.io.tmpdir was added to the plugin-javaopts.conf file
1716 // Spaces in the value caused the argument to be interpreted incorrectly,
1717 // preventing the agent from doing work, so we remove the old line here
1718 def javaOptArray = []
1719 pluginJavaOpts.eachLine("UTF-8") { line ->
1720 line = line.trim()
1721 if (!line.isEmpty() && line != '-Djava.io.tmpdir=${java.io.tmpdir}') {
1722 javaOptArray << line
1723 }
1724 }
1725 pluginJavaOpts.write(javaOptArray.join(System.getProperty("line.separator")), "UTF-8")
1726 }
1727 }
1728
1729 private String getProtocolForRuntime(javaHome, classpath) {
1730 def result = null
1731 try {
1732 def properties = getSystemPropertiesForRuntime(javaHome, classpath)
1733 if (properties != null && properties["java.vendor"].toLowerCase().contains("ibm")) {
1734 result = 'SSL_TLSv2'
1735 }
1736 }
1737 catch (Exception e) {
1738 }
1739
1740 if (result == null || result.size() == 0) {
1741 result = 'TLSv1.2'
1742 }
1743 return result
1744 }
1745
1746 private boolean parseBoolean(String s) {
1747 return Boolean.valueOf(s) ||
1748 "Y".equalsIgnoreCase(s) ||
1749 "YES".equalsIgnoreCase(s)
1750 }
1751
1752
1753 /*
1754 * Groovy 1.8.8 adds the current working directory to the CLASSPATH even
1755 * when the CLASSPATH is explicitly defined. This is incorrect behavior and
1756 * will cause issues since users may download artifacts and or set a current
1757 * working directory which contains classes which we don't want to have
1758 * loaded.
1759 *
1760 * We modify the startGroovy scripts on to fix this issue. If the version of
1761 * groovy is changed it will likely break our fix.I have put a check in
1762 * place to alert future DEVs to this if or when the groovy version is
1763 * updated.
1764 */
1765 private void warnAboutGroovyVersion(String contents) {
1766 // I split the string here to prevent a a find/replace from changing this
1767 if (contents.indexOf("groovy-1"+".8"+".8.jar") == -1) {
1768 println("Warning: using a version of groovy other than 1"+".8"+".8 may introduce a regression where" +
1769 "the current working directory is added onto Groovy's classpath.")
1770 }
1771 }
1772
1773 private void removeWorkingDirFromClasspathUnix(String agentDir) {
1774 File startGroovyFile = new File(agentDir + "/opt/groovy-1.8.8/bin/startGroovy");
1775 String contents = startGroovyFile.getText();
1776 warnAboutGroovyVersion(contents)
1777 contents = contents.replace('CP="$CLASSPATH":.', 'CP="$CLASSPATH"');
1778 contents = contents.replace('CP="$CP":.', 'CP="$CP"')
1779 contents = contents.replace('CP="$CP:.', 'CP=')
1780 startGroovyFile.write(contents)
1781 }
1782
1783 private void removeWorkingDirFromClasspathWindows(String agentDir) {
1784 File startGroovyFile = new File(agentDir + "/opt/groovy-1.8.8/bin/startGroovy.bat");
1785 String contents = startGroovyFile.getText();
1786 warnAboutGroovyVersion(contents)
1787 contents = contents.replace('set CP=%CP%;.":.', 'set CP=%CP%')
1788 contents = contents.replace('set CP=.', 'set CP=');
1789 startGroovyFile.write(contents)
1790 }
1791
1792 /**
1793 * Makes a HTTP request to the given URL. Throws an exception if the request fails.
1794 */
1795 private executeGetMethod (requestUrl) {
1796 HttpGet request = new HttpGet(requestUrl)
1797
1798 request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
1799 request.addHeader("Content-Type", "text/html;charset=UTF-8")
1800 request.addHeader("User-Agent", "Mozilla") // required because deploy server rejects httpclient's default
1801
1802 HttpClient client = createHttpClient()
1803
1804 def response = client.execute(request)
1805 def statusLine = response.getStatusLine()
1806 def statusReason = statusLine.getReasonPhrase()
1807 def statusCode = statusLine.getStatusCode()
1808
1809 // Throws an exception if the request did not return status code of 200.
1810 if (statusCode != 200) {
1811 throw new Exception ("Response reason: \"${statusReason}\"; status code: ${statusCode}")
1812 }
1813 }
1814
1815 /**
1816 * Create a instance of HttpClient that shares connections and adheres to the JVM proxy settings.
1817 */
1818 private HttpClient createHttpClient() {
1819
1820 HttpClientBuilder builder = new HttpClientBuilder()
1821
1822 // so we do not get "null"
1823 def tmpInstallAgentProxyHost = installAgentProxyHost ? installAgentProxyHost : ""
1824 def tmpInstallAgentProxyPort = installAgentProxyPort ? installAgentProxyPort : ""
1825
1826 int httpProxyPort = 0
1827 if (StringUtils.isNotBlank(tmpInstallAgentProxyPort)) {
1828 httpProxyPort = Integer.parseInt(tmpInstallAgentProxyPort)
1829 }
1830
1831 if (StringUtils.isNotBlank(tmpInstallAgentProxyHost)) {
1832 builder.setProxyHost(tmpInstallAgentProxyHost)
1833 }
1834 if (httpProxyPort > 0) {
1835 builder.setProxyPort(httpProxyPort)
1836 }
1837
1838 boolean trustAllCerts = !installAgentVerifyServerIdentity
1839 builder.setTrustAllCerts(trustAllCerts)
1840
1841 builder.setTimeoutMillis(10000)
1842
1843 return builder.buildClient()
1844 }
1845
1846 private void createSecretKey() {
1847 File installDir = new File(installAgentDir)
1848 File confDir = new File(installDir, "conf")
1849 File keyStoreFile = new File(confDir, encryptionKeyStorePath)
1850 ant.property(name: "encryption.keystore", value: keyStoreFile.absolutePath)
1851
1852 KeyStore keyStore = loadKeyStore(keyStoreFile)
1853
1854 boolean isKeyStored = false;
1855 isKeyStored = keyStore.isKeyEntry(encryptionKeystoreAlias)
1856 if (!isKeyStored) {
1857 try {
1858 println "Creating new encryption key."
1859 SecureRandom sr = SecureRandomHelper.getSecureRandom()
1860 KeyGenerator keygen = KeyGenerator.getInstance("AES")
1861 keygen.init(128, sr)
1862 SecretKey key = keygen.generateKey()
1863
1864 keyStore.setKeyEntry(encryptionKeystoreAlias, key, keyStorePassword.toCharArray(), null)
1865 def isKeyStoredNow = keyStore.isKeyEntry(encryptionKeystoreAlias);
1866
1867 }
1868 catch (NoSuchAlgorithmException impossible) {
1869 throw new RuntimeException(impossible)
1870 }
1871 catch (UnsupportedEncodingException impossible) {
1872 }
1873 catch (IOException e) {
1874 throw new SecurityException(e)
1875 }
1876
1877 OutputStream output = new FileOutputStream(keyStoreFile)
1878 try {
1879 keyStore.store(output, keyStorePassword.toCharArray())
1880 }
1881 finally {
1882 output.close()
1883 }
1884 }
1885 else {
1886 println "Encryption key retrieved from keystore. Proceeding..."
1887 }
1888 ant.property(name: "key.store.password", value: keyStorePassword)
1889 ant.property(name: "key.store.alias", value: encryptionKeystoreAlias)
1890 }
1891
1892 private KeyStore loadKeyStore(File keyStoreFile)
1893 throws GeneralSecurityException, IOException {
1894
1895 String type = "JCEKS"
1896 KeyStore keyStore = null
1897 try {
1898 keyStore = KeyStore.getInstance(type)
1899 }
1900 catch (KeyStoreException e) {
1901 throw new RuntimeException("Key store type \"" + type + "\" is not available", e)
1902 }
1903
1904 if (keyStoreFile.exists()) {
1905 InputStream input = new FileInputStream(keyStoreFile)
1906 try {
1907 keyStore.load(input, keyStorePassword.toCharArray())
1908 }
1909 finally {
1910 input.close()
1911 }
1912 }
1913 else {
1914 //new keystores are loaded with null for first arg
1915 keyStore.load(null, keyStorePassword.toCharArray())
1916 }
1917
1918 return keyStore
1919 }
1920}