Skip to content

Commit 7fd60e2

Browse files
committed
Merge branch 'main' into PR #1492 to update
2 parents bd40d5f + 419a943 commit 7fd60e2

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

src/main/java/com/google/cloud/logging/logback/LoggingAppender.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import ch.qos.logback.core.UnsynchronizedAppenderBase;
2424
import ch.qos.logback.core.util.Loader;
2525
import com.google.api.core.InternalApi;
26+
import com.google.api.core.ObsoleteApi;
2627
import com.google.auth.oauth2.GoogleCredentials;
2728
import com.google.cloud.MonitoredResource;
2829
import com.google.cloud.logging.Instrumentation;
@@ -35,10 +36,12 @@
3536
import com.google.cloud.logging.Payload;
3637
import com.google.cloud.logging.Severity;
3738
import com.google.cloud.logging.Synchronicity;
39+
import com.google.common.base.Preconditions;
3840
import com.google.common.base.Strings;
3941
import com.google.common.collect.ImmutableList;
40-
import java.io.FileInputStream;
4142
import java.io.IOException;
43+
import java.nio.file.Files;
44+
import java.nio.file.Paths;
4245
import java.time.Instant;
4346
import java.util.ArrayList;
4447
import java.util.HashMap;
@@ -138,6 +141,7 @@ public class LoggingAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
138141
private String log;
139142
private String resourceType;
140143
private String credentialsFile;
144+
private GoogleCredentials credentials;
141145
private String logDestinationProjectId;
142146
private boolean autoPopulateMetadata = true;
143147
private boolean redirectToStdout = false;
@@ -185,17 +189,46 @@ public void setResourceType(String resourceType) {
185189
}
186190

187191
/**
188-
* Sets the path to the <a
192+
* This method is obsolete because of a potential security risk. Use the {@link
193+
* #setCredentials(GoogleCredentials)} method instead.
194+
*
195+
* <p>If you know that you will be loading credential configurations of a specific type, it is
196+
* recommended to use a credential-type-specific `fromStream()` method. This will ensure that an
197+
* unexpected credential type with potential for malicious intent is not loaded unintentionally.
198+
* You might still have to do validation for certain credential types. Please follow the
199+
* recommendation for that method.
200+
*
201+
* <p>If you are loading your credential configuration from an untrusted source and have not
202+
* mitigated the risks (e.g. by validating the configuration yourself), make these changes as soon
203+
* as possible to prevent security risks to your environment.
204+
*
205+
* <p>Regardless of the method used, it is always your responsibility to validate configurations
206+
* received from external sources.
207+
*
208+
* <p>Sets the path to the <a
189209
* href="https://cloud.google.com/iam/docs/creating-managing-service-account-keys">credential
190210
* file</a>. If not set the appender will use {@link GoogleCredentials#getApplicationDefault()} to
191211
* authenticate.
192212
*
193213
* @param credentialsFile the path to the credentials file.
194214
*/
215+
@ObsoleteApi(
216+
"This method is obsolete because of a potential security risk. Use the setCredentials() method instead")
195217
public void setCredentialsFile(String credentialsFile) {
196218
this.credentialsFile = credentialsFile;
197219
}
198220

221+
/**
222+
* Sets the credential to use. If not set the appender will use {@link
223+
* GoogleCredentials#getApplicationDefault()} to authenticate.
224+
*
225+
* @param credentials the GoogleCredentials to set
226+
*/
227+
public void setCredentials(GoogleCredentials credentials) {
228+
Preconditions.checkNotNull(credentials, "Credentials cannot be null");
229+
this.credentials = credentials;
230+
}
231+
199232
/**
200233
* Sets project ID to be used to customize log destination name for written log entries.
201234
*
@@ -445,10 +478,12 @@ protected LoggingOptions getLoggingOptions() {
445478
if (loggingOptions == null) {
446479
LoggingOptions.Builder builder = LoggingOptions.newBuilder();
447480
builder.setProjectId(logDestinationProjectId);
448-
if (!Strings.isNullOrEmpty(credentialsFile)) {
481+
if (credentials != null) {
482+
builder.setCredentials(credentials);
483+
} else if (!Strings.isNullOrEmpty(credentialsFile)) {
449484
try {
450485
builder.setCredentials(
451-
GoogleCredentials.fromStream(new FileInputStream(credentialsFile)));
486+
GoogleCredentials.fromStream(Files.newInputStream(Paths.get(credentialsFile))));
452487
} catch (IOException e) {
453488
throw new RuntimeException(
454489
String.format(

src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-logging-logback/reflect-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
{"name":"<init>","parameterTypes":[] },
3636
{"name":"setAutoPopulateMetadata","parameterTypes":["boolean"] },
3737
{"name":"setCredentialsFile","parameterTypes":["java.lang.String"] },
38+
{"name":"setCredentials","parameterTypes":["com.google.auth.oauth2.GoogleCredentials"] },
3839
{"name":"setFlushLevel","parameterTypes":["ch.qos.logback.classic.Level"] },
3940
{"name":"setLog","parameterTypes":["java.lang.String"] },
4041
{"name":"setLogDestinationProjectId","parameterTypes":["java.lang.String"] },

src/test/java/com/google/cloud/logging/logback/LoggingAppenderTest.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
import static org.easymock.EasyMock.replay;
2424
import static org.easymock.EasyMock.verify;
2525
import static org.junit.Assert.assertEquals;
26+
import static org.junit.Assert.assertThrows;
2627

2728
import ch.qos.logback.classic.Level;
2829
import ch.qos.logback.classic.filter.ThresholdFilter;
2930
import ch.qos.logback.classic.spi.ILoggingEvent;
3031
import ch.qos.logback.classic.spi.LoggingEvent;
32+
import com.google.auth.oauth2.GoogleCredentials;
3133
import com.google.cloud.MonitoredResource;
3234
import com.google.cloud.Timestamp;
3335
import com.google.cloud.logging.Instrumentation;
@@ -60,7 +62,7 @@
6062
public class LoggingAppenderTest {
6163
private static final String PROJECT_ID = "test-project";
6264
private static final String CRED_FILE_PROJECT_ID = "project-12345";
63-
private static final String OVERRIDED_PROJECT_ID = "some-project-id";
65+
private static final String OVERRIDDEN_PROJECT_ID = "some-project-id";
6466
private static final String DUMMY_CRED_FILE_PATH =
6567
"src/test/java/com/google/cloud/logging/logback/dummy-credentials.json";
6668
private static final Payload.JsonPayload JSON_PAYLOAD =
@@ -289,6 +291,22 @@ public void testMdcValuesAreConvertedToLabels() {
289291
assertThat(capturedArgument.getValue().iterator().next()).isEqualTo(INFO_ENTRY);
290292
}
291293

294+
@Test
295+
public void testCreateLoggingOptionsWithValidCredentials() {
296+
LoggingAppender appender = new LoggingAppender();
297+
appender.setCredentials(GoogleCredentials.newBuilder().build());
298+
// ServiceOptions requires a projectId to be set. Normally this is determined by the
299+
// GoogleCredentials (Credential set above is a dummy value with no ProjectId).
300+
appender.setLogDestinationProjectId(PROJECT_ID);
301+
appender.getLoggingOptions();
302+
}
303+
304+
@Test
305+
public void testCreateLoggingOptionsWithNullCredentials() {
306+
LoggingAppender appender = new LoggingAppender();
307+
assertThrows(NullPointerException.class, () -> appender.setCredentials(null));
308+
}
309+
292310
@Test(expected = RuntimeException.class)
293311
public void testCreateLoggingOptionsWithInvalidCredentials() {
294312
final String nonExistentFile = "/path/to/non/existent/file";
@@ -310,8 +328,8 @@ public void testCreateLoggingOptionsWithDestination() {
310328
// Try to build LoggingOptions with file based credentials.
311329
LoggingAppender appender = new LoggingAppender();
312330
appender.setCredentialsFile(DUMMY_CRED_FILE_PATH);
313-
appender.setLogDestinationProjectId(OVERRIDED_PROJECT_ID);
314-
assertThat(appender.getLoggingOptions().getProjectId()).isEqualTo(OVERRIDED_PROJECT_ID);
331+
appender.setLogDestinationProjectId(OVERRIDDEN_PROJECT_ID);
332+
assertThat(appender.getLoggingOptions().getProjectId()).isEqualTo(OVERRIDDEN_PROJECT_ID);
315333
}
316334

317335
private LoggingEvent createLoggingEvent(Level level, long timestamp) {

0 commit comments

Comments
 (0)