Azure Notification Hubs in C++ apps? - c++

In Microsoft documentation there is the example for C# implementation of Azure Notification Hubs -- https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-windows-store-dotnet-get-started-wns-push-notification#create-a-sample-windows-app
private async void InitNotificationsAsync()
{
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub("<your hub name>", "<Your DefaultListenSharedAccessSignature connection string>");
var result = await hub.RegisterNativeAsync(channel.Uri);
// Displays the registration ID so you know it was successful
if (result.RegistrationId != null)
{
var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}
but our app use C++ and we found part of example code in WinRT/C++ documentation:
https://learn.microsoft.com/en-us/uwp/api/windows.networking.pushnotifications.pushnotificationchannelmanager?view=winrt-22621
...but without part of Azure code:
var hub = new NotificationHub("<your hub name>", "<Your DefaultListenSharedAccessSignature connection string>");
Is it means that for apps with bare C++ Azure Messaging is impossible theme?

At this moment, only a few Azure Services can be used using the c++ SDK. You can check in here:
https://azure.github.io/azure-sdk/cpp_introduction.html
However, you can interact directly to the REST Api:
https://learn.microsoft.com/en-us/rest/api/notificationhubs/create-update-registration

Related

How to create an AWS service client object for a .NET Core desktop app

I am coding an app in .NET 5.0 to run on the desktop. It will query AWS CloudWatch and download log entries.
I am using the following method to create the AWS service client that contains the query method. When the program enters the CreateServiceClient() method however, it hangs for a minute then returns directly to the method that calls my GetLogs() method, with no error.
using Amazon.CloudWatchLogs;
using Amazon.CloudWatchLogs.Model;
using Amazon.Extensions.NETCore.Setup;
.
.
.
public async Task<GetQueryResultsResponse> GetLogs()
{
AWSOptions awsOptions = new AWSOptions { Profile = "myprofile" };
IAmazonCloudWatchLogs logs = awsOptions.CreateServiceClient<IAmazonCloudWatchLogs>();
.
.
.
I have a credentials file located at C:\Users\Username\.aws\credentials with the contents
[myprofile]
aws_access_key_id = <myid>
aws_secret_access_key = <mykey>
I have verified the credentials work with AWS CLI. What am I missing?
YOu are not using the latest .NET API. Here is an example that shows how to create an Amazon CloudWatch log group using AmazonCloudWatchLogsClient. The example was created using the AWS SDK for .NET version 3.7 and .NET Core 5.0.
You should be using version 3.0 of the AWS SDK for .NET.
More examples here:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/CloudWatchLogs
namespace CreateLogGroupExample
{
using System;
using System.Threading.Tasks;
using Amazon.CloudWatchLogs;
using Amazon.CloudWatchLogs.Model;
/// <summary>
/// Shows how to create an Amazon CloudWatch Logs log group. The example
/// was created using the AWS SDK for .NET version 3.7 and .NET Core 5.0.
/// </summary>
public class CreateLogGroup
{
// snippet-start:[CloudWatchLogs.dotnetv3.CreateLogGroupExample]
public static async Task Main()
{
// This client object will be associated with the same AWS Region
// as the default user on this system. If you need to use a
// different AWS Region, pass it as a parameter to the client
// constructor.
var client = new AmazonCloudWatchLogsClient();
string logGroupName = "cloudwatchlogs-example-loggroup";
var request = new CreateLogGroupRequest
{
LogGroupName = logGroupName,
};
var response = await client.CreateLogGroupAsync(request);
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
Console.WriteLine($"Successfully create log group with ID: {logGroupName}.");
}
else
{
Console.WriteLine("Could not create log group.");
}
}
// snippet-end:[CloudWatchLogs.dotnetv3.CreateLogGroupExample]
}
}

GCP cloud build VIEW RAW logs link

I have written a small cloud function in GCP which is subscribed to Pub/Sub event. When any cloud builds triggered function post message into the slack channel over webook.
In response, we get lots of details to trigger name, branch name, variables details but i am more interested in Build logs URL.
Currently getting build logs URL in response is like : logUrl: https://console.cloud.google.com/cloud-build/builds/899-08sdf-4412b-e3-bd52872?project=125205252525252
which requires GCP console access to check logs.
While in the console there an option View Raw. Is it possible to get that direct URL in the event response? so that i can directly sent it to slack and anyone can access direct logs without having GCP console access.
In your Cloud Build event message, you need to extract 2 values from the JSON message:
logsBucket
id
The raw file is stored here
<logsBucket>/log-<id>.txt
So, you can get it easily in your function with Cloud Storage client library (preferred solution) or with a simple HTTP Get call to the storage API.
If you need more guidance, let me know your dev language, I will send you a piece of code.
as #guillaume blaquiere helped.
Just sharing the piece of code used in cloud function to generate the singedURL of cloud build logs.
var filename ='log-' + build.id + '.txt';
var file = gcs.bucket(BUCKET_NAME).file(filename);
const getURL = async () => {
return new Promise((resolve, reject) => {
file.getSignedUrl({
action: 'read',
expires: Date.now() + 76000000
}, (err, url) => {
if (err) {
console.error(err);
reject(err);
}
console.log("URL");
resolve(url);
});
})
}
const singedUrl = await getURL();
if anyone looking for the whole code please follow this link : https://github.com/harsh4870/Cloud-build-slack-notification/blob/master/singedURL.js

Get AzureWebJobsDashboard through KeyVault

As I have read, Azure Webjobs SDK requires the value of AzureWebJobsDashboard to be defined in the connection string section of an App Service. If I do that manually by going to the portal, and configuring the values, my webjob works fine.
What I want now is to provide the value of the connectionString in KeyVault and provide a secretURI provided by KeyVault in the ApplicationSettings of the App Service. Thereafter, I want the SDK to parse the secretURI and obtain the secret stored underneath in KeyVault.
I have tried to do this but am not able to get a definite solution for this. Is there any way to do this, or is currently not supported ?
Here is working example of what Mike suggested:
var config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
else
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var vaultBaseUrl = ConfigurationManager.AppSettings["KeyVaultUri"];
var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
config.DashboardConnectionString = client.GetSecretAsync(vaultBaseUrl, "DashboardConnectionString").Result.Value;;
config.StorageConnectionString = client.GetSecretAsync(vaultBaseUrl, "StorageConnectionString").Result.Value;;
}
config.UseTimers();
var host = new JobHost(config);
References:
https://learn.microsoft.com/en-us/azure/key-vault/service-to-service-authentication
WebJobs SDK will not automatically get from KeyVault.
But you could also fetch from keyvault yourself and then programmatically set the result on the JobHostConfiguration.Dashboard property.
You could file a request here to have more direct integration: https://github.com/Azure/azure-webjobs-sdk

How to send Firebase Cloud Message with AWS SNS? [duplicate]

I am using AWS resources for my android project, I am planning to add push notification service for my project with AWS SNS.there are few questions bothering me much. I did not find any questions regarding these, except one or two but with unclear explanations.
1.Does AWS support FCM? SNS work with GCM. But Google recommends to use FCM instead of GCM. I did not find AWS supporting FCM.
2.Do AWS store messages (or data) into their databases even after sending push notifications?
3.I tried putting FCM api key in SNS application platform, it is showing invalid parameters why?
FCM is backwards compatible with GCM. The steps for setting up FCM on AWS are identical to the GCM set up procedure and (at least for the moment) FCM works transparently with GCM and SNS with respect to server-side configuration.
However, if you are sending data payloads to the Android device they will not be processed unless you implement a client side service that extends FirebaseMessagingService. The default JSON message generator in the AWS console sends data messages, which will be ignored by your app unless the aforementioned service is implemented. To get around this for initial testing you can provide a custom notification payload which will be received by your device (as long as your app is not in the foreground)
There are GCM-FCM migration instructions provided by Google however the changes you need to make are predominantly on the App side.
The steps you need to follow to test GCM/FCM on your app with SNS are:
Create a Platform Application in SNS, selecting Google Cloud Messaging (GCM) as the Push Notification Platform, and providing your Server API key in the API key field.
Select the Platform Application and click the Create platform endpoint button.
Provide the InstanceID (Device Token) generated by your app. You must extend the FirebaseInstanceIDService and override the onTokenRefresh method to see this within your Android App. Once you have done this, uninstall and reinstall your app and your token should be printed to the Debug console in Android Studio on first boot.
Click the Add endpoint button.
Click on the ARN link for your platform application.
Select the newly created Endpoint for your device and click the Publish to endpoint button.
Select the JSON Message Format, and click the JSON message generator button.
Enter a test message and click the Generate JSON button
Now comes the "gotcha part".
The message that is generated by SNS will be of the form:
{
"GCM": "{ \"data\": { \"message\": \"test message\" } }"
}
As we mentioned earlier, data payloads will be ignored if no service to receive them has been implemented. We would like to test without writing too much code, so instead we should send a notification payload. To do this, simply change the JSON message to read:
{
"GCM": "{ \"notification\": { \"title\": \"test title\", \"body\": \"test body\" } }"
}
(For more information about the JSON format of an FCM message, see the FCM documentation.)
Once you have done this, make sure your app is not running on the device, and hit the Publish Message button. You should now see a notification pop up on your device.
You can of course do all this programmatically through the Amazon SNS API, however all the examples seem to use the data payload so you need to keep that in mind and generate a payload appropriate to your use case.
Now you can go to your firebase console (https://console.firebase.google.com/) select your project, click the gear icon and choose project settings, then click on the cloud messaging tab...
You'll see the legacy Server Key which is the GCM API Key and you'll have the option to generate new Server Keys which are the FCM versions
SNS will accept both versions but their menu option is still categorizing it under GCM
Here is picture for your reference:
Note that you can "accidentally" remove your Server Keys but the Legacy server key is not deletable. Also, if you click the add server key button, you'll get a new server key BELOW the first one, WITH NO WARNING! ...Nice job Google ;)
One more additional note to Nathan Dunn's great answer.
How to send data with the notification from SNS to Firebase.
We need to add data to the Json (inside the notification):
{
"default": “any value",
"GCM": "{ \"notification\": { \"body\": \”message body\”, \”title\”: \”message title \”, \"sound\":\"default\" } , \"data\" : {\”key\" : \”value\", \”key2\" : \”value\” } }”
}
In your FirebaseMessagingService implementation (Xamarin example)
public override void OnMessageReceived(RemoteMessage message)
{
try
{
var body = message?.GetNotification()?.Body;
var title = message?.GetNotification()?.Title;
var tag = message?.GetNotification()?.Tag;
var sound = message?.GetNotification()?.Sound;
var data = message?.Data
foreach (string key in data.Keys)
{
// get your data values here
}
}
catch (Exception e)
{
}
}
I tried to use solution with notification payload instead of data, but I did not receive push notifications on the mobile device. I found this tutorial https://youtu.be/iBTFLu30dSg with English subtitles of how to use FCM with AWS SNS step by step and example of how to send push notifications from AWS console and implement it on php with aws php sdk. It helped me a lot.
Just an additional note to Nathan Dunn's Answer: to add sound use the following JSON message
{
"GCM": "{ \"notification\": { \"text\": \"test message\",\"sound\":\"default\" } }"
}
It took me a while to figure out how to send the notification with the right payload (publish to topic). So I will put it here.
private void PublishToTopic(string topicArn)
{
AmazonSimpleNotificationServiceClient snsClient =
new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.EUWest1);
PublishRequest publishRequest = new PublishRequest();
publishRequest.TopicArn = topicArn;
publishRequest.MessageStructure = "json";
string payload = "\\\"data\\\":{\\\"text\\\":\\\"Test \\\"}";
publishRequest.Message = "{\"default\": \"default\",\"GCM\":\"{" + payload + "}\"}";
PublishResponse publishResult = snsClient.Publish(publishRequest);
}
Amazon does support FCM as all previous code has been migrated from GCM to FCM. Below article explains in detail.
Article Published by Amazon
To answer the questions:
AWS SNS does support FCM.
No AWS does not store messages after sending push notifications.
For a detailed tutorial on setting up FCM with SNS please read this article.

System.Security.Cryptography.CryptographicException: 'The key {00000000-0000-0000-0000-000000000000} was not found in the key ring.'

I have deployed a webjob (.Net 4.6) which encrypts some url strings and sends it to customers via email. I used .NET Core's IDataProtector for the encrpytion and I had to manually reference the DLL since webjob .net 4.6 was not supporting its library.
For example in webjob:
IDataProtector protector = provider.CreateProtector("myProtector")
http://test.com/Email/Agreement?n=" + protector.Protect(name) + "&a=" + protector.Protect(address)
which becomes a link
http://test.com/Email/Agreement?n=CfDJ8AAAAAAAAAAAAAAAAAAAAAD96g09022UwEG-GyVftzkm-n2JuL1hmvL5HLyghXliIgJ_N014EBqBFfWjmdA&a=CfDJ8AAAAAAAAAAAAAAAAAAAAAALoq9IuMBZKozhzH3jRaHpyFE1wtXzQK3T_0RNuX9LsSVxPITWgU9ZR21jXLk3YGjt
in the email.
when the customers click on the url link in their email, it would go to my client application's (.Net Core 1.1) controller to decrypt the url string in order to pop up an agreement page.
Ex:
public EmailController(IDataProtectionProvider provider)
{
_protector = provider.CreateProtector("myProtector");
}
public IActionResult Agreement(string n, string a)
{
var decryptName = _protector.Unprotect(n);
var decryptAddress = _protector.Unprotect(a);
}
However, I am getting a following error message when I tried to Unprotect them:
System.Security.Cryptography.CryptographicException: 'The key {00000000-0000-0000-0000-000000000000} was not found in the key ring.'
When I searched for an answer, I realized I can configure Data Protection to store the keys to Azure Blob Storage. This link shows me how to persist keys to azure blob storage.
Questions:
What is the best approach other than storing a key to azure blob storage?
If I am on the right track, how do I store it?
How do I configure the same setting for the webjob project as shown in the link which does not have Startup.cs for configuration?
Help is much appreciated.
What is the best approach other than storing a key to azure blob storage?
Based on the document provided by you, we could store the key in file system, Azure Redis, Azure Storage and Registry. Since Registry is not support by Web Job(Azure Web App). If choosing file system, we also need to transfer the keys between the Web Job and your web application. So Azure Redis and Azure Storage would be the good approaches.
If I am on the right track, how do I store it?
Here are the detail steps of how to store keys on Azure Storage.
Step 1, you need to create an Azure Storage account if you doesn't have one.
Step 2, install Microsoft.AspNetCore.DataProtection.AzureStorage package using NuGet.
Step 3, configure DataProtection using following code. We need to invoke SetApplicationName method and use the same application name as your Web Job.
var storageAccount = CloudStorageAccount.Parse("put your azure storage connection string here");
var client = storageAccount.CreateCloudBlobClient();
var container = client.GetContainerReference("key-container");
container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
services.AddDataProtection().SetApplicationName("myapplication")
.PersistKeysToAzureBlobStorage(container, "keys.xml");
Step 4, in your controller, you could use IDataProtectionProvider as following.
public class HomeController : Controller
{
private IDataProtector _protector;
public HomeController(IDataProtectionProvider provider)
{
_protector = provider.CreateProtector("test-purpose");
}
public IActionResult Index()
{
string encryptedTExt = _protector.Protect("abcd");
return Content(encryptedTExt);
}
}
How do I configure the same setting for the webjob project as shown in the link which does not have Startup.cs for configuration?
Step 1, you need to add reference to following DLLs.
Step 2, Add a wrapper class of IDataProtector as following.
public class EncryptService
{
IDataProtector _protector;
// the 'provider' parameter is provided by DI
public EncryptService(IDataProtectionProvider provider)
{
_protector = provider.CreateProtector("test-purpose");
}
public string Protect(string text)
{
return _protector.Protect(text);
}
public string Unprotect(string encryptedText)
{
return _protector.Unprotect(encryptedText);
}
}
Step 3, use ServiceCollection to configure the Data Protection service. Please note that we need to invoke SetApplicationName method and use the same application name as your web application.
static void Main()
{
var storageAccount = CloudStorageAccount.Parse("put your azure storage connection string here");
var client = storageAccount.CreateCloudBlobClient();
var container = client.GetContainerReference("key-container");
container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
var serviceCollection = new ServiceCollection();
serviceCollection.AddDataProtection().SetApplicationName("myapplication")
.PersistKeysToAzureBlobStorage(container, "keys.xml");
var services = serviceCollection.BuildServiceProvider();
}
Step 4, after that, you could use following code to encrypt or decrypt your data.
var encryptService = ActivatorUtilities.CreateInstance<EncryptService>(services);
string text = encryptService.Protect("abcd");