mirror of
https://github.com/google/nomulus
synced 2026-07-10 10:02:50 +00:00
Sanitize a few log instances (#3135)
Just remove a few possibly-insecure logs
This commit is contained in:
@@ -38,6 +38,7 @@ import google.registry.dns.ReadDnsRefreshRequestsAction;
|
||||
import google.registry.model.common.DnsRefreshRequest;
|
||||
import google.registry.mosapi.MosApiClient;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.rde.RdeUploadUrl;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import google.registry.util.YamlUtils;
|
||||
@@ -842,8 +843,8 @@ public final class RegistryConfig {
|
||||
*/
|
||||
@Provides
|
||||
@Config("rdeUploadUrl")
|
||||
public static URI provideRdeUploadUrl(RegistryConfigSettings config) {
|
||||
return URI.create(config.rde.uploadUrl);
|
||||
public static RdeUploadUrl provideRdeUploadUrl(RegistryConfigSettings config) {
|
||||
return RdeUploadUrl.create(URI.create(config.rde.uploadUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,6 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import google.registry.request.Response;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -55,7 +54,6 @@ public class CookieSessionMetadata extends SessionMetadata {
|
||||
Pattern.compile("serviceExtensionUris=([^,\\s}]+)?");
|
||||
private static final Pattern FAILED_LOGIN_ATTEMPTS_PATTERN =
|
||||
Pattern.compile("failedLoginAttempts=([^,\\s]+)?");
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final Map<String, String> data = new HashMap<>();
|
||||
|
||||
@@ -66,7 +64,6 @@ public class CookieSessionMetadata extends SessionMetadata {
|
||||
Matcher matcher = COOKIE_PATTERN.matcher(cookie);
|
||||
if (matcher.find()) {
|
||||
String sessionInfo = decode(matcher.group(1));
|
||||
logger.atInfo().log("SESSION INFO: %s", sessionInfo);
|
||||
matcher = REGISTRAR_ID_PATTERN.matcher(sessionInfo);
|
||||
if (matcher.find()) {
|
||||
String registrarId = matcher.group(1);
|
||||
|
||||
@@ -68,9 +68,12 @@ public final class EppController {
|
||||
try {
|
||||
eppInput = unmarshalEpp(EppInput.class, inputXmlBytes);
|
||||
} catch (EppException e) {
|
||||
// Log the unmarshalling error, with the raw bytes (in base64) to help with debugging.
|
||||
// Log the unmarshalling error, with the sanitized bytes (in base64) to help with debugging.
|
||||
Optional<String> sanitizedXml = EppXmlSanitizer.sanitizeEppXmlIfValid(inputXmlBytes);
|
||||
String xmlBytesToLog =
|
||||
base64().encode(sanitizedXml.map(xml -> xml.getBytes(UTF_8)).orElse(inputXmlBytes));
|
||||
logger.atInfo().withCause(e).log(
|
||||
"EPP request XML unmarshalling failed - \"%s\":\n%s\n%s\n%s\n%s",
|
||||
"EPP request XML unmarshalling failed - \"%s\":\n%s\n%s",
|
||||
e.getMessage(),
|
||||
lazy(
|
||||
() ->
|
||||
@@ -83,12 +86,7 @@ public final class EppController {
|
||||
"resultMessage",
|
||||
e.getResult().getCode().msg,
|
||||
"xmlBytes",
|
||||
base64().encode(inputXmlBytes)))),
|
||||
LOG_SEPARATOR,
|
||||
lazy(
|
||||
() ->
|
||||
new String(inputXmlBytes, UTF_8)
|
||||
.trim()), // Charset decoding failures are swallowed.
|
||||
xmlBytesToLog))),
|
||||
LOG_SEPARATOR);
|
||||
// Return early by sending an error message, with no clTRID since we couldn't unmarshal it.
|
||||
eppMetricBuilder.setStatus(e.getResult().getCode());
|
||||
|
||||
@@ -87,16 +87,22 @@ public class EppXmlSanitizer {
|
||||
*
|
||||
* <p>Also, an empty element will be formatted as {@code <tag></tag>} instead of {@code <tag/>}.
|
||||
*/
|
||||
public static String sanitizeEppXml(byte[] inputXmlBytes) {
|
||||
public static Optional<String> sanitizeEppXmlIfValid(byte[] inputXmlBytes) {
|
||||
try {
|
||||
// Keep exactly one newline at end of sanitized string.
|
||||
return CharMatcher.whitespace().trimTrailingFrom(sanitizeAndEncode(inputXmlBytes)) + "\n";
|
||||
return Optional.of(
|
||||
CharMatcher.whitespace().trimTrailingFrom(sanitizeAndEncode(inputXmlBytes)) + "\n");
|
||||
} catch (XMLStreamException | UnsupportedEncodingException e) {
|
||||
logger.atWarning().withCause(e).log("Failed to sanitize EPP XML message.");
|
||||
return Base64.getMimeEncoder().encodeToString(inputXmlBytes);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static String sanitizeEppXml(byte[] inputXmlBytes) {
|
||||
return sanitizeEppXmlIfValid(inputXmlBytes)
|
||||
.orElseGet(() -> Base64.getMimeEncoder().encodeToString(inputXmlBytes));
|
||||
}
|
||||
|
||||
private static String sanitizeAndEncode(byte[] inputXmlBytes)
|
||||
throws XMLStreamException, UnsupportedEncodingException {
|
||||
XMLEventReader xmlEventReader =
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.jcraft.jsch.SftpException;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import jakarta.inject.Inject;
|
||||
import java.io.Closeable;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
@@ -57,8 +56,7 @@ final class JSchSshSession implements Closeable {
|
||||
*
|
||||
* @throws JSchException if we fail to open the connection.
|
||||
*/
|
||||
JSchSshSession create(JSch jsch, URI uri) throws JSchException {
|
||||
RdeUploadUrl url = RdeUploadUrl.create(uri);
|
||||
JSchSshSession create(JSch jsch, RdeUploadUrl url) throws JSchException {
|
||||
logger.atInfo().log("Connecting to SSH endpoint: %s", url);
|
||||
Session session = jsch.getSession(
|
||||
url.getUser().orElse("domain-registry"),
|
||||
|
||||
@@ -312,7 +312,8 @@ public final class RdeStagingAction implements Runnable {
|
||||
jobRegion,
|
||||
new LaunchFlexTemplateRequest().setLaunchParameter(parameter))
|
||||
.execute();
|
||||
logger.atInfo().log("Got response: %s", launchResponse.getJob().toPrettyString());
|
||||
logger.atInfo().log(
|
||||
"Launched RDE staging Dataflow job: %s", launchResponse.getJob().getId());
|
||||
jobNameBuilder.add(launchResponse.getJob().getId());
|
||||
} catch (IOException e) {
|
||||
logger.atWarning().withCause(e).log("Pipeline Launch failed");
|
||||
|
||||
@@ -64,7 +64,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
@@ -116,11 +115,16 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
|
||||
@Inject @Config("rdeInterval") Duration interval;
|
||||
@Inject @Config("rdeUploadLockTimeout") Duration timeout;
|
||||
@Inject @Config("rdeUploadSftpCooldown") Duration sftpCooldown;
|
||||
@Inject @Config("rdeUploadUrl") URI uploadUrl;
|
||||
@Inject @Key("rdeReceiverKey") PGPPublicKey receiverKey;
|
||||
@Inject @Key("rdeSigningKey") PGPKeyPair signingKey;
|
||||
@Inject @Key("rdeStagingDecryptionKey") PGPPrivateKey stagingDecryptionKey;
|
||||
|
||||
@Inject
|
||||
@Config("rdeUploadUrl")
|
||||
RdeUploadUrl rdeUploadUrl;
|
||||
|
||||
@Inject RdeUploadAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.atInfo().log("Attempting to acquire RDE upload lock for TLD '%s'.", tld);
|
||||
@@ -135,7 +139,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
|
||||
@Override
|
||||
public void runWithLock(Instant watermark) throws Exception {
|
||||
// If a prefix is not provided,try to determine the prefix. This should only happen when the RDE
|
||||
// upload cron job runs to catch up any un-retried (i. e. expected) RDE failures.
|
||||
// upload cron job runs to catch up any un-retried (i.e. expected) RDE failures.
|
||||
String actualPrefix =
|
||||
prefix.orElseGet(() -> findMostRecentPrefixForWatermark(watermark, bucket, tld, gcsUtils));
|
||||
logger.atInfo().log("Verifying readiness to upload the RDE deposit.");
|
||||
@@ -181,7 +185,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
|
||||
verifyFileExists(xmlFilename);
|
||||
verifyFileExists(xmlLengthFilename);
|
||||
verifyFileExists(reportFilename);
|
||||
logger.atInfo().log("Commencing RDE upload for TLD '%s' to '%s'.", tld, uploadUrl);
|
||||
logger.atInfo().log("Commencing RDE upload for TLD '%s' to '%s'.", tld, rdeUploadUrl);
|
||||
final long xmlLength = readXmlLength(xmlLengthFilename);
|
||||
retrier.callWithRetry(
|
||||
() -> upload(xmlFilename, xmlLength, watermark, name, nameWithoutPrefix),
|
||||
@@ -221,10 +225,10 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
|
||||
private void upload(
|
||||
BlobId xmlFile, long xmlLength, Instant watermark, String name, String nameWithoutPrefix)
|
||||
throws Exception {
|
||||
logger.atInfo().log("Uploading XML file '%s' to remote path '%s'.", xmlFile, uploadUrl);
|
||||
logger.atInfo().log("Uploading XML file '%s' to remote path '%s'.", xmlFile, rdeUploadUrl);
|
||||
try (InputStream gcsInput = gcsUtils.openInputStream(xmlFile);
|
||||
InputStream ghostrydeDecoder = Ghostryde.decoder(gcsInput, stagingDecryptionKey)) {
|
||||
try (JSchSshSession session = jschSshSessionFactory.create(lazyJsch.get(), uploadUrl);
|
||||
try (JSchSshSession session = jschSshSessionFactory.create(lazyJsch.get(), rdeUploadUrl);
|
||||
JSchSftpChannel ftpChan = session.openSftpChannel()) {
|
||||
ByteArrayOutputStream sigOut = new ByteArrayOutputStream();
|
||||
String rydeFilename = nameWithoutPrefix + ".ryde";
|
||||
|
||||
@@ -37,7 +37,7 @@ import javax.annotation.concurrent.Immutable;
|
||||
* @see RdeUploadAction
|
||||
*/
|
||||
@Immutable
|
||||
final class RdeUploadUrl implements Comparable<RdeUploadUrl> {
|
||||
public final class RdeUploadUrl implements Comparable<RdeUploadUrl> {
|
||||
|
||||
public static final Protocol SFTP = new Protocol("sftp", 22);
|
||||
private static final ImmutableMap<String, Protocol> ALLOWED_PROTOCOLS =
|
||||
|
||||
@@ -127,7 +127,7 @@ public class GenerateSpec11ReportAction implements Runnable {
|
||||
jobRegion,
|
||||
new LaunchFlexTemplateRequest().setLaunchParameter(parameter))
|
||||
.execute();
|
||||
logger.atInfo().log("Got response: %s", launchResponse.getJob().toPrettyString());
|
||||
logger.atInfo().log("Launched Spec11 Dataflow job: %s", launchResponse.getJob().getId());
|
||||
String jobId = launchResponse.getJob().getId();
|
||||
if (sendEmail) {
|
||||
cloudTasksUtils.enqueue(
|
||||
|
||||
@@ -155,7 +155,7 @@ public class RdeUploadActionTest {
|
||||
action.timeout = Duration.ofSeconds(23);
|
||||
action.tld = "tld";
|
||||
action.sftpCooldown = Duration.ofSeconds(7);
|
||||
action.uploadUrl = uploadUrl;
|
||||
action.rdeUploadUrl = RdeUploadUrl.create(uploadUrl);
|
||||
action.receiverKey = keyring.getRdeReceiverKey();
|
||||
action.signingKey = keyring.getRdeSigningKey();
|
||||
action.stagingDecryptionKey = keyring.getRdeStagingDecryptionKey();
|
||||
@@ -212,7 +212,7 @@ public class RdeUploadActionTest {
|
||||
@Test
|
||||
void testRun() {
|
||||
createTld("lol");
|
||||
RdeUploadAction action = createAction(null);
|
||||
RdeUploadAction action = createAction(URI.create("sftp://user:password@localhost:5432"));
|
||||
action.tld = "lol";
|
||||
action.run();
|
||||
verify(runner)
|
||||
@@ -231,7 +231,7 @@ public class RdeUploadActionTest {
|
||||
@Test
|
||||
void testRun_withPrefix() throws Exception {
|
||||
createTld("lol");
|
||||
RdeUploadAction action = createAction(null);
|
||||
RdeUploadAction action = createAction(URI.create("sftp://user:password@localhost:5432"));
|
||||
action.prefix = Optional.of("job-name/");
|
||||
action.tld = "lol";
|
||||
action.run();
|
||||
|
||||
Reference in New Issue
Block a user