Skip to content

Commit e64e0e0

Browse files
authored
Fix in Leases section (#18)
1 parent ac3baa3 commit e64e0e0

File tree

3 files changed

+72
-32
lines changed

3 files changed

+72
-32
lines changed

build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ if (hasProperty("publish")) {
203203
id 'tledkov'
204204
name 'Taras Ledkov'
205205
206+
},
207+
developer {
208+
id 'henryx'
209+
name 'Enrico Bianchi'
210+
206211
}
207212
]
208213
}

src/main/java/io/github/jopenlibs/vault/api/Leases.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
/**
1313
* <p>The implementing class for operations on REST endpoints, under the "Leases" section of the
14-
* Vault HTTP API docs (https://www.vaultproject.io/docs/http/index.html).</p>
14+
* Vault HTTP API docs (<a href="https://www.vaultproject.io/docs/http/index.html">
15+
* https://www.vaultproject.io/docs/http/index.html</a>).</p>
1516
*
1617
* <p>This class is not intended to be constructed directly. Rather, it is meant to used by way of
1718
* <code>Vault</code> in a DSL-style builder pattern. See the Javadoc comments of each
@@ -51,22 +52,18 @@ public Leases withNameSpace(final String nameSpace) {
5152
*/
5253
public VaultResponse revoke(final String leaseId) throws VaultException {
5354
return retry(attempt -> {
54-
/**
55-
* 2019-03-21
56-
* Changed the Lease revoke url due to invalid path. Vault deprecated the original
57-
* path (/v1/sys/revoke) in favor of a new leases mount point (/v1/sys/leases/revoke)
58-
* https://github.com/hashicorp/vault/blob/master/CHANGELOG.md#080-august-9th-2017
59-
*/
55+
final String requestJson = Json.object().add("lease_id", leaseId).toString();
6056
final RestResponse restResponse = new Rest()//NOPMD
61-
.url(config.getAddress() + "/v1/sys/leases/revoke/" + leaseId)
57+
.url(config.getAddress() + "/v1/sys/leases/revoke")
6258
.header("X-Vault-Token", config.getToken())
6359
.header("X-Vault-Namespace", this.nameSpace)
6460
.header("X-Vault-Request", "true")
61+
.body(requestJson.getBytes(StandardCharsets.UTF_8))
6562
.connectTimeoutSeconds(config.getOpenTimeout())
6663
.readTimeoutSeconds(config.getReadTimeout())
6764
.sslVerification(config.getSslConfig().isVerify())
6865
.sslContext(config.getSslConfig().getSslContext())
69-
.put();
66+
.post();
7067

7168
// Validate response
7269
if (restResponse.getStatus() != 204) {
@@ -98,15 +95,15 @@ public VaultResponse revoke(final String leaseId) throws VaultException {
9895
public VaultResponse revokePrefix(final String prefix) throws VaultException {
9996
return retry(attempt -> {
10097
final RestResponse restResponse = new Rest()//NOPMD
101-
.url(config.getAddress() + "/v1/sys/revoke-prefix/" + prefix)
98+
.url(config.getAddress() + "/v1/sys/leases/revoke-prefix/" + prefix)
10299
.header("X-Vault-Token", config.getToken())
103100
.header("X-Vault-Namespace", this.nameSpace)
104101
.header("X-Vault-Request", "true")
105102
.connectTimeoutSeconds(config.getOpenTimeout())
106103
.readTimeoutSeconds(config.getReadTimeout())
107104
.sslVerification(config.getSslConfig().isVerify())
108105
.sslContext(config.getSslConfig().getSslContext())
109-
.put();
106+
.post();
110107

111108
// Validate response
112109
if (restResponse.getStatus() != 204) {
@@ -140,15 +137,15 @@ public VaultResponse revokePrefix(final String prefix) throws VaultException {
140137
public VaultResponse revokeForce(final String prefix) throws VaultException {
141138
return retry(attempt -> {
142139
final RestResponse restResponse = new Rest()//NOPMD
143-
.url(config.getAddress() + "/v1/sys/revoke-force/" + prefix)
140+
.url(config.getAddress() + "/v1/sys/leases/revoke-force/" + prefix)
144141
.header("X-Vault-Token", config.getToken())
145142
.header("X-Vault-Namespace", this.nameSpace)
146143
.header("X-Vault-Request", "true")
147144
.connectTimeoutSeconds(config.getOpenTimeout())
148145
.readTimeoutSeconds(config.getReadTimeout())
149146
.sslVerification(config.getSslConfig().isVerify())
150147
.sslContext(config.getSslConfig().getSslContext())
151-
.put();
148+
.post();
152149

153150
// Validate response
154151
if (restResponse.getStatus() != 204) {
@@ -188,7 +185,7 @@ public VaultResponse renew(final String leaseId, final long increment) throws Va
188185
return retry(attempt -> {
189186
final String requestJson = Json.object().add("increment", increment).toString();
190187
final RestResponse restResponse = new Rest()//NOPMD
191-
.url(config.getAddress() + "/v1/sys/renew/" + leaseId)
188+
.url(config.getAddress() + "/v1/sys/leases/renew/" + leaseId)
192189
.header("X-Vault-Token", config.getToken())
193190
.header("X-Vault-Namespace", this.nameSpace)
194191
.header("X-Vault-Request", "true")

src/test-integration/java/io/github/jopenlibs/vault/v1_11_4/api/LeasesTests.java

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,34 @@
22

33
import io.github.jopenlibs.vault.Vault;
44
import io.github.jopenlibs.vault.VaultException;
5+
import io.github.jopenlibs.vault.api.database.DatabaseRoleOptions;
6+
import io.github.jopenlibs.vault.response.DatabaseResponse;
57
import io.github.jopenlibs.vault.response.VaultResponse;
8+
import io.github.jopenlibs.vault.v1_11_4.util.DbContainer;
69
import io.github.jopenlibs.vault.v1_11_4.util.VaultContainer;
710
import java.io.IOException;
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.List;
814
import org.junit.Before;
915
import org.junit.BeforeClass;
1016
import org.junit.ClassRule;
1117
import org.junit.Test;
1218

1319
import static junit.framework.TestCase.assertEquals;
20+
import static junit.framework.TestCase.assertTrue;
1421

1522
/**
16-
* <p>Integration tests for the basic (i.e. "sys") Vault API operations.</p>
23+
* <p>Integration tests for the leases (i.e. "sys/leases") Vault API operations.</p>
1724
*
18-
* <p>Unfortunately, it's not really possible to fully test these endpoints with the current integration testing
19-
* strategy. The "generic" backend, used by the dev server, does not issue leases at all. You CAN obtain leases
20-
* by using the PKI backend, but those aren't renewable:</p>
21-
*
22-
* <p>https://github.com/hashicorp/vault/issues/877</p>
23-
*
24-
* <p>Therefore, these revocation tests are basically just testing that the Vault server returns a 204 status
25-
* code. Which isn't much of a test, since Vault routinely returns 204 even if you pass a non-existent lease ID.</p>
26-
*
27-
* <p>In the future, we may be shifting to an integration testing approach that uses a "real" Vault server
28-
* instance, running in a Docker container (see: https://github.com/BetterCloud/vault-java-driver/pull/25). At
29-
* that time, these tests should be re-visited and better implemented.</p>
30-
*
31-
* TODO: Revisit, now that we're using testcontainers
25+
* According to the Vault documentation, it is possible to use a dynamic secret like database to
26+
* test these methods
3227
*/
3328
public class LeasesTests {
3429

30+
@ClassRule
31+
public static final DbContainer dbContainer = new DbContainer();
32+
3533
@ClassRule
3634
public static final VaultContainer container = new VaultContainer();
3735

@@ -40,29 +38,69 @@ public class LeasesTests {
4038
@BeforeClass
4139
public static void setupClass() throws IOException, InterruptedException {
4240
container.initAndUnsealVault();
41+
container.setupBackendDatabase(DbContainer.hostname);
4342
}
4443

4544
@Before
4645
public void setup() throws VaultException {
4746
vault = container.getRootVault();
4847
}
4948

49+
public DatabaseResponse generateCredentials() throws VaultException {
50+
List<String> creationStatements = new ArrayList<>();
51+
creationStatements.add(
52+
"CREATE USER \"{{name}}\" WITH PASSWORD '{{password}}';"
53+
+ "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";");
54+
55+
DatabaseResponse databaseResponse = vault.database().createOrUpdateRole("new-role",
56+
new DatabaseRoleOptions().dbName("postgres")
57+
.creationStatements(creationStatements));
58+
assertEquals(204, databaseResponse.getRestResponse().getStatus());
59+
60+
DatabaseResponse credsResponse = vault.database().creds("new-role");
61+
assertEquals(200, credsResponse.getRestResponse().getStatus());
62+
63+
assertTrue(credsResponse.getCredential().getUsername().contains("new-role"));
64+
65+
return credsResponse;
66+
}
67+
5068
@Test
5169
public void testRevoke() throws VaultException {
52-
final VaultResponse response = vault.leases().revoke("sys/revoke-prefix/dummy");
70+
DatabaseResponse credsResponse = this.generateCredentials();
71+
72+
final VaultResponse response = vault.leases().revoke(credsResponse.getLeaseId());
5373
assertEquals(204, response.getRestResponse().getStatus());
5474
}
5575

5676
@Test
5777
public void testRevokePrefix() throws VaultException {
58-
final VaultResponse response = vault.leases().revokePrefix("sys/revoke-prefix/dummy");
78+
DatabaseResponse credsResponse = this.generateCredentials();
79+
80+
String prefix = Arrays.stream(credsResponse.getLeaseId().split("([^/]+)$"))
81+
.map(str -> str.substring(0, str.length() - 1)).findFirst().get();
82+
83+
final VaultResponse response = vault.leases().revokePrefix(prefix);
5984
assertEquals(204, response.getRestResponse().getStatus());
6085
}
6186

6287
@Test
6388
public void testRevokeForce() throws VaultException {
64-
final VaultResponse response = vault.leases().revokeForce("sys/revoke-prefix/dummy");
89+
DatabaseResponse credsResponse = this.generateCredentials();
90+
91+
String prefix = Arrays.stream(credsResponse.getLeaseId().split("([^/]+)$"))
92+
.map(str -> str.substring(0, str.length() - 1)).findFirst().get();
93+
94+
final VaultResponse response = vault.leases().revokeForce(prefix);
6595
assertEquals(204, response.getRestResponse().getStatus());
6696
}
6797

98+
@Test
99+
public void testRenew() throws VaultException {
100+
DatabaseResponse credsResponse = this.generateCredentials();
101+
102+
final VaultResponse response = vault.leases().renew(credsResponse.getLeaseId(),
103+
credsResponse.getLeaseDuration());
104+
assertEquals(200, response.getRestResponse().getStatus());
105+
}
68106
}

0 commit comments

Comments
 (0)