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

Some times properties are not set on bean creation #446

Closed
deblockt opened this issue Aug 14, 2020 · 9 comments
Closed

Some times properties are not set on bean creation #446

deblockt opened this issue Aug 14, 2020 · 9 comments

Comments

@deblockt
Copy link

In some case when my beans definitions function are run, properties are not already loaded, so I have some NullPointerException.
This happen randomly and can work after many restart. This happend on computer with limited resources.
I use vault to load properties.

I start spring cloud vault on a bootstrap.yaml like that

spring:
  application:
    name: my-app
  # Default configuration for vault
  cloud.vault:
    enabled: true # Disabled by default, activate it in specific profile
    uri: ---
    namespace: ---
    authentication: APPROLE
    app-role:
      role-id: ---
      secret-id: ---
      app-role-path: approle
    fail-fast: true
    connection-timeout: 5000
    read-timeout: 15000
    config:
      order: -10
      lifecycle:
        enabled: true
        min-renewal: 10s
        expiry-threshold: 1m
        lease-endpoints: Legacy
    generic:
      enabled: false
    kv:
      enabled: true
      backend: secret
      profile-separator: "/"
      default-context: application/global
      application-name: application

My JVM start on 0.5 cpu with this memory data

VM settings:
    Stack Size: 256.00K
    Max. Heap Size (Estimated): 247.50M
    Using VM: OpenJDK 64-Bit Server VM

It seems that happen since my last spring cloud upgrade (from spring-cloud-vault-config 2.2.0 to 2.2.3).
I have a feeling that setting config.lifecycle.enabled to false fix the issue, but I don't understand why.

Can you help to understand this issue?
Thanks

@deblockt
Copy link
Author

deblockt commented Aug 14, 2020

And sometime only some properties are null, and other are correct.
I use Spring boot 2.3.2 and reactor

@deblockt
Copy link
Author

my beans are just created using @Bean or @Components annotations

@nezed
Copy link

nezed commented Aug 31, 2020

We've got exactly same behaviour, and application crashes at startup in ~80% of runs because of uninitialised properties of @ConfigurationProperties

config.lifecycle.enabled: false makes it work fine again.
We didn’t found something unusual and/or specific moment when this issue has began to occur.
There is also no noticeable logs and no ideas to dig in.

Partial sources
# bootstrap.yml
spring:
  profiles: prod
  cloud:
    consul:
      host: http://MASKED
      port: 80
      config:
        format: yaml
        prefix: MASKED/prod
        name: bb/${spring.application.name}
        acl-token: ${acl_token}
    vault:
      scheme: https
      host: MASKED
      port: 443
      authentication: approle
      application-name: bb/${spring.application.name}
      generic:
        backend: MASKED/prod
      app-role:
        secret-id: ${secret_id}
        role-id: ${role_id}
# build.gradle.kts
plugins {
    // ...
    id("org.springframework.boot") version "2.3.3.RELEASE"
    // ...
}
// ...
dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR7")
    }
}
// ....
dependencies {
    // Spring
    // Boot
    developmentOnly(group = "org.springframework.boot", name = "spring-boot-devtools")
    implementation(group = "org.springframework.boot", name = "spring-boot-starter-cache")
    implementation(group = "org.springframework.boot", name = "spring-boot-starter-webflux")
    implementation(group = "org.springframework.boot", name = "spring-boot-starter-actuator")
    // Cloud
    implementation(group = "org.springframework.cloud", name = "spring-cloud-starter-sleuth")
    // ....
}
package MASKED.configuration.properties

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.cloud.context.config.annotation.RefreshScope

@RefreshScope
@ConfigurationProperties(prefix = "service.jira")
class JiraProperties {
    lateinit var host: String
    lateinit var username: String
    lateinit var password: String
}
Startup log
INFO [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService
INFO [or-http-epoll-1] v.a.ReactiveLifecycleAwareSessionManager : Scheduling Token renewal
INFO [           main] o.s.v.c.e.LeaseAwareVaultPropertySource  : Vault location [MASKED/test/bb/metrics-etl/test] not resolvable: Not found
INFO [           main] o.s.v.c.e.LeaseAwareVaultPropertySource  : Vault location [MASKED/test/application/test] not resolvable: Not found
INFO [           main] o.s.v.c.e.LeaseAwareVaultPropertySource  : Vault location [MASKED/test/application] not resolvable: Not found
INFO [           main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-MASKED/test/bb/metrics-etl/test'}, BootstrapPropertySource {name='bootstrapProperties-MASKED/test/bb/metrics-etl'}, BootstrapPropertySource {name='bootstrapProperties-MASKED/test/application/test'}, BootstrapPropertySource {name='bootstrapProperties-MASKED/test/application'}]
INFO [           main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-MASKED/test/bb/metrics-etl,test/'}, BootstrapPropertySource {name='bootstrapProperties-MASKED/test/bb/metrics-etl/'}, BootstrapPropertySource {name='bootstrapProperties-MASKED/test/application,test/'}, BootstrapPropertySource {name='bootstrapProperties-MASKED/test/application/'}]
INFO [           main] r.t.s.d.b.m.MetricsEtlApplicationKt      : The following profiles are active: test
INFO [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data MongoDB repositories in DEFAULT mode.
INFO [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 100ms. Found 2 MongoDB repository interfaces.
INFO [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=be188650-cbb5-3426-8136-12c5cf3c2fcf
WARN [           main] onfigReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processesDispatcher' defined in file [/MASKED/pipeline/processes/dispatcher/ProcessesDispatcher.class]: Unsatisfied dependency expressed through constructor parameter 3; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processesSource' defined in file [/MASKED/pipeline/processes/stage/source/ProcessesSource.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jiraService' defined in file [/MASKED/pipeline/processes/stage/source/service/JiraService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jiraConfiguration' defined in file [/MASKED/pipeline/processes/stage/source/configuration/JiraConfiguration.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312]: Constructor threw exception; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
INFO [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
INFO [           main] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService
ERROR [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processesDispatcher' defined in file [/MASKED/pipeline/processes/dispatcher/ProcessesDispatcher.class]: Unsatisfied dependency expressed through constructor parameter 3; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processesSource' defined in file [/MASKED/pipeline/processes/stage/source/ProcessesSource.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jiraService' defined in file [/MASKED/pipeline/processes/stage/source/service/JiraService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jiraConfiguration' defined in file [/MASKED/pipeline/processes/stage/source/configuration/JiraConfiguration.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312]: Constructor threw exception; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
	at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:62)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at MASKED.MetricsEtlApplicationKt.main(MetricsEtlApplication.kt:42)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processesSource' defined in file [/MASKED/pipeline/processes/stage/source/ProcessesSource.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jiraService' defined in file [/MASKED/pipeline/processes/stage/source/service/JiraService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jiraConfiguration' defined in file [/MASKED/pipeline/processes/stage/source/configuration/JiraConfiguration.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312]: Constructor threw exception; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
	... 20 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jiraService' defined in file [/MASKED/pipeline/processes/stage/source/service/JiraService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jiraConfiguration' defined in file [/MASKED/pipeline/processes/stage/source/configuration/JiraConfiguration.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312]: Constructor threw exception; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
	... 34 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jiraConfiguration' defined in file [/MASKED/pipeline/processes/stage/source/configuration/JiraConfiguration.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312]: Constructor threw exception; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:313)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:294)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:408)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
	... 48 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312]: Constructor threw exception; nested exception is kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:217)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:309)
	... 71 common frames omitted
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property password has not been initialized
	at MASKED.pipeline.processes.stage.source.configuration.properties.JiraProperties.getPassword(JiraProperties.kt:11)
	at MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration.<init>(JiraConfiguration.kt:24)
	at MASKED.pipeline.processes.stage.source.configuration.JiraConfiguration$$EnhancerBySpringCGLIB$$a6e4312.<init>(<generated>)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204)
	... 73 common frames omitted

@domingogomez-asto
Copy link

I have the same issue and I was able to replicate here:
demo.zip
What I think it's happening is that https://github.com/spring-projects/spring-vault/blob/f46ca3d0f1149b70e029f3ed48802a482cf8d464/spring-vault-core/src/main/java/org/springframework/vault/core/env/LeaseAwareVaultPropertySource.java#L228 is sending a SecretLeaseExpiredEvent which clears the properties and right after a SecretLeaseCreatedEvent that repopulates the properties.

That is usually fine but manifests easier in low cpu environments and larger apps. config.lifecycle.enabled does indeed fix the issue but may limit your app if you are using database backends or anything that depends on lease renewals.

@mp911de
Copy link
Member

mp911de commented Nov 4, 2020

SecretLeaseExpiredEvent cleans up the property source to evict properties that are no longer valid. Turning this principle around (retaining only property keys that came with SecretLeaseCreatedEvent) potentially exposes secrets to the application that are no longer valid. I see that a bit as a risk, especially when no subsequent SecretLeaseCreatedEvent happens.

@domingogomez-asto
Copy link

domingogomez-asto commented Nov 4, 2020

SecretLeaseExpiredEvent cleans up the property source to evict properties that are no longer valid. Turning this principle around (retaining only property keys that came with SecretLeaseCreatedEvent) potentially exposes secrets to the application that are no longer valid. I see that a bit as a risk, especially when no subsequent SecretLeaseCreatedEvent happens.

@mp911de that's fine but we also have the scenario where the secret has not changed at all in vault and yet the app throws IllegalArgumentException just because the property read (@value, @ConfigurationProperties or any other read method) kicks in just between SecretLeaseExpiredEvent and SecretLeaseCreatedEvent.

Some ideas:
SecretLeaseCreatedEvent already clears the properties and sets them in an atomic operation, would it be an option to renew the lease before it expires so SecretLeaseCreatedEvent is sent so the lease is replaced and there is no need to send a SecretLeaseExpiredEvent?
Or to keep the lease reference on the properties so a SecretLeaseExpiredEvent can only clear properties one particular lease has set, preventing the removal of properties of a more recent lease.

@mp911de
Copy link
Member

mp911de commented Nov 5, 2020

would it be an option to renew the lease before it expires so SecretLeaseCreatedEvent is sent so the lease is replaced and there is no need to send a SecretLeaseExpiredEvent?

I concluded this would be probably the best option. However, we need to take into account, that rotation of secrets may fail (that's where we typically see a gap).

After reconsidering, it would probably even make sense to introduce a new event SecretRotatedEvent (subclass of SecretLeaseCreatedEvent) that gets emitted when a secret is rotated, holding references to the old and new lease.

If rotation fails, we emit SecretLeaseExpiredEvent followed by SecretLeaseErrorEvent.

All this needs to happen in Spring Vault. Can you file a new ticket there so we can close this ticket and apply the changes to Spring Vault?

@mp911de
Copy link
Member

mp911de commented Nov 5, 2020

Closing in favor of spring-projects/spring-vault#594.

@mp911de mp911de closed this as completed Nov 5, 2020
@mp911de
Copy link
Member

mp911de commented Dec 2, 2020

That's fixed for version 2.3 RC1 of Spring Vault via spring-projects/spring-vault#594 now. We'd like to get feedback on this issue before backporting it to the 2.2.x line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants