javaspringhashicorp-vaultspring-vault

Error with Spring AppRoleAuthentication - URI is not absolute


I'm trying to retrieve secrets from vault using the AppRole authentication. But I get the error :

java.lang.IllegalArgumentException: URI is not absolute

What I do is create a vaultEndpoint then depending on the method choosen I use token authentication or AppRole authentication. There's no issue with the token authentication, however whenever I try to retrive a secret or even get the vaultToken to login with AppRole the URI is not absolute error occurs.

I 've seen in https://docs.oracle.com/javase/8/docs/api/java/net/URI.html that an URI is absolute when it specifies a scheme otherwise it is relative. But I think that my URI is specifing a scheme.

So I'm a bit lost here. Does anyone know what I am doing wrong ? Or why I get this error ?

I use spring-vault-core-2.2.0.RELEASE

Here's my code :

VaultEndpoint ep = VaultEndpoint.create(host, portInt);
    if (scheme != null) {
        ep.setScheme(scheme);
    }

    if (authMethod.equals("token")) {
        vaultTemplate = new VaultTemplate(ep, new TokenAuthentication(token));

    } else if (authMethod.equals("appRole")) {

        RestOperations restOperations = VaultClients.createRestTemplate();

        AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
                .roleId(AppRoleAuthenticationOptions.RoleId.provided(roleId))
                .secretId(AppRoleAuthenticationOptions.SecretId.wrapped(VaultToken.of(secretId))).build();

        vaultTemplate = new VaultTemplate(ep, new AppRoleAuthentication(options, restOperations));
    }
  }

I have the same error if I try to get the vaultToken :

            RestOperations restOperations = VaultClients.createRestTemplate();
        AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
                .roleId(AppRoleAuthenticationOptions.RoleId.provided(roleId))
                .secretId(AppRoleAuthenticationOptions.SecretId.wrapped(VaultToken.of(uncryptedSecretId))).build();

        AppRoleAuthentication appRoleAuth = new AppRoleAuthentication(options, restOperations);
        VaultToken appRoleToken = appRoleAuth.login();

Here is the error :

java.lang.IllegalArgumentException: URI is not absolute
    at java.net.URI.toURL(Unknown Source)
    at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:145)
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:98)
    at org.springframework.vault.client.VaultClients.lambda$createRestTemplate$0(VaultClients.java:128)
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
    at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:77)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:742)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:677)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:586)
    at org.springframework.vault.authentication.AppRoleAuthentication.getSecretId(AppRoleAuthentication.java:305)
    at org.springframework.vault.authentication.AppRoleAuthentication.getAppRoleLoginBody(AppRoleAuthentication.java:344)
    at org.springframework.vault.authentication.AppRoleAuthentication.createTokenUsingAppRole(AppRoleAuthentication.java:201)
    at org.springframework.vault.authentication.AppRoleAuthentication.login(AppRoleAuthentication.java:191)

Solution

  • After further investigation, the issue was how I instanciated the restTemplate. I added the spring context library to my project and implemented the AbstractVaultConfiguration class. This class contains a restOperations() function that solved my problem.

    This is how I solved the issue :

    public class AppRoleAuthenticationService extends AbstractVaultConfiguration {
    
    private String roleId;
    private String secretId;
    private String host;
    private String scheme;
    private String port;
    
    public AppRoleAuthenticationService(String roleId, String secretId, String host, String scheme, String port) {
        this.roleId = roleId;
        this.secretId = secretId;
        this.host = host;
        this.scheme = scheme;
        this.port = port;
    }
    
    @Override
    public VaultEndpoint vaultEndpoint() {
        int portInt = Integer.parseInt(port);
        VaultEndpoint ep = VaultEndpoint.create(host, portInt);
        if (scheme != null) {
            ep.setScheme(scheme);
        }
    
        return ep;
    }
    
    @Override
    public ClientAuthentication clientAuthentication() {
    
        AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
                .roleId(AppRoleAuthenticationOptions.RoleId.provided(roleId))
                .secretId(AppRoleAuthenticationOptions.SecretId.provided(secretId)).build();
    
        return new AppRoleAuthentication(options, restOperations());
    }
    

    }

    And then just use this class :

    AppRoleAuthenticationService appRoleAuth = new AppRoleAuthenticationService(roleId, 
          uncryptedSecretId, host, scheme, port);
    VaultEndpoint vaultEp = appRoleAuth.vaultEndpoint();
    ClientAuthentication auth = appRoleAuth.clientAuthentication();
    
    vaultTemplate = new VaultTemplate(vaultEp, auth);