I installed Vault locally. I was able to start local dev server and write/read some secrets into Vault kv based on this official tutorial https://learn.hashicorp.com/vault/
Then I wanted to create some very basic Java/Spring Boot demo client that would connect to my local Vault dev server in order to write/read secrets. I read Baeldung tutorial for inspiration https://www.baeldung.com/spring-vault.
This is my vault-config.properties:
vault.uri=http://127.0.0.1:8200
vault.token=s.EXg6MQwUuB63Z7Xra4zybOut (token generated after the latest start of server)
Then service class:
@Service
public class CredentialsService {
@Autowired
private VaultTemplate vaultTemplate;
public void secureCredentials(Credentials credentials) throws URISyntaxException {
vaultTemplate.write("credentials/myapp", credentials);
}
public Credentials accessCredentials() throws URISyntaxException {
VaultResponseSupport<Credentials> response = vaultTemplate.read("credentials/myapp", Credentials.class);
return response.getData();
}
}
Configuration class:
@Configuration
public class VaultConfig extends AbstractVaultConfiguration {
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("s.EXg6MQwUuB63Z7Xra4zybOut");
}
@Override
public VaultEndpoint vaultEndpoint() {
return VaultEndpoint.create("host", 8200);
}
}
and this:
@Configuration
@PropertySource(value = { "vault-config.properties" })
@Import(value = EnvironmentVaultConfiguration.class)
public class VaultEnvironmentConfig {
}
One domain object:
public class Credentials {
private String username;
private String password;
public Credentials() {
}
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
@Override
public String toString() {
return "Credential [username=" + username + ", password=" + password + "]";
}
}
And finally my main Spring Boot class:
@RestController
@ComponentScan
@SpringBootApplication
public class SpringVaultTutorial {
@Autowired
CredentialsService credentialsService;
@RequestMapping("/")
String home() throws URISyntaxException {
Credentials credentials = new Credentials("oliver","exxeta123");
credentialsService.secureCredentials(credentials);
return credentialsService.accessCredentials().getUsername().toString();
}
public static void main(String[] args) {
SpringApplication.run(SpringVaultTutorial.class, args);
}
}
Main class should write secret and then immediately read it and print username. But I am getting this error message:
There was an unexpected error (type=Internal Server Error, status=500). I/O error on POST request for "https://host:8200/v1/credentials/myapp": host; nested exception is java.net.UnknownHostException: host
Does somebody have a clue what can be wrong?
EDIT: Based on advice from Arun I followed this tutorial https://drissamri.be/blog/java/enable-https-in-spring-boot/
I have been trying both approaches. 1) Modify application.properties:
server.port: 8443
server.ssl.key-store: keystore.p12
server.ssl.key-store-password: oliver
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat
security.require-ssl=true
After modification, when I call https://localhost:8443, I am getting Exception: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710) ~[na:1.8.0_121] at sun.security.ssl.InputRecord.read(InputRecord.java:527) ~[na:1.8.0_121] at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) ~[na:1.8.0_121] at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) ~[na:1.8.0_121] at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) ~[na:1.8.0_121] at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) ~[na:1.8.0_121]
2) Second approach based on tutorial is about adding ConnectorConfig class:
@Configuration
public class ConnectorConfig {
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat =
new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(redirectConnector());
return tomcat;
}
private Connector redirectConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(8090);
connector.setSecure(false);
connector.setRedirectPort(8443);
return connector;
}
}
But after calling localhost:8090 that redirects me to https://localhost:8443, I am getting the same error: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710) ~
Now the question is: Do I have to configure something also on the Vault side regarding certificate? Or do you think there could be some certificate problem on Java client side? But I thing if there was Java certificate problem, exception would be thrown already during startup.