summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorØyvind Grønnesby <oyving@verizonmedia.com>2021-03-02 13:09:01 +0100
committerGitHub <noreply@github.com>2021-03-02 13:09:01 +0100
commitbfd326596ca51f9a0725cd8595ab67dcead3aeb7 (patch)
tree2540fbfd5f0e951366ac33e110daca5864d43bfa
parente1a6e35483ed567584b4fbc7e65e4c9e01b30ef1 (diff)
parent11eb06c0818e97a8eff09029cbbe0ea26fbfa06f (diff)
Merge pull request #16735 from vespa-engine/olaa/delete-secret-store
Delete tenant secret store
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopTenantSecretService.java3
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/TenantSecretService.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java25
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java26
6 files changed, 60 insertions, 4 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopTenantSecretService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopTenantSecretService.java
index 9f273723c9c..f0d172934ba 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopTenantSecretService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopTenantSecretService.java
@@ -11,4 +11,7 @@ public class NoopTenantSecretService implements TenantSecretService {
@Override
public void addSecretStore(TenantName tenant, TenantSecretStore tenantSecretStore, String externalId) {}
+ @Override
+ public void deleteSecretStore(TenantName tenant, TenantSecretStore tenantSecretStore) {}
+
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/TenantSecretService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/TenantSecretService.java
index bac5a012f79..c8320b9a1cc 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/TenantSecretService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/TenantSecretService.java
@@ -10,4 +10,6 @@ public interface TenantSecretService {
void addSecretStore(TenantName tenant, TenantSecretStore tenantSecretStore, String externalId);
+ void deleteSecretStore(TenantName tenant, TenantSecretStore tenantSecretStore);
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java
index 519c08b66f5..22fa25fc711 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java
@@ -167,6 +167,12 @@ public abstract class LockedTenant {
secretStores.add(tenantSecretStore);
return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, secretStores);
}
+
+ public Cloud withoutSecretStore(TenantSecretStore tenantSecretStore) {
+ ArrayList<TenantSecretStore> secretStores = new ArrayList<>(tenantSecretStores);
+ secretStores.remove(tenantSecretStore);
+ return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, secretStores);
+ }
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 3649bc2ac80..23f62ee3cf5 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -313,6 +313,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
private HttpResponse handleDELETE(Path path, HttpRequest request) {
if (path.matches("/application/v4/tenant/{tenant}")) return deleteTenant(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/key")) return removeDeveloperKey(path.get("tenant"), request);
+ if (path.matches("/application/v4/tenant/{tenant}/secret-store/{name}")) return deleteSecretStore(path.get("tenant"), path.get("name"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}")) return deleteApplication(path.get("tenant"), path.get("application"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deployment")) return removeAllProdDeployments(path.get("tenant"), path.get("application"));
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying")) return cancelDeploy(path.get("tenant"), path.get("application"), "default", "all");
@@ -702,6 +703,30 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new MessageResponse("Configured secret store: " + tenantSecretStore);
}
+ private HttpResponse deleteSecretStore(String tenantName, String name, HttpRequest request) {
+ var tenant = (CloudTenant) controller.tenants().require(TenantName.from(tenantName));
+
+ var optionalSecretStore = tenant.tenantSecretStores().stream()
+ .filter(secretStore -> secretStore.getName().equals(name))
+ .findFirst();
+
+ if (optionalSecretStore.isEmpty())
+ return ErrorResponse.notFoundError("Could not delete secret store '" + name + "': Secret store not found");
+
+ var tenantSecretStore = optionalSecretStore.get();
+ controller.serviceRegistry().tenantSecretService().deleteSecretStore(tenant.name(), tenantSecretStore);
+ controller.tenants().lockOrThrow(tenant.name(), LockedTenant.Cloud.class, lockedTenant -> {
+ lockedTenant = lockedTenant.withoutSecretStore(tenantSecretStore);
+ controller.tenants().store(lockedTenant);
+ });
+ var slime = new Slime();
+ var cursor = slime.setObject();
+ cursor.setString("name", tenantSecretStore.getName());
+ cursor.setString("awsId", tenantSecretStore.getAwsId());
+ cursor.setString("role", tenantSecretStore.getRole());
+ return new SlimeJsonResponse(slime);
+ }
+
private HttpResponse patchApplication(String tenantName, String applicationName, HttpRequest request) {
Inspector requestObject = toSlime(request.getData()).get();
StringJoiner messageBuilder = new StringJoiner("\n").setEmptyValue("No applicable changes.");
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
index 136b37b02e1..6ffac36fd6a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
@@ -212,7 +212,7 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg
}
@Override
- public TenantSecretService tenantSecretService() {
+ public NoopTenantSecretService tenantSecretService() {
return tenantSecretService;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
index 6d8a1b6c025..88307018385 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
@@ -20,6 +20,7 @@ import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest;
import com.yahoo.vespa.hosted.controller.security.Auth0Credentials;
import com.yahoo.vespa.hosted.controller.security.CloudTenantSpec;
import com.yahoo.vespa.hosted.controller.security.Credentials;
+import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import org.junit.Before;
import org.junit.Test;
@@ -28,9 +29,7 @@ import java.util.Collections;
import java.util.Optional;
import java.util.Set;
-import static com.yahoo.application.container.handler.Request.Method.GET;
-import static com.yahoo.application.container.handler.Request.Method.POST;
-import static com.yahoo.application.container.handler.Request.Method.PUT;
+import static com.yahoo.application.container.handler.Request.Method.*;
import static com.yahoo.vespa.hosted.controller.restapi.application.ApplicationApiTest.createApplicationSubmissionData;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -183,6 +182,27 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
"}", 200);
}
+ @Test
+ public void delete_secret_store() {
+ var deleteRequest =
+ request("/application/v4/tenant/scoober/secret-store/secret-foo", DELETE)
+ .roles(Set.of(Role.administrator(tenantName)));
+ tester.assertResponse(deleteRequest, "{" +
+ "\"error-code\":\"NOT_FOUND\"," +
+ "\"message\":\"Could not delete secret store 'secret-foo': Secret store not found\"" +
+ "}", 404);
+
+ tester.controller().tenants().lockOrThrow(tenantName, LockedTenant.Cloud.class, lockedTenant -> {
+ lockedTenant = lockedTenant.withSecretStore(new TenantSecretStore("secret-foo", "123", "some-role"));
+ tester.controller().tenants().store(lockedTenant);
+ });
+ var tenant = (CloudTenant) tester.controller().tenants().require(tenantName);
+ assertEquals(1, tenant.tenantSecretStores().size());
+ tester.assertResponse(deleteRequest, "{\"name\":\"secret-foo\",\"awsId\":\"123\",\"role\":\"some-role\"}", 200);
+ tenant = (CloudTenant) tester.controller().tenants().require(tenantName);
+ assertEquals(0, tenant.tenantSecretStores().size());
+ }
+
private ApplicationPackageBuilder prodBuilder() {
return new ApplicationPackageBuilder()
.instances("default")