Skip to content

Commit

Permalink
Added the ability to configure credentials using a JSON file (#1424)
Browse files Browse the repository at this point in the history
* Added property that allows configuration of credentials using a JSON file instead of using the default credentials. This is necessary to support GCP instances where the configured service account cannot be granted the logging.logWriter role.

* As requested in review, turned the ToChannelCredentials call into an extension method, split the line that creates the LoggingServiceV2Client into multiple lines to limit its length, and changed the TryGetCredentialFromFile method in a GetCredentialFromFile method that returns null if no file is configured.

Change-Id: I02327a980ee7f08cf323d8ab653bdf34ff6278f8

* Switched the credential file loading to use the new GoogleCredential.FromFile() method instead of creating a FileStream.

Change-Id: I5a75c6fb2577b42b09c0279d2ac76e19d9ad9d45
  • Loading branch information
iamatree authored and chrisdunelm committed Sep 22, 2017
1 parent 3d8de4d commit a7dbff3
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 1 deletion.
Expand Up @@ -188,6 +188,7 @@ public async Task PostActivationChangeThrow()
Assert.Throws<InvalidOperationException>(() => appender.AddResourceLabel(new GoogleStackdriverAppender.Label { Key = "a", Value = "b" }));
Assert.Throws<InvalidOperationException>(() => appender.ProjectId = "");
Assert.Throws<InvalidOperationException>(() => appender.LogId = "");
Assert.Throws<InvalidOperationException>(() => appender.CredentialFile = "");
Assert.Throws<InvalidOperationException>(() => appender.MaxUploadBatchSize = 0);
Assert.Throws<InvalidOperationException>(() => appender.LocalQueueType = LocalQueueType.Memory);
Assert.Throws<InvalidOperationException>(() => appender.MaxMemorySize = 0);
Expand All @@ -212,6 +213,7 @@ public void PreActivationChangeDoesntThrow()
appender.AddResourceLabel(new GoogleStackdriverAppender.Label { Key = "a", Value = "b" });
appender.ProjectId = "";
appender.LogId = "";
appender.CredentialFile = "";
appender.MaxUploadBatchSize = 0;
appender.LocalQueueType = LocalQueueType.Memory;
appender.MaxMemorySize = 0;
Expand Down
Expand Up @@ -12,8 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Google.Apis.Auth.OAuth2;
using Google.Cloud.Logging.V2;
using Google.Protobuf.WellKnownTypes;
using Grpc.Auth;
using Grpc.Core;
using System;

namespace Google.Cloud.Logging.Log4Net
Expand All @@ -33,5 +36,10 @@ public static Timestamp ToTimestamp(this DateTime dt)
}
return Timestamp.FromDateTime(dt);
}

public static ChannelCredentials ToChannelCredential(this GoogleCredential credential)
{
return GoogleGrpcCredentials.ToChannelCredentials(credential);
}
}
}
Expand Up @@ -15,6 +15,7 @@
using Google.Api;
using Google.Api.Gax;
using Google.Api.Gax.Grpc;
using Google.Apis.Auth.OAuth2;
using Google.Cloud.DevTools.Source.V1;
using Google.Cloud.Logging.Type;
using Google.Cloud.Logging.V2;
Expand All @@ -23,6 +24,7 @@
using log4net.Core;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading;
Expand Down Expand Up @@ -68,6 +70,11 @@ public sealed partial class GoogleStackdriverAppender : AppenderSkeleton, IDispo
internal const string s_lostDateTimeFmt = "yyyy-MM-dd' 'HH:mm:ss'Z'";
internal const string s_mismatchedProjectIdMessage = "Detected project ID does not match configured project ID; using detected project ID.";

internal static readonly string[] s_oAuthScopes = new string[]
{
"https://www.googleapis.com/auth/logging.write"
};

/// <summary>
/// Construct a Google Stackdriver appender.
/// </summary>
Expand Down Expand Up @@ -134,7 +141,7 @@ public override void ActivateOptions()
base.ActivateOptions();

// Initialise services if not already initialised for testing
_client = _client ?? LoggingServiceV2Client.Create();
_client = _client ?? BuildLoggingServiceClient();
_scheduler = _scheduler ?? SystemScheduler.Instance;
_clock = _clock ?? SystemClock.Instance;
_platform = _platform ?? Platform.Instance();
Expand Down Expand Up @@ -194,6 +201,40 @@ public override void ActivateOptions()
_isActivated = true;
}

private LoggingServiceV2Client BuildLoggingServiceClient()
{
GoogleCredential credential = GetCredentialFromFile();
if(credential == null)
{
return LoggingServiceV2Client.Create();
}

Grpc.Core.Channel channel = new Grpc.Core.Channel(
LoggingServiceV2Client.DefaultEndpoint.Host,
LoggingServiceV2Client.DefaultEndpoint.Port,
credential.ToChannelCredential()
);

return LoggingServiceV2Client.Create(channel);
}

private GoogleCredential GetCredentialFromFile()
{
if(string.IsNullOrWhiteSpace(CredentialFile))
{
return null;
}

GoogleCredential credential = GoogleCredential.FromFile(CredentialFile);

if (credential.IsCreateScopedRequired)
{
credential = credential.CreateScoped(s_oAuthScopes);
}

return credential;
}

private void ActivateLogIdAndResource()
{
string projectId = null;
Expand Down
Expand Up @@ -231,6 +231,17 @@ public int MaxMemoryCount
set => _maxMemoryCount = ThrowIfActivated(value, nameof(MaxMemoryCount));
}

private string _credentialFile;
/// <summary>
/// The file path of a service account JSON file to use for authenitication.
/// Not necessary if running on GCE or GAE or if the GOOGLE_APPLICATION_CREDENTIALS environment variable has been set.
/// </summary>
public string CredentialFile
{
get => _credentialFile;
set => _credentialFile = ThrowIfActivated(value, nameof(CredentialFile));
}

/// <summary>
/// Specify custom labels for all log entries.
/// </summary>
Expand Down

0 comments on commit a7dbff3

Please sign in to comment.