Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shell: Can not connect to SCDF running behind oauth proxy #5701

Open
jnt0r opened this issue Feb 22, 2024 · 7 comments
Open

Shell: Can not connect to SCDF running behind oauth proxy #5701

jnt0r opened this issue Feb 22, 2024 · 7 comments
Assignees
Labels
status/need-triage Team needs to triage and take a first look

Comments

@jnt0r
Copy link

jnt0r commented Feb 22, 2024

Description:
My SCDF instance is running behind an oauth-proxy in kubernetes. When trying to connect using the spring cloud dataflow shell I get an 403 Forbidden. I tried the flag --dataflow.credentials-p
rovider-command= but it seems to not be used in the early requests and only for command calls.

All calls to the instance first go through the oauth proxy and are then passed to the instance. Therefore no request is successfull without a valid bearer token. It seems like there are some requests when starting up that do not contain the Authorization header.

When calling my instance with curl I pass an Authorization Header with the Bearer Token. Is this possible in the Shell too?

403 Forbidden: [no body] org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden: [no body] at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:109) at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:168) at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122) at org.springframework.cloud.dataflow.rest.client.VndErrorResponseErrorHandler.handleError(VndErrorResponseErrorHandler.java:62) at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:825) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:783) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717) at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:340) at org.springframework.cloud.dataflow.shell.command.ConfigCommands.target(ConfigCommands.java:183) at org.springframework.cloud.dataflow.shell.command.ConfigCommands.triggerTarget(ConfigCommands.java:253) at org.springframework.cloud.dataflow.shell.config.InitializeConnectionApplicationRunner.run(InitializeConnectionApplicationRunner.java:73) at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:756) at org.springframework.boot.SpringApplication.lambda$callRunners$2(SpringApplication.java:746) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:744) at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) at org.springframework.cloud.dataflow.shell.ShellApplication.main(ShellApplication.java:35) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)

Release versions:
spring-cloud-dataflow-shell-2.11.2.jar

@github-actions github-actions bot added the status/need-triage Team needs to triage and take a first look label Feb 22, 2024
@corneil
Copy link
Contributor

corneil commented Feb 23, 2024

@jnt0r What IdP do you have configured and how is the Data Flow security configured?

@jnt0r
Copy link
Author

jnt0r commented Feb 23, 2024

There is no security configuration in my SCDF instance. The oauth-proxy is running as a sidecar in kubernetes and all traffic is routed through the proxy. The SCDF instance itself does not do any security related stuff.

@jnt0r
Copy link
Author

jnt0r commented Feb 23, 2024

I configured the credentials-provider-command to return a valid Bearer Token for the oauth-proxy. It seems that the token returned from this command are not passed to every command.

For example this requests, where my shell is failing:

final SecurityInfoResource securityInfoResourceBeforeLogin = restTemplate
.getForObject(uri + "/security/info", SecurityInfoResource.class);

@jnt0r
Copy link
Author

jnt0r commented Feb 24, 2024

The return value of the credentials-provider-command is set in line 202 after the first request is already made.

if (StringUtils.hasText(credentialsProviderCommand) && authenticationEnabled) {
this.targetHolder.getTarget().setTargetCredentials(new TargetCredentials(true));
final CheckableResource credentialsResource = new ProcessOutputResource(credentialsProviderCommand.split("\\s+"));
httpClientConfigurer.addInterceptor(new ResourceBasedAuthorizationInterceptor(credentialsResource));
}

@jnt0r
Copy link
Author

jnt0r commented Feb 29, 2024

@corneil what do you think about this? I think it should be possible to fully secure SCDF with a proxy and still use the Shell for administration. This one request at startup makes this impossible. Event though all tokens etc. are available

@jnt0r
Copy link
Author

jnt0r commented Apr 1, 2024

I see that the request to "/security/info" is done twice. Once before and one after setting the interceptor to the restTemplate.

@corneil
Copy link
Contributor

corneil commented Apr 4, 2024

@jnt0r The output of a CLI command can be used to provide a token to the shell. The problem is that without an SCDF configuration all decisions need to be made by your oauth proxy. So obtaining the token and using it in the shell becomes an 'undefined operation'. This feature was originally designed to work with CloudFoundry and UAA. It doesn't seem to satisfy the ProcessOutputResource.
Which IdP is your oauth proxy interacting with?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/need-triage Team needs to triage and take a first look
Projects
None yet
Development

No branches or pull requests

2 participants