Merge "Add logging of cause of failure when the log list fails to update" into main
This commit is contained in:
commit
06a516c8ae
5 changed files with 151 additions and 14 deletions
|
|
@ -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"],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue