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
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.apache.shenyu.common.utils.ListUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Comparator;
Expand All @@ -79,6 +80,24 @@ public class ConfigsServiceImpl implements ConfigsService {

private static final Logger LOG = LoggerFactory.getLogger(ConfigsServiceImpl.class);

/**
* The max entry size for unzip.
*/
@Value("${shenyu.config.import.max-entry-size:104857600}")
private long maxEntrySize;

/**
* The max total size for unzip.
*/
@Value("${shenyu.config.import.max-total-size:209715200}")
private long maxTotalSize;

/**
* The max entry count for unzip.
*/
@Value("${shenyu.config.import.max-entry-count:1000}")
private int maxEntryCount;

/**
* The AppAuth service.
*/
Expand Down Expand Up @@ -342,7 +361,7 @@ private void exportAuthData(final String namespace, final List<ZipUtil.ZipItem>

@Override
public ShenyuAdminResult configsImport(final byte[] source) {
ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source);
ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source, maxEntrySize, maxTotalSize, maxEntryCount);
List<ZipUtil.ZipItem> zipItemList = unZipResult.getZipItemList();
if (CollectionUtils.isEmpty(zipItemList)) {
LOG.info("import file is empty");
Expand Down Expand Up @@ -387,7 +406,7 @@ public ShenyuAdminResult configsImport(final byte[] source) {

@Override
public ShenyuAdminResult configsImport(final String namespace, final byte[] source) {
ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source);
ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source, maxEntrySize, maxTotalSize, maxEntryCount);
List<ZipUtil.ZipItem> zipItemList = unZipResult.getZipItemList();
if (CollectionUtils.isEmpty(zipItemList)) {
LOG.info("import file is empty");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,21 @@ public final class ZipUtil {

private static final Logger LOG = LoggerFactory.getLogger(ZipUtil.class);

/**
* 100 MB per entry.
*/
private static final long MAX_ENTRY_SIZE = 100L * 1024 * 1024;

/**
* 200 MB total.
*/
private static final long MAX_TOTAL_SIZE = 200L * 1024 * 1024;

private static final int MAX_ENTRY_COUNT = 1000;

private ZipUtil() {
}


/**
* zip method.
*
Expand All @@ -66,23 +77,52 @@ public static byte[] zip(final List<ZipItem> source) {
}

/**
* unzip method.
* unzip method with default size limits.
*
* @param source source
* @return unzip result
*/
public static UnZipResult unzip(final byte[] source) {
return unzip(source, MAX_ENTRY_SIZE, MAX_TOTAL_SIZE, MAX_ENTRY_COUNT);
}

/**
* unzip method with configurable size limits.
*
* @param source source
* @param maxEntrySize max entry size
* @param maxTotalSize max total size
* @param maxEntryCount max entry count
* @return unzip result
*/
public static UnZipResult unzip(final byte[] source, final long maxEntrySize,
final long maxTotalSize, final int maxEntryCount) {
List<ZipItem> itemList = Lists.newArrayList();
long totalSize = 0L;
int entryCount = 0;
try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(source))) {
ZipEntry entry;
while (Objects.nonNull(entry = zipIn.getNextEntry())) {
if (entry.isDirectory()) {
continue;
}
entryCount++;
if (entryCount > maxEntryCount) {
throw new IllegalArgumentException("entry count exceeds maximum of " + maxEntryCount);
}
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int offset;
long entrySize = 0L;
while ((offset = zipIn.read(buffer)) != -1) {
entrySize += offset;
totalSize += offset;
if (entrySize > maxEntrySize) {
throw new IllegalArgumentException("entry size exceeds maximum allowed value.");
}
if (totalSize > maxTotalSize) {
throw new IllegalArgumentException("total size exceeds maximum allowed value.");
}
out.write(buffer, 0, offset);
}
String entryName = entry.getName();
Expand Down
6 changes: 6 additions & 0 deletions shenyu-admin/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ shenyu:
apiServer: "https://127.0.0.1:6443"
token: "token"
caCertPath: "/etc/kubernetes/pki/ca.crt"
config:
import:
max-entry-size: 104857600
max-total-size: 209715200
max-entry-count: 1000

springdoc:
api-docs:
Expand All @@ -246,3 +251,4 @@ logging:
org.apache.shenyu.lottery: info
org.apache.shenyu: info
# org.apache.shenyu.admin.utils.HttpUtils: debug

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.Collections;
import java.util.List;
Expand All @@ -45,6 +46,12 @@
@ExtendWith(MockitoExtension.class)
public final class ConfigsServiceTest {

private static final long MAX_ENTRY_SIZE = 100L * 1024 * 1024;

private static final long MAX_TOTAL_SIZE = 200L * 1024 * 1024;

private static final int MAX_ENTRY_COUNT = 1000;

private ConfigsServiceImpl configsService;

@Mock
Expand Down Expand Up @@ -84,6 +91,9 @@ public final class ConfigsServiceTest {
public void setUp() {
configsService = new ConfigsServiceImpl(appAuthService, pluginService, namespacePluginService, pluginHandleService, selectorService, ruleService,
metaDataService, shenyuDictService, proxySelectorService, discoveryService, discoveryUpstreamService, Collections.emptyList());
ReflectionTestUtils.setField(configsService, "maxEntrySize", MAX_ENTRY_SIZE);
ReflectionTestUtils.setField(configsService, "maxTotalSize", MAX_TOTAL_SIZE);
ReflectionTestUtils.setField(configsService, "maxEntryCount", MAX_ENTRY_COUNT);
}

@Test
Expand Down
Loading