Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Configure general Wave application settings, such as application name, port, ano
`wave.denyPaths` *(optional)*
: API path patterns to filter out. Requests for matching artifacts, such as non-existent manifests, are rejected.

`wave.inject-credentials` *(optional)*
: When `true`, Wave injects the resolved workspace registry credentials when proxying image pulls (default: `true`).
When `false`, Wave does not broker registry credentials on the proxy pull path, so images are pulled directly from the target registry using the caller's own credentials (for example an EC2 instance profile or IAM role). Build, inspect, and augmentation flows are unaffected.

`wave.server.url` *(required)*
: URL of the Wave server.
Can be set using the `${WAVE_SERVER_URL}` environment variable.
Expand Down
13 changes: 13 additions & 0 deletions src/main/groovy/io/seqera/wave/core/RegistryProxyService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import io.micronaut.cache.annotation.Cacheable
import io.micronaut.context.annotation.Context
import io.micronaut.context.annotation.Value
import io.micronaut.core.io.buffer.ByteBuffer
import io.micronaut.http.client.annotation.Client
import io.micronaut.reactor.http.client.ReactorStreamingHttpClient
Expand Down Expand Up @@ -82,6 +83,14 @@ class RegistryProxyService {
@Inject
private RegistryCredentialsProvider credentialsProvider

/**
* When 'false' Wave does not inject/broker registry credentials on the proxy pull path,
* so images are expected to be pulled directly from the target registry using the
* caller's own credentials. Build, inspect and augmentation flows are unaffected.
*/
@Value('${wave.inject-credentials:true}')
private boolean injectCredentials

/**
* Service to query credentials stored into tower
*/
Expand Down Expand Up @@ -130,6 +139,10 @@ class RegistryProxyService {
}

protected RegistryCredentials getCredentials(RoutePath route) {
if( !injectCredentials ) {
log.debug "Credentials injection disabled - skipping credentials for route path=${route.targetContainer}"
return null
}
final result = credentialsProvider.getCredentials(route, route.identity)
log.debug "Credentials for route path=${route.targetContainer}; identity=${route.identity} => ${result}"
return result
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ micronaut:
---
wave:
allowAnonymous: true
# when 'false' Wave does not inject/broker registry credentials on the proxy pull path;
# images are pulled directly from the target registry with the caller's own credentials (default: true)
inject-credentials: true
server:
url: "${WAVE_SERVER_URL:`http://localhost:9090`}"
security:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Wave, containers provisioning service
* Copyright (c) 2023-2026, 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 <https://www.gnu.org/licenses/>.
*/

package io.seqera.wave.core

import spock.lang.Specification

import io.seqera.wave.auth.RegistryCredentials
import io.seqera.wave.auth.RegistryCredentialsProvider

/**
* Verify the 'wave.inject-credentials' flag gates proxy-pull credential injection.
*
* @author Gavin Elder
*/
class RegistryProxyServiceCredentialsTest extends Specification {

def 'should not inject credentials when disabled'() {
given:
def provider = Mock(RegistryCredentialsProvider)
def service = new RegistryProxyService()
service.@credentialsProvider = provider
service.@injectCredentials = false
and:
def route = Mock(RoutePath)

when:
def result = service.getCredentials(route)

then:
0 * provider.getCredentials(_, _)
and:
result == null
}

def 'should inject credentials when enabled'() {
given:
def provider = Mock(RegistryCredentialsProvider)
def creds = Mock(RegistryCredentials)
def service = new RegistryProxyService()
service.@credentialsProvider = provider
service.@injectCredentials = true
and:
def route = Mock(RoutePath)

when:
def result = service.getCredentials(route)

then:
1 * provider.getCredentials(route, _) >> creds
and:
result == creds
}

}
Loading