You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	feat(sonar): reuse existing TLS truststore (#3312)
* do not load sap certificates with groovy * add toggle * add keytool package * copy existing default truststore * ignore import failure * fix typo * rename * extract maven opts * add todo * add tests Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							f16a6beb19
						
					
				
				
					commit
					9180f54f86
				
			| @@ -164,6 +164,7 @@ func createOrUpdateProjectSettingsXML(projectSettingsFile string, altDeploymentR | ||||
| } | ||||
|  | ||||
| func loadRemoteRepoCertificates(certificateList []string, client piperhttp.Downloader, flags *[]string, runner command.ExecRunner, fileUtils piperutils.FileUtils, javaCaCertFilePath string) error { | ||||
| 	//TODO: make use of java/keytool package | ||||
| 	existingJavaCaCerts := filepath.Join(os.Getenv("JAVA_HOME"), "jre", "lib", "security", "cacerts") | ||||
|  | ||||
| 	if len(javaCaCertFilePath) > 0 { | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import ( | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/command" | ||||
| 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	keytool "github.com/SAP/jenkins-library/pkg/java" | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/orchestrator" | ||||
| 	FileUtils "github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| @@ -364,43 +365,41 @@ func loadSonarScanner(url string, client piperhttp.Downloader) error { | ||||
| } | ||||
|  | ||||
| func loadCertificates(certificateList []string, client piperhttp.Downloader, runner command.ExecRunner) error { | ||||
| 	trustStorePath := filepath.Join(getWorkingDir(), ".certificates") | ||||
| 	trustStoreFile := filepath.Join(trustStorePath, "cacerts") | ||||
| 	truststorePath := filepath.Join(getWorkingDir(), ".certificates") | ||||
| 	truststoreFile := filepath.Join(truststorePath, "cacerts") | ||||
|  | ||||
| 	if exists, _ := fileUtilsExists(trustStoreFile); exists { | ||||
| 	if exists, _ := fileUtilsExists(truststoreFile); exists { | ||||
| 		// use local existing trust store | ||||
| 		sonar.addEnvironment("SONAR_SCANNER_OPTS=-Djavax.net.ssl.trustStore=" + trustStoreFile + " -Djavax.net.ssl.trustStorePassword=changeit") | ||||
| 		log.Entry().WithField("trust store", trustStoreFile).Info("Using local trust store") | ||||
| 		sonar.addEnvironment("SONAR_SCANNER_OPTS=" + keytool.GetMavenOpts(truststoreFile)) | ||||
| 		log.Entry().WithField("trust store", truststoreFile).Info("Using local trust store") | ||||
| 	} else if len(certificateList) > 0 { | ||||
| 		// use local created trust store with downloaded certificates | ||||
| 		keytoolOptions := []string{ | ||||
| 			"-import", | ||||
| 			"-noprompt", | ||||
| 			"-storepass", "changeit", | ||||
| 			"-keystore", trustStoreFile, | ||||
| 		} | ||||
| 		// create download temp dir | ||||
| 		tmpFolder := getTempDir() | ||||
| 		os.MkdirAll(trustStorePath, 0777) | ||||
| 		defer os.RemoveAll(tmpFolder) // clean up | ||||
|  | ||||
| 		os.MkdirAll(truststorePath, 0777) | ||||
| 		// copying existing truststore | ||||
| 		defaultTruststorePath := keytool.GetDefaultTruststorePath() | ||||
| 		if exists, _ := fileUtilsExists(defaultTruststorePath); exists { | ||||
| 			if err := keytool.ImportTruststore(runner, truststoreFile, defaultTruststorePath); err != nil { | ||||
| 				return errors.Wrap(err, "Copying existing keystore failed") | ||||
| 			} | ||||
| 		} | ||||
| 		// use local created trust store with downloaded certificates | ||||
| 		for _, certificate := range certificateList { | ||||
| 			filename := path.Base(certificate) // decode? | ||||
| 			target := filepath.Join(tmpFolder, filename) | ||||
|  | ||||
| 			target := filepath.Join(tmpFolder, path.Base(certificate)) | ||||
| 			log.Entry().WithField("source", certificate).WithField("target", target).Info("Downloading TLS certificate") | ||||
| 			// download certificate | ||||
| 			if err := client.DownloadFile(certificate, target, nil, nil); err != nil { | ||||
| 				return errors.Wrapf(err, "Download of TLS certificate failed") | ||||
| 			} | ||||
| 			options := append(keytoolOptions, "-file", target) | ||||
| 			options = append(options, "-alias", filename) | ||||
| 			// add certificate to keystore | ||||
| 			if err := runner.RunExecutable("keytool", options...); err != nil { | ||||
| 				return errors.Wrap(err, "Adding certificate to keystore failed") | ||||
| 			if err := keytool.ImportCert(runner, truststoreFile, target); err != nil { | ||||
| 				log.Entry().Warnf("Adding certificate to keystore failed") | ||||
| 				// return errors.Wrap(err, "Adding certificate to keystore failed") | ||||
| 			} | ||||
| 		} | ||||
| 		sonar.addEnvironment("SONAR_SCANNER_OPTS=-Djavax.net.ssl.trustStore=" + trustStoreFile + " -Djavax.net.ssl.trustStorePassword=changeit") | ||||
| 		log.Entry().WithField("trust store", trustStoreFile).Info("Using local trust store") | ||||
| 		sonar.addEnvironment("SONAR_SCANNER_OPTS=" + keytool.GetMavenOpts(truststoreFile)) | ||||
| 		log.Entry().WithField("trust store", truststoreFile).Info("Using local trust store") | ||||
| 	} else { | ||||
| 		log.Entry().Debug("Download of TLS certificates skipped") | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										46
									
								
								pkg/java/keytool.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								pkg/java/keytool.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| package java | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/command" | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| ) | ||||
|  | ||||
| const defaultTruststorePath = "lib/security/cacerts" | ||||
| const DefaultTruststorePassword = "changeit" | ||||
|  | ||||
| func GetDefaultTruststorePath() string { | ||||
| 	return filepath.Join(os.Getenv("JAVA_HOME"), filepath.FromSlash(defaultTruststorePath)) | ||||
| } | ||||
|  | ||||
| func GetMavenOpts(truststoreFile string) string { | ||||
| 	return "-Djavax.net.ssl.trustStore=" + truststoreFile + " -Djavax.net.ssl.trustStorePassword=" + DefaultTruststorePassword | ||||
| } | ||||
|  | ||||
| func ImportCert(runner command.ExecRunner, destTruststore, certfile string) error { | ||||
| 	options := []string{ | ||||
| 		"-import", | ||||
| 		"-noprompt", | ||||
| 		"-storepass", DefaultTruststorePassword, | ||||
| 		"-keystore", destTruststore, | ||||
| 		"-file", certfile, | ||||
| 		"-alias", filepath.Base(certfile), | ||||
| 	} | ||||
| 	log.Entry().Infof("Importing certificate: %s", certfile) | ||||
| 	return runner.RunExecutable("keytool", options...) | ||||
| } | ||||
|  | ||||
| func ImportTruststore(runner command.ExecRunner, destTruststore, srcTruststore string) error { | ||||
| 	options := []string{ | ||||
| 		"-importkeystore", | ||||
| 		"-noprompt", | ||||
| 		"-srckeystore", srcTruststore, | ||||
| 		"-srcstorepass", DefaultTruststorePassword, | ||||
| 		"-destkeystore", destTruststore, | ||||
| 		"-deststorepass", DefaultTruststorePassword, | ||||
| 	} | ||||
| 	log.Entry().Debugf("Copying existing trust store: %s", srcTruststore) | ||||
| 	return runner.RunExecutable("keytool", options...) | ||||
| } | ||||
							
								
								
									
										65
									
								
								pkg/java/keytool_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								pkg/java/keytool_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| package java | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	piperMock "github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/mock" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| func TestGetDefaultTruststorePath(t *testing.T) { | ||||
| 	// prepare | ||||
| 	os.Setenv("JAVA_HOME", mock.Anything) | ||||
| 	require.Equal(t, mock.Anything, os.Getenv("JAVA_HOME")) | ||||
| 	// test | ||||
| 	result := GetDefaultTruststorePath() | ||||
| 	// assert | ||||
| 	assert.Equal(t, "lib/security/cacerts", defaultTruststorePath) | ||||
| 	assert.Equal(t, filepath.Join(mock.Anything, defaultTruststorePath), result) | ||||
| 	// restore | ||||
| 	os.Unsetenv("JAVA_HOME") | ||||
| } | ||||
|  | ||||
| func TestGetMavenOpts(t *testing.T) { | ||||
| 	// test | ||||
| 	result := GetMavenOpts(mock.Anything) | ||||
| 	// assert | ||||
| 	assert.Equal(t, "changeit", DefaultTruststorePassword) | ||||
| 	assert.Equal(t, "-Djavax.net.ssl.trustStore="+mock.Anything+" -Djavax.net.ssl.trustStorePassword="+DefaultTruststorePassword, result) | ||||
| } | ||||
|  | ||||
| func TestImportCert(t *testing.T) { | ||||
| 	// prepare | ||||
| 	secretstorePath := filepath.Join(mock.Anything, mock.Anything) | ||||
| 	mockRunner := &piperMock.ExecMockRunner{} | ||||
| 	// test | ||||
| 	err := ImportCert(mockRunner, mock.Anything, secretstorePath) | ||||
| 	// assert | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Len(t, mockRunner.Calls, 1) | ||||
| 	for _, call := range mockRunner.Calls { | ||||
| 		assert.Equal(t, "keytool", call.Exec) | ||||
| 		assert.Equal(t, strings.Join(call.Params, " "), "-import -noprompt -storepass changeit -keystore mock.Anything -file "+secretstorePath+" -alias mock.Anything") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestImportTruststore(t *testing.T) { | ||||
| 	// prepare | ||||
| 	srcSecretstorePath := filepath.Join(mock.Anything, mock.Anything) | ||||
| 	destSecretstorePath := filepath.Join(mock.Anything, mock.Anything) | ||||
| 	mockRunner := &piperMock.ExecMockRunner{} | ||||
| 	// test | ||||
| 	err := ImportTruststore(mockRunner, destSecretstorePath, srcSecretstorePath) | ||||
| 	// assert | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Len(t, mockRunner.Calls, 1) | ||||
| 	for _, call := range mockRunner.Calls { | ||||
| 		assert.Equal(t, "keytool", call.Exec) | ||||
| 		assert.Equal(t, strings.Join(call.Params, " "), "-importkeystore -noprompt -srckeystore "+srcSecretstorePath+" -srcstorepass changeit -destkeystore "+destSecretstorePath+" -deststorepass changeit") | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user