diff --git a/docs/src/main/asciidoc/s3.adoc b/docs/src/main/asciidoc/s3.adoc
index 6a9fc318a..9391dff14 100644
--- a/docs/src/main/asciidoc/s3.adoc
+++ b/docs/src/main/asciidoc/s3.adoc
@@ -604,17 +604,51 @@ The Spring Boot Starter for S3 provides the following configuration options:
| `spring.cloud.aws.s3.config.reload.max-wait-time-for-restart` | `Duration`| `2s` | The maximum time between the detection of changes in property source and the application context restart when `restart_context` strategy is used.
|===
+=== S3 Vector Client support
+
+https://aws.amazon.com/blogs/aws/introducing-amazon-s3-vectors-first-cloud-storage-with-native-vector-support-at-scale/[S3 Vector Store] is a vector storage which supports uploading, storing and querying vectors.
+To allow users simpler use of `S3VectorsClient` with https://github.com/spring-projects/spring-ai[Spring AI] project or use of a plain client, we support autoconfiguration of the `S3VectorsClient`.
+
+To enable autoconfiguration you should add the following dependencies
+[source,xml]
+----
+
+ io.awspring.cloud
+ spring-cloud-aws-starter
+
+
+
+ software.amazon.awssdk
+ s3vectors
+
+----
+
+After dependencies are introduced Spring Cloud AWS will automatically create a `S3VectorsClient` bean which can than be autowired and used.
+
+[cols="2,3,1,1"]
+|===
+| Name | Description | Required | Default value
+| `spring.cloud.aws.s3.vector.config.enabled` | Enables the S3 config import integration. | No | `true`
+| `spring.cloud.aws.s3.config.reload.strategy` | `Enum` | `refresh` | The strategy to use when firing a reload (`refresh`, `restart_context`)
+| `spring.cloud.aws.s3.config.reload.period` | `Duration`| `15s` | The period for verifying changes
+| `spring.cloud.aws.s3.config.reload.max-wait-time-for-restart` | `Duration`| `2s` | The maximum time between the detection of changes in property source and the application context restart when `restart_context` strategy is used.
+|===
=== IAM Permissions
Following IAM permissions are required by Spring Cloud AWS:
-[cols="2,1"]
-|===
-| Downloading files | `s3:GetObject`
-| Searching files | `s3:ListObjects`
-| Uploading files | `s3:PutObject`
+[cols="2,3,1,1"]
|===
+| Name | Description | Required | Default value
+| `spring.cloud.aws.s3.vector.enabled` | Enables the S3VectorsClient autoconfiguration. | No | `true`
+| `spring.cloud.aws.s3.vector.endpoint` | Configures endpoint used by `S3VectorsClient`. | No | `http://localhost:4566`
+| `spring.cloud.aws.s3.vector.region` | Configures region used by `S3VectorsClient`. | No | `eu-west-1`
+
+
+
+
+=== Example of IAM policy for Spring Cloud AWS demo bucket
Sample IAM policy granting access to `spring-cloud-aws-demo` bucket:
diff --git a/spring-cloud-aws-autoconfigure/pom.xml b/spring-cloud-aws-autoconfigure/pom.xml
index 81dfca2b2..d0180b1f3 100644
--- a/spring-cloud-aws-autoconfigure/pom.xml
+++ b/spring-cloud-aws-autoconfigure/pom.xml
@@ -176,6 +176,12 @@
amazon-s3-encryption-client-java
true
+
+
+ software.amazon.awssdk
+ s3vectors
+ true
+
io.micrometer
micrometer-observation-test
diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java
new file mode 100644
index 000000000..035de8f98
--- /dev/null
+++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java
@@ -0,0 +1,51 @@
+package io.awspring.cloud.autoconfigure.s3;
+
+import io.awspring.cloud.autoconfigure.AwsSyncClientCustomizer;
+import io.awspring.cloud.autoconfigure.core.*;
+import io.awspring.cloud.autoconfigure.s3.properties.S3VectorProperties;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import software.amazon.awssdk.services.s3vectors.S3VectorsClient;
+import software.amazon.awssdk.services.s3vectors.S3VectorsClientBuilder;
+
+/**
+ * @author Matej Nedic
+ * @since 3.5.0
+ */
+@AutoConfiguration
+@ConditionalOnClass({S3VectorsClient.class})
+@EnableConfigurationProperties({S3VectorProperties.class, AwsProperties.class})
+@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class })
+@ConditionalOnProperty(name = "spring.cloud.aws.s3.vector.enabled", havingValue = "true", matchIfMissing = true)
+public class S3VectorClientAutoConfiguration {
+
+ private final S3VectorProperties properties;
+
+ public S3VectorClientAutoConfiguration(S3VectorProperties properties) {
+ this.properties = properties;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ S3VectorsClientBuilder s3VectorsClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer,
+ ObjectProvider> configurer,
+ ObjectProvider connectionDetails,
+ ObjectProvider s3ClientCustomizers,
+ ObjectProvider awsSyncClientCustomizers) {
+
+ return awsClientBuilderConfigurer.configureSyncClient(S3VectorsClient.builder(), this.properties,
+ connectionDetails.getIfAvailable(), configurer.getIfAvailable(), s3ClientCustomizers.orderedStream(),
+ awsSyncClientCustomizers.orderedStream());
+ }
+
+ @Bean
+ S3VectorsClient s3VectorsClient(S3VectorsClientBuilder builder) {
+ return builder.build();
+ }
+}
diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java
new file mode 100644
index 000000000..a132ca901
--- /dev/null
+++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java
@@ -0,0 +1,15 @@
+package io.awspring.cloud.autoconfigure.s3;
+
+import io.awspring.cloud.autoconfigure.AwsClientCustomizer;
+import software.amazon.awssdk.services.s3.S3ClientBuilder;
+import software.amazon.awssdk.services.s3vectors.S3VectorsClientBuilder;
+
+/**
+ * Callback interface that can be used to customize a {@link S3ClientBuilder}.
+ *
+ * @author Matej Nedic
+ * @since 3.5.0
+ */
+@FunctionalInterface
+public interface S3VectorClientCustomizer extends AwsClientCustomizer {
+}
diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java
new file mode 100644
index 000000000..6303b662e
--- /dev/null
+++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java
@@ -0,0 +1,19 @@
+package io.awspring.cloud.autoconfigure.s3.properties;
+
+import io.awspring.cloud.autoconfigure.AwsClientProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+
+/**
+ * @author Matej Nedic
+ */
+@ConfigurationProperties(prefix = S3VectorProperties.PREFIX)
+public class S3VectorProperties extends AwsClientProperties {
+
+ /**
+ * The prefix used for S3 related properties.
+ */
+ public static final String PREFIX = "spring.cloud.aws.s3.vector";
+
+
+}
diff --git a/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index 657cbf245..9e5b9c476 100644
--- a/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -7,6 +7,7 @@ io.awspring.cloud.autoconfigure.ses.SesAutoConfiguration
io.awspring.cloud.autoconfigure.s3.S3TransferManagerAutoConfiguration
io.awspring.cloud.autoconfigure.s3.S3AutoConfiguration
io.awspring.cloud.autoconfigure.s3.S3CrtAsyncClientAutoConfiguration
+io.awspring.cloud.autoconfigure.s3.S3VectorClientAutoConfiguration
io.awspring.cloud.autoconfigure.sns.SnsAutoConfiguration
io.awspring.cloud.autoconfigure.sqs.SqsAutoConfiguration
io.awspring.cloud.autoconfigure.dynamodb.DynamoDbAutoConfiguration
diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java
new file mode 100644
index 000000000..306d765d8
--- /dev/null
+++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java
@@ -0,0 +1,39 @@
+package io.awspring.cloud.autoconfigure.s3;
+
+import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration;
+import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration;
+import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import software.amazon.awssdk.services.s3vectors.S3VectorsClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test for {@link S3AutoConfiguration} class
+ *
+ * @author Matej Nedic
+ */
+public class S3VectorAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withPropertyValues("spring.cloud.aws.region.static:eu-west-1")
+ .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class,
+ CredentialsProviderAutoConfiguration.class, S3VectorClientAutoConfiguration.class));
+
+
+ @Test
+ void createsS3VectorClientBean() {
+ this.contextRunner.run(context -> {
+ assertThat(context).hasSingleBean(S3VectorsClient.class);
+ });
+ }
+
+ @Test
+ void s3VectorClientAutoConfigurationIsDisabled() {
+ this.contextRunner.withPropertyValues("spring.cloud.aws.s3.vector.enabled:false").run(context -> {
+ assertThat(context).doesNotHaveBean(S3VectorsClient.class);
+ });
+ }
+}
diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java
new file mode 100644
index 000000000..3ec752f68
--- /dev/null
+++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java
@@ -0,0 +1,112 @@
+package io.awspring.cloud.autoconfigure.s3;
+
+import io.awspring.cloud.autoconfigure.AwsSyncClientCustomizer;
+import io.awspring.cloud.autoconfigure.ConfiguredAwsClient;
+import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration;
+import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration;
+import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import software.amazon.awssdk.http.apache.ApacheHttpClient;
+import software.amazon.awssdk.services.s3vectors.S3VectorsClient;
+
+import java.time.Duration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+/**
+ * Tests for {@link S3VectorClientCustomizer}.
+ *
+ * @author Matej Nedic
+ * @author Maciej Walkowiak
+ */
+public class S3VectorClientCustomizerTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withPropertyValues("spring.cloud.aws.region.static:eu-west-1",
+ "spring.cloud.aws.credentials.access-key:noop", "spring.cloud.aws.credentials.secret-key:noop")
+ .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class,
+ CredentialsProviderAutoConfiguration.class, S3VectorClientAutoConfiguration.class));
+
+ @Test
+ void customClientCustomizer() {
+ contextRunner.withUserConfiguration(S3VectorClientCustomizerTests.CustomizerConfig.class).run(context -> {
+ ConfiguredAwsClient client = new ConfiguredAwsClient(context.getBean(S3VectorsClient.class));
+ assertThat(client.getApiCallTimeout()).describedAs("sets property from first customizer")
+ .isEqualTo(Duration.ofMillis(2001));
+ assertThat(client.getApiCallAttemptTimeout()).describedAs("sets property from second customizer")
+ .isEqualTo(Duration.ofMillis(2002));
+ assertThat(client.getSyncHttpClient()).describedAs("sets property from common client customizer")
+ .isNotNull();
+ });
+ }
+
+ @Test
+ void customClientCustomizerWithOrder() {
+ contextRunner.withUserConfiguration(S3VectorClientCustomizerTests.CustomizerConfigWithOrder.class).run(context -> {
+ ConfiguredAwsClient client = new ConfiguredAwsClient(context.getBean(S3VectorsClient.class));
+ assertThat(client.getApiCallTimeout())
+ .describedAs("property from the customizer with higher order takes precedence")
+ .isEqualTo(Duration.ofMillis(2001));
+ });
+ }
+
+
+ @Configuration(proxyBeanMethods = false)
+ static class CustomizerConfig {
+
+ @Bean
+ S3VectorClientCustomizer customizer() {
+ return builder -> {
+ builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> {
+ c.apiCallTimeout(Duration.ofMillis(2001));
+ }));
+ };
+ }
+
+ @Bean
+ S3VectorClientCustomizer customizer2() {
+ return builder -> {
+ builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> {
+ c.apiCallAttemptTimeout(Duration.ofMillis(2002));
+ }));
+ };
+ }
+
+ @Bean
+ AwsSyncClientCustomizer awsSyncClientCustomizer() {
+ return builder -> {
+ builder.httpClient(ApacheHttpClient.builder().connectionTimeout(Duration.ofMillis(1542)).build());
+ };
+ }
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class CustomizerConfigWithOrder {
+
+ @Bean
+ @Order(2)
+ S3VectorClientCustomizer customizer() {
+ return builder -> {
+ builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> {
+ c.apiCallTimeout(Duration.ofMillis(2001));
+ }));
+ };
+ }
+
+ @Bean
+ @Order(1)
+ S3VectorClientCustomizer customizer2() {
+ return builder -> {
+ builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> {
+ c.apiCallTimeout(Duration.ofMillis(2000));
+ }));
+ };
+ }
+ }
+}
diff --git a/spring-cloud-aws-dependencies/pom.xml b/spring-cloud-aws-dependencies/pom.xml
index 3f37598a4..8a2cf1a3f 100644
--- a/spring-cloud-aws-dependencies/pom.xml
+++ b/spring-cloud-aws-dependencies/pom.xml
@@ -24,7 +24,7 @@
2.31.0
- 2.31.54
+ 2.32.4
2.0.5
3.3.5
1.6