Authenticate for Google Cloud PubSub using parameters from a config file in c#.net - google-cloud-platform

I am following this sample in attempt to publish messages in PubSub from a c#.net app on a windows server. As expected it throws auth exception on:
PublisherClient publisher = PublisherClient.Create();
Most of my code base connects to GCS and BigQuery using their respective services, sample below:
private StorageService GetStorageService()
{
X509Certificate2 certificate = new X509Certificate2(certificateFile, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { StorageService.Scope.DevstorageFullControl }
}.FromCertificate(certificate));
return new StorageService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = projectNumber,
});
}
I just pass certificateFile, serviceAccountEmail from a config file as parameters. Is there anyway to Auth similarly for PubSub?

Yes, it's possible, and you're looking in the right repo for samples. I notice the QuickStart directory is missing a README.md. I'll add one shortly.
To get this line of code to work:
PublisherClient publisher = PublisherClient.Create();
Set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the path of a json service account credentials file. Details are in step 3 of the root README:
https://github.com/GoogleCloudPlatform/dotnet-docs-samples/blob/master/README.md
If your environment requires you to manually specify the path to a credential file, the code looks like this:
GoogleCredential googleCredential = null;
using (var jsonStream = new FileStream(jsonPath, FileMode.Open,
FileAccess.Read, FileShare.Read))
{
googleCredential = GoogleCredential.FromStream(jsonStream)
.CreateScoped(PublisherClient.DefaultScopes);
}
Channel channel = new Channel(PublisherClient.DefaultEndpoint.Host,
PublisherClient.DefaultEndpoint.Port,
googleCredential.ToChannelCredentials());
PublisherClient publisher = PublisherClient.Create(channel);
I reported issue https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/1398 to make this common task simpler.

Related

JWT Token Google Cloud Run

I am developing an application with JWT authentication on the google cloud platform. Server side I added authentication via Cloud API Gateway to a cloud run backend. Now I am making a client to generate the JWT token and pass it in the call. To do this I am creating an application that must be deployed on CloudRun and I am following this documentation: https://cloud.google.com/api-gateway/docs/authenticate-service-account#making_an_authenticated_request. My problem is that I don't know how to indicate what it requires as saKeyfile. I tried to put only the name of the file that under src / main / resources / filetest.json but once I try to call the method it tells me file not found. I tried to indicate also the full path. Can anyone help me?
PS I'm using Java
EDIT:
here is my code which is the same of documentation
public void makeCall() {
String fullPath="src/main/resources/TEST1-id.json";
String saEmail="testsa#projectID.iam.gserviceaccount.com";
String audience="auth";
int expiryLenght=600;
String token;
try {
token=generateJwt(fullPath,saEmail,audience,expiryLenght);
System.out.println("Token generated: "+token);
URL url = new URL("apigatewayurl");
makeJwtRequest(token, url);
System.out.println("Call performed");
} catch (IOException e) {
e.printStackTrace();
}
}
private static String generateJwt(final String saKeyfile, final String saEmail,
final String audience, final int expiryLength)
throws FileNotFoundException, IOException {
Date now = new Date();
Date expTime = new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiryLength));
// Build the JWT payload
JWTCreator.Builder token = JWT.create()
.withIssuedAt(now)
// Expires after 'expiraryLength' seconds
.withExpiresAt(expTime)
// Must match 'issuer' in the security configuration in your
// swagger spec (e.g. service account email)
.withIssuer(saEmail)
// Must be either your Endpoints service name, or match the value
// specified as the 'x-google-audience' in the OpenAPI document
.withAudience(audience)
// Subject and email should match the service account's email
.withSubject(saEmail)
.withClaim("email", saEmail);
// Sign the JWT with a service account
FileInputStream stream = new FileInputStream(saKeyfile);
ServiceAccountCredentials cred = ServiceAccountCredentials.fromStream(stream);
RSAPrivateKey key = (RSAPrivateKey) cred.getPrivateKey();
Algorithm algorithm = Algorithm.RSA256(null, key);
return token.sign(algorithm);
}
i've tried to use full path like in example and using only /TEST1-id.json
and here there is project structure. Is a springboot application which i will deploy in cloud run
The OP fixed the issue on this way
In the end I put the file in the root and copied it in the docker image and recover it as an environment variable in cloud run

Send Message to Amazon SQS using credentials in code

Trying to post a message to an AWS SQS Queue that already exists using .Net Core.
Due to some deployment issues, I don't want to create a separate credentials file, I just want to manually add the credentials and add them to my client or request. I can't see how to do this using the documentation.
I've got a simple console app version of what I am trying to do below... I have created the Credentials, I just can't see how to inject them into the client or request so that it authenticates with my IAM user.
Currently the code just hangs creating the client.
var awsCreds = new BasicAWSCredentials("MYKEYGOESHERE", "MYSECRETGOESHERE");
var amazonSQSConfig = new AmazonSQSConfig();
amazonSQSConfig.ServiceURL = "https://sqs.eu-west-1.amazonaws.com";
var amazonSQSClient = new AmazonSQSClient(amazonSQSConfig);
var sendRequest = new SendMessageRequest();
sendRequest.QueueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]";
sendRequest.MessageBody = "{ 'message' : 'hello world' }";
var sendMessageResponse = amazonSQSClient.SendMessageAsync(sendRequest);
You have to pass the credentials to the AmazonSQSClient like so:
var amazonSQSClient = new AmazonSQSClient(awsCreds, amazonSQSConfig);
Five years later, here is what is working for me:
AmazonSQSClient sqsClient = new AmazonSQSClient("MYKEYGOESHERE", "MYSECRETGOESHERE", RegionEndpoint.USWest2);
No use of BasicAWSCredentials or AmazonSQSConfig.

GCloud pubsub emulator doesn't respect "PUBSUB_EMULATOR_HOST" environment variable

I tried running the pubsub emulator locally and send messages to it with existing services that I have running on pubsub. Messages weren't received, and all I get are auth errors in the logs.
[pubsub] Jan 22, 2017 3:43:16 PM com.google.cloud.iam.testing.v1.shared.authorization.AuthInterceptor interceptCall
[pubsub] INFO: Authentication interceptor: Header value is null
[pubsub] Jan 22, 2017 3:43:16 PM com.google.cloud.iam.testing.v1.shared.authorization.AuthInterceptor interceptCall
[pubsub] INFO: Authentication interceptor: invalid or missing token
I'm making requests to publish and pull from both dotnet and nodejs.
C#
var creds = GoogleCredential.GetApplicationDefaultAsync().Result;
if (creds.IsCreateScopedRequired) {
creds = creds.CreateScoped(new [] { PubsubService.Scope.Pubsub } );
}
return new PubsubService(
new BaseClientService.Initializer() {
HttpClientInitializer = creds,
ApplicationName = "My Wonderful App"
}
);
NodeJs
var pubsub = require('#google-cloud/pubsub');
var pubsubClient = pubsub({
projectId: config.get('GCLOUD_PROJECT')
});
I ran in to this problem.
While researching it, I found the following post: "Nothing is going wrong. When using the emulator we pass no credentials and this is what the logs are telling you, that no authentication header was provided with any of the requests." - https://www.bountysource.com/issues/39093553-pubsub-emulator-authinterceptor-question
My messages started publishing while researching the topic, so it's probably just a delay.
The header value null was a red harring. It looks like the dotnet sdk doesn't respect the environment variable like the nodejs sdk does. I corresponded with jskeet and he created an issue to add the documentation for showing how to enable the use of the emulator: https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/859
Here's how I created the PublisherClient in C#
private static PublisherClient CreatePublisherClient() {
var emulatorHostAndPort = Environment.GetEnvironmentVariable("PUBSUB_EMULATOR_HOST");
if (String.IsNullOrWhiteSpace(emulatorHostAndPort)) {
return PublisherClient.Create();
} else {
var channel = new Channel(emulatorHostAndPort, ChannelCredentials.Insecure);
return PublisherClient.Create(channel);
}
}

Unable to authenticate in accessing Dynamic CRM Online Web Service

I need to utilize Dynamic CRM Data Service Endpoint exposed to get data from one of the methods.
Service(microsoft) account has access to this service.
I've tried authenticating to Discovery Service and Organization Service using sample code provided here [https://msdn.microsoft.com/en-us/library/hh675404.aspx] and succeed. However am not able to use same authentication to access data Service as I could find anyway to relate Data Service with the other two. Doing basic authentication using Network Credentials does not work.
I have downloaded the CSDL exposed and added that as service reference to my project, which created an class of web service which extends from DataServiceContext. Am trying to retrieve data of one of the methods using LinQ queries. It returs following error:
"The response payload is a not a valid response payload. Please make sure that the top level element is a valid Atom or JSON element or belongs to 'http://schemas.microsoft.com/ado/2007/08/dataservices' namespace." On capturing using fiddle I realized that on hitting data service URL it is redirected to sign in page 'login.microsoftonline.com/'
Can anybody suggest a way to authenticate the user to access Data Serivce?
Adding code:
//<snippetAuthenticateWithNoHelp1>
IServiceManagement<IDiscoveryService> serviceManagement =
ServiceConfigurationFactory.CreateManagement<IDiscoveryService>(
new Uri(_discoveryServiceAddress));
AuthenticationProviderType endpointType = serviceManagement.AuthenticationType;
// Set the credentials.
AuthenticationCredentials authCredentials = GetCredentials(serviceManagement, endpointType);
String organizationUri = String.Empty;
// Get the discovery service proxy.
using (DiscoveryServiceProxy discoveryProxy =
GetProxy<IDiscoveryService, DiscoveryServiceProxy>(serviceManagement, authCredentials))
{
// Obtain organization information from the Discovery service.
if (discoveryProxy != null)
{
// Obtain information about the organizations that the system user belongs to.
OrganizationDetailCollection orgs = DiscoverOrganizations(discoveryProxy);
// Obtains the Web address (Uri) of the target organization.
organizationUri = FindOrganization(_organizationUniqueName,
orgs.ToArray()).Endpoints[EndpointType.OrganizationService];
}
}
//</snippetAuthenticateWithNoHelp1>
if (!String.IsNullOrWhiteSpace(organizationUri))
{
//<snippetAuthenticateWithNoHelp3>
IServiceManagement<IOrganizationService> orgServiceManagement =
ServiceConfigurationFactory.CreateManagement<IOrganizationService>(
new Uri(organizationUri));
// Set the credentials.
AuthenticationCredentials credentials = GetCredentials(orgServiceManagement, endpointType);
// Get the organization service proxy.
using (OrganizationServiceProxy organizationProxy =
GetProxy<IOrganizationService, OrganizationServiceProxy>(orgServiceManagement, credentials))
{
// This statement is required to enable early-bound type support.
organizationProxy.EnableProxyTypes();
// Now make an SDK call with the organization service proxy.
// Display information about the logged on user.
Guid userid = ((WhoAmIResponse)organizationProxy.Execute(
new WhoAmIRequest())).UserId;
SystemUser systemUser = organizationProxy.Retrieve("systemuser", userid,
new ColumnSet(new string[] { "firstname", "lastname" })).ToEntity<SystemUser>();
Console.WriteLine("Logged on user is {0} {1}.",
systemUser.FirstName, systemUser.LastName);
Uri x = new Uri("https://<MyOrgainzationName>.crm.dynamics.com/XRMServices/2011/OrganizationData.svc/");
MyOrgainzationContext saContext = new MyOrgainzationContext(x);
NetworkCredential nc = new NetworkCredential();
nc.UserName = "*****#microsoft.com";
nc.Password = "********";
saContext.Credentials = nc;
var query_where3 = from c in saContext.new_productSet
select new
{
ProductStatus = c.new_ProductStatus,
LineofBusiness = c.new_LineofBusiness
};
var temp = saContext.Entities;
foreach (var c in query_where3)
{
System.Console.WriteLine("ProductStatus: " +
c.ProductStatus +
"\t\t\t" +
"LineofBusiness: " +
c.LineofBusiness);
}
}
//</snippetAuthenticateWithNoHelp3>
}
MyOrganizationContext is the context class created on adding CSDL file exposed at service endpoints
Have a look at the CRM Web Api Preview: https://msdn.microsoft.com/en-us/dynamics/crm/webapipreview.aspx. You can call this endpoint from outside xRM and you can authenticate with OAuth 2.0.

New Google Drive Directory APIs error out: Bad request

I am using below piece of code to list all domain users in my simple Console application
var certificate = new X509Certificate2("D:\\3acf2c2008cecd33b43de27e30016a72e1482c41-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable);
var privateKey = certificate.Export(X509ContentType.Cert);
var provider = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
{
ServiceAccountId = "877926787679-b7fd15en1sh2oc65e164v90cfcvrfftq#developer.gserviceaccount.com",
Scope = DirectoryService.Scopes.AdminDirectoryUserReadonly.GetStringValue(),
ServiceAccountUser = "user1#05.mygbiz.com"
};
var auth = new OAuth2Authenticator<AssertionFlowClient>(provider, AssertionFlowClient.GetState);
DirectoryService dirService = new DirectoryService(new BaseClientService.Initializer()
{
Authenticator = auth,
ApplicationName = "My APP"
});
Users users = dirService.Users.List().Execute();
Execute() method errors out saying Bad Request.
Questions:
How to overcome this issue?
Does this Admin SDK support trial version of Google APP account?
I have updated service account Client ID in Google Console and also updated in Admin Console with below scopes
https://www.googleapis.com/auth/admin.directory.group
https://www.googleapis.com/auth/admin.directory.user
and also set API access check box. Do I missing something in settings?
Like JoBe said, you should include the domain parameter.
happy_user = service.users().list(domain='mydomain.com').execute()
This has worked for me.