Browse Source

Add white & black list. Fix after review

pull/440/head
vparomskiy 9 years ago
parent
commit
12951115f9
  1. 9
      application/src/main/resources/thingsboard.yml
  2. 25
      common/transport/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistry.java
  3. 2
      common/transport/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLogger.java
  4. 16
      common/transport/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestsQuotaServiceTest.java
  5. 30
      common/transport/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistryTest.java
  6. 1
      transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java

9
application/src/main/resources/thingsboard.yml

@ -110,11 +110,20 @@ coap:
#Quota parameters
quota:
host:
# Max allowed number of API requests in interval for single host
limit: "${QUOTA_HOST_LIMIT:10000}"
# Interval duration
intervalMs: "${QUOTA_HOST_INTERVAL_MS:60000}"
# Maximum silence duration for host after which Host removed from QuotaService. Must be bigger than intervalMs
ttlMs: "${QUOTA_HOST_TTL_MS:60000}"
# Interval for scheduled task that cleans expired records. TTL is used for expiring
cleanPeriodMs: "${QUOTA_HOST_CLEAN_PERIOD_MS:300000}"
# Enable Host API Limits
enabled: "${QUOTA_HOST_ENABLED:false}"
# Array of whitelist hosts
whitelist: "${QUOTA_HOST_WHITELIST:localhost,127.0.0.1}"
# Array of blacklist hosts
blacklist: "${QUOTA_HOST_BLACKLIST:}"
log:
topSize: 10
intervalMin: 2

25
common/transport/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistry.java

@ -1,12 +1,12 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* <p>
* Licensed 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
*
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
@ -15,12 +15,15 @@
*/
package org.thingsboard.server.common.transport.quota.inmemory;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@ -35,11 +38,17 @@ public class HostRequestIntervalRegistry {
private final Map<String, IntervalCount> hostCounts = new ConcurrentHashMap<>();
private final long intervalDurationMs;
private final long ttlMs;
private final Set<String> whiteList;
private final Set<String> blackList;
public HostRequestIntervalRegistry(@Value("${quota.host.intervalMs}") long intervalDurationMs,
@Value("${quota.host.ttlMs}") long ttlMs) {
@Value("${quota.host.ttlMs}") long ttlMs,
@Value("${quota.host.whitelist}") String whiteList,
@Value("${quota.host.blacklist}") String blackList) {
this.intervalDurationMs = intervalDurationMs;
this.ttlMs = ttlMs;
this.whiteList = Sets.newHashSet(StringUtils.split(whiteList, ','));
this.blackList = Sets.newHashSet(StringUtils.split(blackList, ','));
}
@PostConstruct
@ -47,11 +56,15 @@ public class HostRequestIntervalRegistry {
if (ttlMs < intervalDurationMs) {
log.warn("TTL for IntervalRegistry [{}] smaller than interval duration [{}]", ttlMs, intervalDurationMs);
}
log.info("Start Host Quota Service with whitelist {}", whiteList);
log.info("Start Host Quota Service with blacklist {}", blackList);
}
public long tick(String clientHostId) {
if ("localhost".equals(clientHostId) || "127.0.0.1".equals(clientHostId)) {
if (whiteList.contains(clientHostId)) {
return 0;
} else if (blackList.contains(clientHostId)) {
return Long.MAX_VALUE;
}
IntervalCount intervalCount = hostCounts.computeIfAbsent(clientHostId, s -> new IntervalCount(intervalDurationMs));
return intervalCount.resetIfExpiredAndTick();

2
common/transport/src/main/java/org/thingsboard/server/common/transport/quota/inmemory/IntervalRegistryLogger.java

@ -80,7 +80,7 @@ public class IntervalRegistryLogger {
private void log(Map<String, Long> top) {
StringBuilder builder = new StringBuilder("Quota Statistic : ");
for (Map.Entry<String, Long> host : top.entrySet()) {
builder.append(host.getKey()).append(" : ").append(host.getValue());
builder.append(host.getKey()).append(" : ").append(host.getValue()).append(" ; ");
}
log.info(builder.toString());

16
common/transport/src/test/java/org/thingsboard/server/common/transport/quota/HostRequestsQuotaServiceTest.java

@ -44,9 +44,9 @@ public class HostRequestsQuotaServiceTest {
}
@Test
public void hostQuotaValidated() {
public void quotaExceededIfRequestCountBiggerThanAllowed() {
when(requestRegistry.tick("key")).thenReturn(10L);
when(requestsPolicy.isValid(10L)).thenReturn(true);
when(requestsPolicy.isValid(10L)).thenReturn(false);
assertTrue(quotaService.isQuotaExceeded("key"));
@ -55,6 +55,18 @@ public class HostRequestsQuotaServiceTest {
verifyNoMoreInteractions(requestRegistry, requestsPolicy);
}
@Test
public void quotaNotExceededIfRequestCountLessThanAllowed() {
when(requestRegistry.tick("key")).thenReturn(10L);
when(requestsPolicy.isValid(10L)).thenReturn(true);
assertFalse(quotaService.isQuotaExceeded("key"));
verify(requestRegistry).tick("key");
verify(requestsPolicy).isValid(10L);
verifyNoMoreInteractions(requestRegistry, requestsPolicy);
}
@Test
public void serviceCanBeDisabled() {
quotaService = new HostRequestsQuotaService(requestRegistry, requestsPolicy, registryCleaner, registryLogger, false);

30
common/transport/src/test/java/org/thingsboard/server/common/transport/quota/inmemory/HostRequestIntervalRegistryTest.java

@ -15,9 +15,12 @@
*/
package org.thingsboard.server.common.transport.quota.inmemory;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
/**
@ -30,7 +33,7 @@ public class HostRequestIntervalRegistryTest {
@Before
public void init() {
registry = new HostRequestIntervalRegistry(10000L, 100L);
registry = new HostRequestIntervalRegistry(10000L, 100L,"g1,g2", "b1");
}
@Test
@ -54,4 +57,29 @@ public class HostRequestIntervalRegistryTest {
assertEquals(1L, registry.tick("aaa"));
assertEquals(2L, registry.tick("bbb"));
}
@Test
public void domainFromWhitelistNotCounted(){
assertEquals(0L, registry.tick("g1"));
assertEquals(0L, registry.tick("g1"));
assertEquals(0L, registry.tick("g2"));
}
@Test
public void domainFromBlackListReturnMaxValue(){
assertEquals(Long.MAX_VALUE, registry.tick("b1"));
assertEquals(Long.MAX_VALUE, registry.tick("b1"));
}
@Test
public void emptyWhitelistParsedOk(){
registry = new HostRequestIntervalRegistry(10000L, 100L,"", "b1");
assertEquals(1L, registry.tick("aaa"));
}
@Test
public void emptyBlacklistParsedOk(){
registry = new HostRequestIntervalRegistry(10000L, 100L,"", "");
assertEquals(1L, registry.tick("aaa"));
}
}

1
transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java

@ -75,7 +75,6 @@ public class CoapTransportResource extends CoapResource {
@Override
public void handleGET(CoapExchange exchange) {
if(quotaService.isQuotaExceeded(exchange.getSourceAddress().getHostAddress())) {
log.warn("Missing feature type parameter");
log.warn("COAP Quota exceeded for [{}:{}] . Disconnect", exchange.getSourceAddress().getHostAddress(), exchange.getSourcePort());
exchange.respond(ResponseCode.BAD_REQUEST);
return;

Loading…
Cancel
Save