Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/src/main/java/org/apache/atlas/AtlasConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public final class AtlasConstants {
public static final String ATLAS_SERVICES_ENABLED = "atlas.services.enabled";
public static final String CLUSTER_NAME_ATTRIBUTE = "clusterName";
public static final String DEFAULT_APP_PORT_STR = "21000";
public static final String DEFAULT_ATLAS_REST_ADDRESS = "http://localhost:21000";
public static final String DEFAULT_ATLAS_REST_ADDRESS = "http://localhost:21000";
public static final String DEFAULT_REST_NOTIFICATION_ADDRESS = "http://localhost:41000/rest";
public static final String DEFAULT_TYPE_VERSION = "1.0";
public static final int ATLAS_SHUTDOWN_HOOK_PRIORITY = 30;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@ public class RestNotification extends AbstractNotification {
private static final Logger LOG = LoggerFactory.getLogger(RestNotification.class);

private static final int BATCH_MAX_LENGTH_BYTES = AtlasConfiguration.NOTIFICATION_REST_BODY_MAX_LENGTH_BYTES.getInt();
private static final String ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT = "atlas.hook.rest.notification.address";
private static final String ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT = AtlasConfiguration.NOTIFICATION_HOOK_REST_ADDRESS.getPropertyName();
private static final String BASIC_AUTH_USERNAME = "atlas.rest.basic.auth.username";
private static final String BASIC_AUTH_PASSWORD = "atlas.rest.basic.auth.password";
private static final String DEFAULT_ATLAS_URL = "http://localhost:31000/";

private static final Map<NotificationType, String> PRODUCER_TOPIC_MAP = new HashMap<>();

Expand Down Expand Up @@ -115,11 +114,10 @@ private AtlasClientV2 setupAtlasClientV2(Configuration configuration) throws Atl
String[] atlasEndPoint = configuration.getStringArray(ATLAS_HOOK_REST_NOTIFICATION_ENDPOINT);

if (isEndpointNotSpecified(atlasEndPoint)) {
atlasEndPoint = configuration.getStringArray(AtlasConstants.ATLAS_REST_ADDRESS_KEY);
}

if (isEndpointNotSpecified(atlasEndPoint)) {
atlasEndPoint = new String[] {DEFAULT_ATLAS_URL};
throw new AtlasException("atlas.hook.rest.notification.address must be configured when REST notification is enabled. "
+ "Hook REST ingress is served only by rest-notification-webapp (port 41000); "
+ "the main Atlas webapp notification endpoint has been removed. "
+ "Example: " + AtlasConstants.DEFAULT_REST_NOTIFICATION_ADDRESS);
}

if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.atlas.AtlasClientV2;
import org.apache.atlas.AtlasConfiguration;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.AtlasException;
import org.apache.atlas.kafka.NotificationProvider;
import org.apache.atlas.notification.rest.RestNotification;
import org.apache.commons.configuration2.BaseConfiguration;
Expand Down Expand Up @@ -68,6 +69,7 @@ public void setup() throws Exception {
conf = ApplicationProperties.get();

conf.setProperty(AtlasConfiguration.NOTIFICATION_HOOK_REST_ENABLED.getPropertyName(), true);
conf.setProperty(AtlasConfiguration.NOTIFICATION_HOOK_REST_ADDRESS.getPropertyName(), "http://localhost:41000/rest");
conf.setProperty(NotificationProvider.CONF_ATLAS_HOOK_SPOOL_ENABLED, false);

notifier = NotificationProvider.get();
Expand Down Expand Up @@ -150,36 +152,48 @@ public void testRestNotificationEndpointPrefersHookRestAddress() throws Exceptio
assertEquals(configuredEndpoints[0], "http://atlas-rest.example.com:41000/rest");
}

@Test
public void testRestNotificationEndpointFallsBackToAtlasRestAddress() throws Exception {
@Test(expectedExceptions = AtlasException.class)
public void testRestNotificationFailsFastWhenHookAddressNotConfigured() throws Exception {
Configuration localConf = new BaseConfiguration();
localConf.setProperty("atlas.rest.address", "http://atlas-main.example.com:21000");
localConf.setProperty("atlas.rest.basic.auth.username", "admin");
localConf.setProperty("atlas.rest.basic.auth.password", "admin123");

RestNotification restNotification = new RestNotification(localConf);

String[] configuredEndpoints = getConfiguredBaseUrls(restNotification.atlasClientV2);

assertEquals(configuredEndpoints.length, 1);
assertEquals(configuredEndpoints[0], "http://atlas-main.example.com:21000");
new RestNotification(localConf);
}

@Test
public void testRestNotificationFallsBackToAtlasRestWhenNotificationAddressesAllBlank() throws Exception {
@Test(expectedExceptions = AtlasException.class)
public void testRestNotificationFailsFastWhenHookAddressesAllBlank() throws Exception {
Configuration localConf = new BaseConfiguration();
localConf.addProperty("atlas.hook.rest.notification.address", "");
localConf.addProperty("atlas.hook.rest.notification.address", " ");
localConf.setProperty("atlas.rest.address", "http://atlas-main.example.com:21000");
localConf.setProperty("atlas.rest.basic.auth.username", "admin");
localConf.setProperty("atlas.rest.basic.auth.password", "admin123");

RestNotification restNotification = new RestNotification(localConf);
new RestNotification(localConf);
}

String[] configuredEndpoints = getConfiguredBaseUrls(restNotification.atlasClientV2);
@Test(expectedExceptions = AtlasException.class)
public void testRestNotificationFailsFastWhenOnlyAtlasRestAddressConfigured() throws Exception {
Configuration localConf = new BaseConfiguration();
localConf.setProperty("atlas.rest.address", "http://atlas-main.example.com:21000");
localConf.setProperty("atlas.rest.basic.auth.username", "admin");
localConf.setProperty("atlas.rest.basic.auth.password", "admin123");

assertEquals(configuredEndpoints.length, 1);
assertEquals(configuredEndpoints[0], "http://atlas-main.example.com:21000");
new RestNotification(localConf);
}

@Test
public void testRestNotificationFailFastExceptionMessage() {
Configuration localConf = new BaseConfiguration();

try {
new RestNotification(localConf);
fail("Expected AtlasException when atlas.hook.rest.notification.address is not configured");
} catch (AtlasException e) {
assertTrue(e.getMessage().contains("atlas.hook.rest.notification.address must be configured"));
assertTrue(e.getMessage().contains("http://localhost:41000/rest"));
}
}

private String[] getConfiguredBaseUrls(AtlasClientV2 atlasClientV2) throws Exception {
Expand Down
132 changes: 0 additions & 132 deletions webapp/src/main/java/org/apache/atlas/web/rest/NotificationREST.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package org.apache.atlas.web.integration;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.sun.jersey.api.client.ClientResponse;
import org.apache.atlas.AtlasClientV2;
import org.apache.atlas.AtlasServiceException;
import org.apache.atlas.utils.TestResourceFileUtils;
Expand All @@ -30,40 +30,46 @@

import static org.apache.atlas.kafka.KafkaNotification.ATLAS_HOOK_TOPIC;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

/**
* ATLAS-5377: hook notification REST ingress was removed from the main Atlas webapp.
* Canonical endpoint is rest-notification-webapp only. These integration tests verify
* that POST /api/atlas/v2/notification/topic/{topicName} is not served on main webapp.
*/
public class NotificationRestIT extends BaseResourceIT {
@Test
public void unAuthPostNotification() throws IOException {
public void unAuthPostNotificationRejected() throws IOException {
AtlasClientV2 unAuthClient = new AtlasClientV2(atlasUrls, new String[] {"admin", "wr0ng_pa55w0rd"});

try {
unAuthClient.postNotificationToTopic(ATLAS_HOOK_TOPIC, new ArrayList<String>(Collections.singletonList("Dummy")));
unAuthClient.postNotificationToTopic(ATLAS_HOOK_TOPIC, new ArrayList<>(Collections.singletonList("Dummy")));

fail("Expected postNotificationToTopic to fail on main webapp");
} catch (AtlasServiceException e) {
assertNotNull(e.getStatus(), "expected server error code in the status");
}
}

@Test
public void postNotificationBasicTest() throws Exception {
public void notificationEndpointRemovedFromMainWebapp() throws Exception {
String dbName = "db_" + randomString();
String clusterName = "cl" + randomString();
String qualifiedName = dbName + "@" + clusterName;

String notificationString = TestResourceFileUtils.getJson("notifications/create-db")
.replaceAll("--name--", dbName).replaceAll("--clName--", clusterName)
.replace("\"--ts--\"", String.valueOf((new Date()).getTime()));

try {
atlasClientV2.postNotificationToTopic(ATLAS_HOOK_TOPIC, new ArrayList<String>(Collections.singletonList(notificationString)));
atlasClientV2.postNotificationToTopic(ATLAS_HOOK_TOPIC, new ArrayList<>(Collections.singletonList(notificationString)));

waitFor(MAX_WAIT_TIME, () -> {
ArrayNode results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, qualifiedName));

return results.size() == 1;
});
fail("Expected notification POST to fail — endpoint removed from main webapp (ATLAS-5377)");
} catch (AtlasServiceException e) {
assertNull(e.getStatus(), "expected no server error code in the status");
assertNotNull(e.getStatus(), "expected HTTP error when posting to removed endpoint");

assertTrue(e.getStatus().getStatusCode() != ClientResponse.Status.NO_CONTENT.getStatusCode(),
"notification POST must not return 204 on main webapp");
}
}
}