Merge "Add logging of cause of failure when the log list fails to update" into main

This commit is contained in:
Bessie Jiang 2024-12-24 02:22:54 -08:00 • committed by Gerrit Code Review
commit 06a516c8ae
5 changed files with 151 additions and 14 deletions

View file

@ -24,12 +24,14 @@ java_library {
srcs: [
"src/**/*.java",
":statslog-certificate-transparency-java-gen",
],
libs: [
"framework-configinfrastructure.stubs.module_lib",
"framework-connectivity-pre-jarjar",
"service-connectivity-pre-jarjar",
"framework-statsd.stubs.module_lib",
],
static_libs: [
@ -49,3 +51,10 @@ java_library {
sdk_version: "system_server_current",
apex_available: ["com.android.tethering"],
}
genrule {
name: "statslog-certificate-transparency-java-gen",
tools: ["stats-log-api-gen"],
cmd: "$(location stats-log-api-gen) --java $(out) --module certificate_transparency --javaPackage com.android.server.net.ct --javaClass CertificateTransparencyStatsLog",
out: ["com/android/server/net/ct/CertificateTransparencyStatsLog.java"],
}

View file

@ -16,6 +16,15 @@
package com.android.server.net.ct;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_DEVICE_OFFLINE;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_DOWNLOAD_CANNOT_RESUME;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_HTTP_ERROR;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_NO_DISK_SPACE;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_UNKNOWN;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_TOO_MANY_REDIRECTS;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_VERSION_ALREADY_EXISTS;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__PENDING_WAITING_FOR_WIFI;
import static java.nio.charset.StandardCharsets.UTF_8;
import android.annotation.RequiresApi;
@ -50,18 +59,21 @@ class CertificateTransparencyDownloader extends BroadcastReceiver {
private final DownloadHelper mDownloadHelper;
private final SignatureVerifier mSignatureVerifier;
private final CertificateTransparencyInstaller mInstaller;
private final CertificateTransparencyLogger mLogger;
CertificateTransparencyDownloader(
Context context,
DataStore dataStore,
DownloadHelper downloadHelper,
SignatureVerifier signatureVerifier,
CertificateTransparencyInstaller installer) {
CertificateTransparencyInstaller installer,
CertificateTransparencyLogger logger) {
mContext = context;
mSignatureVerifier = signatureVerifier;
mDataStore = dataStore;
mDownloadHelper = downloadHelper;
mInstaller = installer;
mLogger = logger;
}
void initialize() {
@ -197,6 +209,8 @@ class CertificateTransparencyDownloader extends BroadcastReceiver {
}
if (!success) {
Log.w(TAG, "Log list did not pass verification");
// TODO(b/384931263): add logging for failed signature verification
return;
}
@ -225,7 +239,10 @@ class CertificateTransparencyDownloader extends BroadcastReceiver {
mDataStore.store();
} else {
if (updateFailureCount()) {
// TODO(378626065): Report FAILURE_VERSION_ALREADY_EXISTS failure via statsd.
mLogger.logCTLogListUpdateFailedEvent(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_VERSION_ALREADY_EXISTS,
mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0));
}
}
}
@ -234,7 +251,46 @@ class CertificateTransparencyDownloader extends BroadcastReceiver {
Log.e(TAG, "Download failed with " + status);
if (updateFailureCount()) {
// TODO(378626065): Report download failure via statsd.
int failureCount = mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0);
// HTTP Error
if (400 <= status.reason() && status.reason() <= 600) {
mLogger.logCTLogListUpdateFailedEvent(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_HTTP_ERROR,
failureCount,
status.reason()
);
} else {
// TODO(b/384935059): handle blocked domain logging
// TODO(b/384936292): add additionalchecks for pending wifi status
mLogger.logCTLogListUpdateFailedEvent(
downloadStatusToFailureReason(status.reason()),
failureCount
);
}
}
}
/** Converts DownloadStatus reason into failure reason to log. */
private int downloadStatusToFailureReason(int downloadStatusReason) {
switch(downloadStatusReason) {
case DownloadManager.PAUSED_WAITING_TO_RETRY:
case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_DEVICE_OFFLINE;
case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
case DownloadManager.ERROR_HTTP_DATA_ERROR:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_HTTP_ERROR;
case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_TOO_MANY_REDIRECTS;
case DownloadManager.ERROR_CANNOT_RESUME:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_DOWNLOAD_CANNOT_RESUME;
case DownloadManager.ERROR_INSUFFICIENT_SPACE:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_NO_DISK_SPACE;
case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__PENDING_WAITING_FOR_WIFI;
default:
return CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_UNKNOWN;
}
}
@ -253,7 +309,7 @@ class CertificateTransparencyDownloader extends BroadcastReceiver {
boolean shouldReport = new_failure_count >= Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD;
if (shouldReport) {
Log.e(TAG,
Log.d(TAG,
"Log list update failure count exceeds threshold: " + new_failure_count);
}
return shouldReport;

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.net.ct;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED;
/** Helper class to interface with logging to statsd. */
public class CertificateTransparencyLogger {
public CertificateTransparencyLogger() {}
/**
* Logs a CTLogListUpdateFailed event to statsd, when no HTTP error status code is present.
*
* @param failureReason reason why the log list wasn't updated (e.g. DownloadManager failures)
* @param failureCount number of consecutive log list update failures
*/
public void logCTLogListUpdateFailedEvent(int failureReason, int failureCount) {
logCTLogListUpdateFailedEvent(failureReason, failureCount, /* httpErrorStatusCode= */ 0);
}
/**
* Logs a CTLogListUpdateFailed event to statsd, when an HTTP error status code is provided.
*
* @param failureReason reason why the log list wasn't updated (e.g. DownloadManager failures)
* @param failureCount number of consecutive log list update failures
* @param httpErrorStatusCode if relevant, the HTTP error status code from DownloadManager
*/
public void logCTLogListUpdateFailedEvent(
int failureReason, int failureCount, int httpErrorStatusCode) {
CertificateTransparencyStatsLog.write(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED,
failureReason,
failureCount,
httpErrorStatusCode
);
}
}

View file

@ -59,7 +59,8 @@ public class CertificateTransparencyService extends ICertificateTransparencyMana
dataStore,
downloadHelper,
signatureVerifier,
new CertificateTransparencyInstaller());
new CertificateTransparencyInstaller(),
new CertificateTransparencyLogger());
mFlagsListener =
new CertificateTransparencyFlagsListener(dataStore, signatureVerifier, downloader);
mCertificateTransparencyJob =

View file

@ -15,12 +15,17 @@
*/
package com.android.server.net.ct;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_NO_DISK_SPACE;
import static com.android.server.net.ct.CertificateTransparencyStatsLog.CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_VERSION_ALREADY_EXISTS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -67,6 +72,7 @@ public class CertificateTransparencyDownloaderTest {
@Mock private DownloadManager mDownloadManager;
@Mock private CertificateTransparencyInstaller mCertificateTransparencyInstaller;
@Mock private CertificateTransparencyLogger mLogger;
private PrivateKey mPrivateKey;
private PublicKey mPublicKey;
@ -96,7 +102,8 @@ public class CertificateTransparencyDownloaderTest {
mDataStore,
new DownloadHelper(mDownloadManager),
mSignatureVerifier,
mCertificateTransparencyInstaller);
mCertificateTransparencyInstaller,
mLogger);
prepareDataStore();
prepareDownloadManager();
@ -203,7 +210,10 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD);
// TODO(378626065): Verify logged failure via statsd.
verify(mLogger, times(1)).logCTLogListUpdateFailedEvent(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_NO_DISK_SPACE,
Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD
);
}
@Test
@ -223,7 +233,7 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(1);
// TODO(378626065): Verify no failure logged via statsd.
verify(mLogger, never()).logCTLogListUpdateFailedEvent(anyInt(), anyInt());
}
@Test
@ -274,7 +284,10 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD);
// TODO(378626065): Verify logged failure via statsd.
verify(mLogger, times(1)).logCTLogListUpdateFailedEvent(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_NO_DISK_SPACE,
Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD
);
}
@Test
@ -295,7 +308,7 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(1);
// TODO(378626065): Verify no failure logged via statsd.
verify(mLogger, never()).logCTLogListUpdateFailedEvent(anyInt(), anyInt());
}
@Test
@ -356,7 +369,10 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD);
// TODO(378626065): Verify logged failure via statsd.
verify(mLogger, times(1)).logCTLogListUpdateFailedEvent(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_NO_DISK_SPACE,
Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD
);
}
@Test
@ -377,7 +393,7 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(1);
// TODO(378626065): Verify no failure logged via statsd.
verify(mLogger, never()).logCTLogListUpdateFailedEvent(anyInt(), anyInt());
}
@Test
@ -425,7 +441,10 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD);
// TODO(378626065): Verify logged failure via statsd.
verify(mLogger, times(1)).logCTLogListUpdateFailedEvent(
CERTIFICATE_TRANSPARENCY_LOG_LIST_UPDATE_FAILED__FAILURE_REASON__FAILURE_VERSION_ALREADY_EXISTS,
Config.LOG_LIST_UPDATE_FAILURE_THRESHOLD
);
}
@Test
@ -451,7 +470,7 @@ public class CertificateTransparencyDownloaderTest {
assertThat(mDataStore.getPropertyInt(
Config.LOG_LIST_UPDATE_FAILURE_COUNT, /* defaultValue= */ 0))
.isEqualTo(1);
// TODO(378626065): Verify no failure logged via statsd.
verify(mLogger, never()).logCTLogListUpdateFailedEvent(anyInt(), anyInt());
}
@Test