GithubHelp home page GithubHelp logo

Comments (22)

kvmw avatar kvmw commented on June 26, 2024 1

@cobar79 I don't have admin access to the repo. You need to fork the repo and submit the PR from your fork.

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

The commercial offer of Spring Cloud, Spring Cloud Services, uses OAuth2 to authorize the client to use the config server.
You can find the code for how they do that here
spring-cloud-services-config-client-autoconfigure/src/main/java/io/pivotal/spring/cloud/config/client

I suppose you could do something similar.

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

spring-cloud-services-starters looks to be a heavy port.

I was looking for a 3-5 story point way of overwriting the current RestTemplate logic.

Unfortunately, attempts of old school filter/interceptors did not work as the call was made before the filter/interceptors where instantiated. I guess I will look at extending the existing framework to override the basic authorization.

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

@ryanjbaxter Should I just close this? It was meant as a feature request. However, it doesn't look it is being considered.

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

I am not saying you need to port exactly what spring-cloud-services did I am just showing that it is possible to authorize the client before the request to the server is made, specifically I think this class is where that is done.

https://github.com/pivotal-cf/spring-cloud-services-starters/blob/29b7961ec57ec918110b669fb2409d55aacc8974/spring-cloud-services-config-client-autoconfigure/src/main/java/io/pivotal/spring/cloud/config/client/ConfigResourceClientAutoConfiguration.java#L39

@kvmw am I correct?

from spring-cloud-config.

kvmw avatar kvmw commented on June 26, 2024

@ryanjbaxter @cobar79 ,
You need to configure the RestTemplate in 2 different places :

  1. Firstly, you need a BootstrapRegistryInitializer. Since the call to config-server is done during the application startup you need to configure the RestTemplate before startup, during the bootstrapping using a BootstrapRegistryInitializer. check ConfigClientOAuth2BootstrapRegistryInitializer in SCS Starters, for example. This has been mentioned in the Spring Cloud Config Docs too.

  2. Also, if your client application consumes plain text or binary resources, you need to configure a ConfigResouceClient as well. check ConfigResourceClientAutoConfiguration in SCS Starters, for example. You can ignore this configuration if you don't need to consume such resources.

The ConfigResourceClientAutoConfiguration which was mentioned above by @ryanjbaxter, is for the client applications with legacy processing enabled. This is the alternative for BootstrapRegistryInitializer and you can ignore it if your application is developed recently and does not need legacy processing.

@ryanjbaxter ,
It would be nice if ConfigServerConfigDataLoader in Spring Cloud Config Client would provide an easier way to inject the RestTemplate. I don't know if alternative approach is even possible but the current one (using BootstrapRegistryInitializer) is not the most straightforward and intuitive one.

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

I am not sure there would be an easier way because we are so early in the startup of the Boot application at the point we are loading configuration.

from spring-cloud-config.

spring-cloud-issues avatar spring-cloud-issues commented on June 26, 2024

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

@ryanjbaxter @kvmw

Great discussion. However, this was just meant to be a feature request. As a Spring Developer, I have a requirement to lock down the config server, thus making it an OAuth2 resource server. Therefore, this requires the config server clients to authenticate with a Bearer token from the IDP. I would think this would be very common occurrence in the Spring Community?

As a proof of concept I cloned this project and with small changes to ConfigClientRequestTemplateFactory and ConfigClientProperties I was able to obtain a Bearer token from IDP and append it to the config server endpoint call.

We are investigating the commercial Cloud-Services-for-VMware-Tanzu product cost and portability to AWS. However, it would be more convenient and easier to maintain the additional feature to this project than it will be to implement the commercial version.

from spring-cloud-config.

kvmw avatar kvmw commented on June 26, 2024

@cobar79
As I mentioned above the call to Config Server happens during bootstrap before any of those beans you mentioned above are even initialised. So changing those beans doesn't help.

Have a look at this code once again:
https://github.com/spring-cloud/spring-cloud-config/blob/main/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java#L262

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

@kvmw
Again, just proof of concept but it works:

The method below creates a Rest Template. I simply detect an OAuth2 property and use the Rest Template to get the Token from IDP and add it to the headers map which is added to the GenericRequestHeaderInterceptor. Later when the Config Server call is made, it uses the GenericRequestHeaderInterceptor adds the Bearer Token header in included in the call.

ConfigClientRequestTemplateFactory.create

                String tokenUri = properties.getTokenUri();
		if (tokenUri != null) {
			String token = getOAuthToken(template, tokenUri);
			headers.put(AUTHORIZATION, "Bearer " + token);
			properties.setHeaders(headers);
		}

injected just before adding the inteceptor

		if (!headers.isEmpty()) {
			template.setInterceptors(Arrays.asList(new GenericRequestHeaderInterceptor(headers)));
		}

from spring-cloud-config.

kvmw avatar kvmw commented on June 26, 2024

@cobar79
I see what you mean now. I was thinking your poc work is in your code rather than spring-cloud-config code.
I think that would work but not sure if the spring-config team would want that.

@ryanjbaxter
would you consider a pull-request to support this requirement?

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

Absolutely!

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

Thanks @ryanjbaxter
I will look over the guidelines and supporting documentation. I may need guidance moving from POC to PR since this will be my first open source contribution. Here are some areas or questions I have.

  1. I replicated the spring.security.oauth2.client properties to fit into the spring.cloud.config properties. I wasn't crazy about duplicating the properties but given the impact of loading multiple properties and complexity of OAuth2 properties I think I would stick with updating ConfigClientProperties with OAuth2 properties. Even the commercial version flattened the OAuth2 properties into a single client registration.
spring:
  cloud:
    config:
        token-uri: ${oauth.scheme}://localhost:${env.idp.port}/realms/${oauth.realm}/protocol/openid-connect/token
        client-id:

I was planning on leaving the basic authentication properties as is and using username/password for both oauth2 and basic authentication. Thoughts?

spring:
  cloud:
    config:
      username:
      password:
      token:
  1. Client/User credential encryption: Most cyber teams won't allow plain text credentials in property files. That leaves environment/system properties or encrypting the credentials. I assume the Spring team would just want to go with environment/system properties for this? In the POC, I actually incorporated a Jayspt SimplePBEStringEncryptor. I passed in the algorithm and iterations via the properties and set the encryption password as an environment variable.
spring:
  cloud:
    config:
      token-uri: 
      client-id: ENC(blablabla)
      client-secret: ENC(yaddaYaddaYadda)
      username: ENC()
      password: ENC()
      encryptor-algorithm: PBEWITHHMACSHA512ANDAES_256
      encryptor-iterations: 1000
		<dependency>
			<groupId>com.github.ulisesbocchio</groupId>
			<artifactId>jasypt-spring-boot</artifactId>
			<version>3.0.5</version>
		</dependency>

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

We love first time contributors ❤️

  1. That sounds fine to me

  2. We have the ability to encrypt and decrypt properties as part of Spring Cloud Config. Have you looked into leveraging that functionality?

https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#_encryption_and_decryption

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

Thanks Ryan.

I have it mostly stubbed out with JCE. I am having issues with JCE cypher properties in the Config Client application. I can't seem to find any documentation on using JCE in a normal Boot application. Do you happen to know where I can find documentation?

Removed old Jasypt encryption and attempted to try simple Symmetric encryption first.

    Property: spring.cloud.config.client-secret
    Value: "{cipher}cdac3c554d3f6fbdc6f2f553a7b3b3e1b64b1fbb3b1c8fa5b2766be4dafc0b6a6ca38e13442787f5b779dbbd3634001f7a89d030ad8f0363c61a7719d425ef21"
    Origin: URL [file:config/application-local.yml] - 78:22
    Reason: java.lang.UnsupportedOperationException: No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?

This seems to say you can't do Symmetric Encryption, but thought I would ask.

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

@ryanjbaxter
Ready for PR. How do I obtain access to push feature branch and create PR?

I went with Jasypt encryption since I couldn't find supporting documentation of JCE support for the client boot application. See comment above.

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

@kvmw
Can you help me with getting access to push my branch and create a PR?

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

You can configure encryption using symetric or asymmetric encryption
https://docs.spring.io/spring-cloud-config/docs/4.0.4/reference/html/#_key_management

Ultimately that shouldn't really matter I believe since the user will configure encryption however they want to encrypt the secret right?

As far as the PR goes, fork the repo, create a branch from the 4.0.x branch, then push that branch to your forked repo and create a PR from that branch against the 4.0.x branch in this repo on GitHub.

from spring-cloud-config.

cobar79 avatar cobar79 commented on June 26, 2024

@ryanjbaxter
Since the config server logic is way before spring boot sequence, there is no encryption bean created yet. So the properties loaded in the ConfigClientProperties were encrypted.

I can try the JCE again, but I had issues with the cipher in the properties. It failed with the cipher unquoted for yaml syntax and failed for "No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?" when quoted.

I went with Jayspt since it is the most common practice for encrypting properties in Spring applications.

PR

from spring-cloud-config.

DasAmpharos avatar DasAmpharos commented on June 26, 2024

@ryanjbaxter do you have any idea on the timeline for this feature? My team is really interested in this feature and we are trying to determine if we should wait for official support or implement a custom solution.

from spring-cloud-config.

ryanjbaxter avatar ryanjbaxter commented on June 26, 2024

It won't be for a while since we need to wait for a major release of Spring Cloud where we can introduce major changes like this.

from spring-cloud-config.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.