diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc index f895d2a9..a3d4ee67 100644 --- a/docs/src/main/asciidoc/README.adoc +++ b/docs/src/main/asciidoc/README.adoc @@ -9,7 +9,7 @@ include::intro.adoc[] Specifically for Spring applications: * Retrieve secrets from Vault and initialize Spring Environment with remote property sources. -* Obtain {docs}#vault.config.backends.generic[secrets] secured with SSL. +* Obtain {docs}#vault.config.backends.kv[Key-Value secrets] secured with SSL. * Generate credentials for {docs}#vault.config.backends.mysql[MySQL], {docs}#vault.config.backends.postgresql[PostgreSQL], diff --git a/docs/src/main/asciidoc/spring-cloud-vault.adoc b/docs/src/main/asciidoc/spring-cloud-vault.adoc index 61399d0f..63724e2f 100644 --- a/docs/src/main/asciidoc/spring-cloud-vault.adoc +++ b/docs/src/main/asciidoc/spring-cloud-vault.adoc @@ -711,8 +711,11 @@ See also: https://www.vaultproject.io/docs/auth/pcf.html[Vault Documentation: Us [[vault.config.backends.generic]] === Generic Backend -Spring Cloud Vault supports at the basic level the generic secret -backend. The generic secret backend allows storage of arbitrary +NOTE: This backend is deprecated in favor of the Key-Value backend and will be removed +with the next major version. + +Spring Cloud Vault supports at the basic level the key-value secret +backend. The key-value secret backend allows storage of arbitrary values as key-value store. A single context can store one or many key-value tuples. Contexts can be organized hierarchically. Spring Cloud Vault allows using the Application name @@ -730,7 +733,7 @@ The application name is determined by the properties: * `spring.cloud.vault.application-name` * `spring.application.name` -Secrets can be obtained from other contexts within the generic backend by adding their +Secrets can be obtained from other contexts within the key-value backend by adding their paths to the application name, separated by commas. For example, given the application name `usefulapp,mysql1,projectx/aws`, each of these folders will be used: @@ -760,21 +763,20 @@ spring.cloud.vault: config usage * `backend` sets the path of the secret mount to use * `default-context` sets the context name used by all applications -* `application-name` overrides the application name for use in the generic backend +* `application-name` overrides the application name for use in the key-value backend * `profile-separator` separates the profile name from the context in property sources with profiles -NOTE: The key-value secret backend can be operated in versioned (v2) and non-versioned (v1) modes. Depending on the mode of operation, a different API is required to access secrets. Make sure to enable `generic` secret backend usage for non-versioned key-value backends and `kv` secret backend usage for versioned key-value backends. - See also: https://www.vaultproject.io/docs/secrets/kv/kv-v1.html[Vault Documentation: Using the KV Secrets Engine - Version 1 (generic secret backend)] [[vault.config.backends.kv.versioned]] -=== Versioned Key-Value Backend +=== Key-Value Backend -Spring Cloud Vault supports the versioned Key-Value secret +Spring Cloud Vault supports the Key-Value secret backend. The key-value backend allows storage of arbitrary values as key-value store. A single context can store one or many -key-value tuples. Contexts can be organized hierarchically. +key-value tuples. Contexts can be organized hierarchically. Spring Cloud Vault +determines itself whether a secret is using versioning. Spring Cloud Vault allows using the Application name and a default context name (`application`) in combination with active profiles. @@ -822,13 +824,16 @@ spring.cloud.vault: config usage * `backend` sets the path of the secret mount to use * `default-context` sets the context name used by all applications -* `application-name` overrides the application name for use in the generic backend +* `application-name` overrides the application name for use in the key-value backend * `profile-separator` separates the profile name from the context in property sources with profiles -NOTE: The key-value secret backend can be operated in versioned (v2) and non-versioned (v1) modes. Depending on the mode of operation, a different API is required to access secrets. Make sure to enable `generic` secret backend usage for non-versioned key-value backends and `kv` secret backend usage for versioned key-value backends. +NOTE: The key-value secret backend can be operated in versioned (v2) and non-versioned (v1) modes. -See also: https://www.vaultproject.io/docs/secrets/kv/kv-v2.html[Vault Documentation: Using the KV Secrets Engine - Version 2 (versioned key-value backend)] +See also: + +* https://www.vaultproject.io/docs/secrets/kv/kv-v1.html[Vault Documentation: Using the KV Secrets Engine - Version 1 (generic secret backend)] +* https://www.vaultproject.io/docs/secrets/kv/kv-v2.html[Vault Documentation: Using the KV Secrets Engine - Version 2 (versioned key-value backend)] [[vault.config.backends.consul]] === Consul @@ -1236,7 +1241,7 @@ See also: https://www.vaultproject.io/docs/secrets/postgresql/index.html[Vault D == Configure `PropertySourceLocator` behavior Spring Cloud Vault uses property-based configuration to create ``PropertySource``s -for generic and discovered secret backends. +for key-value and discovered secret backends. Discovered backends provide `VaultSecretBackendDescriptor` beans to describe the configuration state to use secret backend as `PropertySource`. A `SecretBackendMetadataFactory` is required @@ -1246,9 +1251,9 @@ configuration. `SecretBackendMetadata` is used to back a particular `PropertySource`. You can register an arbitrary number of beans implementing `VaultConfigurer` for customization. -Default generic and discovered backend registration is disabled if Spring Cloud Vault discovers +Default key-value and discovered backend registration is disabled if Spring Cloud Vault discovers at least one `VaultConfigurer` bean. You can however enable default registration with -`SecretBackendConfigurer.registerDefaultGenericSecretBackends()` and `SecretBackendConfigurer.registerDefaultDiscoveredSecretBackends()`. +`SecretBackendConfigurer.registerDefaultKeyValueSecretBackends()` and `SecretBackendConfigurer.registerDefaultDiscoveredSecretBackends()`. ==== [source,java] @@ -1260,7 +1265,7 @@ public class CustomizationBean implements VaultConfigurer { configurer.add("secret/my-application"); - configurer.registerDefaultGenericSecretBackends(false); + configurer.registerDefaultKeyValueSecretBackends(false); configurer.registerDefaultDiscoveredSecretBackends(true); } } diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/DefaultSecretBackendConfigurer.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/DefaultSecretBackendConfigurer.java index 76720e92..0cf6fe8c 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/DefaultSecretBackendConfigurer.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/DefaultSecretBackendConfigurer.java @@ -39,7 +39,7 @@ class DefaultSecretBackendConfigurer private final Map secretBackends = new LinkedHashMap<>(); - private boolean registerDefaultGenericSecretBackends = false; + private boolean registerDefaultKeyValueSecretBackends = false; private boolean registerDefaultDiscoveredSecretBackends = false; @@ -100,10 +100,10 @@ class DefaultSecretBackendConfigurer } @Override - public SecretBackendConfigurer registerDefaultGenericSecretBackends( - boolean registerDefault) { - this.registerDefaultGenericSecretBackends = registerDefault; + public SecretBackendConfigurer registerDefaultKeyValueSecretBackends( + boolean registerDefault) { + this.registerDefaultKeyValueSecretBackends = registerDefault; return this; } @@ -117,8 +117,8 @@ class DefaultSecretBackendConfigurer return this; } - public boolean isRegisterDefaultGenericSecretBackends() { - return this.registerDefaultGenericSecretBackends; + public boolean isRegisterDefaultKeyValueSecretBackends() { + return this.registerDefaultKeyValueSecretBackends; } public boolean isRegisterDefaultDiscoveredSecretBackends() { diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/GenericSecretBackendMetadata.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/GenericSecretBackendMetadata.java index 3b81d2be..ac3676e1 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/GenericSecretBackendMetadata.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/GenericSecretBackendMetadata.java @@ -24,7 +24,9 @@ import org.springframework.util.Assert; * {@link SecretBackendMetadata} for the {@code generic} secret backend. * * @author Mark Paluch + * @deprecated since 2.2.3, will be removed with 3.0. */ +@Deprecated public final class GenericSecretBackendMetadata extends KeyValueSecretBackendMetadata implements SecretBackendMetadata { @@ -33,8 +35,8 @@ public final class GenericSecretBackendMetadata extends KeyValueSecretBackendMet } /** - * Create a {@link SecretBackendMetadata} for the {@code generic} secret backend given - * a {@code secretBackendPath} and {@code key}. + * Create a {@link SecretBackendMetadata} for the {@code kv} secret backend given a + * {@code secretBackendPath} and {@code key}. * @param secretBackendPath the secret backend mount path without leading/trailing * slashes, must not be empty or {@literal null}. * @param key the key within the secret backend. May contain slashes but not @@ -51,8 +53,8 @@ public final class GenericSecretBackendMetadata extends KeyValueSecretBackendMet } /** - * Create a {@link SecretBackendMetadata} for the {@code generic} secret backend given - * a {@code path}. + * Create a {@link SecretBackendMetadata} for the {@code kv} secret backend given a + * {@code path}. * @param path the relative path of the secret. slashes, must not be empty or * {@literal null}. * @return the {@link SecretBackendMetadata} diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/KeyValueSecretBackendMetadata.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/KeyValueSecretBackendMetadata.java index e895d069..1994f635 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/KeyValueSecretBackendMetadata.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/KeyValueSecretBackendMetadata.java @@ -79,8 +79,8 @@ public class KeyValueSecretBackendMetadata extends SecretBackendMetadataSupport } /** - * Create a {@link SecretBackendMetadata} for the {@code generic} secret backend given - * a {@code path}. + * Create a {@link SecretBackendMetadata} for the {@code kv} secret backend given a + * {@code path}. * @param path the relative path of the secret. slashes, must not be empty or * {@literal null}. * @return the {@link SecretBackendMetadata} @@ -90,8 +90,8 @@ public class KeyValueSecretBackendMetadata extends SecretBackendMetadataSupport } /** - * Create a {@link SecretBackendMetadata} for the {@code generic} secret backend given - * a {@code path}. + * Create a {@link SecretBackendMetadata} for the {@code kv} secret backend given a + * {@code path}. * @param path the relative path of the secret. slashes, must not be empty or * {@literal null}. * @param propertyTransformer property transformer. diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/SecretBackendConfigurer.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/SecretBackendConfigurer.java index 9482fb0c..f6fac302 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/SecretBackendConfigurer.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/SecretBackendConfigurer.java @@ -27,7 +27,7 @@ import org.springframework.vault.core.util.PropertyTransformer; * Assists configuration with a fluent style. This configurer allows configuration via * context paths and direct registration of {@link SecretBackendMetadata}. *

- * Use {@link #registerDefaultGenericSecretBackends(boolean)} to register default generic + * Use {@link #registerDefaultKeyValueSecretBackends(boolean)} to register default kv * secret backend property sources and * {@link #registerDefaultDiscoveredSecretBackends(boolean)} to register additional secret * backend property sources such as MySQL and RabbitMQ. @@ -87,8 +87,23 @@ public interface SecretBackendConfigurer { * @param registerDefault {@literal true} to enable default generic secret backend * registration. * @return {@code this} {@link SecretBackendConfigurer}. + * @deprecated since 2.2.3 */ - SecretBackendConfigurer registerDefaultGenericSecretBackends(boolean registerDefault); + @Deprecated + default SecretBackendConfigurer registerDefaultGenericSecretBackends( + boolean registerDefault) { + return registerDefaultKeyValueSecretBackends(registerDefault); + } + + /** + * Register default key-value secret backend property sources. + * @param registerDefault {@literal true} to enable default kv secret backend + * registration. + * @return {@code this} {@link SecretBackendConfigurer}. + * @since 2.3.3 + */ + SecretBackendConfigurer registerDefaultKeyValueSecretBackends( + boolean registerDefault); /** * Register default discovered secret backend property sources from diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultBootstrapPropertySourceConfiguration.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultBootstrapPropertySourceConfiguration.java index 68ad8c92..46962969 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultBootstrapPropertySourceConfiguration.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultBootstrapPropertySourceConfiguration.java @@ -134,7 +134,7 @@ public class VaultBootstrapPropertySourceConfiguration implements InitializingBe } } - if (secretBackendConfigurer.isRegisterDefaultGenericSecretBackends()) { + if (secretBackendConfigurer.isRegisterDefaultKeyValueSecretBackends()) { for (VaultKeyValueBackendPropertiesSupport keyValueBackend : keyValueBackends) { diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigurer.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigurer.java index ab7d420f..fa98c626 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigurer.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigurer.java @@ -27,7 +27,7 @@ package org.springframework.cloud.vault.config; * *

* Registered bean instances of {@link VaultConfigurer} disable default secret backend - * registration for the generic and integrative (other discovered + * registration for the kv and integrative (other discovered * {@link SecretBackendMetadata}) backends. See * {@link SecretBackendConfigurer#registerDefaultGenericSecretBackends(boolean)} and * {@link SecretBackendConfigurer#registerDefaultDiscoveredSecretBackends(boolean)} for diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultGenericBackendProperties.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultGenericBackendProperties.java index 772ea79d..bf3d2f02 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultGenericBackendProperties.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultGenericBackendProperties.java @@ -19,6 +19,7 @@ package org.springframework.cloud.vault.config; import javax.validation.constraints.NotEmpty; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; import org.springframework.util.StringUtils; @@ -83,22 +84,42 @@ public class VaultGenericBackendProperties } } + @Deprecated + @DeprecatedConfigurationProperty( + reason = "spring.cloud.vault.generic.* is deprecated in favor of spring.cloud.vault.kv", + replacement = "spring.cloud.vault.kv.enabled") public boolean isEnabled() { return this.enabled; } + @Deprecated + @DeprecatedConfigurationProperty( + reason = "spring.cloud.vault.generic.* is deprecated in favor of spring.cloud.vault.kv", + replacement = "spring.cloud.vault.kv.backend") public String getBackend() { return this.backend; } + @Deprecated + @DeprecatedConfigurationProperty( + reason = "spring.cloud.vault.generic.* is deprecated in favor of spring.cloud.vault.kv", + replacement = "spring.cloud.vault.kv.default-context") public String getDefaultContext() { return this.defaultContext; } + @Deprecated + @DeprecatedConfigurationProperty( + reason = "spring.cloud.vault.generic.* is deprecated in favor of spring.cloud.vault.kv", + replacement = "spring.cloud.vault.kv.profile-separator") public String getProfileSeparator() { return this.profileSeparator; } + @Deprecated + @DeprecatedConfigurationProperty( + reason = "spring.cloud.vault.generic.* is deprecated in favor of spring.cloud.vault.kv", + replacement = "spring.cloud.vault.kv.application-name") public String getApplicationName() { return this.applicationName; } diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultKeyValueBackendProperties.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultKeyValueBackendProperties.java index 95970612..9f51225e 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultKeyValueBackendProperties.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultKeyValueBackendProperties.java @@ -19,6 +19,7 @@ package org.springframework.cloud.vault.config; import javax.validation.constraints.NotEmpty; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; import org.springframework.util.StringUtils; @@ -112,6 +113,9 @@ public class VaultKeyValueBackendProperties return this.applicationName; } + @Deprecated + @DeprecatedConfigurationProperty( + reason = "Backend version no longer required. The kv version is determined during secret retrieval") public int getBackendVersion() { return this.backendVersion; } diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultPropertySourceLocatorSupport.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultPropertySourceLocatorSupport.java index 40011283..26d3f9c4 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultPropertySourceLocatorSupport.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultPropertySourceLocatorSupport.java @@ -32,7 +32,7 @@ import org.springframework.util.Assert; /** * Abstract {@link PropertySourceLocator} to create {@link PropertySource}s based on - * {@link VaultGenericBackendProperties} and {@link SecretBackendMetadata}. + * {@link VaultKeyValueBackendProperties} and {@link SecretBackendMetadata}. * * @author Mark Paluch */ @@ -82,7 +82,7 @@ public abstract class VaultPropertySourceLocatorSupport implements PropertySourc "VaultGenericBackendProperties must not be null"); Assert.notNull(backendAccessors, "BackendAccessors must not be null"); - GenericPropertySourceLocatorConfiguration generic = new GenericPropertySourceLocatorConfiguration( + KeyValuePropertySourceLocatorConfiguration generic = new KeyValuePropertySourceLocatorConfiguration( genericBackendProperties); WrappedPropertySourceLocatorConfiguration backends = new WrappedPropertySourceLocatorConfiguration( @@ -97,7 +97,7 @@ public abstract class VaultPropertySourceLocatorSupport implements PropertySourc Assert.notNull(genericBackendProperties, "VaultGenericBackendProperties must not be null"); - return new GenericPropertySourceLocatorConfiguration(genericBackendProperties); + return new KeyValuePropertySourceLocatorConfiguration(genericBackendProperties); } @Override @@ -155,7 +155,7 @@ public abstract class VaultPropertySourceLocatorSupport implements PropertySourc AnnotationAwareOrderComparator.sort(sorted); - propertySources.addAll(doCreateGenericPropertySources(environment)); + propertySources.addAll(doCreateKeyValuePropertySources(environment)); for (SecretBackendMetadata backendAccessor : sorted) { @@ -168,13 +168,13 @@ public abstract class VaultPropertySourceLocatorSupport implements PropertySourc } /** - * Create {@link PropertySource}s using the generic {@literal secret} backend. - * Property sources for the generic secret backend derive from the application name - * and active profiles to generate context paths. + * Create {@link PropertySource}s using the kv {@literal secret} backend. Property + * sources for the kv secret backend derive from the application name and active + * profiles to generate context paths. * @param environment must not be {@literal null}. * @return {@link List} of {@link PropertySource}s. */ - protected List> doCreateGenericPropertySources( + protected List> doCreateKeyValuePropertySources( Environment environment) { return new ArrayList<>(); } @@ -208,16 +208,16 @@ public abstract class VaultPropertySourceLocatorSupport implements PropertySourc protected abstract PropertySource createVaultPropertySource( SecretBackendMetadata accessor); - private static class GenericPropertySourceLocatorConfiguration + private static class KeyValuePropertySourceLocatorConfiguration implements EnvironmentAware, PropertySourceLocatorConfiguration { - private final VaultKeyValueBackendPropertiesSupport genericBackendProperties; + private final VaultKeyValueBackendPropertiesSupport keyValueBackendProperties; private Environment environment; - GenericPropertySourceLocatorConfiguration( - VaultKeyValueBackendPropertiesSupport genericBackendProperties) { - this.genericBackendProperties = genericBackendProperties; + KeyValuePropertySourceLocatorConfiguration( + VaultKeyValueBackendPropertiesSupport keyValueBackendProperties) { + this.keyValueBackendProperties = keyValueBackendProperties; } @Override @@ -228,17 +228,17 @@ public abstract class VaultPropertySourceLocatorSupport implements PropertySourc @Override public Collection getSecretBackends() { - if (this.genericBackendProperties.isEnabled()) { + if (this.keyValueBackendProperties.isEnabled()) { List contexts = GenericSecretBackendMetadata.buildContexts( - this.genericBackendProperties, + this.keyValueBackendProperties, Arrays.asList(this.environment.getActiveProfiles())); List result = new ArrayList<>(contexts.size()); for (String context : contexts) { - result.add(GenericSecretBackendMetadata - .create(this.genericBackendProperties.getBackend(), context)); + result.add(GenericSecretBackendMetadata.create( + this.keyValueBackendProperties.getBackend(), context)); } return result; diff --git a/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicatorIntegrationTests.java b/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicatorIntegrationTests.java index 0effe65a..e5a02658 100644 --- a/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicatorIntegrationTests.java +++ b/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicatorIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2019-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,15 +42,18 @@ public class VaultReactiveHealthIndicatorIntegrationTests extends IntegrationTes public void shouldReturnHealthState() { ReactiveVaultTemplate vaultTemplate = new ReactiveVaultTemplate( - TestRestTemplateFactory.TEST_VAULT_ENDPOINT, ClientHttpConnectorFactory - .create(new ClientOptions(), Settings - .createSslConfiguration()), () -> Mono.just(Settings.token())); + TestRestTemplateFactory.TEST_VAULT_ENDPOINT, + ClientHttpConnectorFactory.create(new ClientOptions(), + Settings.createSslConfiguration()), + () -> Mono.just(Settings.token())); - VaultReactiveHealthIndicator healthIndicator = new VaultReactiveHealthIndicator(vaultTemplate); + VaultReactiveHealthIndicator healthIndicator = new VaultReactiveHealthIndicator( + vaultTemplate); healthIndicator.doHealthCheck(Health.up()).as(StepVerifier::create) .consumeNextWith(actual -> { assertThat(actual.getStatus()).isEqualTo(Status.UP); }).verifyComplete(); } + }