How to Configure using STSAssumeRoleSessionCredentialsProvider in spring-cloud-stream-binder-kinesis - java

I am using spring-cloud-stream-binder-kinesis, version: 2.0.2.RELEASE.
I was able to successfully use binder and access it locally using the default ContextCredentialsAutoConfiguration mentioned in the KinesisBinderConfiguration.
Now I know this set-up wont work for me because,
The Kinesis data stream is in AWS account 1
The Service is running in AWS account 2
(I have already done the setup of assumed Role so that Account 2 can access streams in account 1 using the assumed role)
However I am not sure how can I override the credentials in binder to use STSAssumeRoleSessionCredentialsProvider
Can someone help please?

The KinesisBinderConfiguration is fully based on the auto-configuration from the Spring Cloud AWS, which provides for us a ContextCredentialsAutoConfiguration and expose an AWSCredentialsProvider bean under the credentialsProvider name if not present yet.
So, probably you just need to have your STSAssumeRoleSessionCredentialsProvider as a bean in your configuration class and give it that credentialsProvider bean name.

Related

How to have Spring boot give access to a Datasource if a certain url is accessed by a user?

We have a Spring boot application that caters to 2 different organisations. Depending on some user-info in the database, the correct datasource is returned in a class that extends AbstractRoutingDataSource. An anonymous user gets access to a limited datasource that only provides some info needed to create an account. We also have a class that extends AbstractJwtWebSecurityConfig where our HttpSecurity rules are defined.
This all works perfectly fine.
The 2 organisations also get a new ‘view’ privilege to some of their information. This is a new feature, and I am not sure how to implement this correctly.
We have an nginx server that screens incoming requests and it allows most traffic. But if the view-url of organisation 1 is accessed nginx checks the ip-address to check if it’s the ip-address of organisation 1 and they are allowed, requests from other ip-addresses are denied. The same for organisation 2 but with a different view-url. They are anonymous users and can not login.
What would be the way to have Spring boot give requests from organisation 1 access to datasource 1 and organisation 2 access to Datasource 2? We have full control of the nginx server, so we could for instance add a header to the request and I was thinking along those lines but I am stumped as to how this could be correctly done and was hoping that Spring boot has a solution for this situation.
So my question is: What would be the way to have Spring boot give access to a specific Datasource if a certain url is accessed by an anonymous user?

Alternate way of providing Credentials to Spring Cloud GCP

I am trying to use the Spring Cloud GCP. I want to know how to programmatically load GCP credentials rather than loading the GCP credentials from a json file using spring.cloud.gcp.credentials.location .
Does creating a bean of type com.google.auth.Credentials let Spring-Boot auto-configure Spring-Cloud-GCP correctly to use within the application?
If not, what is the way to inject Credentials so that Spring Cloud GCP is configured correctly?
Not Credentials, but a bean of type CredentialsProvider will take precedence over any properties/autoconfiguration.
It's a functional interface, so you can return a lambda:
#Bean
public CredentialsProvider credentialsProvider() {
return () -> NoCredentialsProvider.create().getCredentials();
}

Quarkus: Data source custom credentials provider

How can I create a custom data source credentials provider that for example reads the credentials from a file on the disk? I need a way to set the credentials from code. I guess that's the way to go in Quarkus.
quarkus.datasource.username=I want to set this in the code
quarkus.datasource.password=I want to set this in the code
I only see a hashicorp vault integration. I need a way to do this in a custom credentials provider. I can see that there is a way to set the class that represent your provider but what interface that class should implement?
From the docs:
quarkus.datasource.credentials-provider=?
quarkus.datasource.credentials-provider-type=?
The credentials provider type. It is the #Named value of the credentials provider bean. It is used to discriminate if multiple CredentialsProvider beans are available. For Vault it is: vault-credentials-provider. Not necessary if there is only one credentials provider available.
Can somebody please help with this?
this pattern is now officially supported in https://github.com/quarkusio/quarkus/pull/9032 and documented in https://github.com/quarkusio/quarkus/pull/9552
Interesting. We have designed that contract with only Vault in mind so the interface is called io.quarkus.vault.CredentialsProvider and is in the quarkus-vault-spi module.
That being said, I think you could just add that module to your project (it doesn't have any Vault dependency). Then you could just implement that interface and things should be OK.
Your CredentialsProvider needs to be a CDI bean so you should make it either #Singleton or #ApplicationScoped.
Then you would just need to define a value for quarkus.datasource.credentials-provider=<value here>. The name is passed to the crendentials provider and is used in the case of Vault.
In your case, it just needs to be defined.
If it works for you, could you open an issue in our tracker? I think we should make that interface part of the datasource extension and not Vault specific.
UPDATE: I created an example project here: https://github.com/gsmet/quarkus-credentials-provider . Just run mvn clean install (you need Docker) and you'll see your CredentialsProvider being called.
Yes, o.quarkus.vault.CredentialsProvider is meant to be HashiCorp Vault neutral.
Please see this issue for some guidance: https://github.com/quarkusio/quarkus/issues/6896#issuecomment-581014674

How can I get the Discovery Client working when using spring-cloud together with netflix Eureka?

I'm trying to make a basic project using spring cloud with the netflix addons such as Hystrix, Eureka and Ribbon to learn how this works. The project I'm trying to make is a simple message server that will keep messages. And a message-client that will just ask the server for a message, and I want to use the auto discovery client for this, or the RestTemplate discovery. But I can't get either to work.
I have the following structure:
message-client (eureka client)
message-server (eureka client)
configuration-service (config server)
discovery-service (eureka server)
What I currently do is I start up the configuration-service, and expose the application.yml details to all of these "apps/clients" when they are connecting by the following structure:
config-service\src\main\resources\config\appname.yml
app\src\main\resources\bootstrap.yml (contains the appname and url to cloud config)
This is working just fine, and my apps start up on the port they receive from the config server, as well as they all connect to my eureka server, and all of them are visible there. As well as the Hystrix failover is also working, not that it is related to this but it tells me that it can't be completely wrong then.
But here comes my confusion...
When using the #Autowired annotation in my service class (#Service annotated) inside my client module, I get a discoveryClient object, but I am unable to find any other services using that one.
Message Client - boot class:
#EnableAutoConfiguration
#EnableHystrix
#EnableEurekaClient
#ComponentScan("cloud.rest.resources, spring.cloud.client")
public class ClientBoot {
public static void main(String[] args) {
SpringApplication.run(ClientBoot.class, args);
}
}
Message Client - REST Resource:
#RestController
public class MessageResource {
#Autowired
private MessageClient messageClient;
#RequestMapping(value = "/message/{client}", method = RequestMethod.GET)
public Message getMessage(#PathVariable String client) {
return messageClient.getMessage(client);
}
}
Message Client - MessageClient:
#Service
public class RestMessageClient implements MessageClient {
#Autowired
private DiscoveryClient discoveryClient;
#Autowired
private RestTemplate restTemplate;
#Override
public Message getMessage(String client) {
return restTemplate.getForObject(String.format("http://message-server/message/%s", client), Message.class);
}
}
My message server boot class that is holding the messages has the same annotations as my client one.
And as I said, my service class are unable to find anything..
Which leads me to all of my questions:
What is required to actually use ribbon load balancer?
Do I have to use ribbon to be able to use the "auto discovery", I thought not but now I'm just confused.
From what I've understood, when using EnableEurekaClient I should not need to use the EnableDiscoveryClient as well?
Can I change the yml files on my config-server for the clients in runtime and just have to reboot the client?
How much configuration is really meant to be shared by the config-server, because currently all of my clients just contain a super basic bootstrap.yml file.
Does anyone have a good link to where I can read more about all the properties that is being set in my yml files? Both a documentation of what the properties that exists actually do as well as some documentation on how I can use them in combination with spring cloud?
Do I need specific properties to enable my apps/clients to find other apps/clients?
Edited information
Thank you for your quick and excellent reply, I've gone through this over and over today and I finally got my application working..
The problem (I can't understand why and was hoping you could help me understand that) is that my discovery service contains yml files for each of my other clients where I specify things like port and eureka information.. What I specified here as well was:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
So, when I set this value it seems to override something that makes my service discovery not working.. Even tho I can see all my applications in the eureka server, they were unable to find each other when I had this value set.
I set this value by having a message-server.yml file in my configuration service that is sent out to my message-server application after bootstrap..
So then I have two new questions.
How do I override this eureka server property?
Why does my discovery client stop working when I set this value, what is it that it actually does?
What is required to actually use ribbon load balancer?
The ribbon-loadbalancer must be on the classpath (e.g. via "spring-cloud-starter-ribbon"). Then you can inject one as a LoadBalancerClient or you can inject a RestTemplate (it will be load-balancer aware if you have a LoadBalancerClient).
Do I have to use ribbon to be able to use the "auto discovery", I thought not but now I'm just confused.
What is "auto discovery"? You don't need to use Ribbon to use the DiscoveryClient (Ribbon is a load balancer, not a service registry).
From what I've understood, when using EnableEurekaClient I should not need to use the EnableDiscoveryClient as well?
Correct. #EnableEurekaClient is annotated with #EnableDiscoveryClient so it is only there to express a preference.
Can I change the yml files on my config-server for the clients in runtime and just have to reboot the client?
Yes. Or you can use the /refresh or /restart endpoints (a full reboot is probably best in production, at least periodically).
How much configuration is really meant to be shared by the config-server, because currently all of my clients just contain a super basic bootstrap.yml file.
As much as you want. How long is a piece of string? If I were you I would try and keep the central config to a minimum (only the things that change between environments, or at runtime).
Does anyone have a good link to where I can read more about all the properties that is being set in my yml files? Both a documentation of what the properties that exists actually do as well as some documentation on how I can use them in combination with spring cloud?
Spring Boot and Spring Cloud have autogenerated metadata for externalized properties. The new generation of IDEs understands them (so get STS 3.6.4 or IDEA 14.1), and they are listed in the user guide (for Spring Boot at least) under http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties
Do I need specific properties to enable my apps/clients to find other apps/clients?
You need to be able to locate your service registry (Eureka in this case). If you are using Eureka and your clients have registered then that is enough.

Accessing CloudFoundry user-provided services using Spring Cloud connectors

I'm trying to use Spring Cloud to consume a generic REST service from a Cloud Foundry app.
This service is created using Spring Boot, as follows:
package com.something;
#RestController
public class DemoServiceController {
#RequestMapping("/sayHi")
public String sayHi() {
return "Hello!";
}
}
This works fine - I can access http://www.example.com/srv/demo/sayHi and get "Hello!" back.
Next, I created a user-provided service instance using the CF-CLI and bound it to my app. I can now see the bound service in VCAP_SERVICES.
cf cups my-demo-service -p '{"url":"http://www.example.com/srv/demo/"}'
cf bs my-demo-app my-demo-service
Next, as described here, I added this bean to my app's Spring config, with the connector-type set to my original controller (I have a reference to it as well).
<cloud:service id="myDemoService"
service-name="my-demo-service"
connector-type="com.something.DemoServiceController"
/>
Now when I auto-wire "myDemoService" into my app,
#Autowired
private DemoController myDemoService;
I get an error:
No services of the specified type could be found.
I've made sure to include all required dependencies, including spring-cloud-spring-service-connector and spring-cloud-cloudfoundry-connector.
What's going wrong here? Am I giving the wrong bean parameters? Any help is much appreciated.
Spring Cloud Connectors won't know what to do with this service, as each supported service must be of a known type (MySQL, Postgres, Redis, MongoDB, RabbitMQ, etc). Setting the connector-type to your Controller class won't do what you want.
What you will need to do is to create a custom Connectors extension. Here's an example of a project that does that: https://github.com/cf-platform-eng/spring-boot-cities.

Categories