Add support for sensitive data in dumps (#1149)

* Add sensitive dumps

* Add better arg handling and offline dumps

* Add sensitive parameters for plugin IPs

* Add sensitive property to the Bedrock remote address

Co-authored-by: Camotoy <20743703+DoctorMacc@users.noreply.github.com>
This commit is contained in:
rtm516 2020-08-15 21:06:50 +01:00 committed by GitHub
parent 4bcf44638e
commit 4af17df46f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 28 deletions

View file

@ -28,6 +28,7 @@ package org.geysermc.platform.bungeecord;
import lombok.Getter; import lombok.Getter;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
import org.geysermc.connector.common.serializer.AsteriskSerializer;
import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.dump.BootstrapDumpInfo;
import java.util.ArrayList; import java.util.ArrayList;
@ -52,7 +53,13 @@ public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();
for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) { for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) {
this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort())); String hostname;
if (AsteriskSerializer.showSensitive || (listener.getHost().getHostString().equals("") || listener.getHost().getHostString().equals("0.0.0.0"))) {
hostname = listener.getHost().getHostString();
} else {
hostname = "***";
}
this.listeners.add(new ListenerInfo(hostname, listener.getHost().getPort()));
} }
for (Plugin plugin : proxy.getPluginManager().getPlugins()) { for (Plugin plugin : proxy.getPluginManager().getPlugins()) {

View file

@ -28,6 +28,7 @@ package org.geysermc.platform.spigot;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.geysermc.connector.common.serializer.AsteriskSerializer;
import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.dump.BootstrapDumpInfo;
import java.util.ArrayList; import java.util.ArrayList;
@ -50,7 +51,11 @@ public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
this.platformVersion = Bukkit.getVersion(); this.platformVersion = Bukkit.getVersion();
this.platformAPIVersion = Bukkit.getBukkitVersion(); this.platformAPIVersion = Bukkit.getBukkitVersion();
this.onlineMode = Bukkit.getOnlineMode(); this.onlineMode = Bukkit.getOnlineMode();
if (AsteriskSerializer.showSensitive || (Bukkit.getIp().equals("") || Bukkit.getIp().equals("0.0.0.0"))) {
this.serverIP = Bukkit.getIp(); this.serverIP = Bukkit.getIp();
} else {
this.serverIP = "***";
}
this.serverPort = Bukkit.getPort(); this.serverPort = Bukkit.getPort();
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();

View file

@ -28,6 +28,7 @@ package org.geysermc.platform.velocity;
import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import lombok.Getter; import lombok.Getter;
import org.geysermc.connector.common.serializer.AsteriskSerializer;
import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.dump.BootstrapDumpInfo;
import java.util.ArrayList; import java.util.ArrayList;
@ -50,7 +51,11 @@ public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
this.platformVersion = proxy.getVersion().getVersion(); this.platformVersion = proxy.getVersion().getVersion();
this.platformVendor = proxy.getVersion().getVendor(); this.platformVendor = proxy.getVersion().getVendor();
this.onlineMode = proxy.getConfiguration().isOnlineMode(); this.onlineMode = proxy.getConfiguration().isOnlineMode();
if (AsteriskSerializer.showSensitive || (proxy.getBoundAddress().getHostString().equals("") || proxy.getBoundAddress().getHostString().equals("0.0.0.0"))) {
this.serverIP = proxy.getBoundAddress().getHostString(); this.serverIP = proxy.getBoundAddress().getHostString();
} else {
this.serverIP = "***";
}
this.serverPort = proxy.getBoundAddress().getPort(); this.serverPort = proxy.getBoundAddress().getPort();
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();

View file

@ -33,10 +33,12 @@ import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand; import org.geysermc.connector.command.GeyserCommand;
import org.geysermc.connector.common.serializer.AsteriskSerializer;
import org.geysermc.connector.dump.DumpInfo; import org.geysermc.connector.dump.DumpInfo;
import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.connector.utils.WebUtils; import org.geysermc.connector.utils.WebUtils;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
public class DumpCommand extends GeyserCommand { public class DumpCommand extends GeyserCommand {
@ -49,26 +51,61 @@ public class DumpCommand extends GeyserCommand {
super(name, description, permission); super(name, description, permission);
this.connector = connector; this.connector = connector;
final SimpleFilterProvider filter = new SimpleFilterProvider();
filter.addFilter("dump_user_auth", SimpleBeanPropertyFilter.serializeAllExcept(new String[] {"password"}));
MAPPER.setFilterProvider(filter);
} }
@Override @Override
public void execute(CommandSender sender, String[] args) { public void execute(CommandSender sender, String[] args) {
boolean showSensitive = false;
boolean offlineDump = false;
if (args.length >= 1) {
for (String arg : args) {
switch (arg) {
case "full":
showSensitive = true;
break;
case "offline":
offlineDump = true;
break;
}
}
}
AsteriskSerializer.showSensitive = showSensitive;
sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collecting")); sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collecting"));
String dumpData = ""; String dumpData = "";
try { try {
if (offlineDump) {
dumpData = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(new DumpInfo());
} else {
dumpData = MAPPER.writeValueAsString(new DumpInfo()); dumpData = MAPPER.writeValueAsString(new DumpInfo());
}
} catch (IOException e) { } catch (IOException e) {
sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error")); sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error"));
connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e); connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e);
return; return;
} }
String uploadedDumpUrl = "";
if (offlineDump) {
sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.writing"));
try {
FileOutputStream outputStream = new FileOutputStream(GeyserConnector.getInstance().getBootstrap().getConfigFolder().resolve("dump.json").toFile());
outputStream.write(dumpData.getBytes());
outputStream.close();
} catch (IOException e) {
sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.write_error"));
connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.write_error_short"), e);
return;
}
uploadedDumpUrl = "dump.json";
} else {
sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.uploading")); sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.uploading"));
String response; String response;
JsonNode responseNode; JsonNode responseNode;
try { try {
@ -85,7 +122,9 @@ public class DumpCommand extends GeyserCommand {
return; return;
} }
String uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText(); uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText();
}
sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.message") + " " + ChatColor.DARK_AQUA + uploadedDumpUrl); sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.message") + " " + ChatColor.DARK_AQUA + uploadedDumpUrl);
if (!sender.isConsole()) { if (!sender.isConsole()) {
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.commands.dump.created", sender.getName(), uploadedDumpUrl)); connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.commands.dump.created", sender.getName(), uploadedDumpUrl));

View file

@ -42,34 +42,46 @@ import java.lang.annotation.Target;
import java.util.Optional; import java.util.Optional;
public class AsteriskSerializer extends StdSerializer<Object> implements ContextualSerializer { public class AsteriskSerializer extends StdSerializer<Object> implements ContextualSerializer {
public static boolean showSensitive = false;
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside @JacksonAnnotationsInside
@JsonSerialize(using = AsteriskSerializer.class) @JsonSerialize(using = AsteriskSerializer.class)
public @interface Asterisk { public @interface Asterisk {
String value() default "***"; String value() default "***";
boolean sensitive() default false;
} }
String asterisk; String asterisk;
boolean sensitive;
public AsteriskSerializer() { public AsteriskSerializer() {
super(Object.class); super(Object.class);
} }
public AsteriskSerializer(String asterisk) { public AsteriskSerializer(String asterisk, boolean sensitive) {
super(Object.class); super(Object.class);
this.asterisk = asterisk; this.asterisk = asterisk;
this.sensitive = sensitive;
} }
@Override @Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) { public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) {
Optional<Asterisk> anno = Optional.ofNullable(property) Optional<Asterisk> anno = Optional.ofNullable(property)
.map(prop -> prop.getAnnotation(Asterisk.class)); .map(prop -> prop.getAnnotation(Asterisk.class));
return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null));
return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null), anno.map(Asterisk::sensitive).orElse(null));
} }
@Override @Override
public void serialize(Object obj, JsonGenerator gen, SerializerProvider prov) throws IOException { public void serialize(Object obj, JsonGenerator gen, SerializerProvider prov) throws IOException {
if (sensitive && showSensitive) {
gen.writeObject(obj);
return;
}
gen.writeString(asterisk); gen.writeString(asterisk);
} }
} }

View file

@ -98,6 +98,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@Getter @Getter
public static class BedrockConfiguration implements IBedrockConfiguration { public static class BedrockConfiguration implements IBedrockConfiguration {
@AsteriskSerializer.Asterisk(sensitive = true)
private String address; private String address;
@Setter @Setter
@ -114,6 +115,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
public static class RemoteConfiguration implements IRemoteConfiguration { public static class RemoteConfiguration implements IRemoteConfiguration {
@Setter @Setter
@AsteriskSerializer.Asterisk(sensitive = true)
private String address; private String address;
@Setter @Setter

@ -1 +1 @@
Subproject commit 57e5986bd99bf3d81d67c75299ea3dde67d53554 Subproject commit 2641db5aa9100cdbe21b4493489e9be19092a600