Daniil Baev
Daniil Baev

Reputation: 131

Kubernetes Authentication no re-create token

I can't configure spring.cloud.vault to re-authenticate the application when the token expire. I use Kubernetes Authentication with service token, bun in the SessionManager class I find the batch token (it`s TTL ending and spring vault just throw errors) and it cant be re-new

What I have to check or search in first time? Or how I can fix the error?

I can`t use Vault Agent in my company

Stack trace:

Caused by: org.springframework.vault.VaultException: Status 403 Forbidden: permission denied; nested exception is org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden: "{"errors":["permission denied"]}<EOL>"
at org.springframework.vault.client.VaultResponses.buildException(VaultResponses.java:85)
at org.springframework.vault.core.VaultKeyValueAccessor.lambda$doRead$2(VaultKeyValueAccessor.java:174)
at org.springframework.vault.core.VaultTemplate.doWithSession(VaultTemplate.java:448)
at org.springframework.vault.core.VaultKeyValueAccessor.doRead(VaultKeyValueAccessor.java:163)
at org.springframework.vault.core.VaultKeyValueAccessor.doRead(VaultKeyValueAccessor.java:132)
at org.springframework.vault.core.VaultKeyValueAccessor.doRead(VaultKeyValueAccessor.java:107)
at org.springframework.vault.core.VaultKeyValue1Template.get(VaultKeyValue1Template.java:69)
at sbp.bpm.designer.utils.credential.VaultAwareCredentialSetup.lambda$createSecretRetriever$2(VaultAwareCredentialSetup.java:127)
at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4868)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3533)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2282)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2159)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2049)
... 16 common frames omitted

Here is the application.yaml config

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 10MB
      max-request-size: 10MB
  cloud:
    vault:
      enabled: true
      uri: http://vault.url:8080
      authentication: KUBERNETES
      kubernetes:
        role: role
        kubernetes-path: k8s/dap.url.com
        service-account-token-file: /var/run/secrets/kubernetes.io/serviceaccount/token

Dependency version:

<spring-cloud-vault.version>3.1.3</spring-cloud-vault.version> <spring-cloud-starter-config.version>3.1.7</spring-cloud-starter-config.version>

Upvotes: 2

Views: 100

Answers (1)

Daniil Baev
Daniil Baev

Reputation: 131

Spring vault don`t use own revoke/renew logic if your token has type = renew false, this code helps me:

@Component                              
@ConditionalOnProperty(name = "spring.cloud.vault.enabled", havingValue = "true") 
public class CustomVaultSessionManager implements SessionManager {

    private final ClientAuthentication authentication;

    private Optional<VaultToken> actualToken = Optional.empty();
    private Optional<Long> expirationTime = Optional.empty();

    public CustomVaultSessionManager(ClientAuthentication authentication) {
        this.authentication = authentication;
    }

    @NotNull
    @Synchronized
    @Override
    public VaultToken getSessionToken() {
        if (isTokenExpired() || actualToken.isEmpty()) {
            actualToken = Optional.of(generateNewToken());
            log.info("Get session token : {}", actualToken.get());
        }
         return actualToken.get();
    }

    private boolean isTokenExpired() {
        Boolean isTokenExpired = expirationTime
                .map(expiration -> expiration < System.currentTimeMillis())
                .orElse(false);
        return isTokenExpired;
    }

    private VaultToken generateNewToken() {
        VaultToken newToken = authentication.login();
        if (newToken instanceof LoginToken) {
            LoginToken loginToken = (LoginToken) newToken;
            expirationTime = updateExpirationTime(loginToken);
        } else {
            expirationTime = Optional.empty();
        }
        return newToken;
    }

    private Optional<Long> updateExpirationTime(LoginToken loginToken) {
        return Optional.of(System.currentTimeMillis() + loginToken.getLeaseDuration().toMillis() - 500);
    } }

Upvotes: 1

Related Questions