Allow db wipeouts in non-prod/sandbox enviroments (#1263)

* Allow db wipeouts in non-prod/sandbox enviroments
This commit is contained in:
Weimin Yu 2021-08-03 17:41:10 -04:00 committed by GitHub
parent 917b34701f
commit fa74048916
4 changed files with 42 additions and 33 deletions

View file

@ -22,7 +22,7 @@ import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger; import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryEnvironment;
import google.registry.persistence.PersistenceModule.SchemaManagerConnection; import google.registry.persistence.PersistenceModule.SchemaManagerConnection;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.Response; import google.registry.request.Response;
@ -48,22 +48,18 @@ import javax.inject.Inject;
public class WipeOutCloudSqlAction implements Runnable { public class WipeOutCloudSqlAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private static final FluentLogger logger = FluentLogger.forEnclosingClass();
// As a short-lived class, hardcode allowed projects here instead of using config files. private static final ImmutableSet<RegistryEnvironment> FORBIDDEN_ENVIRONMENTS =
private static final ImmutableSet<String> ALLOWED_PROJECTS = ImmutableSet.of(RegistryEnvironment.PRODUCTION, RegistryEnvironment.SANDBOX);
ImmutableSet.of("domain-registry-qa");
private final String projectId;
private final Supplier<Connection> connectionSupplier; private final Supplier<Connection> connectionSupplier;
private final Response response; private final Response response;
private final Retrier retrier; private final Retrier retrier;
@Inject @Inject
WipeOutCloudSqlAction( WipeOutCloudSqlAction(
@Config("projectId") String projectId,
@SchemaManagerConnection Supplier<Connection> connectionSupplier, @SchemaManagerConnection Supplier<Connection> connectionSupplier,
Response response, Response response,
Retrier retrier) { Retrier retrier) {
this.projectId = projectId;
this.connectionSupplier = connectionSupplier; this.connectionSupplier = connectionSupplier;
this.response = response; this.response = response;
this.retrier = retrier; this.retrier = retrier;
@ -73,9 +69,9 @@ public class WipeOutCloudSqlAction implements Runnable {
public void run() { public void run() {
response.setContentType(PLAIN_TEXT_UTF_8); response.setContentType(PLAIN_TEXT_UTF_8);
if (!ALLOWED_PROJECTS.contains(projectId)) { if (FORBIDDEN_ENVIRONMENTS.contains(RegistryEnvironment.get())) {
response.setStatus(SC_FORBIDDEN); response.setStatus(SC_FORBIDDEN);
response.setPayload("Wipeout is not allowed in " + projectId); response.setPayload("Wipeout is not allowed in " + RegistryEnvironment.get());
return; return;
} }
@ -90,11 +86,11 @@ public class WipeOutCloudSqlAction implements Runnable {
}, },
e -> !(e instanceof SQLException)); e -> !(e instanceof SQLException));
response.setStatus(SC_OK); response.setStatus(SC_OK);
response.setPayload("Wiped out Cloud SQL in " + projectId); response.setPayload("Wiped out Cloud SQL in " + RegistryEnvironment.get());
} catch (RuntimeException e) { } catch (RuntimeException e) {
logger.atSevere().withCause(e).log("Failed to wipe out Cloud SQL data."); logger.atSevere().withCause(e).log("Failed to wipe out Cloud SQL data.");
response.setStatus(SC_INTERNAL_SERVER_ERROR); response.setStatus(SC_INTERNAL_SERVER_ERROR);
response.setPayload("Failed to wipe out Cloud SQL in " + projectId); response.setPayload("Failed to wipe out Cloud SQL in " + RegistryEnvironment.get());
} }
} }

View file

@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger; import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.Response; import google.registry.request.Response;
import google.registry.request.auth.Auth; import google.registry.request.auth.Auth;
@ -49,9 +50,8 @@ public class WipeoutDatastoreAction implements Runnable {
private static final String PIPELINE_NAME = "bulk_delete_datastore_pipeline"; private static final String PIPELINE_NAME = "bulk_delete_datastore_pipeline";
// As a short-lived class, hardcode allowed projects here instead of using config files. private static final ImmutableSet<RegistryEnvironment> FORBIDDEN_ENVIRONMENTS =
private static final ImmutableSet<String> ALLOWED_PROJECTS = ImmutableSet.of(RegistryEnvironment.PRODUCTION, RegistryEnvironment.SANDBOX);
ImmutableSet.of("domain-registry-qa");
private final String projectId; private final String projectId;
private final String jobRegion; private final String jobRegion;
@ -80,9 +80,9 @@ public class WipeoutDatastoreAction implements Runnable {
public void run() { public void run() {
response.setContentType(PLAIN_TEXT_UTF_8); response.setContentType(PLAIN_TEXT_UTF_8);
if (!ALLOWED_PROJECTS.contains(projectId)) { if (FORBIDDEN_ENVIRONMENTS.contains(RegistryEnvironment.get())) {
response.setStatus(SC_FORBIDDEN); response.setStatus(SC_FORBIDDEN);
response.setPayload("Wipeout is not allowed in " + projectId); response.setPayload("Wipeout is not allowed in " + RegistryEnvironment.get());
return; return;
} }

View file

@ -28,6 +28,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import google.registry.config.RegistryEnvironment;
import google.registry.testing.FakeClock; import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse; import google.registry.testing.FakeResponse;
import google.registry.testing.FakeSleeper; import google.registry.testing.FakeSleeper;
@ -73,8 +74,7 @@ public class WipeOutCloudSqlActionTest {
@Test @Test
void run_projectAllowed() throws Exception { void run_projectAllowed() throws Exception {
WipeOutCloudSqlAction action = WipeOutCloudSqlAction action = new WipeOutCloudSqlAction(() -> conn, response, retrier);
new WipeOutCloudSqlAction("domain-registry-qa", () -> conn, response, retrier);
action.run(); action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK); assertThat(response.getStatus()).isEqualTo(SC_OK);
verify(stmt, times(1)).executeQuery(anyString()); verify(stmt, times(1)).executeQuery(anyString());
@ -84,18 +84,21 @@ public class WipeOutCloudSqlActionTest {
@Test @Test
void run_projectNotAllowed() { void run_projectNotAllowed() {
WipeOutCloudSqlAction action = try {
new WipeOutCloudSqlAction("domain-registry", () -> conn, response, retrier); RegistryEnvironment.SANDBOX.setup();
WipeOutCloudSqlAction action = new WipeOutCloudSqlAction(() -> conn, response, retrier);
action.run(); action.run();
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN); assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
verifyNoInteractions(stmt); verifyNoInteractions(stmt);
} finally {
RegistryEnvironment.UNITTEST.setup();
}
} }
@Test @Test
void run_nonRetrieableFailure() throws Exception { void run_nonRetrieableFailure() throws Exception {
doThrow(new SQLException()).when(conn).getMetaData(); doThrow(new SQLException()).when(conn).getMetaData();
WipeOutCloudSqlAction action = WipeOutCloudSqlAction action = new WipeOutCloudSqlAction(() -> conn, response, retrier);
new WipeOutCloudSqlAction("domain-registry-qa", () -> conn, response, retrier);
action.run(); action.run();
assertThat(response.getStatus()).isEqualTo(SC_INTERNAL_SERVER_ERROR); assertThat(response.getStatus()).isEqualTo(SC_INTERNAL_SERVER_ERROR);
verifyNoInteractions(stmt); verifyNoInteractions(stmt);
@ -104,8 +107,7 @@ public class WipeOutCloudSqlActionTest {
@Test @Test
void run_retrieableFailure() throws Exception { void run_retrieableFailure() throws Exception {
when(conn.getMetaData()).thenThrow(new RuntimeException()).thenReturn(metaData); when(conn.getMetaData()).thenThrow(new RuntimeException()).thenReturn(metaData);
WipeOutCloudSqlAction action = WipeOutCloudSqlAction action = new WipeOutCloudSqlAction(() -> conn, response, retrier);
new WipeOutCloudSqlAction("domain-registry-qa", () -> conn, response, retrier);
action.run(); action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK); assertThat(response.getStatus()).isEqualTo(SC_OK);
verify(stmt, times(1)).executeQuery(anyString()); verify(stmt, times(1)).executeQuery(anyString());

View file

@ -25,6 +25,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import google.registry.beam.BeamActionTestBase; import google.registry.beam.BeamActionTestBase;
import google.registry.config.RegistryEnvironment;
import google.registry.testing.FakeClock; import google.registry.testing.FakeClock;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,12 +36,22 @@ class WipeOutDatastoreActionTest extends BeamActionTestBase {
@Test @Test
void run_projectNotAllowed() { void run_projectNotAllowed() {
try {
RegistryEnvironment.SANDBOX.setup();
WipeoutDatastoreAction action = WipeoutDatastoreAction action =
new WipeoutDatastoreAction( new WipeoutDatastoreAction(
"domain-registry", "us-central1", "gs://some-bucket", clock, response, dataflow); "domain-registry-sandbox",
"us-central1",
"gs://some-bucket",
clock,
response,
dataflow);
action.run(); action.run();
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN); assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
verifyNoInteractions(dataflow); verifyNoInteractions(dataflow);
} finally {
RegistryEnvironment.UNITTEST.setup();
}
} }
@Test @Test