1
0
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:
Christopher Fenner
2021-12-16 12:49:15 +01:00
committed by GitHub
parent f16a6beb19
commit 9180f54f86
4 changed files with 134 additions and 23 deletions

View File

@@ -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 {

View File

@@ -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
View 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
View 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")
}
}