From 0f6003063507e196158ec06ccbf9892feac4ee0d Mon Sep 17 00:00:00 2001 From: Paolo Di Tommaso Date: Fri, 25 Oct 2024 17:39:36 +0200 Subject: [PATCH] Add ability to configure trivy dbs (#720) Signed-off-by: Paolo Di Tommaso --- .../wave/configuration/ScanConfig.groovy | 27 ++++++++---- .../wave/service/k8s/K8sServiceImpl.groovy | 7 +++- .../service/scan/DockerScanStrategy.groovy | 12 +++--- src/main/resources/application-dev.yml | 1 - src/main/resources/application.yml | 6 ++- .../wave/configuration/ScanConfigTest.groovy | 41 +++++++++++++++++++ .../service/k8s/K8sServiceImplTest.groovy | 2 +- .../scan/DockerScanStrategyTest.groovy | 6 ++- 8 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 src/test/groovy/io/seqera/wave/configuration/ScanConfigTest.groovy diff --git a/src/main/groovy/io/seqera/wave/configuration/ScanConfig.groovy b/src/main/groovy/io/seqera/wave/configuration/ScanConfig.groovy index a0f833f27..1223d137e 100644 --- a/src/main/groovy/io/seqera/wave/configuration/ScanConfig.groovy +++ b/src/main/groovy/io/seqera/wave/configuration/ScanConfig.groovy @@ -21,16 +21,14 @@ package io.seqera.wave.configuration import java.nio.file.Files import java.nio.file.Path import java.time.Duration - -import io.micronaut.context.annotation.Requires -import io.micronaut.core.annotation.Nullable import javax.annotation.PostConstruct import groovy.transform.CompileStatic import groovy.transform.Memoized import groovy.util.logging.Slf4j +import io.micronaut.context.annotation.Requires import io.micronaut.context.annotation.Value -import io.seqera.wave.util.StringUtils +import io.micronaut.core.annotation.Nullable import jakarta.inject.Singleton /** * Container Scan service settings @@ -83,8 +81,8 @@ class ScanConfig { Duration scanIdDuration @Nullable - @Value('${wave.scan.github-token}') - String githubToken + @Value('${wave.scan.environment}') + List environment String getScanImage() { return scanImage @@ -118,8 +116,23 @@ class ScanConfig { return severity } + List> getEnvironmentAsTuples() { + if( !environment ) + return List.of() + final result = new ArrayList>() + for( String entry : environment ) { + final p=entry.indexOf('=') + final name = p!=-1 ? entry.substring(0,p) : entry + final value = p!=-1 ? entry.substring(p+1) : '' + if( !value ) + log.warn "Invalid 'wave.scan.environment value' -- offending entry: '$entry'" + result.add(new Tuple2(name,value)) + } + return result + } + @PostConstruct private void init() { - log.info("Scanner config: docker image name: ${scanImage}; cache directory: ${cacheDirectory}; timeout=${timeout}; cpus: ${requestsCpu}; mem: ${requestsMemory}; severity: $severity; retry-attempts: $retryAttempts; github-token=${StringUtils.redact(githubToken)}") + log.info("Scan config: docker image name: ${scanImage}; cache directory: ${cacheDirectory}; timeout=${timeout}; cpus: ${requestsCpu}; mem: ${requestsMemory}; severity: $severity; retry-attempts: $retryAttempts; env=${environment}") } } diff --git a/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy b/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy index ac46c912d..48cecbc30 100644 --- a/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy +++ b/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy @@ -784,8 +784,11 @@ class K8sServiceImpl implements K8sService { .withVolumeMounts(mounts) .withResources(requests) - if( scanConfig.githubToken ) { - container.withEnv(new V1EnvVar().name('GITHUB_TOKEN').value(scanConfig.githubToken)) + final env = scanConfig.environmentAsTuples + for( Tuple2 entry : env ) { + final String k = entry.v1 + final String v = entry.v2 + container.withEnv(new V1EnvVar().name(k).value(v)) } // spec section diff --git a/src/main/groovy/io/seqera/wave/service/scan/DockerScanStrategy.groovy b/src/main/groovy/io/seqera/wave/service/scan/DockerScanStrategy.groovy index 430b7ed1d..084e36ec8 100644 --- a/src/main/groovy/io/seqera/wave/service/scan/DockerScanStrategy.groovy +++ b/src/main/groovy/io/seqera/wave/service/scan/DockerScanStrategy.groovy @@ -73,7 +73,7 @@ class DockerScanStrategy extends ScanStrategy { // outfile file name final reportFile = req.workDir.resolve(Trivy.OUTPUT_FILE_NAME) // create the launch command - final dockerCommand = dockerWrapper(jobName, req.workDir, configFile, scanConfig.githubToken) + final dockerCommand = dockerWrapper(jobName, req.workDir, configFile, scanConfig.environment) final trivyCommand = List.of(scanConfig.scanImage) + scanCommand(req.targetImage, reportFile, req.platform, scanConfig) final command = dockerCommand + trivyCommand @@ -89,7 +89,7 @@ class DockerScanStrategy extends ScanStrategy { } } - protected List dockerWrapper(String jobName, Path scanDir, Path credsFile, String githubToken) { + protected List dockerWrapper(String jobName, Path scanDir, Path credsFile, List env) { final wrapper = ['docker','run'] wrapper.add('--detach') @@ -112,9 +112,11 @@ class DockerScanStrategy extends ScanStrategy { wrapper.add("${credsFile}:${Trivy.CONFIG_MOUNT_PATH}:ro".toString()) } - if( githubToken ) { - wrapper.add('-e') - wrapper.add("GITHUB_TOKEN="+githubToken) + if( env ) { + for( String it : env ) { + wrapper.add('-e') + wrapper.add(it) + } } return wrapper diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 7f15e570a..4481f847d 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -4,7 +4,6 @@ wave: enabled: true failure: duration: '30s' - github-token: "${GITHUB_TOKEN:}" build: workspace: 'build-workspace' metrics: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 38d685608..bd030f589 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -84,7 +84,11 @@ wave: multiplier: '1.75' scan: image: - name: aquasec/trivy:0.55.0 + name: aquasec/trivy:0.56.2 + environment: + # see https://github.com/aquasecurity/trivy/discussions/7668#discussioncomment-11028887 + - "TRIVY_DB_REPOSITORY=public.ecr.aws/aquasecurity/trivy-db" + - "TRIVY_JAVA_DB_REPOSITORY=public.ecr.aws/aquasecurity/trivy-java-db" blobCache: s5cmdImage: public.cr.seqera.io/wave/s5cmd:v2.2.2 --- diff --git a/src/test/groovy/io/seqera/wave/configuration/ScanConfigTest.groovy b/src/test/groovy/io/seqera/wave/configuration/ScanConfigTest.groovy new file mode 100644 index 000000000..c1447b452 --- /dev/null +++ b/src/test/groovy/io/seqera/wave/configuration/ScanConfigTest.groovy @@ -0,0 +1,41 @@ +/* + * Wave, containers provisioning service + * Copyright (c) 2023-2024, Seqera Labs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.seqera.wave.configuration + +import spock.lang.Specification + +/** + * + * @author Paolo Di Tommaso + */ +class ScanConfigTest extends Specification { + + def 'should convert env to tuples' () { + given: + def config1 = new ScanConfig() + def config2 = new ScanConfig(environment: ['FOO=one','BAR=two']) + def config3 = new ScanConfig(environment: ['FOO','BAR=']) + + expect: + config1.environmentAsTuples == [] + config2.environmentAsTuples == [new Tuple2('FOO','one'), new Tuple2('BAR','two')] + config3.environmentAsTuples == [new Tuple2('FOO',''), new Tuple2('BAR','')] + + } +} diff --git a/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy b/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy index 03d136e19..4ebdd7c34 100644 --- a/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy +++ b/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy @@ -748,7 +748,7 @@ class K8sServiceImplTest extends Specification { getCacheDirectory() >> Path.of('/build/cache/dir') getRequestsCpu() >> '2' getRequestsMemory() >> '4Gi' - getGithubToken() >> '123abc' + getEnvironmentAsTuples() >> [new Tuple2('GITHUB_TOKEN', '123abc')] } when: diff --git a/src/test/groovy/io/seqera/wave/service/scan/DockerScanStrategyTest.groovy b/src/test/groovy/io/seqera/wave/service/scan/DockerScanStrategyTest.groovy index f490e0aa1..5e9c898e5 100644 --- a/src/test/groovy/io/seqera/wave/service/scan/DockerScanStrategyTest.groovy +++ b/src/test/groovy/io/seqera/wave/service/scan/DockerScanStrategyTest.groovy @@ -42,7 +42,7 @@ class DockerScanStrategyTest extends Specification { when: def scanDir = Path.of('/some/scan/dir') def config = Path.of("/user/test/build-workspace/config.json") - def command = dockerContainerStrategy.dockerWrapper('foo-123', scanDir, config, 'xyz') + def command = dockerContainerStrategy.dockerWrapper('foo-123', scanDir, config, ['FOO=1', 'BAR=2']) then: command == [ @@ -60,7 +60,9 @@ class DockerScanStrategyTest extends Specification { '-v', '/user/test/build-workspace/config.json:/root/.docker/config.json:ro', '-e', - 'GITHUB_TOKEN=xyz' + 'FOO=1', + '-e', + 'BAR=2' ] cleanup: