@@ -26,7 +26,7 @@ sudo apt update -y || die "Error running apt update" | |||
sudo apt upgrade -y || die "Error running apt upgrade" | |||
# Install packages | |||
sudo apt install openjdk-11-jdk maven postgresql redis-server jq python3 python3-pip npm webpack curl zip unzip -y || die "Error installing apt packages" | |||
sudo apt install openjdk-11-jdk maven postgresql redis-server jq python3 python3-pip npm webpack curl zip unzip whois -y || die "Error installing apt packages" | |||
sudo pip3 install setuptools psycopg2-binary || die "Error installing pip packages" | |||
# Install packer | |||
@@ -19,7 +19,6 @@ import bubble.server.BubbleConfiguration; | |||
import com.fasterxml.jackson.databind.JsonNode; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.util.collection.ExpirationMap; | |||
import org.cobbzilla.util.string.ValidationRegexes; | |||
import org.cobbzilla.wizard.validation.ValidationResult; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
@@ -36,8 +35,7 @@ import static org.cobbzilla.util.http.HttpSchemes.isHttpOrHttps; | |||
import static org.cobbzilla.util.http.URIUtil.getHost; | |||
import static org.cobbzilla.util.http.URIUtil.getPath; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.string.ValidationRegexes.HTTPS_PATTERN; | |||
import static org.cobbzilla.util.string.ValidationRegexes.HTTP_PATTERN; | |||
import static org.cobbzilla.util.string.ValidationRegexes.*; | |||
import static org.cobbzilla.wizard.model.BasicConstraintConstants.URL_MAXLEN; | |||
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; | |||
import static org.cobbzilla.wizard.resources.ResourceUtil.notFoundEx; | |||
@@ -213,7 +211,7 @@ public class BubbleBlockAppConfigDriver extends AppConfigDriverBase { | |||
} catch (Exception e) { | |||
throw invalidEx("err.testUrl.invalid", "Test URL was not valid", shortError(e)); | |||
} | |||
if (empty(host) || !ValidationRegexes.HOST_PATTERN.matcher(host).matches()) { | |||
if (empty(host) || !isHostname(host)) { | |||
throw invalidEx("err.testUrl.invalidHostname", "Test URL was not valid"); | |||
} | |||
@@ -10,6 +10,8 @@ import lombok.Setter; | |||
import lombok.experimental.Accessors; | |||
import org.cobbzilla.util.reflect.OpenApiSchema; | |||
import java.util.Comparator; | |||
import static org.cobbzilla.util.reflect.ReflectionUtil.copy; | |||
@NoArgsConstructor @Accessors(chain=true) @OpenApiSchema | |||
@@ -23,4 +25,14 @@ public class CloudRegionRelative extends CloudRegion { | |||
if (hasLocation()) distance = getLocation().distance(latitude, longitude); | |||
} | |||
public static final CloudRegionRelativeComparator SORT_DISTANCE_THEN_NAME = new CloudRegionRelativeComparator(); | |||
public static class CloudRegionRelativeComparator implements Comparator<CloudRegionRelative> { | |||
@Override public int compare(CloudRegionRelative crr1, CloudRegionRelative crr2) { | |||
final int diff = Double.compare(crr1.getDistance(), crr2.getDistance()); | |||
if (diff != 0) return diff; | |||
return crr1.getInternalName().compareTo(crr2.getInternalName()); | |||
} | |||
} | |||
} |
@@ -16,10 +16,7 @@ import org.cobbzilla.util.string.StringUtil; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
@@ -27,6 +24,8 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.dns.DnsRecord.OPT_NS_NAME; | |||
import static org.cobbzilla.util.network.NetworkUtil.IPv4_ALL_ADDRS; | |||
import static org.cobbzilla.util.network.NetworkUtil.ipEquals; | |||
import static org.cobbzilla.util.string.StringUtil.safeShellArg; | |||
import static org.cobbzilla.util.string.ValidationRegexes.isHostname; | |||
import static org.cobbzilla.util.system.CommandShell.execScript; | |||
import static org.cobbzilla.util.system.Sleep.sleep; | |||
@@ -61,11 +60,19 @@ public interface DnsServiceDriver extends CloudServiceDriver { | |||
static Collection<DnsRecord> dig(String host, DnsType type, String name) { return dig(host, 53, type, name); } | |||
static Collection<DnsRecord> dig(String host, int port, DnsType type, String name) { | |||
if (!isHostname(host)) { | |||
log.warn("dig: invalid host: "+host); | |||
return Collections.emptyList(); | |||
} | |||
if (!isHostname(name)) { | |||
log.warn("dig: invalid name: "+name); | |||
return Collections.emptyList(); | |||
} | |||
final String output = execScript("dig +tcp +short +nocomment " | |||
+ "@" + host | |||
+ "@" + safeShellArg(host) | |||
+ " -p " + port | |||
+ " -t " + type.name() | |||
+ " -q " + name); | |||
+ " -q " + safeShellArg(name)); | |||
log.info("dig @"+host+" "+name+": output: "+output.trim()); | |||
final List<DnsRecord> records = new ArrayList<>(); | |||
for (String line : output.split("[\n]+")) { | |||
@@ -22,14 +22,20 @@ import org.cobbzilla.wizard.cache.redis.RedisService; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import java.io.*; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.concurrent.TimeUnit; | |||
import java.util.Map; | |||
import java.util.regex.Pattern; | |||
import java.util.stream.Collectors; | |||
import static java.util.concurrent.TimeUnit.DAYS; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
import static java.util.function.Function.identity; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.http.HttpSchemes.SCHEME_FILE; | |||
import static org.cobbzilla.util.http.HttpUtil.getHeadMetadata; | |||
import static org.cobbzilla.util.io.FileUtil.*; | |||
import static org.cobbzilla.util.io.StreamUtil.stream2string; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.system.Sleep.sleep; | |||
import static org.cobbzilla.wizard.cache.redis.RedisService.EX; | |||
@@ -38,7 +44,7 @@ import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; | |||
@Slf4j | |||
public abstract class GeoLocateServiceDriverBase<T> extends CloudServiceDriverBase<T> implements GeoLocateServiceDriver { | |||
public static final long CACHE_TTL = TimeUnit.DAYS.toSeconds(20); | |||
public static final long CACHE_TTL = DAYS.toSeconds(20); | |||
public static final long ERROR_TTL = SECONDS.toSeconds(20); | |||
private static final int MAX_FILE_RETRIES = 5; | |||
@@ -57,6 +63,14 @@ public abstract class GeoLocateServiceDriverBase<T> extends CloudServiceDriverBa | |||
@Autowired private RedisService redis; | |||
@Getter(lazy=true) private final RedisService cache = redis.prefixNamespace(getClass().getName()+"_cache_"); | |||
@Getter(lazy=true) private final Map<String, GeoLocation> countryMap = initCountryMap(); | |||
private Map<String, GeoLocation> initCountryMap() { | |||
final String countryJson = stream2string("bubble/cloud/geoLocation/country-locations.json"); | |||
final GeoLocation[] countryLocations = json(countryJson, GeoLocation[].class); | |||
return Arrays.stream(countryLocations) | |||
.collect(Collectors.toMap(GeoLocation::getCountry, identity())); | |||
} | |||
@Override public GeoLocation geolocate (String ip) { | |||
String val = getCache().get(ip); | |||
long ttl = CACHE_TTL; | |||
@@ -90,7 +104,7 @@ public abstract class GeoLocateServiceDriverBase<T> extends CloudServiceDriverBa | |||
final String urlWithLicense = HandlebarsUtil.apply(getHandlebars(), url, getCredentials().newContext(), '[', ']') | |||
.replace("&", "&"); | |||
final HttpRequestBean request = new HttpRequestBean(urlWithLicense).setHeaders(headers); | |||
final HttpMeta meta = HttpUtil.getHeadMetadata(request); | |||
final HttpMeta meta = getHeadMetadata(request); | |||
final String uniq = hashOf(url, headers); | |||
final String dbKey = "dbcache_" + uniq; | |||
@@ -19,6 +19,7 @@ import org.cobbzilla.wizard.model.entityconfig.annotations.ECField; | |||
import javax.persistence.Transient; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.reflect.ReflectionUtil.copy; | |||
@NoArgsConstructor @Accessors(chain=true) @ToString(of={"lat", "lon"}) @OpenApiSchema | |||
public class GeoLocation { | |||
@@ -34,6 +35,11 @@ public class GeoLocation { | |||
public static final GeoLocation NULL_LOCATION = new GeoLocation().setLat("-1.0").setLon("-1.0"); | |||
public static final double INVALID_LOCATION = -1.0; | |||
public GeoLocation(String country) { | |||
copy(this, NULL_LOCATION); | |||
setCountry(country); | |||
} | |||
@Getter @Setter private String country; | |||
public boolean hasCountry() { return !empty(country); } | |||
@@ -16,7 +16,7 @@ import java.net.InetAddress; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
public class MaxMindDriver extends GeoLocateServiceDriverBase<CloudApiUrlConfig> { | |||
public class MaxMindGeoLocationDriver extends GeoLocateServiceDriverBase<CloudApiUrlConfig> { | |||
private DatabaseReader reader; | |||
@@ -0,0 +1,16 @@ | |||
package bubble.cloud.geoLocation.whois; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.empty; | |||
public class WhoisConfig { | |||
@Getter @Setter private String host; | |||
public boolean hasHost() { return !empty(host); } | |||
@Getter @Setter private Integer port; | |||
public boolean hasPort() { return port != null && port > 0 && port < 65536; } | |||
} |
@@ -0,0 +1,71 @@ | |||
package bubble.cloud.geoLocation.whois; | |||
import bubble.cloud.geoLocation.GeoLocateServiceDriverBase; | |||
import bubble.cloud.geoLocation.GeoLocation; | |||
import lombok.Getter; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.exec.CommandLine; | |||
import org.cobbzilla.util.system.CommandResult; | |||
import java.util.Arrays; | |||
import java.util.Optional; | |||
import static bubble.cloud.geoLocation.GeoLocation.NULL_LOCATION; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.string.StringUtil.safeShellArg; | |||
import static org.cobbzilla.util.string.ValidationRegexes.isHostname; | |||
import static org.cobbzilla.util.system.CommandShell.exec; | |||
import static org.cobbzilla.util.system.CommandShell.execScript; | |||
@Slf4j | |||
public class WhoisGeoLocationDriver extends GeoLocateServiceDriverBase<WhoisConfig> { | |||
@Getter(lazy=true) private final String whois = initWhois(); | |||
private String initWhois() { | |||
final String cmd = execScript("which whois"); | |||
return empty(cmd) ? die("initWhois: 'whois' command not found") : cmd; | |||
} | |||
@Override protected GeoLocation _geolocate(String ip) { | |||
try { | |||
final CommandLine commandLine = new CommandLine(getWhois()); | |||
final WhoisConfig config = getConfig(); | |||
if (config.hasHost()) { | |||
final String host = config.getHost(); | |||
if (!isHostname(host)) return die("_geolocate: invalid host: "+host); | |||
commandLine.addArgument("-h").addArgument(safeShellArg(host)); | |||
} | |||
if (config.hasPort()) commandLine.addArgument("-p").addArgument(""+config.getPort()); | |||
commandLine.addArgument(ip); | |||
final CommandResult result = exec(commandLine); | |||
if (!result.isZeroExitStatus()) { | |||
log.error("_geolocate: 'whois' had non-zero exit status: " + result.getExitStatus() + "\nstderr=" + result.getStderr()); | |||
return NULL_LOCATION; | |||
} | |||
final String[] lines = result.getStdout().split("\n"); | |||
final Optional<String> countryLine = Arrays.stream(lines) | |||
.filter(line -> line.trim().startsWith("Country:")) | |||
.findFirst(); | |||
if (countryLine.isEmpty()) { | |||
log.warn("_geolocate: No 'Country:' found in 'whois' output"); | |||
return NULL_LOCATION; | |||
} | |||
final String[] parts = countryLine.get().split("\\s+"); | |||
if (parts.length != 2) { | |||
log.warn("_geolocate: invalid Country: line: "+countryLine); | |||
return NULL_LOCATION; | |||
} | |||
final String country = parts[1]; | |||
final GeoLocation found = getCountryMap().get(country.toUpperCase()); | |||
return found == null ? NULL_LOCATION : found; | |||
} catch (Exception e) { | |||
log.error("_geolocate: error: "+shortError(e)); | |||
return NULL_LOCATION; | |||
} | |||
} | |||
} |
@@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicReference; | |||
import static java.util.concurrent.TimeUnit.MINUTES; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.background; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.getJava; | |||
import static org.cobbzilla.util.string.StringUtil.safeShellArg; | |||
public class RekeyDatabaseMain extends BaseMain<RekeyDatabaseOptions> { | |||
@@ -93,13 +94,13 @@ public class RekeyDatabaseMain extends BaseMain<RekeyDatabaseOptions> { | |||
commandLine = commandLine | |||
.addArgument(clazz.getName()) | |||
.addArgument(RekeyOptions.LONGOPT_DB) | |||
.addArgument(dbName) | |||
.addArgument(safeShellArg(dbName)) | |||
.addArgument(RekeyOptions.LONGOPT_DB_USER) | |||
.addArgument(options.getDbUser()) | |||
.addArgument(safeShellArg(options.getDbUser())) | |||
.addArgument(RekeyOptions.LONGOPT_DB_PASS) | |||
.addArgument(options.getDbPass()) | |||
.addArgument(safeShellArg(options.getDbPass())) | |||
.addArgument(RekeyOptions.LONGOPT_KEY) | |||
.addArgument(key) | |||
.addArgument(safeShellArg(key)) | |||
.addArgument(RekeyOptions.LONGOPT_PORT) | |||
.addArgument("" + options.getPort()); | |||
@@ -16,8 +16,8 @@ import java.util.Collection; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import static bubble.cloud.CloudRegionRelative.SORT_DISTANCE_THEN_NAME; | |||
import static bubble.cloud.geoLocation.GeoLocation.*; | |||
import static java.util.Comparator.comparingDouble; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.shortError; | |||
public interface RegionalServiceDriver { | |||
@@ -51,24 +51,23 @@ public interface RegionalServiceDriver { | |||
} | |||
if (regions != null) { | |||
for (CloudRegion region : regions) { | |||
if (exclude != null && exclude.contains(new CloudAndRegion(c, region))) { | |||
log.info("findClosestRegions: skipping excluded region: "+region); | |||
continue; | |||
} | |||
if (!region.hasLocation() || region.getLocation() == NULL_LOCATION) { | |||
// region has no location, it will always match with a distance of zero | |||
final CloudRegionRelative r = new CloudRegionRelative(region); | |||
r.setDistance(0).setCloud(c.getUuid()); | |||
allRegions.add(r); | |||
addRegionWithUnknownDistance(allRegions, c, region); | |||
continue; | |||
} | |||
if (latitude == INVALID_LOCATION && longitude == INVALID_LOCATION) { | |||
// region has a location, we can never match with invalid coordinates | |||
addRegionWithUnknownDistance(allRegions, c, region); | |||
continue; | |||
} | |||
if (footprint != null && region.hasLocation() && !footprint.isAllowedCountry(region.getLocation().getCountry())) { | |||
continue; | |||
} | |||
if (exclude != null && exclude.contains(new CloudAndRegion(c, region))) { | |||
log.info("findClosestRegions: skipping excluded region: "+region); | |||
continue; | |||
} | |||
final CloudRegionRelative r = new CloudRegionRelative(region); | |||
r.setCloud(c.getUuid()); | |||
if (latLonIsValid && latitude >= 0 && longitude >= 0) { | |||
@@ -80,10 +79,19 @@ public interface RegionalServiceDriver { | |||
} | |||
} | |||
} | |||
allRegions.sort(comparingDouble(CloudRegionRelative::getDistance)); | |||
allRegions.sort(SORT_DISTANCE_THEN_NAME); | |||
return allRegions; | |||
} | |||
private static void addRegionWithUnknownDistance(List<CloudRegionRelative> allRegions, | |||
CloudService c, | |||
CloudRegion region) { | |||
final CloudRegionRelative r = new CloudRegionRelative(region); | |||
r.setDistance(0); | |||
r.setCloud(c.getUuid()); | |||
allRegions.add(r); | |||
} | |||
List<CloudRegion> getRegions(); | |||
default List<CloudRegion> getRegions(BubbleFootprint footprint) { | |||
@@ -172,7 +172,7 @@ public class AccountPlansResource extends AccountOwnedResource<AccountPlan, Acco | |||
request.setDomain(domain.getUuid()); | |||
} else { | |||
if (!validateRegexMatches(HOST_PATTERN, forkHost)) { | |||
if (!isHostname(forkHost)) { | |||
errors.addViolation("err.forkHost.invalid"); | |||
} else if (domain != null && !forkHost.endsWith("." + domain.getName())) { | |||
final BubbleDomain foundDomain = domainDAO.findByAccount(caller.getUuid()).stream() | |||
@@ -108,7 +108,9 @@ public class CloudServiceRegionsResource { | |||
if (footprint == null) return notFound(footprintId); | |||
} | |||
return ok(findClosestRegions(configuration, computeClouds(), footprint, loc.getLatitude(), loc.getLongitude(), null, geoService.supportsGeoLocation())); | |||
return ok(findClosestRegions(configuration, computeClouds(), footprint, | |||
loc.getLatitude(), loc.getLongitude(), | |||
null, geoService.supportsGeoLocation())); | |||
} | |||
public List<CloudRegion> findRegions(List<CloudService> clouds, BubbleFootprint footprint) { | |||
@@ -30,7 +30,10 @@ import org.glassfish.grizzly.http.server.Request; | |||
import org.glassfish.jersey.server.ContainerRequest; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import javax.ws.rs.*; | |||
import javax.ws.rs.GET; | |||
import javax.ws.rs.Path; | |||
import javax.ws.rs.PathParam; | |||
import javax.ws.rs.QueryParam; | |||
import javax.ws.rs.core.Context; | |||
import javax.ws.rs.core.MultivaluedMap; | |||
import javax.ws.rs.core.Response; | |||
@@ -164,6 +167,7 @@ public class NetworksResource extends AccountOwnedResource<BubbleNetwork, Bubble | |||
} catch (Exception e) { | |||
return invalid("err.latlon.invalid", "lat/lon was invalid: "+e.getMessage(), lat+","+lon); | |||
} | |||
if (latitude < 0 || longitude < 0) return invalid("err.latlon.invalid"); | |||
} else { | |||
// try to figure it out from the IP | |||
final String remoteHost = getRemoteHost(req); | |||
@@ -46,8 +46,7 @@ import static org.cobbzilla.util.json.JsonUtil.COMPACT_MAPPER; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.string.StringUtil.EMPTY; | |||
import static org.cobbzilla.util.string.StringUtil.getPackagePath; | |||
import static org.cobbzilla.util.string.ValidationRegexes.HOST_PATTERN; | |||
import static org.cobbzilla.util.string.ValidationRegexes.validateRegexMatches; | |||
import static org.cobbzilla.util.string.ValidationRegexes.*; | |||
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; | |||
@Slf4j | |||
@@ -504,7 +503,7 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver | |||
if (data.getKey().startsWith(PREFIX_APPDATA_SHOW_STATS)) { | |||
final DeviceService deviceService = configuration.getBean(DeviceService.class); | |||
final String fqdn = fqdnFromKey(data.getKey()); | |||
if (validateRegexMatches(HOST_PATTERN, fqdn)) { | |||
if (isHostname(fqdn)) { | |||
if (data.deleting()) { | |||
if (log.isInfoEnabled()) log.info(prefix+"unsetting fqdn: "+fqdn); | |||
deviceService.unsetBlockStatsForFqdn(account, fqdn); | |||
@@ -10,7 +10,6 @@ import bubble.server.listener.NodeInitializerListener; | |||
import lombok.NoArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.util.io.FileUtil; | |||
import org.cobbzilla.util.system.CommandShell; | |||
import org.cobbzilla.wizard.server.RestServer; | |||
import org.cobbzilla.wizard.server.RestServerBase; | |||
import org.cobbzilla.wizard.server.RestServerLifecycleListener; | |||
@@ -39,6 +38,7 @@ import static org.cobbzilla.util.io.FileUtil.abs; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.network.NetworkUtil.IPv4_ALL_ADDRS; | |||
import static org.cobbzilla.util.network.NetworkUtil.IPv4_LOCALHOST; | |||
import static org.cobbzilla.util.system.CommandShell.loadShellExports; | |||
import static org.cobbzilla.util.system.OutOfMemoryErrorUncaughtExceptionHandler.EXIT_ON_OOME; | |||
@NoArgsConstructor @Slf4j | |||
@@ -126,7 +126,7 @@ public class BubbleServer extends RestServerBase<BubbleConfiguration> { | |||
final File envFile = getEnvFile(args); | |||
if (envFile == null) return die("loadEnvironment: no env file found"); | |||
if (!envFile.exists()) return die("loadEnvironment: env file does not exist: "+abs(envFile)); | |||
env.putAll(CommandShell.loadShellExports(envFile)); | |||
env.putAll(loadShellExports(envFile)); | |||
} catch (Exception e) { | |||
log.warn("Error loading environment: "+e); | |||
} | |||
@@ -8,16 +8,11 @@ import bubble.model.cloud.BubbleVersionInfo; | |||
import bubble.server.BubbleConfiguration; | |||
import lombok.Cleanup; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.util.daemon.SimpleDaemon; | |||
import org.cobbzilla.util.io.Decompressors; | |||
import org.cobbzilla.util.io.FileUtil; | |||
import org.cobbzilla.util.io.TempDir; | |||
import org.cobbzilla.wizard.model.SemanticVersion; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Service; | |||
import java.io.File; | |||
import java.util.regex.Pattern; | |||
import static java.util.concurrent.TimeUnit.HOURS; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
@@ -26,8 +21,6 @@ import static org.cobbzilla.util.http.HttpUtil.url2file; | |||
import static org.cobbzilla.util.http.HttpUtil.url2string; | |||
import static org.cobbzilla.util.io.Decompressors.extract; | |||
import static org.cobbzilla.util.io.FileUtil.*; | |||
import static org.cobbzilla.util.system.CommandShell.execScript; | |||
import static org.cobbzilla.wizard.model.SemanticVersion.SEMANTIC_VERSION_RE; | |||
import static org.cobbzilla.wizard.model.SemanticVersion.isNewerVersion; | |||
@Service @Slf4j | |||
@@ -89,6 +89,7 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.io.FileUtil.*; | |||
import static org.cobbzilla.util.io.StreamUtil.stream2string; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.string.StringUtil.safeShellArg; | |||
import static org.cobbzilla.util.system.CommandShell.chmod; | |||
import static org.cobbzilla.util.system.Sleep.sleep; | |||
import static org.cobbzilla.util.time.TimeUtil.formatDuration; | |||
@@ -304,7 +305,7 @@ public class StandardNetworkService implements NetworkService { | |||
+ "-o StrictHostKeyChecking=no " | |||
+ "-o PreferredAuthentications=publickey " | |||
+ "-i " + abs(sshKeyFile); | |||
final String sshTarget = node.getUser() + "@" + computeDriver.getNodeIp4(node); | |||
final String sshTarget = safeShellArg(node.getUser() + "@" + computeDriver.getNodeIp4(node)); | |||
boolean setupOk = false; | |||
final String nodeUser = node.getUser(); | |||
@@ -28,6 +28,7 @@ import static org.cobbzilla.util.io.FileUtil.abs; | |||
import static org.cobbzilla.util.io.FileUtil.mkdirOrDie; | |||
import static org.cobbzilla.util.io.StreamUtil.stream2string; | |||
import static org.cobbzilla.util.security.ShaUtil.sha256_file; | |||
import static org.cobbzilla.util.string.StringUtil.safeShellArg; | |||
import static org.cobbzilla.util.string.StringUtil.splitAndTrim; | |||
import static org.cobbzilla.util.system.CommandShell.chmod; | |||
import static org.cobbzilla.util.system.CommandShell.execScript; | |||
@@ -125,7 +126,7 @@ public class PackerService { | |||
final File privateKeyFile = new File(keyDir, PACKER_KEY_NAME); | |||
if (!pubKeyFile.exists() || !privateKeyFile.exists()) { | |||
final String comment = configuration.getShortVersion() + "_" + configuration.getJarSha(); | |||
execScript("ssh-keygen -t rsa -q -N '' -C '"+comment+"' -f "+abs(privateKeyFile)); | |||
execScript("ssh-keygen -t rsa -q -N '' -C '"+safeShellArg(comment)+"' -f "+abs(privateKeyFile)); | |||
if (!pubKeyFile.exists() || !privateKeyFile.exists()) return die("initPackerKey: error creating packer key"); | |||
} | |||
return pub ? pubKeyFile : privateKeyFile; | |||
@@ -0,0 +1,246 @@ | |||
[ | |||
{"name": "AD", "lat": 42.546245, "lon": 1.601554}, | |||
{"name": "AE", "lat": 23.424076, "lon": 53.847818}, | |||
{"name": "AF", "lat": 33.93911, "lon": 67.709953}, | |||
{"name": "AG", "lat": 17.060816, "lon": -61.796428}, | |||
{"name": "AI", "lat": 18.220554, "lon": -63.068615}, | |||
{"name": "AL", "lat": 41.153332, "lon": 20.168331}, | |||
{"name": "AM", "lat": 40.069099, "lon": 45.038189}, | |||
{"name": "AN", "lat": 12.226079, "lon": -69.060087}, | |||
{"name": "AO", "lat": -11.202692, "lon": 17.873887}, | |||
{"name": "AQ", "lat": -75.250973, "lon": -0.071389}, | |||
{"name": "AR", "lat": -38.416097, "lon": -63.616672}, | |||
{"name": "AS", "lat": -14.270972, "lon": -170.132217}, | |||
{"name": "AT", "lat": 47.516231, "lon": 14.550072}, | |||
{"name": "AU", "lat": -25.274398, "lon": 133.775136}, | |||
{"name": "AW", "lat": 12.52111, "lon": -69.968338}, | |||
{"name": "AZ", "lat": 40.143105, "lon": 47.576927}, | |||
{"name": "BA", "lat": 43.915886, "lon": 17.679076}, | |||
{"name": "BB", "lat": 13.193887, "lon": -59.543198}, | |||
{"name": "BD", "lat": 23.684994, "lon": 90.356331}, | |||
{"name": "BE", "lat": 50.503887, "lon": 4.469936}, | |||
{"name": "BF", "lat": 12.238333, "lon": -1.561593}, | |||
{"name": "BG", "lat": 42.733883, "lon": 25.48583}, | |||
{"name": "BH", "lat": 25.930414, "lon": 50.637772}, | |||
{"name": "BI", "lat": -3.373056, "lon": 29.918886}, | |||
{"name": "BJ", "lat": 9.30769, "lon": 2.315834}, | |||
{"name": "BM", "lat": 32.321384, "lon": -64.75737}, | |||
{"name": "BN", "lat": 4.535277, "lon": 114.727669}, | |||
{"name": "BO", "lat": -16.290154, "lon": -63.588653}, | |||
{"name": "BR", "lat": -14.235004, "lon": -51.92528}, | |||
{"name": "BS", "lat": 25.03428, "lon": -77.39628}, | |||
{"name": "BT", "lat": 27.514162, "lon": 90.433601}, | |||
{"name": "BV", "lat": -54.423199, "lon": 3.413194}, | |||
{"name": "BW", "lat": -22.328474, "lon": 24.684866}, | |||
{"name": "BY", "lat": 53.709807, "lon": 27.953389}, | |||
{"name": "BZ", "lat": 17.189877, "lon": -88.49765}, | |||
{"name": "CA", "lat": 56.130366, "lon": -106.346771}, | |||
{"name": "CC", "lat": -12.164165, "lon": 96.870956}, | |||
{"name": "CD", "lat": -4.038333, "lon": 21.758664}, | |||
{"name": "CF", "lat": 6.611111, "lon": 20.939444}, | |||
{"name": "CG", "lat": -0.228021, "lon": 15.827659}, | |||
{"name": "CH", "lat": 46.818188, "lon": 8.227512}, | |||
{"name": "CI", "lat": 7.539989, "lon": -5.54708}, | |||
{"name": "CK", "lat": -21.236736, "lon": -159.777671}, | |||
{"name": "CL", "lat": -35.675147, "lon": -71.542969}, | |||
{"name": "CM", "lat": 7.369722, "lon": 12.354722}, | |||
{"name": "CN", "lat": 35.86166, "lon": 104.195397}, | |||
{"name": "CO", "lat": 4.570868, "lon": -74.297333}, | |||
{"name": "CR", "lat": 9.748917, "lon": -83.753428}, | |||
{"name": "CU", "lat": 21.521757, "lon": -77.781167}, | |||
{"name": "CV", "lat": 16.002082, "lon": -24.013197}, | |||
{"name": "CX", "lat": -10.447525, "lon": 105.690449}, | |||
{"name": "CY", "lat": 35.126413, "lon": 33.429859}, | |||
{"name": "CZ", "lat": 49.817492, "lon": 15.472962}, | |||
{"name": "DE", "lat": 51.165691, "lon": 10.451526}, | |||
{"name": "DJ", "lat": 11.825138, "lon": 42.590275}, | |||
{"name": "DK", "lat": 56.26392, "lon": 9.501785}, | |||
{"name": "DM", "lat": 15.414999, "lon": -61.370976}, | |||
{"name": "DO", "lat": 18.735693, "lon": -70.162651}, | |||
{"name": "DZ", "lat": 28.033886, "lon": 1.659626}, | |||
{"name": "EC", "lat": -1.831239, "lon": -78.183406}, | |||
{"name": "EE", "lat": 58.595272, "lon": 25.013607}, | |||
{"name": "EG", "lat": 26.820553, "lon": 30.802498}, | |||
{"name": "EH", "lat": 24.215527, "lon": -12.885834}, | |||
{"name": "ER", "lat": 15.179384, "lon": 39.782334}, | |||
{"name": "ES", "lat": 40.463667, "lon": -3.74922}, | |||
{"name": "ET", "lat": 9.145, "lon": 40.489673}, | |||
{"name": "FI", "lat": 61.92411, "lon": 25.748151}, | |||
{"name": "FJ", "lat": -16.578193, "lon": 179.414413}, | |||
{"name": "FK", "lat": -51.796253, "lon": -59.523613}, | |||
{"name": "FM", "lat": 7.425554, "lon": 150.550812}, | |||
{"name": "FO", "lat": 61.892635, "lon": -6.911806}, | |||
{"name": "FR", "lat": 46.227638, "lon": 2.213749}, | |||
{"name": "GA", "lat": -0.803689, "lon": 11.609444}, | |||
{"name": "GB", "lat": 55.378051, "lon": -3.435973}, | |||
{"name": "GD", "lat": 12.262776, "lon": -61.604171}, | |||
{"name": "GE", "lat": 42.315407, "lon": 43.356892}, | |||
{"name": "GF", "lat": 3.933889, "lon": -53.125782}, | |||
{"name": "GG", "lat": 49.465691, "lon": -2.585278}, | |||
{"name": "GH", "lat": 7.946527, "lon": -1.023194}, | |||
{"name": "GI", "lat": 36.137741, "lon": -5.345374}, | |||
{"name": "GL", "lat": 71.706936, "lon": -42.604303}, | |||
{"name": "GM", "lat": 13.443182, "lon": -15.310139}, | |||
{"name": "GN", "lat": 9.945587, "lon": -9.696645}, | |||
{"name": "GP", "lat": 16.995971, "lon": -62.067641}, | |||
{"name": "GQ", "lat": 1.650801, "lon": 10.267895}, | |||
{"name": "GR", "lat": 39.074208, "lon": 21.824312}, | |||
{"name": "GS", "lat": -54.429579, "lon": -36.587909}, | |||
{"name": "GT", "lat": 15.783471, "lon": -90.230759}, | |||
{"name": "GU", "lat": 13.444304, "lon": 144.793731}, | |||
{"name": "GW", "lat": 11.803749, "lon": -15.180413}, | |||
{"name": "GY", "lat": 4.860416, "lon": -58.93018}, | |||
{"name": "GZ", "lat": 31.354676, "lon": 34.308825}, | |||
{"name": "HK", "lat": 22.396428, "lon": 114.109497}, | |||
{"name": "HM", "lat": -53.08181, "lon": 73.504158}, | |||
{"name": "HN", "lat": 15.199999, "lon": -86.241905}, | |||
{"name": "HR", "lat": 45.1, "lon": 15.2}, | |||
{"name": "HT", "lat": 18.971187, "lon": -72.285215}, | |||
{"name": "HU", "lat": 47.162494, "lon": 19.503304}, | |||
{"name": "ID", "lat": -0.789275, "lon": 113.921327}, | |||
{"name": "IE", "lat": 53.41291, "lon": -8.24389}, | |||
{"name": "IL", "lat": 31.046051, "lon": 34.851612}, | |||
{"name": "IM", "lat": 54.236107, "lon": -4.548056}, | |||
{"name": "IN", "lat": 20.593684, "lon": 78.96288}, | |||
{"name": "IO", "lat": -6.343194, "lon": 71.876519}, | |||
{"name": "IQ", "lat": 33.223191, "lon": 43.679291}, | |||
{"name": "IR", "lat": 32.427908, "lon": 53.688046}, | |||
{"name": "IS", "lat": 64.963051, "lon": -19.020835}, | |||
{"name": "IT", "lat": 41.87194, "lon": 12.56738}, | |||
{"name": "JE", "lat": 49.214439, "lon": -2.13125}, | |||
{"name": "JM", "lat": 18.109581, "lon": -77.297508}, | |||
{"name": "JO", "lat": 30.585164, "lon": 36.238414}, | |||
{"name": "JP", "lat": 36.204824, "lon": 138.252924}, | |||
{"name": "KE", "lat": -0.023559, "lon": 37.906193}, | |||
{"name": "KG", "lat": 41.20438, "lon": 74.766098}, | |||
{"name": "KH", "lat": 12.565679, "lon": 104.990963}, | |||
{"name": "KI", "lat": -3.370417, "lon": -168.734039}, | |||
{"name": "KM", "lat": -11.875001, "lon": 43.872219}, | |||
{"name": "KN", "lat": 17.357822, "lon": -62.782998}, | |||
{"name": "KP", "lat": 40.339852, "lon": 127.510093}, | |||
{"name": "KR", "lat": 35.907757, "lon": 127.766922}, | |||
{"name": "KW", "lat": 29.31166, "lon": 47.481766}, | |||
{"name": "KY", "lat": 19.513469, "lon": -80.566956}, | |||
{"name": "KZ", "lat": 48.019573, "lon": 66.923684}, | |||
{"name": "LA", "lat": 19.85627, "lon": 102.495496}, | |||
{"name": "LB", "lat": 33.854721, "lon": 35.862285}, | |||
{"name": "LC", "lat": 13.909444, "lon": -60.978893}, | |||
{"name": "LI", "lat": 47.166, "lon": 9.555373}, | |||
{"name": "LK", "lat": 7.873054, "lon": 80.771797}, | |||
{"name": "LR", "lat": 6.428055, "lon": -9.429499}, | |||
{"name": "LS", "lat": -29.609988, "lon": 28.233608}, | |||
{"name": "LT", "lat": 55.169438, "lon": 23.881275}, | |||
{"name": "LU", "lat": 49.815273, "lon": 6.129583}, | |||
{"name": "LV", "lat": 56.879635, "lon": 24.603189}, | |||
{"name": "LY", "lat": 26.3351, "lon": 17.228331}, | |||
{"name": "MA", "lat": 31.791702, "lon": -7.09262}, | |||
{"name": "MC", "lat": 43.750298, "lon": 7.412841}, | |||
{"name": "MD", "lat": 47.411631, "lon": 28.369885}, | |||
{"name": "ME", "lat": 42.708678, "lon": 19.37439}, | |||
{"name": "MG", "lat": -18.766947, "lon": 46.869107}, | |||
{"name": "MH", "lat": 7.131474, "lon": 171.184478}, | |||
{"name": "MK", "lat": 41.608635, "lon": 21.745275}, | |||
{"name": "ML", "lat": 17.570692, "lon": -3.996166}, | |||
{"name": "MM", "lat": 21.913965, "lon": 95.956223}, | |||
{"name": "MN", "lat": 46.862496, "lon": 103.846656}, | |||
{"name": "MO", "lat": 22.198745, "lon": 113.543873}, | |||
{"name": "MP", "lat": 17.33083, "lon": 145.38469}, | |||
{"name": "MQ", "lat": 14.641528, "lon": -61.024174}, | |||
{"name": "MR", "lat": 21.00789, "lon": -10.940835}, | |||
{"name": "MS", "lat": 16.742498, "lon": -62.187366}, | |||
{"name": "MT", "lat": 35.937496, "lon": 14.375416}, | |||
{"name": "MU", "lat": -20.348404, "lon": 57.552152}, | |||
{"name": "MV", "lat": 3.202778, "lon": 73.22068}, | |||
{"name": "MW", "lat": -13.254308, "lon": 34.301525}, | |||
{"name": "MX", "lat": 23.634501, "lon": -102.552784}, | |||
{"name": "MY", "lat": 4.210484, "lon": 101.975766}, | |||
{"name": "MZ", "lat": -18.665695, "lon": 35.529562}, | |||
{"name": "NA", "lat": -22.95764, "lon": 18.49041}, | |||
{"name": "NC", "lat": -20.904305, "lon": 165.618042}, | |||
{"name": "NE", "lat": 17.607789, "lon": 8.081666}, | |||
{"name": "NF", "lat": -29.040835, "lon": 167.954712}, | |||
{"name": "NG", "lat": 9.081999, "lon": 8.675277}, | |||
{"name": "NI", "lat": 12.865416, "lon": -85.207229}, | |||
{"name": "NL", "lat": 52.132633, "lon": 5.291266}, | |||
{"name": "NO", "lat": 60.472024, "lon": 8.468946}, | |||
{"name": "NP", "lat": 28.394857, "lon": 84.124008}, | |||
{"name": "NR", "lat": -0.522778, "lon": 166.931503}, | |||
{"name": "NU", "lat": -19.054445, "lon": -169.867233}, | |||
{"name": "NZ", "lat": -40.900557, "lon": 174.885971}, | |||
{"name": "OM", "lat": 21.512583, "lon": 55.923255}, | |||
{"name": "PA", "lat": 8.537981, "lon": -80.782127}, | |||
{"name": "PE", "lat": -9.189967, "lon": -75.015152}, | |||
{"name": "PF", "lat": -17.679742, "lon": -149.406843}, | |||
{"name": "PG", "lat": -6.314993, "lon": 143.95555}, | |||
{"name": "PH", "lat": 12.879721, "lon": 121.774017}, | |||
{"name": "PK", "lat": 30.375321, "lon": 69.345116}, | |||
{"name": "PL", "lat": 51.919438, "lon": 19.145136}, | |||
{"name": "PM", "lat": 46.941936, "lon": -56.27111}, | |||
{"name": "PN", "lat": -24.703615, "lon": -127.439308}, | |||
{"name": "PR", "lat": 18.220833, "lon": -66.590149}, | |||
{"name": "PS", "lat": 31.952162, "lon": 35.233154}, | |||
{"name": "PT", "lat": 39.399872, "lon": -8.224454}, | |||
{"name": "PW", "lat": 7.51498, "lon": 134.58252}, | |||
{"name": "PY", "lat": -23.442503, "lon": -58.443832}, | |||
{"name": "QA", "lat": 25.354826, "lon": 51.183884}, | |||
{"name": "RE", "lat": -21.115141, "lon": 55.536384}, | |||
{"name": "RO", "lat": 45.943161, "lon": 24.96676}, | |||
{"name": "RS", "lat": 44.016521, "lon": 21.005859}, | |||
{"name": "RU", "lat": 61.52401, "lon": 105.318756}, | |||
{"name": "RW", "lat": -1.940278, "lon": 29.873888}, | |||
{"name": "SA", "lat": 23.885942, "lon": 45.079162}, | |||
{"name": "SB", "lat": -9.64571, "lon": 160.156194}, | |||
{"name": "SC", "lat": -4.679574, "lon": 55.491977}, | |||
{"name": "SD", "lat": 12.862807, "lon": 30.217636}, | |||
{"name": "SE", "lat": 60.128161, "lon": 18.643501}, | |||
{"name": "SG", "lat": 1.352083, "lon": 103.819836}, | |||
{"name": "SH", "lat": -24.143474, "lon": -10.030696}, | |||
{"name": "SI", "lat": 46.151241, "lon": 14.995463}, | |||
{"name": "SJ", "lat": 77.553604, "lon": 23.670272}, | |||
{"name": "SK", "lat": 48.669026, "lon": 19.699024}, | |||
{"name": "SL", "lat": 8.460555, "lon": -11.779889}, | |||
{"name": "SM", "lat": 43.94236, "lon": 12.457777}, | |||
{"name": "SN", "lat": 14.497401, "lon": -14.452362}, | |||
{"name": "SO", "lat": 5.152149, "lon": 46.199616}, | |||
{"name": "SR", "lat": 3.919305, "lon": -56.027783}, | |||
{"name": "ST", "lat": 0.18636, "lon": 6.613081}, | |||
{"name": "SV", "lat": 13.794185, "lon": -88.89653}, | |||
{"name": "SY", "lat": 34.802075, "lon": 38.996815}, | |||
{"name": "SZ", "lat": -26.522503, "lon": 31.465866}, | |||
{"name": "TC", "lat": 21.694025, "lon": -71.797928}, | |||
{"name": "TD", "lat": 15.454166, "lon": 18.732207}, | |||
{"name": "TF", "lat": -49.280366, "lon": 69.348557}, | |||
{"name": "TG", "lat": 8.619543, "lon": 0.824782}, | |||
{"name": "TH", "lat": 15.870032, "lon": 100.992541}, | |||
{"name": "TJ", "lat": 38.861034, "lon": 71.276093}, | |||
{"name": "TK", "lat": -8.967363, "lon": -171.855881}, | |||
{"name": "TL", "lat": -8.874217, "lon": 125.727539}, | |||
{"name": "TM", "lat": 38.969719, "lon": 59.556278}, | |||
{"name": "TN", "lat": 33.886917, "lon": 9.537499}, | |||
{"name": "TO", "lat": -21.178986, "lon": -175.198242}, | |||
{"name": "TR", "lat": 38.963745, "lon": 35.243322}, | |||
{"name": "TT", "lat": 10.691803, "lon": -61.222503}, | |||
{"name": "TV", "lat": -7.109535, "lon": 177.64933}, | |||
{"name": "TW", "lat": 23.69781, "lon": 120.960515}, | |||
{"name": "TZ", "lat": -6.369028, "lon": 34.888822}, | |||
{"name": "UA", "lat": 48.379433, "lon": 31.16558}, | |||
{"name": "UG", "lat": 1.373333, "lon": 32.290275}, | |||
{"name": "US", "lat": 37.09024, "lon": -95.712891}, | |||
{"name": "UY", "lat": -32.522779, "lon": -55.765835}, | |||
{"name": "UZ", "lat": 41.377491, "lon": 64.585262}, | |||
{"name": "VA", "lat": 41.902916, "lon": 12.453389}, | |||
{"name": "VC", "lat": 12.984305, "lon": -61.287228}, | |||
{"name": "VE", "lat": 6.42375, "lon": -66.58973}, | |||
{"name": "VG", "lat": 18.420695, "lon": -64.639968}, | |||
{"name": "VI", "lat": 18.335765, "lon": -64.896335}, | |||
{"name": "VN", "lat": 14.058324, "lon": 108.277199}, | |||
{"name": "VU", "lat": -15.376706, "lon": 166.959158}, | |||
{"name": "WF", "lat": -13.768752, "lon": -177.156097}, | |||
{"name": "WS", "lat": -13.759029, "lon": -172.104629}, | |||
{"name": "XK", "lat": 42.602636, "lon": 20.902977}, | |||
{"name": "YE", "lat": 15.552727, "lon": 48.516388}, | |||
{"name": "YT", "lat": -12.8275, "lon": 45.166244}, | |||
{"name": "ZA", "lat": -30.559482, "lon": 22.937506}, | |||
{"name": "ZM", "lat": -13.133897, "lon": 27.849332}, | |||
{"name": "ZW", "lat": -19.015438, "lon": 29.154857} | |||
] |
@@ -55,7 +55,7 @@ | |||
}, | |||
{ | |||
"name": "GoogleGeoCoder", | |||
"name": "GoogleGeoCode", | |||
"type": "geoCode", | |||
"driverClass": "bubble.cloud.geoCode.google.GoogleGeoCodeDriver", | |||
"credentials": { "params": [ {"name": "apiKey", "value": "{{GOOGLE_API_KEY}}"} ] }, | |||
@@ -130,9 +130,9 @@ | |||
}, | |||
{ | |||
"name": "MaxMind", | |||
"name": "MaxMindGeoLocation", | |||
"type": "geoLocation", | |||
"driverClass": "bubble.cloud.geoLocation.maxmind.MaxMindDriver", | |||
"driverClass": "bubble.cloud.geoLocation.maxmind.MaxMindGeoLocationDriver", | |||
"driverConfig": { | |||
"url": "{{#exists MAXMIND_URL}}{{{MAXMIND_URL}}}{{else}}https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=[[apiKey]]&suffix=tar.gz{{/exists}}", | |||
"file": "{{#exists MAXMIND_FILE_REGEX}}{{{MAXMIND_FILE_REGEX}}}{{else}}GeoLite2-City_20[\\d]{6}/GeoLite2-City\\.mmdb{{/exists}}" | |||
@@ -143,6 +143,17 @@ | |||
"template": true | |||
}, | |||
{ | |||
"name": "WhoisGeoLocation", | |||
"type": "geoLocation", | |||
"driverClass": "bubble.cloud.geoLocation.whois.WhoisGeoLocationDriver", | |||
"driverConfig": { | |||
"host": null, | |||
"port": null | |||
}, | |||
"template": true | |||
}, | |||
{ | |||
"name": "GoogleGeoTime", | |||
"type": "geoTime", | |||
@@ -169,9 +169,12 @@ | |||
// GeoLocation | |||
/////////////////////// | |||
// Required for locale and "nearest compute region" auto-detection. Currently only MaxMind is supported | |||
// Required for locale and "nearest compute region" auto-detection. | |||
// Currently only MaxMind and Whois are supported. | |||
// MaxMind is free, but now requires registration and an API token. | |||
// Comment this out if you're not going to use it | |||
"MaxMind": { | |||
"MaxMindGeoLocation": { | |||
"config": { | |||
// these values work for the free GeoLite database, but you still have to specify an apiKey | |||
"url": "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=[[apiKey]]&suffix=tar.gz", | |||
@@ -180,13 +183,28 @@ | |||
"credentials": {"apiKey": "your_maxmind_api_key"} | |||
}, | |||
// Whois is also free, but less accurate. It's worth a try if you have nothing better. | |||
"WhoisGeoLocation": { | |||
"config": { | |||
// Normally the default 'whois' settings are used. | |||
// If you want to pass `-h` and `-p` to whois to set the host and port | |||
// of another whois server to use, set the config params below | |||
"host": null, | |||
"port": null | |||
// If you're not going to change host/port, you can reduce this | |||
// config object to an empty JSON object {} | |||
}, | |||
"credentials": {}, | |||
"template": true | |||
}, | |||
/////////////////////// | |||
// GeoCode | |||
/////////////////////// | |||
// Required for "nearest compute region" auto-detection. Currently only Google GeoCoder is supported | |||
// Comment this out if you're not going to use it | |||
"GoogleGeoCoder": { | |||
"GoogleGeoCode": { | |||
"credentials": {"apiKey": "your_google_api_key"} | |||
}, | |||
@@ -1 +1 @@ | |||
Subproject commit 4627dfbec2ccb9fd9e7829b00f6dec44316f2819 | |||
Subproject commit 507530784e203e6b5ba4c0b63b8fa946b352212e |
@@ -1 +1 @@ | |||
Subproject commit 8e75e7087316977e9ee3a5201ba328e62f184ffa | |||
Subproject commit 51a4ce4a48b44a47bec611354cdd8bf2a17d56ee |
@@ -1 +1 @@ | |||
Subproject commit 228fa8d952790d848d4551a7859766e3f23f74d9 | |||
Subproject commit 8deb7c2f886720eb6f0791083be594b1b41f5814 |