imbajin commented on code in PR #2945:
URL: https://github.com/apache/hugegraph/pull/2945#discussion_r4301036873
##########
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/arthas/ArthasAPI.java:
##########
@@ -17,48 +17,110 @@
package org.apache.hugegraph.api.arthas;
+import java.net.InetAddress;
import java.util.HashMap;
import org.apache.hugegraph.api.API;
+import org.apache.hugegraph.auth.HugeAuthenticator;
+import org.apache.hugegraph.config.ConfigOption;
import org.apache.hugegraph.config.HugeConfig;
import org.apache.hugegraph.config.ServerOptions;
+import org.apache.hugegraph.core.GraphManager;
+import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.JsonUtil;
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
import com.codahale.metrics.annotation.Timed;
+import com.google.common.net.InetAddresses;
import com.taobao.arthas.agent.attach.ArthasAgent;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Singleton;
+import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.SecurityContext;
@Path("arthas")
@Singleton
@Tag(name = "ArthasAPI")
public class ArthasAPI extends API {
+ private static final Logger LOG = Log.logger(ArthasAPI.class);
+
@Context
private jakarta.inject.Provider<HugeConfig> configProvider;
@PUT
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
+ @RolesAllowed("admin")
@Operation(summary = "start arthas agent")
- public Object startArthas() {
+ public Object startArthas(@Context GraphManager manager,
+ @Context SecurityContext context) {
+ checkAccess(manager, context);
HugeConfig config = this.configProvider.get();
- HashMap<String, String> configMap = new HashMap<>(4);
- configMap.put("arthas.telnetPort",
config.get(ServerOptions.ARTHAS_TELNET_PORT));
- configMap.put("arthas.httpPort",
config.get(ServerOptions.ARTHAS_HTTP_PORT));
- configMap.put("arthas.ip", config.get(ServerOptions.ARTHAS_IP));
- configMap.put("arthas.disabledCommands",
- config.get(ServerOptions.ARTHAS_DISABLED_COMMANDS));
+ HashMap<String, String> configMap = arthasConfig(config);
String response = JsonUtil.toJson(configMap);
// Keep the optional MCP endpoint disabled without extending the
activation response.
configMap.put("arthas.mcpEndpoint", "");
+ // Do not let external Arthas properties override the validated local
listener.
+ configMap.put("arthas.config.overrideAll", "false");
+ configMap.put("arthas.tunnelServer", "");
ArthasAgent.attach(configMap);
return response;
}
+
+ static void checkAccess(GraphManager manager, SecurityContext context) {
+ // No-auth requests receive an anonymous admin role, so a role check
alone is insufficient.
+ if (!manager.requireAuthentication()) {
+ throw new ForbiddenException("HTTP Arthas activation requires
authentication; " +
+ "use bin/arthas.sh on the server host
instead");
+ }
+ if (context == null || context.getUserPrincipal() == null ||
+
HugeAuthenticator.USER_ANONY.equals(context.getUserPrincipal().getName()) ||
+ !context.isUserInRole("admin")) {
+ throw new ForbiddenException("Arthas activation requires an
authenticated administrator");
+ }
+ }
+
+ static HashMap<String, String> arthasConfig(HugeConfig config) {
+ HashMap<String, String> configMap = new HashMap<>(4);
+ configMap.put("arthas.telnetPort",
+ option(config, ServerOptions.ARTHAS_TELNET_PORT,
+ ServerOptions.ARTHAS_TELNET_PORT_LEGACY));
+ configMap.put("arthas.httpPort",
+ option(config, ServerOptions.ARTHAS_HTTP_PORT,
+ ServerOptions.ARTHAS_HTTP_PORT_LEGACY));
+ String ip = config.get(ServerOptions.ARTHAS_IP);
+ // Do not resolve arbitrary hostnames: their address may change after
validation.
+ ip = "localhost".equalsIgnoreCase(ip) ? "127.0.0.1" : ip;
+ E.checkArgument(InetAddresses.isInetAddress(ip) &&
+ InetAddresses.forString(ip).isLoopbackAddress(),
Review Comment:
Kept the existing API loopback-address compatibility, as requested by the
user, and added optional --target-ip to the helper. The same validated numeric
loopback address is used for attachment, Arthas boot, and cleanup; arbitrary
hostnames and remote addresses are rejected before attach. Defaults remain
127.0.0.1, with localhost mapped to it. Native checks pass for ::1 and
localhost, plus 127.0.0.2 on Linux; the documentation includes an IPv6 example.
##########
hugegraph-store/hg-store-node/pom.xml:
##########
@@ -121,15 +121,10 @@
<artifactId>hg-store-core</artifactId>
</dependency>
- <dependency>
- <groupId>com.taobao.arthas</groupId>
- <artifactId>arthas-agent-attach</artifactId>
- <version>3.6.4</version>
- </dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-packaging</artifactId>
Review Comment:
Moved arthas-packaging out of hg-store-node and into hg-store-dist as a
direct provided dependency. The prepare-arthas antrun property resolves and
extracts the bundle; the packaged Store boot JAR no longer contains
arthas-packaging, while lib/arthas remains available for the helper. The
license/inventory entry is retained because Server still ships the packaging
dependency and both distributions still include Arthas files.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]