Skip to content

Commit 95353a3

Browse files
gavinelderclaude
andcommitted
feat: add global wave.inject-credentials flag for proxy-pull credential injection
Introduce an installation-level flag 'wave.inject-credentials' (default true). When false, RegistryProxyService no longer injects/brokers registry credentials on the proxy-pull path (getCredentials returns null), so images are pulled directly from the target registry with the caller's own credentials. Build, inspect and augmentation credential resolution are unaffected. Default behaviour is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 307b932 commit 95353a3

3 files changed

Lines changed: 86 additions & 0 deletions

File tree

src/main/groovy/io/seqera/wave/core/RegistryProxyService.groovy

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import groovy.transform.CompileStatic
2828
import groovy.util.logging.Slf4j
2929
import io.micronaut.cache.annotation.Cacheable
3030
import io.micronaut.context.annotation.Context
31+
import io.micronaut.context.annotation.Value
3132
import io.micronaut.core.io.buffer.ByteBuffer
3233
import io.micronaut.http.client.annotation.Client
3334
import io.micronaut.reactor.http.client.ReactorStreamingHttpClient
@@ -82,6 +83,14 @@ class RegistryProxyService {
8283
@Inject
8384
private RegistryCredentialsProvider credentialsProvider
8485

86+
/**
87+
* When 'false' Wave does not inject/broker registry credentials on the proxy pull path,
88+
* so images are expected to be pulled directly from the target registry using the
89+
* caller's own credentials. Build, inspect and augmentation flows are unaffected.
90+
*/
91+
@Value('${wave.inject-credentials:true}')
92+
private boolean injectCredentials
93+
8594
/**
8695
* Service to query credentials stored into tower
8796
*/
@@ -130,6 +139,10 @@ class RegistryProxyService {
130139
}
131140

132141
protected RegistryCredentials getCredentials(RoutePath route) {
142+
if( !injectCredentials ) {
143+
log.debug "Credentials injection disabled - skipping credentials for route path=${route.targetContainer}"
144+
return null
145+
}
133146
final result = credentialsProvider.getCredentials(route, route.identity)
134147
log.debug "Credentials for route path=${route.targetContainer}; identity=${route.identity} => ${result}"
135148
return result

src/main/resources/application.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ micronaut:
5656
---
5757
wave:
5858
allowAnonymous: true
59+
# when 'false' Wave does not inject/broker registry credentials on the proxy pull path;
60+
# images are pulled directly from the target registry with the caller's own credentials (default: true)
61+
inject-credentials: true
5962
server:
6063
url: "${WAVE_SERVER_URL:`http://localhost:9090`}"
6164
security:
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Wave, containers provisioning service
3+
* Copyright (c) 2023-2024, Seqera Labs
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
package io.seqera.wave.core
20+
21+
import spock.lang.Specification
22+
23+
import io.seqera.wave.auth.RegistryCredentials
24+
import io.seqera.wave.auth.RegistryCredentialsProvider
25+
26+
/**
27+
* Verify the 'wave.inject-credentials' flag gates proxy-pull credential injection.
28+
*
29+
* @author Gavin Elder
30+
*/
31+
class RegistryProxyServiceCredentialsTest extends Specification {
32+
33+
def 'should not inject credentials when disabled'() {
34+
given:
35+
def provider = Mock(RegistryCredentialsProvider)
36+
def service = new RegistryProxyService()
37+
service.@credentialsProvider = provider
38+
service.@injectCredentials = false
39+
and:
40+
def route = Mock(RoutePath)
41+
42+
when:
43+
def result = service.getCredentials(route)
44+
45+
then:
46+
0 * provider.getCredentials(_, _)
47+
and:
48+
result == null
49+
}
50+
51+
def 'should inject credentials when enabled'() {
52+
given:
53+
def provider = Mock(RegistryCredentialsProvider)
54+
def creds = Mock(RegistryCredentials)
55+
def service = new RegistryProxyService()
56+
service.@credentialsProvider = provider
57+
service.@injectCredentials = true
58+
and:
59+
def route = Mock(RoutePath)
60+
61+
when:
62+
def result = service.getCredentials(route)
63+
64+
then:
65+
1 * provider.getCredentials(route, _) >> creds
66+
and:
67+
result == creds
68+
}
69+
70+
}

0 commit comments

Comments
 (0)