diff --git a/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriverBase.java b/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriverBase.java index 160fd2ea..8100d1fc 100644 --- a/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriverBase.java +++ b/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriverBase.java @@ -39,9 +39,9 @@ public abstract class ComputeServiceDriverBase @Override public void postSetup() { final String prefix = "postSetup("+getClass().getSimpleName()+"/"+cloud.getUuid()+"): "; - if (configuration.isSelfSage()) { + if (configuration.getThisNetwork().sage()) { if (cloud.delegated()) { - log.info(prefix+"NOT starting NodeReaper for delegated driver"); + log.info(prefix + "NOT starting NodeReaper for delegated driver"); } else { synchronized (reapers) { if (reapers.get(getCredentials()) == null) { diff --git a/bubble-server/src/main/java/bubble/cloud/geoLocation/GeoLocateServiceDriverBase.java b/bubble-server/src/main/java/bubble/cloud/geoLocation/GeoLocateServiceDriverBase.java index d54cf476..83ff3eaa 100644 --- a/bubble-server/src/main/java/bubble/cloud/geoLocation/GeoLocateServiceDriverBase.java +++ b/bubble-server/src/main/java/bubble/cloud/geoLocation/GeoLocateServiceDriverBase.java @@ -10,6 +10,7 @@ import lombok.Cleanup; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; import org.cobbzilla.util.collection.NameAndValue; import org.cobbzilla.util.handlebars.HandlebarsUtil; import org.cobbzilla.util.http.HttpMeta; @@ -21,8 +22,7 @@ import org.cobbzilla.util.io.TempDir; import org.cobbzilla.wizard.cache.redis.RedisService; import org.springframework.beans.factory.annotation.Autowired; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; @@ -139,9 +139,15 @@ public abstract class GeoLocateServiceDriverBase extends CloudServiceDriverBa private File downloadDbFile(HttpRequestBean request, File archive) throws IOException { Exception lastEx = null; + if (!archive.getParentFile().exists()) { + mkdirOrDie(archive.getParentFile()); + } for (int i=0; i implements SqlViewSearc final BubbleNetwork thisNetwork = selfNodeService.getThisNetwork(); if (parentEntity.delegated() && thisNetwork != null - && thisNetwork.getInstallType() == AnsibleInstallType.node - && thisNetwork.getComputeSizeType() != ComputeNodeSizeType.local) { + && thisNetwork.node() + && thisNetwork.local()) { // on a node, sub-accounts can use the same cloud/config/credentials as their admin return accountEntity.setDelegated(parentEntity.getDelegated()) .setCredentialsJson(parentEntity.getCredentialsJson()) diff --git a/bubble-server/src/main/java/bubble/dao/account/AccountSshKeyDAO.java b/bubble-server/src/main/java/bubble/dao/account/AccountSshKeyDAO.java index 56b3e012..ebc6bd27 100644 --- a/bubble-server/src/main/java/bubble/dao/account/AccountSshKeyDAO.java +++ b/bubble-server/src/main/java/bubble/dao/account/AccountSshKeyDAO.java @@ -9,7 +9,6 @@ import bubble.dao.cloud.BubbleNetworkDAO; import bubble.model.account.Account; import bubble.model.account.AccountSshKey; import bubble.model.bill.AccountPlan; -import bubble.model.cloud.AnsibleInstallType; import bubble.model.cloud.BubbleNetwork; import bubble.server.BubbleConfiguration; import lombok.extern.slf4j.Slf4j; @@ -53,7 +52,7 @@ public class AccountSshKeyDAO extends AccountOwnedEntityDAO { final Account owner = accountDAO.findByUuid(key.getAccount()); final BubbleNetwork thisNetwork = configuration.getThisNetwork(); - if (thisNetwork == null || thisNetwork.getInstallType() == AnsibleInstallType.sage) { + if (thisNetwork == null || thisNetwork.sage()) { // only allow installation of a key on a sage if the user is the first admin and has no keys final Account firstAdmin = accountDAO.getFirstAdmin(); if (owner.getUuid().equals(firstAdmin.getUuid())) { @@ -65,7 +64,7 @@ public class AccountSshKeyDAO extends AccountOwnedEntityDAO { } else { // admin keys are always installed on a node // never install key for non-admin - key.setInstallSshKey(owner.admin() && thisNetwork.getInstallType() == AnsibleInstallType.node); + key.setInstallSshKey(owner.admin() && thisNetwork.node()); } final String hash = sha256_hex(key.getSshPublicKey()); diff --git a/bubble-server/src/main/java/bubble/dao/cloud/BubbleNetworkDAO.java b/bubble-server/src/main/java/bubble/dao/cloud/BubbleNetworkDAO.java index 13d68c3c..e9e9d554 100644 --- a/bubble-server/src/main/java/bubble/dao/cloud/BubbleNetworkDAO.java +++ b/bubble-server/src/main/java/bubble/dao/cloud/BubbleNetworkDAO.java @@ -46,7 +46,7 @@ public class BubbleNetworkDAO extends AccountOwnedEntityDAO { if (errors.hasSuggestedName()) network.setName(errors.getSuggestedName()); } if (!network.hasNickname()) network.setNickname(network.getName()); - final AnsibleInstallType installType = network.hasForkHost() && configuration.isSageLauncher() + final AnsibleInstallType installType = network.hasForkHost() && network.getLaunchType() == LaunchType.fork_sage && configuration.isSageLauncher() ? AnsibleInstallType.sage : AnsibleInstallType.node; network.setInstallType(installType); diff --git a/bubble-server/src/main/java/bubble/main/rekey/RekeyReaderMain.java b/bubble-server/src/main/java/bubble/main/rekey/RekeyReaderMain.java index 99431330..5531f3ea 100644 --- a/bubble-server/src/main/java/bubble/main/rekey/RekeyReaderMain.java +++ b/bubble-server/src/main/java/bubble/main/rekey/RekeyReaderMain.java @@ -57,7 +57,7 @@ public class RekeyReaderMain extends BaseMain { } protected Iterator getEntityProducer(BubbleConfiguration fromConfig, AtomicReference error) { - return new FullEntityIterator(fromConfig, null, error); + return new FullEntityIterator(fromConfig, null, null, null, error); } } diff --git a/bubble-server/src/main/java/bubble/model/bill/AccountPlan.java b/bubble-server/src/main/java/bubble/model/bill/AccountPlan.java index b2506ebb..8001fe32 100644 --- a/bubble-server/src/main/java/bubble/model/bill/AccountPlan.java +++ b/bubble-server/src/main/java/bubble/model/bill/AccountPlan.java @@ -10,6 +10,7 @@ import bubble.model.account.HasNetwork; import bubble.model.cloud.BubbleDomain; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.CloudService; +import bubble.model.cloud.LaunchType; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Getter; import lombok.NoArgsConstructor; @@ -46,7 +47,7 @@ public class AccountPlan extends IdentifiableBase implements HasNetwork { public static final String[] UPDATE_FIELDS = {"description", "paymentMethod", "paymentMethodObject"}; public static final String[] CREATE_FIELDS = ArrayUtil.append(UPDATE_FIELDS, - "name", "forkHost", "locale", "timezone", "domain", "network", + "name", "launchType", "forkHost", "locale", "timezone", "domain", "network", "sshKey", "syncAccount", "launchLock", "sendErrors", "sendMetrics", "plan", "footprint"); @SuppressWarnings("unused") @@ -159,6 +160,9 @@ public class AccountPlan extends IdentifiableBase implements HasNetwork { @JsonIgnore @Transient @Getter @Setter private transient Account accountObject = null; public boolean hasAccountObject () { return account != null; } + @Transient @Getter @Setter private transient LaunchType launchType = null; + public boolean hasLaunchType () { return launchType != null; } + @Transient @Getter @Setter private transient String forkHost = null; public boolean hasForkHost () { return !empty(forkHost); } @@ -195,6 +199,7 @@ public class AccountPlan extends IdentifiableBase implements HasNetwork { .setFootprint(getFootprint()) .setComputeSizeType(plan.getComputeSizeType()) .setStorage(storage.getUuid()) + .setLaunchType(hasForkHost() && hasLaunchType() ? getLaunchType() : LaunchType.node) .setForkHost(hasForkHost() ? getForkHost() : null); } diff --git a/bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java b/bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java index 50a372d4..94c74c58 100644 --- a/bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java +++ b/bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java @@ -136,6 +136,10 @@ public class BubbleNetwork extends IdentifiableBase implements HasNetwork, HasBu @ECIndex @Column(nullable=false, updatable=false, length=60) @ECField(index=70) @Enumerated(EnumType.STRING) @Getter @Setter private AnsibleInstallType installType; + public boolean sage() { return installType == AnsibleInstallType.sage; } + public boolean notSage() { return !sage(); } + public boolean node() { return installType == AnsibleInstallType.node; } + public boolean notNode() { return !node(); } @ECSearchable @ECField(index=80) @ECForeignKey(entity=AccountSshKey.class) @@ -146,6 +150,7 @@ public class BubbleNetwork extends IdentifiableBase implements HasNetwork, HasBu @ECSearchable @ECField(index=90) @ECIndex @Column(nullable=false, updatable=false, length=20) @Enumerated(EnumType.STRING) @Getter @Setter private ComputeNodeSizeType computeSizeType; + public boolean local() { return computeSizeType == ComputeNodeSizeType.local; } @ECSearchable @ECField(index=100) @ECForeignKey(entity=BubbleFootprint.class) @@ -202,8 +207,11 @@ public class BubbleNetwork extends IdentifiableBase implements HasNetwork, HasBu public boolean hasForkHost () { return !empty(forkHost); } public boolean fork() { return hasForkHost(); } - @ECSearchable @ECField(index=190) - @Column(length=20) + @ECField(index=190) @Column(length=20, updatable=false) + @Enumerated(EnumType.STRING) @Getter @Setter private LaunchType launchType = null; + public boolean hasLaunchType () { return launchType != null; } + + @ECSearchable @ECField(index=200) @Column(length=20) @Enumerated(EnumType.STRING) @Getter @Setter private BubbleNetworkState state = created; public String hostFromFqdn(String fqdn) { diff --git a/bubble-server/src/main/java/bubble/model/cloud/BubbleNode.java b/bubble-server/src/main/java/bubble/model/cloud/BubbleNode.java index 7f1465ad..e84d3c0c 100644 --- a/bubble-server/src/main/java/bubble/model/cloud/BubbleNode.java +++ b/bubble-server/src/main/java/bubble/model/cloud/BubbleNode.java @@ -131,6 +131,8 @@ public class BubbleNode extends IdentifiableBase implements HasNetwork, HasBubbl @ECIndex @Column(nullable=false, updatable=false, length=60) @Enumerated(EnumType.STRING) @Getter @Setter private AnsibleInstallType installType; + public boolean sage() { return installType == AnsibleInstallType.sage; } + public boolean node() { return installType == AnsibleInstallType.node; } @ECSearchable @ECField(index=50) @ECForeignKey(entity=BubbleNode.class, cascade=false) diff --git a/bubble-server/src/main/java/bubble/model/cloud/LaunchType.java b/bubble-server/src/main/java/bubble/model/cloud/LaunchType.java new file mode 100644 index 00000000..eb6c8a7b --- /dev/null +++ b/bubble-server/src/main/java/bubble/model/cloud/LaunchType.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2020 Bubble, Inc. All rights reserved. + * For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ + */ +package bubble.model.cloud; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import static bubble.ApiConstants.enumFromString; + +public enum LaunchType { + + node, fork_node, fork_sage; + + @JsonCreator public static LaunchType fromString(String v) { return enumFromString(LaunchType.class, v); } + +} diff --git a/bubble-server/src/main/java/bubble/notify/NewNodeNotification.java b/bubble-server/src/main/java/bubble/notify/NewNodeNotification.java index 00983f26..5356ccc7 100644 --- a/bubble-server/src/main/java/bubble/notify/NewNodeNotification.java +++ b/bubble-server/src/main/java/bubble/notify/NewNodeNotification.java @@ -8,6 +8,7 @@ import bubble.cloud.CloudAndRegion; import bubble.model.account.AccountContact; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNode; +import bubble.model.cloud.LaunchType; import bubble.model.cloud.NetLocation; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Getter; @@ -51,6 +52,8 @@ public class NewNodeNotification { @Getter @Setter private Boolean fork; public boolean fork() { return fork != null && fork; } + @Getter @Setter private LaunchType launchType; + @Getter @Setter private String restoreKey; public boolean hasRestoreKey () { return !empty(restoreKey); } diff --git a/bubble-server/src/main/java/bubble/notify/NotificationHandler_sync_account.java b/bubble-server/src/main/java/bubble/notify/NotificationHandler_sync_account.java index aa5c006b..ab9992c6 100644 --- a/bubble-server/src/main/java/bubble/notify/NotificationHandler_sync_account.java +++ b/bubble-server/src/main/java/bubble/notify/NotificationHandler_sync_account.java @@ -7,7 +7,6 @@ package bubble.notify; import bubble.dao.account.AccountDAO; import bubble.dao.account.AccountPolicyDAO; import bubble.dao.cloud.BubbleNodeDAO; -import bubble.model.cloud.AnsibleInstallType; import bubble.model.cloud.notify.ReceivedNotification; import bubble.service.account.SyncAccountNotification; import lombok.extern.slf4j.Slf4j; @@ -49,7 +48,7 @@ public class NotificationHandler_sync_account extends ReceivedNotificationHandle localAccount.getHashedPassword().setHashedPassword(incomingHashedPassword); // if we are a node, set skipSync so we don't get caught in an infinite loop // (the node would notify the sage, which would notify the node, ad infinitum) - localAccount.setSkipSync(configuration.getThisNetwork().getInstallType() == AnsibleInstallType.node); + localAccount.setSkipSync(configuration.getThisNetwork().node()); // update password, if we are a sage, this will notify all networks of password change accountDAO.update(localAccount); } @@ -63,7 +62,7 @@ public class NotificationHandler_sync_account extends ReceivedNotificationHandle } localPolicy.update(incomingPolicy); localPolicy.setAccountContactsJson(incomingPolicy.getAccountContactsJson()); - localPolicy.setSkipSync(configuration.getThisNetwork().getInstallType() == AnsibleInstallType.node); + localPolicy.setSkipSync(configuration.getThisNetwork().node()); accountPolicyDAO.update(localPolicy); } } diff --git a/bubble-server/src/main/java/bubble/resources/account/AuthResource.java b/bubble-server/src/main/java/bubble/resources/account/AuthResource.java index ce516dff..d1092d89 100644 --- a/bubble-server/src/main/java/bubble/resources/account/AuthResource.java +++ b/bubble-server/src/main/java/bubble/resources/account/AuthResource.java @@ -432,8 +432,9 @@ public class AuthResource { final BubbleNetwork thisNetwork = configuration.getThisNetwork(); if (thisNetwork != null && thisNetwork.syncAccount() - && thisNetwork.getInstallType() == AnsibleInstallType.node - && configuration.hasSageNode()) { + && thisNetwork.node() + && configuration.hasSageNode() + && !configuration.isSelfSage()) { // check if session is valid on sage @Cleanup final BubbleNodeClient sageClient = configuration.getSageNode().getApiQuickClient(configuration); try { diff --git a/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java b/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java index 6724d59d..6123a988 100644 --- a/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java +++ b/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java @@ -143,12 +143,13 @@ public class BubbleConfiguration extends PgRestServerConfiguration return selfNode != null && selfNode.selfSage(); } @JsonIgnore @Transient public boolean isSageLauncher() { - return isSelfSage() || !hasSageNode(); + final BubbleNetwork thisNetwork = getThisNetwork(); + return (isSelfSage() || !hasSageNode()) && thisNetwork.sage(); } @JsonIgnore @Transient public boolean isSage() { final BubbleNetwork thisNetwork = getThisNetwork(); - return thisNetwork != null && thisNetwork.getInstallType() == AnsibleInstallType.sage; + return thisNetwork != null && thisNetwork.sage(); } @JsonIgnore @Transient public synchronized BubbleNetwork getThisNetwork () { @@ -356,7 +357,7 @@ public class BubbleConfiguration extends PgRestServerConfiguration {TAG_ALLOW_REGISTRATION, thisNetwork == null ? null : thisNetwork.getBooleanTag(TAG_ALLOW_REGISTRATION, false)}, {TAG_NETWORK_UUID, thisNetwork == null ? null : thisNetwork.getUuid()}, {TAG_SAGE_LAUNCHER, thisNetwork == null || isSageLauncher()}, - {TAG_BUBBLE_NODE, isSageLauncher() || thisNetwork == null ? null : thisNetwork.getInstallType() == AnsibleInstallType.node}, + {TAG_BUBBLE_NODE, isSageLauncher() || thisNetwork == null ? null : thisNetwork.node()}, {TAG_PAYMENTS_ENABLED, cloudDAO.paymentsEnabled()}, {TAG_PROMO_CODE_POLICY, getPromoCodePolicy().name()}, {TAG_REQUIRE_SEND_METRICS, requireSendMetrics()}, diff --git a/bubble-server/src/main/java/bubble/server/listener/NodeInitializerListener.java b/bubble-server/src/main/java/bubble/server/listener/NodeInitializerListener.java index f2c1c3ef..745382d6 100644 --- a/bubble-server/src/main/java/bubble/server/listener/NodeInitializerListener.java +++ b/bubble-server/src/main/java/bubble/server/listener/NodeInitializerListener.java @@ -7,14 +7,13 @@ package bubble.server.listener; import bubble.dao.account.AccountDAO; import bubble.dao.cloud.CloudServiceDAO; import bubble.model.account.Account; -import bubble.model.cloud.AnsibleInstallType; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNode; import bubble.model.cloud.CloudService; import bubble.server.BubbleConfiguration; import bubble.service.boot.SelfNodeService; -import bubble.service.device.DeviceService; import bubble.service.cloud.NetworkMonitorService; +import bubble.service.device.DeviceService; import bubble.service.device.StandardFlexRouterService; import bubble.service.stream.AppDataCleaner; import bubble.service.stream.AppPrimerService; @@ -111,7 +110,7 @@ public class NodeInitializerListener extends RestServerLifecycleListenerBase { @@ -165,7 +167,7 @@ public class StandardSelfNodeService implements SelfNodeService { } // start RefundService if payments are enabled and this is a SageLauncher - if (c.paymentsEnabled() && c.isSageLauncher()) { + if (c.paymentsEnabled() && c.isSageLauncher() && thisNode.sage()) { log.info("onStart: starting BillingService and RefundService"); c.getBean(BillingService.class).start(); c.getBean(StandardRefundService.class).start(); @@ -435,7 +437,7 @@ public class StandardSelfNodeService implements SelfNodeService { @Override public BubblePlan getThisPlan() { final BubbleNetwork network = safeGetThisNetwork(); if (network == null) return null; - if (network.getInstallType() != AnsibleInstallType.node) return null; + if (network.notNode()) return null; final AccountPlan accountPlan = accountPlanDAO.findByNetwork(network.getUuid()); if (accountPlan == null) return null; return planDAO.findByUuid(accountPlan.getPlan()); @@ -451,8 +453,7 @@ public class StandardSelfNodeService implements SelfNodeService { return ttl < 0 ? Optional.empty() : Optional.of(now() + ttl * 1000); } - @Override - public void setLogFlag(final boolean logFlag, @NonNull final Optional ttlInSeconds) { + @Override public void setLogFlag(final boolean logFlag, @NonNull final Optional ttlInSeconds) { if (logFlag) { getNodeConfig().set_plaintext(REDIS_LOG_FLAG_KEY, "true", EX, ttlInSeconds.orElse(isSelfSage() ? TTL_LOG_FLAG_SAGE : TTL_LOG_FLAG_NODE)); diff --git a/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java b/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java index e26ff231..ed5b6e06 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java @@ -16,6 +16,7 @@ import bubble.model.bill.BubblePlanApp; import bubble.model.cloud.AnsibleInstallType; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNode; +import bubble.model.cloud.LaunchType; import bubble.server.BubbleConfiguration; import bubble.service.dbfilter.DatabaseFilterService; import com.github.jknack.handlebars.Handlebars; @@ -61,6 +62,7 @@ public class AnsiblePrepService { ComputeServiceDriver computeDriver, ValidationResult errors, boolean fork, + LaunchType launchType, String restoreKey) throws IOException { final BubbleConfiguration c = configuration; @@ -113,7 +115,7 @@ public class AnsiblePrepService { } // Copy database with new encryption key - final String key = dbFilter.copyDatabase(fork, network, node, account, planApps, new File(bubbleFilesDir, "bubble.sql.gz")); + final String key = dbFilter.copyDatabase(fork, launchType, network, node, account, planApps, new File(bubbleFilesDir, "bubble.sql.gz")); ctx.put("dbEncryptionKey", key); // if this is a fork, and current server is local, then sage will be self diff --git a/bubble-server/src/main/java/bubble/service/cloud/NodeLaunchMonitor.java b/bubble-server/src/main/java/bubble/service/cloud/NodeLaunchMonitor.java index c4fb55b2..60689b26 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/NodeLaunchMonitor.java +++ b/bubble-server/src/main/java/bubble/service/cloud/NodeLaunchMonitor.java @@ -4,7 +4,6 @@ */ package bubble.service.cloud; -import bubble.model.cloud.AnsibleInstallType; import bubble.model.cloud.BubbleNetwork; import bubble.notify.NewNodeNotification; import bubble.server.BubbleConfiguration; @@ -80,7 +79,7 @@ public class NodeLaunchMonitor extends SimpleDaemon { if (thisNetwork == null) { die("register: thisNetwork is null"); - } else if (configuration.isSageLauncher() || thisNetwork.getInstallType() == AnsibleInstallType.sage) { + } else if (thisNetwork.sage()) { if (log.isInfoEnabled()) log.info("register: first registration, starting launch monitor"); start(); diff --git a/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java b/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java index 58dcc47f..d58ccdea 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java @@ -352,7 +352,7 @@ public class StandardNetworkService implements NetworkService { if (!setupOk) return launchFailureCanRetry(node, "newNode: error setting up, all retries failed for node: "+node.getUuid()); // wait for node to be ready - if (node.getInstallType() == AnsibleInstallType.node) { + if (node.node()) { final long readyStart = now(); boolean ready = false; Exception lastEx = null; @@ -479,7 +479,7 @@ public class StandardNetworkService implements NetworkService { progressMeter.write(METER_TICK_PREPARING_ROLES); final Map ctx = ansiblePrep.prepAnsible( automation, bubbleFilesDir, account, network, node, computeDriver, - errors, nn.fork(), nn.getRestoreKey()); + errors, nn.fork(), nn.getLaunchType(), nn.getRestoreKey()); if (errors.isInvalid()) { progressMeter.error(METER_ERROR_ROLE_VALIDATION_ERRORS); fatalLaunchFailure(node, new MultiViolationException(errors.getViolationBeans())); @@ -519,7 +519,7 @@ public class StandardNetworkService implements NetworkService { writeFile(bubbleFilesDir, null, SAGE_KEY_JSON, json(BubbleNodeKey.sageMask(sageKey))); // write packer keys if launching sage - if (network.getInstallType() == AnsibleInstallType.sage) { + if (network.sage()) { final File packerPubKeyFile = new File(bubbleFilesDir, PACKER_KEY_NAME+".pub"); copyFile(packerService.getPackerPublicKey(), packerPubKeyFile); @@ -726,6 +726,7 @@ public class StandardNetworkService implements NetworkService { final NewNodeNotification newNodeRequest = new NewNodeNotification() .setFork(network.fork()) + .setLaunchType(network.getLaunchType()) .setNodeHost(network) .setNetLocation(netLocation) .setLock(lock); diff --git a/bubble-server/src/main/java/bubble/service/dbfilter/DatabaseFilterService.java b/bubble-server/src/main/java/bubble/service/dbfilter/DatabaseFilterService.java index 4ec8c95d..504747f2 100644 --- a/bubble-server/src/main/java/bubble/service/dbfilter/DatabaseFilterService.java +++ b/bubble-server/src/main/java/bubble/service/dbfilter/DatabaseFilterService.java @@ -12,6 +12,7 @@ import bubble.model.account.Account; import bubble.model.bill.BubblePlanApp; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNode; +import bubble.model.cloud.LaunchType; import bubble.server.BubbleConfiguration; import lombok.Cleanup; import lombok.extern.slf4j.Slf4j; @@ -53,11 +54,12 @@ public class DatabaseFilterService { public static final String ENV_OLD_DB_KEY = "OLD_DB_KEY"; public static final String ENV_NEW_DB_KEY = "NEW_DB_KEY"; - public static final String[] FLYWAY_DUMP_OPTIONS = {"--table=flyway_schema_history", "--data-only"}; + public static final String[] FLYWAY_DUMP_OPTIONS = {"--table="+getFlywayTableName(), "--data-only"}; @Autowired private BubbleConfiguration configuration; public String copyDatabase(boolean fork, + LaunchType launchType, BubbleNetwork network, BubbleNode node, Account account, @@ -112,7 +114,7 @@ public class DatabaseFilterService { @Override public RekeyOptions getOptions() { return readerOptions; } @Override protected Iterator getEntityProducer(BubbleConfiguration fromConfig, AtomicReference error) { return fork - ? new FullEntityIterator(configuration, network, readerError) + ? new FullEntityIterator(configuration, account, network, launchType, readerError) : new FilteredEntityIterator(configuration, account, network, node, planApps, readerError); } }.runInBackground("RekeyReaderMain.reader", readerError::set); diff --git a/bubble-server/src/main/java/bubble/service/dbfilter/FullEntityIterator.java b/bubble-server/src/main/java/bubble/service/dbfilter/FullEntityIterator.java index 81be5085..84fa5be1 100644 --- a/bubble-server/src/main/java/bubble/service/dbfilter/FullEntityIterator.java +++ b/bubble-server/src/main/java/bubble/service/dbfilter/FullEntityIterator.java @@ -4,32 +4,49 @@ */ package bubble.service.dbfilter; +import bubble.dao.device.DeviceDAO; +import bubble.model.account.Account; import bubble.model.cloud.BubbleNetwork; +import bubble.model.cloud.LaunchType; import bubble.server.BubbleConfiguration; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.atomic.AtomicReference; +import static bubble.model.device.Device.newUninitializedDevice; import static org.cobbzilla.wizard.dao.AbstractCRUDDAO.ORDER_CTIME_ASC; @Slf4j public class FullEntityIterator extends EntityIterator { private final BubbleConfiguration config; + private final Account account; private final BubbleNetwork network; + private final LaunchType launchType; public FullEntityIterator (BubbleConfiguration config, + Account account, BubbleNetwork network, + LaunchType launchType, AtomicReference error) { super(error); this.config = config; this.network = network; + this.account = account; + this.launchType = launchType; } protected void iterate() { config.getEntityClasses() .forEach(c -> addEntities(true, c, config.getDaoForEntityClass(c).findAll(ORDER_CTIME_ASC), network, null, null)); + if (account != null && launchType != null && launchType == LaunchType.fork_node) { + // add an initial device so that algo starts properly the first time + // name and totp key will be overwritten when the device is initialized for use + log.info("iterate: creating a single dummy device for algo to start properly"); + final var initDevice = newUninitializedDevice(network.getUuid(), account.getUuid()); + add(config.getBean(DeviceDAO.class).create(initDevice)); + } log.info("iterate: completed"); } diff --git a/bubble-server/src/main/java/bubble/service/stream/StandardAppPrimerService.java b/bubble-server/src/main/java/bubble/service/stream/StandardAppPrimerService.java index b9f64a3e..85a52a3b 100644 --- a/bubble-server/src/main/java/bubble/service/stream/StandardAppPrimerService.java +++ b/bubble-server/src/main/java/bubble/service/stream/StandardAppPrimerService.java @@ -9,7 +9,6 @@ import bubble.dao.app.*; import bubble.dao.device.DeviceDAO; import bubble.model.account.Account; import bubble.model.app.*; -import bubble.model.cloud.AnsibleInstallType; import bubble.model.cloud.BubbleNetwork; import bubble.model.device.Device; import bubble.rule.AppRuleDriver; @@ -54,7 +53,7 @@ public class StandardAppPrimerService implements AppPrimerService { log.info("initPrimingEnabled: thisNetwork is null, not priming"); return false; } - if (thisNetwork.getInstallType() != AnsibleInstallType.node) { + if (thisNetwork.notNode()) { log.info("initPrimingEnabled: thisNetwork is not a node, not priming"); return false; } diff --git a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties index beb64e55..5e08d551 100644 --- a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties +++ b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties @@ -1 +1 @@ -bubble.version=Adventure 1.2.1 +bubble.version=Adventure 1.2.2 diff --git a/bubble-server/src/main/resources/apps.json b/bubble-server/src/main/resources/apps.json deleted file mode 100644 index 04e5b8d9..00000000 --- a/bubble-server/src/main/resources/apps.json +++ /dev/null @@ -1,1486 +0,0 @@ -{ - "id" : "979b7850-ed94-4200-97da-4ea73045fb6f", - "drivers" : [ { - "uuid" : "0e022cda-7069-41f8-ba43-f6ab304ff085", - "name" : "BubbleBlockRuleDriver", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "template" : true, - "enabled" : true, - "driverClass" : "bubble.rule.bblock.BubbleBlockRuleDriver", - "version" : { - "major" : 1, - "minor" : 0, - "patch" : 0 - }, - "userConfig" : { - "fields" : [ ] - }, - "shortId" : "0e022cda" - }, { - "uuid" : "f314f0ed-2144-4141-850d-c607a7ab010c", - "name" : "JsUserBlockerRuleDriver", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "template" : true, - "enabled" : true, - "driverClass" : "bubble.rule.social.block.JsUserBlockerRuleDriver", - "version" : { - "major" : 1, - "minor" : 0, - "patch" : 0 - }, - "userConfig" : { - "fields" : [ ] - }, - "shortId" : "f314f0ed" - }, { - "uuid" : "c487b2ba-65f7-462f-af7f-c1ca2af5bc8a", - "name" : "TlsPassthruRuleDriver", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "template" : true, - "enabled" : true, - "driverClass" : "bubble.rule.passthru.TlsPassthruRuleDriver", - "version" : { - "major" : 1, - "minor" : 0, - "patch" : 0 - }, - "userConfig" : { - "fields" : [ ] - }, - "shortId" : "c487b2ba" - }, { - "uuid" : "49125b81-03af-438d-8603-7dab3c9f1111", - "name" : "TrafficAnalyticsRuleDriver", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "template" : true, - "enabled" : true, - "driverClass" : "bubble.rule.analytics.TrafficAnalyticsRuleDriver", - "version" : { - "major" : 1, - "minor" : 0, - "patch" : 0 - }, - "userConfig" : { - "fields" : [ ] - }, - "shortId" : "49125b81" - }, { - "uuid" : "abc524fb-6b40-4e67-b8a3-582b6fb2208e", - "name" : "UserBlockerRuleDriver", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "template" : true, - "enabled" : true, - "driverClass" : "bubble.rule.social.block.UserBlockerRuleDriver", - "version" : { - "major" : 1, - "minor" : 0, - "patch" : 0 - }, - "userConfig" : { - "fields" : [ ] - }, - "shortId" : "abc524fb" - } ], - "apps" : [ { - "uuid" : "5e23d5ca-e2eb-4317-a992-7081383961b1", - "children" : { - "AppMatcher" : [ { - "uuid" : "a4a22808-8b06-470c-bbc0-21a3934a367c", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "TrafficAnalyticsMatcher", - "app" : "5e23d5ca-e2eb-4317-a992-7081383961b1", - "site" : "fc07ab36-d89e-42ca-8e8f-4a50ffaec5aa", - "fqdn" : "*", - "urlRegex" : ".*", - "rule" : "e030e9d7-5fee-4e00-9164-0666c18389c2", - "template" : true, - "enabled" : true, - "connCheck" : false, - "requestCheck" : true, - "priority" : 0, - "shortId" : "a4a22808" - } ], - "AppRule" : [ { - "uuid" : "e030e9d7-5fee-4e00-9164-0666c18389c2", - "name" : "traffic_analytics", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "5e23d5ca-e2eb-4317-a992-7081383961b1", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "49125b81-03af-438d-8603-7dab3c9f1111", - "config" : { - "filterPatterns" : [ "\\.stripe\\.com", "\\.stripe\\.network" ] - }, - "shortId" : "e030e9d7" - } ], - "AppMessage" : [ { - "uuid" : "cfbafbb0-233d-4356-8c2a-735d0c132070", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "5e23d5ca-e2eb-4317-a992-7081383961b1", - "locale" : "en_US", - "priority" : 1, - "template" : true, - "enabled" : true, - "messages" : [ { - "name" : "name", - "value" : "Snitcher" - }, { - "name" : "icon", - "value" : "classpath:models/apps/analytics/snitcher-icon.svg" - }, { - "name" : "summary", - "value" : "Traffic Analytics" - }, { - "name" : "description", - "value" : "Review recent traffic for your devices. Block stuff that you don't like." - }, { - "name" : "field.ctime", - "value" : "When" - }, { - "name" : "field.requestTime", - "value" : "When" - }, { - "name" : "field.accountName", - "value" : "Account" - }, { - "name" : "field.fqdn", - "value" : "Host" - }, { - "name" : "field.device", - "value" : "Device" - }, { - "name" : "field.deviceName", - "value" : "Device" - }, { - "name" : "field.ip", - "value" : "From IP" - }, { - "name" : "field.uri", - "value" : "Path" - }, { - "name" : "field.userAgent", - "value" : "User Agent" - }, { - "name" : "field.referer", - "value" : "Referer" - }, { - "name" : "field.data", - "value" : "Count" - }, { - "name" : "param.meta2", - "value" : "Site" - }, { - "name" : "param.device", - "value" : "Device" - }, { - "name" : "action.filterHost", - "value" : "Block Host" - }, { - "name" : "action.filterUrl", - "value" : "Block URL" - }, { - "name" : "view.recent", - "value" : "Recent Traffic" - }, { - "name" : "view.recent.requestTime.format", - "value" : "{{MMM}} {{d}} @ {{h}}:{{m}}:{{s}}{{a}}" - }, { - "name" : "view.last_24_hours", - "value" : "Last 24 Hours" - }, { - "name" : "view.last_24_hours.ctime.format", - "value" : "{{MMM}} {{d}} @ {{h}}{{a}}" - }, { - "name" : "view.last_7_days", - "value" : "Last 7 Days" - }, { - "name" : "view.last_7_days.ctime.format", - "value" : "{{MMM}} {{d}}, {{YYYY}}" - }, { - "name" : "view.last_30_days", - "value" : "Last 30 Days" - }, { - "name" : "view.last_30_days.ctime.format", - "value" : "{{MMM}} {{d}}, {{YYYY}}" - }, { - "name" : "config.view.manageFilters", - "value" : "Manage Filters" - }, { - "name" : "config.field.analyticsFilter", - "value" : "Filter Pattern" - }, { - "name" : "config.field.analyticsFilter.description", - "value" : "Skip logging for URLs that match this pattern" - }, { - "name" : "config.action.addFilter", - "value" : "Add New Filter" - }, { - "name" : "config.button.addFilter", - "value" : "Add" - }, { - "name" : "config.action.removeFilter", - "value" : "Remove" - } ], - "shortId" : "cfbafbb0" - } ], - "AppSite" : [ { - "uuid" : "fc07ab36-d89e-42ca-8e8f-4a50ffaec5aa", - "name" : "All_Sites", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "5e23d5ca-e2eb-4317-a992-7081383961b1", - "template" : true, - "enabled" : true, - "description" : "All websites", - "url" : "*", - "shortId" : "fc07ab36" - } ] - }, - "name" : "TrafficAnalytics", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "url" : "https://getbubblenow.com/apps/analytics", - "description" : "Traffic analytics for your Bubble", - "canPrime" : false, - "template" : true, - "enabled" : true, - "priority" : 100, - "dataConfig" : { - "presentation" : "app", - "dataDriver" : "bubble.app.analytics.TrafficAnalyticsAppDataDriver", - "fields" : [ { - "name" : "ctime", - "displayName" : "Ctime", - "mode" : "standard", - "control" : "text", - "customFormat" : true, - "when" : "view !== \"recent\"" - }, { - "name" : "requestTime", - "displayName" : "Request Time", - "mode" : "standard", - "control" : "text", - "customFormat" : true, - "when" : "view === \"recent\"" - }, { - "name" : "accountName", - "displayName" : "Account Name", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "deviceName", - "displayName" : "Device Name", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "ip", - "displayName" : "Ip", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "fqdn", - "displayName" : "Fqdn", - "mode" : "standard", - "control" : "text" - }, { - "name" : "uri", - "displayName" : "Uri", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "userAgent", - "displayName" : "User Agent", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "referer", - "displayName" : "Referer", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "device", - "displayName" : "Device", - "mode" : "standard", - "control" : "text", - "when" : "view !== \"recent\"" - }, { - "name" : "data", - "displayName" : "Data", - "mode" : "standard", - "control" : "text", - "when" : "view !== \"recent\"" - } ], - "params" : [ { - "name" : "device", - "required" : false, - "index" : 10, - "displayName" : "Device", - "mode" : "standard", - "control" : "text", - "operator" : "eq", - "when" : "view !== \"recent\"" - }, { - "name" : "meta2", - "required" : false, - "index" : 20, - "displayName" : "Meta2", - "mode" : "standard", - "control" : "text", - "operator" : "like", - "when" : "view !== \"recent\"" - } ], - "actions" : [ { - "name" : "filterHost", - "when" : "view === \"recent\"", - "route" : "/app/BubbleBlock/config/manageRules/local?action=createRule&rule={{fqdn}}" - }, { - "name" : "filterUrl", - "when" : "view === \"recent\"", - "route" : "/app/BubbleBlock/config/manageRules/local?action=createRule&rule={{ encodeURIComponent( fqdn + (uri.startsWith('/') ? uri : '/'+uri) ) }}" - } ], - "views" : [ { - "presentation" : "app", - "layout" : "tiles", - "name" : "recent", - "priority" : 0 - }, { - "presentation" : "app", - "layout" : "table", - "name" : "last_24_hours", - "priority" : 0 - }, { - "presentation" : "app", - "layout" : "table", - "name" : "last_7_days", - "priority" : 0 - }, { - "presentation" : "app", - "layout" : "table", - "name" : "last_30_days", - "priority" : 0 - } ], - "configDriver" : "bubble.app.analytics.TrafficAnalyticsAppConfigDriver", - "configFields" : [ { - "name" : "analyticsFilter", - "displayName" : "Analytics Filter", - "mode" : "standard", - "control" : "text", - "truncate" : false - }, { - "name" : "ctime", - "displayName" : "Ctime", - "mode" : "standard", - "control" : "text", - "customFormat" : true, - "when" : "view !== \"recent\"" - }, { - "name" : "requestTime", - "displayName" : "Request Time", - "mode" : "standard", - "control" : "text", - "customFormat" : true, - "when" : "view === \"recent\"" - }, { - "name" : "accountName", - "displayName" : "Account Name", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "deviceName", - "displayName" : "Device Name", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "ip", - "displayName" : "Ip", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "fqdn", - "displayName" : "Fqdn", - "mode" : "standard", - "control" : "text" - }, { - "name" : "uri", - "displayName" : "Uri", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "userAgent", - "displayName" : "User Agent", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "referer", - "displayName" : "Referer", - "mode" : "standard", - "control" : "text", - "when" : "view === \"recent\"" - }, { - "name" : "device", - "displayName" : "Device", - "mode" : "standard", - "control" : "text", - "when" : "view !== \"recent\"" - }, { - "name" : "data", - "displayName" : "Data", - "mode" : "standard", - "control" : "text", - "when" : "view !== \"recent\"" - } ], - "configViews" : [ { - "name" : "manageFilters", - "scope" : "app", - "root" : true, - "fields" : [ "analyticsFilter" ], - "actions" : [ { - "name" : "removeFilter", - "scope" : "item", - "index" : 10 - }, { - "name" : "addFilter", - "scope" : "app", - "index" : 10, - "params" : [ "analyticsFilter" ], - "button" : "addFilter" - } ] - } ] - }, - "shortId" : "5e23d5ca" - }, { - "uuid" : "12ed9f89-5335-41fe-bb14-b5a7d34b0246", - "children" : { - "AppMatcher" : [ { - "uuid" : "caa7959d-3119-456d-8d53-a0b6de9bfd71", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "BubbleBlockMatcher", - "app" : "12ed9f89-5335-41fe-bb14-b5a7d34b0246", - "site" : "5bb7f4f0-a54f-4f1e-b61a-815a05f4de44", - "fqdn" : "*", - "urlRegex" : ".*", - "rule" : "fda8e014-9209-45fb-84b3-832b6750e5b6", - "template" : true, - "enabled" : true, - "connCheck" : true, - "requestCheck" : false, - "priority" : -1000, - "shortId" : "caa7959d" - } ], - "AppRule" : [ { - "uuid" : "fda8e014-9209-45fb-84b3-832b6750e5b6", - "name" : "bubble_block", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "12ed9f89-5335-41fe-bb14-b5a7d34b0246", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "0e022cda-7069-41f8-ba43-f6ab304ff085", - "config" : { - "blockLists" : [ { - "name" : "EasyList", - "id" : "easylist", - "url" : "https://v.firebog.net/hosts/Easylist.txt", - "description" : "EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists.", - "tags" : [ "ads" ] - }, { - "name" : "Peter Lowe's Ad and tracking server list", - "id" : "peter_lowes_ad_and_tracking_list", - "url" : "https://pgl.yoyo.org/adservers/serverlist.php?showintro=0;hostformat=raw", - "description" : "A comprehensive list of ad and tracking servers", - "tags" : [ "ads", "privacy" ] - }, { - "name" : "Dandelion Sprout's Anti-Malware List", - "id" : "dandelion_sprouts_anti_malware_list", - "url" : "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareABP.txt", - "description" : "Most anti-malware lists are pretty big and can cover a 5- or 6-digit amount of specific domains. But my list hereby claims to remove more than 25% of all known malware sites with just a 2-digit amount of entries. This is mostly done by blocking top-level domains that have become devastatingly abused by spammers, usually because they allowed for free and uncontrolled domain registrations. There's also additional categories that cover unusual malware and phishing domains that very few other lists seem to cover.", - "tags" : [ "malware", "phishing" ] - }, { - "name" : "Bubble Ads/Tracking List", - "id" : "bubble_ads_and_trackers1", - "url" : "https://raw.githubusercontent.com/getbubblenow/bubble-filter-lists/master/ads_and_trackers1.txt", - "description" : "Blocks lots of ads and trackers, with a focus on ads and trackers used in native mobile apps", - "tags" : [ "ads", "privacy" ] - }, { - "name" : "Bubble Custom List", - "id" : "local", - "url" : "", - "description" : "A place to maintain your own block rules for this Bubble.", - "tags" : [ "custom" ] - } ] - }, - "shortId" : "fda8e014" - } ], - "AppMessage" : [ { - "uuid" : "d9a52173-4bfa-45b6-8a53-29dc7767c05a", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "12ed9f89-5335-41fe-bb14-b5a7d34b0246", - "locale" : "en_US", - "priority" : 1, - "template" : true, - "enabled" : true, - "messages" : [ { - "name" : "name", - "value" : "Block Party!" - }, { - "name" : "icon", - "value" : "classpath:models/apps/bubble_block/blockparty-icon.svg" - }, { - "name" : "summary", - "value" : "Network Filter" - }, { - "name" : "description", - "value" : "Block adware, malware, phishing/scam sites, and much more" - }, { - "name" : "field.ctime", - "value" : "When" - }, { - "name" : "field.fqdn", - "value" : "URL" - }, { - "name" : "field.device", - "value" : "Device" - }, { - "name" : "field.uri", - "value" : "Path" - }, { - "name" : "field.data", - "value" : "Count" - }, { - "name" : "view.last_24_hours", - "value" : "Last 24 Hours" - }, { - "name" : "view.last_24_hours.ctime.format", - "value" : "{{MMM}} {{d}} @ {{h}}{{a}}" - }, { - "name" : "view.last_7_days", - "value" : "Last 7 Days" - }, { - "name" : "view.last_7_days.ctime.format", - "value" : "{{MMM}} {{d}}, {{YYYY}}" - }, { - "name" : "view.last_30_days", - "value" : "Last 30 Days" - }, { - "name" : "view.last_30_days.ctime.format", - "value" : "{{MMM}} {{d}}, {{YYYY}}" - }, { - "name" : "config.view.manageLists", - "value" : "Manage Filter Lists" - }, { - "name" : "config.view.manageList", - "value" : "Manage Filter List" - }, { - "name" : "config.view.manageRules", - "value" : "Manage Filter Rules" - }, { - "name" : "config.view.manageUserAgents", - "value" : "Manage User-Agents" - }, { - "name" : "config.field.name", - "value" : "Name" - }, { - "name" : "config.field.description", - "value" : "Description" - }, { - "name" : "config.field.url", - "value" : "URL" - }, { - "name" : "config.field.url.description", - "value" : "URL of the Filter List" - }, { - "name" : "config.field.tagString", - "value" : "Tags" - }, { - "name" : "config.field.tagString.description", - "value" : "A comma-separated list of tags" - }, { - "name" : "config.field.tags", - "value" : "Tags" - }, { - "name" : "config.field.enabled", - "value" : "Enabled" - }, { - "name" : "config.field.rule", - "value" : "Rule" - }, { - "name" : "config.field.rule.description", - "value" : "Enter a rule. Can be a hostname, or use AdBlockPlus format" - }, { - "name" : "config.field.ruleType", - "value" : "Rule Type" - }, { - "name" : "config.field.testUrl", - "value" : "Test URL" - }, { - "name" : "config.field.testUrl.description", - "value" : "URL to check against filters" - }, { - "name" : "config.field.testUserAgent", - "value" : "Test User-Agent" - }, { - "name" : "config.field.testUserAgent.description", - "value" : "User-Agent to check against filters" - }, { - "name" : "config.field.testUrlPrimary", - "value" : "Primary" - }, { - "name" : "config.field.testUrlPrimary.description", - "value" : "A primary request will receive either an ALLOW or BLOCK decision from your Bubble. A non-primary request (for example a request for a webpage) may additionally receive a FILTER decision. This means the request will be permitted, but the response will be instrumented with Bubble filters to remove ads, malware and blocked elements." - }, { - "name" : "config.field.urlRegex", - "value" : "URL" - }, { - "name" : "config.field.urlRegex.description", - "value" : "A regular expression to match against the URL" - }, { - "name" : "config.field.userAgentRegex", - "value" : "User-Agent" - }, { - "name" : "config.field.userAgentRegex.description", - "value" : "A regular expression to match against the User-Agent" - }, { - "name" : "config.action.enableList", - "value" : "Enable" - }, { - "name" : "config.action.disableList", - "value" : "Disable" - }, { - "name" : "config.action.manageList", - "value" : "Edit" - }, { - "name" : "config.action.removeList", - "value" : "Remove" - }, { - "name" : "config.action.createList", - "value" : "Add New" - }, { - "name" : "config.button.createList", - "value" : "Add" - }, { - "name" : "config.action.updateList", - "value" : "Update" - }, { - "name" : "config.action.manageRules", - "value" : "Rules" - }, { - "name" : "config.action.manageUserAgents", - "value" : "User-Agents" - }, { - "name" : "config.action.removeRule", - "value" : "Remove Rule" - }, { - "name" : "config.action.createRule", - "value" : "Add New Rule" - }, { - "name" : "config.button.createRule", - "value" : "Add" - }, { - "name" : "config.action.createUserAgentBlock", - "value" : "Add New User-Agent Rule" - }, { - "name" : "config.button.createUserAgentBlock", - "value" : "Add" - }, { - "name" : "config.action.removeUserAgentBlock", - "value" : "Remove Rule" - }, { - "name" : "config.button.removeUserAgentBlock", - "value" : "Remove" - }, { - "name" : "config.action.testUrl", - "value" : "Test URL" - }, { - "name" : "config.button.testUrl", - "value" : "Test" - }, { - "name" : "config.response.block", - "value" : "Block" - }, { - "name" : "config.response.block.description", - "value" : "Requests to this URL would be blocked by your Bubble" - }, { - "name" : "config.response.allow", - "value" : "Allow" - }, { - "name" : "config.response.allow.description", - "value" : "Requests to this URL would be allowed by your Bubble, and would not be filtered" - }, { - "name" : "config.response.filter", - "value" : "Filter" - }, { - "name" : "config.response.filter.description", - "value" : "Requests to this URL would be allowed by your Bubble, but would be filtered" - } ], - "shortId" : "d9a52173" - } ], - "AppSite" : [ { - "uuid" : "5bb7f4f0-a54f-4f1e-b61a-815a05f4de44", - "name" : "All_Sites", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "12ed9f89-5335-41fe-bb14-b5a7d34b0246", - "template" : true, - "enabled" : true, - "description" : "All websites", - "url" : "*", - "shortId" : "5bb7f4f0" - } ] - }, - "name" : "BubbleBlock", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "url" : "https://getbubblenow.com/apps/bblock", - "description" : "Block Adware, Malware and More", - "canPrime" : true, - "template" : true, - "enabled" : true, - "priority" : 200, - "dataConfig" : { - "presentation" : "app", - "dataDriver" : "bubble.app.bblock.BubbleBlockAppDataDriver", - "fields" : [ { - "name" : "ctime", - "displayName" : "Ctime", - "mode" : "standard", - "control" : "text", - "customFormat" : true - }, { - "name" : "device", - "displayName" : "Device", - "mode" : "standard", - "control" : "text" - }, { - "name" : "fqdn", - "displayName" : "Fqdn", - "mode" : "standard", - "control" : "text" - }, { - "name" : "uri", - "displayName" : "Uri", - "mode" : "standard", - "control" : "text" - }, { - "name" : "data", - "displayName" : "Data", - "mode" : "standard", - "control" : "text" - } ], - "params" : [ { - "name" : "device", - "required" : false, - "index" : 10, - "displayName" : "Device", - "mode" : "standard", - "control" : "text", - "operator" : "eq" - } ], - "views" : [ { - "presentation" : "app", - "layout" : "table", - "name" : "last_24_hours", - "priority" : 0 - }, { - "presentation" : "app", - "layout" : "table", - "name" : "last_7_days", - "priority" : 0 - }, { - "presentation" : "app", - "layout" : "table", - "name" : "last_30_days", - "priority" : 0 - } ], - "configDriver" : "bubble.app.bblock.BubbleBlockAppConfigDriver", - "configFields" : [ { - "name" : "name", - "displayName" : "Name", - "mode" : "standard", - "control" : "text" - }, { - "name" : "description", - "displayName" : "Description", - "mode" : "standard", - "control" : "textarea" - }, { - "name" : "url", - "displayName" : "Url", - "mode" : "standard", - "type" : "http_url", - "control" : "text" - }, { - "name" : "tags", - "displayName" : "Tags", - "mode" : "standard", - "control" : "text" - }, { - "name" : "tagString", - "displayName" : "Tag String", - "mode" : "standard", - "control" : "text" - }, { - "name" : "enabled", - "displayName" : "Enabled", - "mode" : "readOnly", - "type" : "flag", - "control" : "flag" - }, { - "name" : "rule", - "displayName" : "Rule", - "mode" : "standard", - "control" : "text" - }, { - "name" : "ruleType", - "displayName" : "Rule Type", - "mode" : "readOnly", - "control" : "text" - }, { - "name" : "testUrl", - "displayName" : "Test Url", - "mode" : "standard", - "type" : "http_url", - "control" : "text" - }, { - "name" : "testUserAgent", - "required" : false, - "displayName" : "Test User Agent", - "mode" : "standard", - "control" : "text" - }, { - "name" : "testUrlPrimary", - "displayName" : "Test Url Primary", - "mode" : "standard", - "type" : "flag", - "control" : "flag" - }, { - "name" : "urlRegex", - "required" : false, - "displayName" : "Url Regex", - "mode" : "standard", - "control" : "text" - }, { - "name" : "userAgentRegex", - "displayName" : "User Agent Regex", - "mode" : "standard", - "control" : "text" - }, { - "name" : "ctime", - "displayName" : "Ctime", - "mode" : "standard", - "control" : "text", - "customFormat" : true - }, { - "name" : "device", - "displayName" : "Device", - "mode" : "standard", - "control" : "text" - }, { - "name" : "fqdn", - "displayName" : "Fqdn", - "mode" : "standard", - "control" : "text" - }, { - "name" : "uri", - "displayName" : "Uri", - "mode" : "standard", - "control" : "text" - }, { - "name" : "data", - "displayName" : "Data", - "mode" : "standard", - "control" : "text" - } ], - "configViews" : [ { - "name" : "manageLists", - "scope" : "app", - "root" : true, - "fields" : [ "name", "description", "url", "enabled", "tagString" ], - "actions" : [ { - "name" : "enableList", - "scope" : "item", - "when" : "!item.enabled", - "index" : 10 - }, { - "name" : "disableList", - "scope" : "item", - "when" : "item.enabled", - "index" : 20 - }, { - "name" : "manageList", - "scope" : "item", - "view" : "manageList", - "index" : 30 - }, { - "name" : "manageRules", - "scope" : "item", - "when" : "item.url === \\'\\'", - "view" : "manageRules", - "index" : 40 - }, { - "name" : "removeList", - "scope" : "item", - "when" : "item.url !== ''", - "index" : 50 - }, { - "name" : "createList", - "scope" : "app", - "view" : "manageList", - "index" : 10, - "params" : [ "url" ], - "button" : "createList" - }, { - "name" : "testUrl", - "scope" : "app", - "successMessage" : "decisionType", - "index" : 20, - "params" : [ "testUrl", "testUrlPrimary" ], - "button" : "testUrl" - } ] - }, { - "name" : "manageList", - "scope" : "item", - "root" : false, - "fields" : [ "name", "description", "url", "tagString", "enabled" ], - "actions" : [ { - "name" : "updateList", - "scope" : "item", - "successView" : "manageLists", - "index" : 10 - }, { - "name" : "enableList", - "scope" : "item", - "when" : "!item.enabled", - "index" : 20 - }, { - "name" : "disableList", - "scope" : "item", - "when" : "item.enabled", - "index" : 30 - }, { - "name" : "manageRules", - "scope" : "item", - "when" : "item.url === ''", - "view" : "manageRules", - "index" : 40 - }, { - "name" : "removeList", - "scope" : "item", - "when" : "item.url !== ''", - "successView" : "manageLists", - "index" : 50 - } ] - }, { - "name" : "manageRules", - "scope" : "item", - "root" : false, - "fields" : [ "rule" ], - "actions" : [ { - "name" : "removeRule", - "scope" : "item", - "index" : 10 - }, { - "name" : "createRule", - "scope" : "app", - "index" : 10, - "params" : [ "rule" ], - "button" : "createRule" - }, { - "name" : "testUrl", - "scope" : "app", - "successMessage" : "decisionType", - "index" : 20, - "params" : [ "testUrl", "testUserAgent", "testUrlPrimary" ], - "button" : "testUrl" - } ] - }, { - "name" : "manageUserAgents", - "scope" : "app", - "root" : true, - "fields" : [ "userAgentRegex", "urlRegex" ], - "actions" : [ { - "name" : "removeUserAgentBlock", - "scope" : "item", - "index" : 10 - }, { - "name" : "createUserAgentBlock", - "scope" : "app", - "index" : 10, - "params" : [ "userAgentRegex", "urlRegex" ], - "button" : "createUserAgentBlock" - }, { - "name" : "testUrl", - "scope" : "app", - "successMessage" : "decisionType", - "index" : 20, - "params" : [ "testUrl", "testUserAgent", "testUrlPrimary" ], - "button" : "testUrl" - } ] - } ] - }, - "shortId" : "12ed9f89" - }, { - "uuid" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "children" : { - "AppMatcher" : [ { - "uuid" : "a9f35a6b-7fb0-40b4-9154-ede9a481f5b7", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "HNCommentMatcher", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "site" : "7569f7f0-6ad0-4709-9a77-c217e4fc7ccb", - "fqdn" : "news.ycombinator.com", - "urlRegex" : "/item\\?id=\\d+", - "rule" : "30dfe23b-e7d7-4fe6-8aa9-9620d028df97", - "template" : true, - "enabled" : true, - "connCheck" : false, - "requestCheck" : true, - "priority" : 0, - "shortId" : "a9f35a6b" - }, { - "uuid" : "e4be80d1-56d8-4dd1-9bba-baefb0c91989", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "HNThreadsMatcher", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "site" : "7569f7f0-6ad0-4709-9a77-c217e4fc7ccb", - "fqdn" : "news.ycombinator.com", - "urlRegex" : "/threads\\?id=\\w+", - "rule" : "30dfe23b-e7d7-4fe6-8aa9-9620d028df97", - "template" : true, - "enabled" : true, - "connCheck" : false, - "requestCheck" : true, - "priority" : 0, - "shortId" : "e4be80d1" - }, { - "uuid" : "2e175923-44fd-40b4-a1da-849cc7941582", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "MRMatcher", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "site" : "76bb15ba-c184-43e4-99e6-989957e7cb62", - "fqdn" : "marginalrevolution.com", - "urlRegex" : "(/marginalrevolution)?/20\\d{2}/\\d{2}/\\w+", - "rule" : "b17ef6a7-6de9-4ab1-8335-dfd9e834008a", - "template" : true, - "enabled" : true, - "connCheck" : false, - "requestCheck" : true, - "priority" : 0, - "shortId" : "2e175923" - }, { - "uuid" : "157232b8-5ed3-4c8f-9837-c3ea6edf0eb9", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "ReasonMatcher", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "site" : "e6adce40-8b78-44a7-b7f3-394fe6856de4", - "fqdn" : "reason.com", - "urlRegex" : "/20\\d{2}/\\d{2}/\\d{2}/[-\\w]+/", - "rule" : "75716dd0-ebbd-4410-99d3-86ab0a206849", - "template" : true, - "enabled" : true, - "connCheck" : false, - "requestCheck" : true, - "priority" : 0, - "shortId" : "157232b8" - }, { - "uuid" : "7b634b87-ca36-4b13-828b-803c71a2c17c", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "TwitterMatcher", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "site" : "d78bbb36-75f0-4974-b3f3-b5cf93780582", - "fqdn" : "twitter.com", - "urlRegex" : ".*", - "rule" : "a904ee63-039d-4914-8ec7-7d5d22d9e0ca", - "template" : true, - "enabled" : true, - "connCheck" : false, - "requestCheck" : true, - "priority" : 0, - "shortId" : "7b634b87" - } ], - "AppRule" : [ { - "uuid" : "30dfe23b-e7d7-4fe6-8aa9-9620d028df97", - "name" : "hn_user_blocker", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "f314f0ed-2144-4141-850d-c607a7ab010c", - "config" : { - "siteJsTemplate" : "bubble/rule/social/block/site/HackerNews.js.hbs" - }, - "shortId" : "30dfe23b" - }, { - "uuid" : "b17ef6a7-6de9-4ab1-8335-dfd9e834008a", - "name" : "mr_user_blocker", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "f314f0ed-2144-4141-850d-c607a7ab010c", - "config" : { - "siteJsTemplate" : "bubble/rule/social/block/site/MR.js.hbs" - }, - "shortId" : "b17ef6a7" - }, { - "uuid" : "75716dd0-ebbd-4410-99d3-86ab0a206849", - "name" : "reason_user_blocker", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "f314f0ed-2144-4141-850d-c607a7ab010c", - "config" : { - "siteJsTemplate" : "bubble/rule/social/block/site/Reason.js.hbs" - }, - "shortId" : "75716dd0" - }, { - "uuid" : "a904ee63-039d-4914-8ec7-7d5d22d9e0ca", - "name" : "twitter_user_blocker", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "f314f0ed-2144-4141-850d-c607a7ab010c", - "config" : { - "siteJsTemplate" : "bubble/rule/social/block/site/Twitter.js.hbs", - "insertionRegex" : "<\\s*html[^>]*>" - }, - "shortId" : "a904ee63" - } ], - "AppMessage" : [ { - "uuid" : "aa88397b-644a-48d9-aafa-b2bc912c49cd", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "locale" : "en_US", - "priority" : 1, - "template" : true, - "enabled" : true, - "messages" : [ { - "name" : "name", - "value" : "Shadow Ban" - }, { - "name" : "icon", - "value" : "classpath:models/apps/user_block/shadowban-icon.svg" - }, { - "name" : "summary", - "value" : "User Blocker" - }, { - "name" : "description", - "value" : "Throw the garbage to the curb!" - }, { - "name" : "view.blocked_users", - "value" : "Manage Blocked Users" - }, { - "name" : "field.key", - "value" : "Username" - }, { - "name" : "field.enabled", - "value" : "Enforce Block" - }, { - "name" : "field.ctime", - "value" : "Created" - }, { - "name" : "action.enable", - "value" : "Enforce Block" - }, { - "name" : "action.disable", - "value" : "Disable Block" - }, { - "name" : "action.delete", - "value" : "Delete Block" - } ], - "shortId" : "aa88397b" - } ], - "AppSite" : [ { - "uuid" : "7569f7f0-6ad0-4709-9a77-c217e4fc7ccb", - "name" : "HackerNews", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "description" : "A blog and discussion site for technology news, operated by YCombinator", - "url" : "https://news.ycombinator.com", - "shortId" : "7569f7f0" - }, { - "uuid" : "76bb15ba-c184-43e4-99e6-989957e7cb62", - "name" : "MarginalRevolution", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "description" : "An economics blog by Tyler Cowen and Alex Tabarrok, professors at George Mason University", - "url" : "https://marginalrevolution.com", - "shortId" : "76bb15ba" - }, { - "uuid" : "e6adce40-8b78-44a7-b7f3-394fe6856de4", - "name" : "Reason", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "description" : "A leading libertarian magazine", - "url" : "https://reason.com", - "shortId" : "e6adce40" - }, { - "uuid" : "d78bbb36-75f0-4974-b3f3-b5cf93780582", - "name" : "Twitter", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "0a6b53b5-ef6a-4826-979d-7c0b1fce1ea2", - "template" : true, - "enabled" : true, - "description" : "what’s happening in the world and what people are talking about right now.", - "url" : "https://twitter.com", - "shortId" : "d78bbb36" - } ] - }, - "name" : "UserBlocker", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "url" : "https://getbubblenow.com/apps/UserBlocker", - "description" : "ShadowBan User Blocker", - "canPrime" : true, - "template" : true, - "enabled" : true, - "priority" : 300, - "dataConfig" : { - "presentation" : "site", - "dataDriver" : "bubble.app.social.block.UserBlockerAppDataDriver", - "fields" : [ { - "name" : "key", - "displayName" : "Key", - "mode" : "standard", - "control" : "text" - }, { - "name" : "enabled", - "displayName" : "Enabled", - "mode" : "standard", - "control" : "text" - }, { - "name" : "ctime", - "displayName" : "Ctime", - "mode" : "standard", - "control" : "text" - } ], - "actions" : [ { - "name" : "enable", - "when" : "!data.enabled" - }, { - "name" : "disable", - "when" : "data.enabled" - }, { - "name" : "delete" - } ], - "views" : [ { - "presentation" : "site", - "layout" : "table", - "name" : "blocked_users", - "priority" : 0 - } ], - "configFields" : [ { - "name" : "key", - "displayName" : "Key", - "mode" : "standard", - "control" : "text" - }, { - "name" : "enabled", - "displayName" : "Enabled", - "mode" : "standard", - "control" : "text" - }, { - "name" : "ctime", - "displayName" : "Ctime", - "mode" : "standard", - "control" : "text" - } ] - }, - "shortId" : "0a6b53b5" - }, { - "uuid" : "7af54a16-c7e9-4f80-b7ef-45353689ba9b", - "children" : { - "AppMatcher" : [ { - "uuid" : "f0e275af-e461-4d7e-932b-12fff0881a11", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "name" : "TlsPassthruMatcher", - "app" : "7af54a16-c7e9-4f80-b7ef-45353689ba9b", - "site" : "2793e94c-34c5-4ec2-a3d3-426518fc4a55", - "fqdn" : "*", - "urlRegex" : ".*", - "rule" : "a446487a-d841-468e-925b-e3435b2f2a50", - "template" : true, - "enabled" : true, - "connCheck" : true, - "requestCheck" : false, - "priority" : -1000000, - "shortId" : "f0e275af" - } ], - "AppRule" : [ { - "uuid" : "a446487a-d841-468e-925b-e3435b2f2a50", - "name" : "passthru", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "7af54a16-c7e9-4f80-b7ef-45353689ba9b", - "template" : true, - "enabled" : true, - "priority" : 0, - "driver" : "c487b2ba-65f7-462f-af7f-c1ca2af5bc8a", - "config" : { - "fqdnList" : [ ], - "feedList" : [ { - "feedUrl" : "https://raw.githubusercontent.com/getbubblenow/bubble-filter-lists/master/tls_passthru.txt" - } ] - }, - "shortId" : "a446487a" - } ], - "AppMessage" : [ { - "uuid" : "e3874ec0-e9c5-4ad5-a33d-3a489f58ed38", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "7af54a16-c7e9-4f80-b7ef-45353689ba9b", - "locale" : "en_US", - "priority" : 1, - "template" : true, - "enabled" : true, - "messages" : [ { - "name" : "name", - "value" : "DirectConnect" - }, { - "name" : "icon", - "value" : "classpath:models/apps/passthru/passthru-icon.svg" - }, { - "name" : "summary", - "value" : "Network Bypass" - }, { - "name" : "description", - "value" : "Do not perform SSL interception for certificate-pinned domains" - }, { - "name" : "config.view.manageDomains", - "value" : "Manage Bypass Domains" - }, { - "name" : "config.view.manageFeeds", - "value" : "Manage Bypass Domain Feeds" - }, { - "name" : "config.field.passthruFqdn", - "value" : "Domain" - }, { - "name" : "config.field.passthruFqdn.description", - "value" : "Bypass traffic interception for this hostname" - }, { - "name" : "config.field.feedName", - "value" : "Name" - }, { - "name" : "config.field.feedUrl", - "value" : "Bypass Domains List URL" - }, { - "name" : "config.field.feedUrl.description", - "value" : "URL returning a list of bypass domains and/or hostnames, one per line" - }, { - "name" : "config.action.addFqdn", - "value" : "Add New Bypass Domain" - }, { - "name" : "config.button.addFqdn", - "value" : "Add" - }, { - "name" : "config.action.removeFqdn", - "value" : "Remove" - }, { - "name" : "config.action.addFeed", - "value" : "Add New Bypass Domain Feed" - }, { - "name" : "config.button.addFeed", - "value" : "Add" - }, { - "name" : "config.action.removeFeed", - "value" : "Remove" - } ], - "shortId" : "e3874ec0" - } ], - "AppSite" : [ { - "uuid" : "2793e94c-34c5-4ec2-a3d3-426518fc4a55", - "name" : "All_Sites", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "app" : "7af54a16-c7e9-4f80-b7ef-45353689ba9b", - "template" : true, - "enabled" : true, - "description" : "All websites", - "url" : "*", - "shortId" : "2793e94c" - } ] - }, - "name" : "TlsPassthru", - "account" : "a4e4921a-0755-4b91-a858-7b4888b7433b", - "url" : "https://getbubblenow.com/apps/passthru", - "description" : "Do not perform SSL interception for certificate-pinned domains", - "canPrime" : false, - "template" : true, - "enabled" : true, - "priority" : 1000000, - "dataConfig" : { - "presentation" : "none", - "dataDriver" : "bubble.app.passthru.TlsPassthruAppDataDriver", - "configDriver" : "bubble.app.passthru.TlsPassthruAppConfigDriver", - "configFields" : [ { - "name" : "passthruFqdn", - "displayName" : "Passthru Fqdn", - "mode" : "standard", - "type" : "hostname", - "control" : "text", - "truncate" : false - }, { - "name" : "feedName", - "displayName" : "Feed Name", - "mode" : "standard", - "control" : "text", - "truncate" : false - }, { - "name" : "feedUrl", - "displayName" : "Feed Url", - "mode" : "standard", - "type" : "http_url", - "control" : "text" - } ], - "configViews" : [ { - "name" : "manageDomains", - "scope" : "app", - "root" : true, - "fields" : [ "passthruFqdn" ], - "actions" : [ { - "name" : "removeFqdn", - "scope" : "item", - "index" : 10 - }, { - "name" : "addFqdn", - "scope" : "app", - "index" : 10, - "params" : [ "passthruFqdn" ], - "button" : "addFqdn" - } ] - }, { - "name" : "manageFeeds", - "scope" : "app", - "root" : true, - "fields" : [ "feedName", "feedUrl" ], - "actions" : [ { - "name" : "removeFeed", - "scope" : "item", - "index" : 10 - }, { - "name" : "addFeed", - "scope" : "app", - "index" : 10, - "params" : [ "feedUrl" ], - "button" : "addFeed" - } ] - } ] - }, - "shortId" : "7af54a16" - } ] -} diff --git a/bubble-server/src/main/resources/db/migration/V2020091801__add_network_launch_type.sql b/bubble-server/src/main/resources/db/migration/V2020091801__add_network_launch_type.sql new file mode 100644 index 00000000..66806b60 --- /dev/null +++ b/bubble-server/src/main/resources/db/migration/V2020091801__add_network_launch_type.sql @@ -0,0 +1 @@ +ALTER TABLE bubble_network ADD COLUMN launch_type VARCHAR(200); diff --git a/bubble-server/src/main/resources/messages b/bubble-server/src/main/resources/messages index 61fc9667..9d1ecac6 160000 --- a/bubble-server/src/main/resources/messages +++ b/bubble-server/src/main/resources/messages @@ -1 +1 @@ -Subproject commit 61fc9667c4c66c0bcbbb8eb4d128e8ab58f50869 +Subproject commit 9d1ecac6514696721effe012e9c726896c368ebe diff --git a/bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_api.py b/bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_api.py index 47f88908..a42661df 100644 --- a/bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_api.py +++ b/bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_api.py @@ -25,7 +25,6 @@ from bubble_config import bubble_port, debug_capture_fqdn, \ from mitmproxy import http from mitmproxy.net.http import headers as nheaders from mitmproxy.proxy.protocol.async_stream_body import AsyncStreamBody -from mitmproxy.proxy.protocol.request_capture import RequestCapture bubble_log = logging.getLogger(__name__) @@ -401,7 +400,7 @@ def is_bubble_health_check(path): def is_sage_request(ip, fqdns): - return (ip == bubble_sage_ip4 or ip == bubble_sage_ip6) and bubble_sage_host in fqdns + return fqdns is not None and (ip == bubble_sage_ip4 or ip == bubble_sage_ip6) and bubble_sage_host in fqdns def is_not_from_vpn(client_addr): @@ -416,7 +415,7 @@ def is_flex_domain(client_addr, server_addr, fqdns): return False fqdn = fqdns[0] - if fqdn == bubble_host or fqdn == bubble_host_alias or fqdn == bubble_sage_host: + if fqdn == bubble_host or fqdn == bubble_host_alias or (bubble_sage_host is not None and fqdn == bubble_sage_host): if bubble_log.isEnabledFor(DEBUG): bubble_log.debug('is_flex_domain: (early) returning False for: '+fqdn) return False diff --git a/bubble-web b/bubble-web index 66d46695..37dd89bd 160000 --- a/bubble-web +++ b/bubble-web @@ -1 +1 @@ -Subproject commit 66d46695a64ff58934560c4b35aa43a0ab32fbe2 +Subproject commit 37dd89bd78949a63c68a64596b4e1c105809a577 diff --git a/utils/cobbzilla-utils b/utils/cobbzilla-utils index dfafe62c..fab2bdaf 160000 --- a/utils/cobbzilla-utils +++ b/utils/cobbzilla-utils @@ -1 +1 @@ -Subproject commit dfafe62c7eb3413cf1210e40e551094458f4d9d0 +Subproject commit fab2bdafe756fc53ff80b58171fb9000846bf0ef