Google-cloud-dotnet: Alternative authorisation using code or dotnet app settings.

Created on 6 Jun 2018  路  18Comments  路  Source: googleapis/google-cloud-dotnet

Hi,

I would like to know if there is any alternative method for authentication rather than using separate deployed file and environment variables.

The current defacto for dotnet standard for setting is to use the appsettings.json. Is there an opportunity to use appsettings.json ConfigurationSection to define google authentication?

Ideally to do something like.

SessionsClient.Create(new GoogleCredential(_configurationSection["dialogflow-test"]))

Or

SessionsClient.Create(new GoogleCredential(_type,_client,_pkey)

Sorry there might be something like this already but I can't seem to find the documentation for it.

Thanks
Rolf

question

Most helpful comment

@huberzeljko: I included the content of the service key as the Azure Key Value.

I no longer use it, but the code I did use is here: https://github.com/nodatime/nodatime.org/blob/cc7a29f31dec100e05e156367d6810fd6ca8b7e0/src/NodaTime.Web/Providers/GoogleCredentialProvider.cs

All 18 comments

It's not clear what you'd expect to put in the configuration. Presumably you wouldn't want to put any sensitive data there, and I wouldn't recommend doing so.

If you can get a stream of data that represents a service account file, you can use GoogleCredential.FromStream to create a GoogleCredential.

Once you've got a GoogleCredential, you'd follow the instructions here. It's a bit long-winded at the moment (and we have an issue tracking that but it should work.

Note that if your code is hosted on Google Cloud Platform, the default credentials should just work with no configuration at all - you only need to jump through any hoops if you're running the code elsewhere.

Does this help?

Yes it does help. Thanks.

To start off, we host on AWS so we can't unfortunately just go for the no configuration option.

GoogleCredential.FromStream could work in a very round about way. I will give it a go and see where I can get to.

In terms of your configuration file comment. C# appsettings.json has a way to separate environmental data into separate files. Our 'appsettings.{environment}.json' (equivalent to 'sample-652cfa5.json') is not inherently more secure because it is in a separate file but rather that it is excluded from our source repo and gets deployed securely by our CI/CD. I just wanted to get around the shlep of updating our deployment process to deploy additional files and environment variables per environment when we already have a system in place.

As a point of reference, for nodatime.org (currently hosted in Azure, but I'm moving it to GKE) I use the Azure Key Vault to store the service credential. I dare say AWS has something similar.

If you want to put the actual data into the appsettings, you could do so (maybe just base64-encode the whole file so it's a single string - then base64 decode it to a byte array, create a memory stream from that, and you're away).

Are you happy for me to close this issue now? (While acknowledging that this isn't as simple as it might be still...)

Yup, AWS has something similar (this project does not use it ... yet ? )

Yes thank you the FromStream is working.

Appreciate the quick responses.

@jskeet How exactly did you incorporate Azure Key Vault to provide credentials?

Thanks.

@huberzeljko: I included the content of the service key as the Azure Key Value.

I no longer use it, but the code I did use is here: https://github.com/nodatime/nodatime.org/blob/cc7a29f31dec100e05e156367d6810fd6ca8b7e0/src/NodaTime.Web/Providers/GoogleCredentialProvider.cs

Given that most of us would be using Azure Keyvault or similar, it would be highly useful to be able to pull the values of the json values into Azure keyvault and then pass those secrets as simple parameters when creating the credentials.

(even if it was a file in dev, it would be in the config secrets on the dev machine)

The current way is very problematic in C#.

@JohnGalt1717:

it would be highly useful to be able to pull the values of the json values into Azure keyvault and then pass those secrets as simple parameters when creating the credentials.

You can do exactly that - once you've got the JSON, you could use GoogleCredential.FromJson...

var credential = GoogleCredential.FromJson(json);

... or if you've got a stream, you can use:

var credential = GoogleCredential.FromStream(stream);

(I don't think FromJson existed when I wrote the Noda Time code.)

I think that's about as simple as we can make it from the Google side. What would you expect to be provided to make this simpler?

@jskeet That adds an unnecessary step forcing me to push it into json which is redundant and not how C# encourages you to work and defeats the built-in configuration providers. None of the options provided are consistent with how .NET core works and follow patterns from other languages that aren't desirable in C#.

@JohnGalt1717: I still don't really understand what you're asking for. You wrote "it would be highly useful to be able to pull the values of the json values into Azure keyvault" which suggested to me that you did want to store the JSON in KeyVault. I certainly think it's simpler to store one blob of data (the JSON) in KeyVault than store each of the 10 fields separately in KeyVault.

Additionally, for a service account, the JSON is what you download directly in the first place - there's no need to "push it into JSON", that's just how it comes. You take the file, as-is, and store it in KeyVault. You then recover it from KeyVault and use GoogleCredential.FromStream or GoogleCredential.FromJson. Could you walk me through what you would consider to be simpler? (Note that I would not want Google to provide libraries directly integrating with KeyVault - that's just a recipe for dependencies rotting over time, IMO.)

Note that if you do want to create a ServiceAccountCredential directly, you can do so:

var initializer = new ServiceAccountCredential.Initializer
{
    Id = ...,
    Scopes = ...,
    User = ...,
    Key = ..., // This is an RSA, which may not be terribly simple to construct
    ...
};
var credential = new ServiceAccountCredential(initializer);

If you want to wrap that in a GoogleCredential, you can use GoogleCredential.FromServiceAccountCredential.

So my hack was to convert the .json file into base64 and put that in key vault and then use the fromJson method. Not optimal but it will do for now.

@JohnGalt1717: I don't see why you'd need to use base64 here... the JSON file is inherently text, which is what what KeyVault deals with already (via SecretBundle.Value) isn't it? Certainly the code I used for NodaTime a long time ago didn't need to base64-encode anything.

What happened when you tried storing the JSON without using base64?

@jskeet The reason why is that you can't put in multi-line strings in the online editor for Azure Keyvault so you can't just paste in a json file as an example.

Ah - in that case I'd just take out the line breaks, but still keep it as text :) (Or submit it programmatically still with the line breaks in, which I'd expect to work.) The JSON parsing code definitely doesn't require the line breaks in, so it shouldn't fail on that front.

@jskeet Or just copy and paste base64 and be done since this is designed to defeat the built in configuration mechanisms of .net. Hence I took the shortest route between 2 points so that I don't have to deal with Google hostility to .NET.

There's no hostility to .NET, and it's not "designed to defeat the built in configuration mechanisms of .NET". I think we should conclude the discussion at this point.

Ok. Sure. Let's ignore the fact that there is virtually 0 documentation for any of firebase for .NET as a small example and the entire setup for FirebaseApp configuration is not done in a .net way.

Over and out.

Was this page helpful?
0 / 5 - 0 ratings