Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: IP white list #2299

Merged
merged 9 commits into from
Oct 2, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,38 @@

package org.apache.hugegraph.api.filter;

import static org.apache.hugegraph.config.ServerOptions.WHITE_IP_STATUS;

import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.xml.bind.DatatypeConverter;

import org.apache.hugegraph.auth.HugeAuthenticator;
import org.apache.hugegraph.auth.HugeAuthenticator.RequiredPerm;
import org.apache.hugegraph.auth.HugeAuthenticator.RolePerm;
import org.apache.hugegraph.auth.HugeAuthenticator.User;
import org.apache.hugegraph.auth.RolePermission;
import org.apache.hugegraph.config.HugeConfig;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.utils.Charsets;
import org.slf4j.Logger;

import com.alipay.remoting.util.StringUtils;
import com.google.common.collect.ImmutableList;

import jakarta.annotation.Priority;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.NotAuthorizedException;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
Expand All @@ -35,23 +59,6 @@
import jakarta.ws.rs.core.SecurityContext;
import jakarta.ws.rs.core.UriInfo;
import jakarta.ws.rs.ext.Provider;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.lang3.StringUtils;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.utils.Charsets;
import org.slf4j.Logger;

import org.apache.hugegraph.auth.HugeAuthenticator;
import org.apache.hugegraph.auth.HugeAuthenticator.RequiredPerm;
import org.apache.hugegraph.auth.HugeAuthenticator.RolePerm;
import org.apache.hugegraph.auth.HugeAuthenticator.User;
import org.apache.hugegraph.auth.RolePermission;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import com.google.common.collect.ImmutableList;

@Provider
@PreMatching
Expand All @@ -68,12 +75,20 @@
"versions"
);

private static String whiteIpStatus;

private static final String STRING_WHITE_IP_LIST = "whiteiplist";
private static final String STRING_ENABLE = "enable";

@Context
private jakarta.inject.Provider<GraphManager> managerProvider;

@Context
private jakarta.inject.Provider<Request> requestProvider;

@Context
private jakarta.inject.Provider<HugeConfig> configProvider;

@Override
public void filter(ContainerRequestContext context) throws IOException {
if (AuthenticationFilter.isWhiteAPI(context)) {
Expand Down Expand Up @@ -102,6 +117,26 @@
path = request.getRequestURI();
}

// Check whiteIp
if (whiteIpStatus == null) {
whiteIpStatus = this.configProvider.get().get(WHITE_IP_STATUS);
}

if (Objects.equals(whiteIpStatus, STRING_ENABLE) && request != null) {
peer = request.getRemoteAddr() + ":" + request.getRemotePort();
path = request.getRequestURI();

Check warning on line 127 in hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java#L126-L127

Added lines #L126 - L127 were not covered by tests

String remoteIp = request.getRemoteAddr();
Set<String> whiteIpList = manager.authManager().listWhiteIPs();
boolean whiteIpEnabled = manager.authManager().getWhiteIpStatus();

Check warning on line 131 in hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java#L129-L131

Added lines #L129 - L131 were not covered by tests
if (!path.contains(STRING_WHITE_IP_LIST) && whiteIpEnabled &&
!whiteIpList.contains(remoteIp)) {
throw new ForbiddenException(
String.format("Remote ip '%s' is not permitted",

Check warning on line 135 in hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java#L134-L135

Added lines #L134 - L135 were not covered by tests
remoteIp));
}
}

Map<String, String> credentials = new HashMap<>();
// Extract authentication credentials
String auth = context.getHeaderString(HttpHeaders.AUTHORIZATION);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package org.apache.hugegraph.api.profile;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.api.filter.StatusFilter;
import org.apache.hugegraph.auth.AuthManager;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import org.slf4j.Logger;

import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableMap;

import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;

@Path("whiteiplist")
@Singleton
public class WhiteIpListAPI extends API {

Check warning on line 53 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L53

Added line #L53 was not covered by tests

private static final Logger LOG = Log.logger(WhiteIpListAPI.class);

Check warning on line 55 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L55

Added line #L55 was not covered by tests

@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Map<String, Object> list(@Context GraphManager manager) {
LOG.debug("List white ips");
AuthManager authManager = manager.authManager();
Set<String> whiteIpList = authManager.listWhiteIPs();
return ImmutableMap.of("whiteIpList", whiteIpList);

Check warning on line 65 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L62-L65

Added lines #L62 - L65 were not covered by tests
}

@POST
@Timed
@StatusFilter.Status(StatusFilter.Status.ACCEPTED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Map<String, Object> updateWhiteIPs(@Context GraphManager manager, Map<String, Object> actionMap) {
E.checkArgument(actionMap != null,
"Missing argument: actionMap");
Set<String> whiteIpList = manager.authManager().listWhiteIPs();
Object ipListRaw = actionMap.get("ips");
E.checkArgument(ipListRaw instanceof List,
"Invalid ips type '%s', must be list", ipListRaw.getClass());
List<String> ipList = (List<String>) ipListRaw;
Object actionRaw = actionMap.get("action");

Check warning on line 82 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L77-L82

Added lines #L77 - L82 were not covered by tests
E.checkArgument(actionRaw != null,
"Missing argument: action");
E.checkArgument(actionRaw instanceof String,

Check warning on line 85 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L85

Added line #L85 was not covered by tests
"Invalid action type '%s', must be string",
actionRaw.getClass());
String action = (String) actionRaw;
E.checkArgument(StringUtils.isNotEmpty(action),

Check warning on line 89 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L87-L89

Added lines #L87 - L89 were not covered by tests
"Missing argument: action");
Set<String> existedIPs = new HashSet<>();
Set<String> loadedIPs = new HashSet<>();
Set<String> illegalIPs = new HashSet<>();
Map<String, Object> result = new HashMap<>();

Check warning on line 94 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L91-L94

Added lines #L91 - L94 were not covered by tests
for (String ip : ipList) {
if (whiteIpList.contains(ip)) {
existedIPs.add(ip);
continue;

Check warning on line 98 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L97-L98

Added lines #L97 - L98 were not covered by tests
}
if ("load".equals(action)) {
boolean rightIp = checkIp(ip) ? loadedIPs.add(ip) : illegalIPs.add(ip);
}
}

Check warning on line 103 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L103

Added line #L103 was not covered by tests
switch (action) {
case "load":
LOG.debug("Load to white ip list");
result.put("existed_ips", existedIPs);
result.put("added_ips", loadedIPs);

Check warning on line 108 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L106-L108

Added lines #L106 - L108 were not covered by tests
if (!illegalIPs.isEmpty()) {
result.put("illegal_ips", illegalIPs);

Check warning on line 110 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L110

Added line #L110 was not covered by tests
}
whiteIpList.addAll(loadedIPs);
break;

Check warning on line 113 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L112-L113

Added lines #L112 - L113 were not covered by tests
case "remove":
LOG.debug("Remove from white ip list");
result.put("removed_ips", existedIPs);
result.put("non_existed_ips", loadedIPs);
whiteIpList.removeAll(existedIPs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to set the type of whiteIpList to Set<String>

break;

Check warning on line 119 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L115-L119

Added lines #L115 - L119 were not covered by tests
default:
throw new AssertionError(String.format("Invalid action '%s', " +

Check warning on line 121 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L121

Added line #L121 was not covered by tests
"supported action is " +
"'load' or 'remove'",
action));
}
manager.authManager().setWhiteIPs(whiteIpList);
return result;

Check warning on line 127 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L126-L127

Added lines #L126 - L127 were not covered by tests
}

@PUT
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Map<String, Object> updateStatus(@Context GraphManager manager, @QueryParam("status") String status) {
LOG.debug("Enable or disable white ip list");

Check warning on line 135 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L135

Added line #L135 was not covered by tests
E.checkArgument("true".equals(status) ||
"false".equals(status),
"Invalid status, valid status is 'true' or 'false'");
boolean open = Boolean.parseBoolean(status);
manager.authManager().enabledWhiteIpList(open);
Map<String, Object> map = new HashMap<>();
map.put("WhiteIpListOpen", open);
return map;

Check warning on line 143 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L139-L143

Added lines #L139 - L143 were not covered by tests
}

private boolean checkIp(String ipStr) {
String ip = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."

Check warning on line 147 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L147

Added line #L147 was not covered by tests
+ "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
Pattern pattern = Pattern.compile(ip);
Matcher matcher = pattern.matcher(ipStr);
return matcher.matches();

Check warning on line 153 in hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/WhiteIpListAPI.java#L151-L153

Added lines #L151 - L153 were not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,26 @@
}
}

@Override
public Set<String> listWhiteIPs() {
return this.authManager.listWhiteIPs();

Check warning on line 1573 in hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java#L1573

Added line #L1573 was not covered by tests
}

@Override
public void setWhiteIPs(Set<String> whiteIpList) {
this.authManager.setWhiteIPs(whiteIpList);
}

Check warning on line 1579 in hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java#L1578-L1579

Added lines #L1578 - L1579 were not covered by tests

@Override
public boolean getWhiteIpStatus() {
return this.authManager.getWhiteIpStatus();

Check warning on line 1583 in hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java#L1583

Added line #L1583 was not covered by tests
}

@Override
public void enabledWhiteIpList(boolean status) {
this.authManager.enabledWhiteIpList(status);
}

Check warning on line 1589 in hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java#L1588-L1589

Added lines #L1588 - L1589 were not covered by tests

@Override
public String loginUser(String username, String password) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,12 @@ public static synchronized ServerOptions instance() {
disallowEmpty(),
true
);
}

public static final ConfigOption<String> WHITE_IP_STATUS =
new ConfigOption<>(
"white_ip.status",
"The status of whether enable white ip.",
disallowEmpty(),
"disable"
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,12 @@ public interface AuthManager {
UserWithRole validateUser(String username, String password);

UserWithRole validateUser(String token);

Set<String> listWhiteIPs();

void setWhiteIPs(Set<String> whiteIpList);

boolean getWhiteIpStatus();
SunnyBoy-WYH marked this conversation as resolved.
Show resolved Hide resolved

void enabledWhiteIpList(boolean status);
}
Loading
Loading