Unspecified error when connecting to a Network Share on Windows 10 #Emtec

There is probably a million fixes for this online, but perhaps this may be one of the more obscure fixes. I got a new network hard drive, from Emtec, which would connect to every other device in the house (mac, old PC, Android TV, Apple TV) but not my main Windows PC. So why?

Not a very helpful error message, when I simply tried to connect to \\emtec, since I just got a “Unspecified error”. I could ping the device, and even the path \\emtec\data worked, but this didn’t grant write access.

So when I tried \\emtec\WiFiDisk1_Volume1 it told me that it was using a deprecated version of SMB, SMB 1 instead of SMB 2. Thankfully, this was at last a meaningful error message, so I could use “Add Windows Features” to add SMB 1 support to my PC, and it finally worked.

A lesson for developers … give descriptive error messages. Something may seem super-obvious to you, but if you just swallow the error, then you give your end users nothing to go on.

I can’t say if the problem is with Emtec, using an old version of SMB, or with Windows for not describing the error properly. But the easier fix would be at the Windows level.

Categories: Uncategorized

Evaluate #Javascript in the cloud with #AWS #Lambda

TL;DR;

https://rapidapi.com/dananos/api/evaluate-javascript

Evaluating Javascript on the server side is a bit of an unusual ask, but perhaps you have an application that you’d like to be highly user-configurable, like you want to support fields that are supplied as complex mathematical formulae, or with complex if/else conditions.

Now, this opens a Pandora’s box of problems. What happens if someone writes malicious or simply bad code that could potentially damage or expose private data on your server, in which case, it’s good to run this in an isolated environment like Lambda (Running under a least-privilege IAM Role)

So, I first create a super simple lambda function as follows

exports.handler = async (event) => {
     const response = {
         statusCode: 200,
         body: JSON.stringify(eval(event.body)),
     };
     return response;
 };

And then create an API gateway as a Trigger, which means that I can now evaluate Javascript on the server side, using a CURL command as follows;

curl -X POST "https://xxxxxx.execute-api.eu-west-1.amazonaws.com/eval" -d "1+5" -H "Content-Type: application/json"

Where xxxx is dynamically assigned during the API gateway setup, and eval was the name of my Lambda function

The result of “1+5” is returned as “6” in the response.

Now, be aware, that the inner workings of your lambda can be exposed by executing Javascript like “process.env”, but as long as the Lambda itself has little permissions, then the damage it can do is limited also. Also, the running time and memory limits are capped, so it is unlikely to cost much.

Categories: Uncategorized

CRUD with #AWS #DynamoDB in .NET Core

One of the true benefits of DynamoDB is that it’s great for mini-projects, where you have to run on virtually zero budget. It doesn’t charge per-hour like the amazon RDS options, or Document DB options. It charges per storage >25GB and per million requests.

So, I set up a DynamoDB via the UI, and named it “test”. It’s much better if you name this something more meaningful, but I was just messing. I added a primary key of ID which is a number.

Then, as you create a new .NET Core project, you’ll need a Nuget package as follows;

Install-Package AWSSDK.DynamoDBv2

So with any Database, the first thing is to connect to it, which you’ll need to set up your IAM credentials, and then write some code like;

var credentials = new BasicAWSCredentials(AWS_USER, AWS_KEY);
 var client = new AmazonDynamoDBClient(credentials, RegionEndpoint.EUWest1);
 var tableResponse = client.ListTablesAsync().Result;
 var context = new DynamoDBContext(client);

I’ve written everything synchronously here, not best design, but it makes it easy to follow the flow. The ListTablesAsync is optional, but helps verify that it’s working.

The Object I defined, named “test” is as follows;

class test
 {
     public int id { get; set; }
     public string animal { get; set; }
 }

CREATE

context.SaveAsync(new test {id = 4, animal = "Frog"}).Wait();

READ

var conditions = new List
 {
     new ScanCondition("id", ScanOperator.Equal, 4)
 };
 var allDocs = context.ScanAsync(conditions).GetRemainingAsync().Result;
 allDocs.ForEach(t => Console.WriteLine(t.animal));

UPDATE

context.SaveAsync(new test { id = 4, animal = "Lion" }).Wait();

DELETE

context.DeleteAsync(new test {id = 4, animal = "Lion"}).Wait();

Categories: Uncategorized

Send #APNS #Push notifications using #RapidAPI

TLDR; Go Here: https://rapidapi.com/dananos/api/simplified-apns-apple-push-notification-service

This is a simple tutorial to send an APNS (Apple Push Notification Service), to production using C# (RestSharp) and Rapid API. It uses HTTP/2, so will continue to work after the March 31st deadline.

To do this, you will need:

  • The P12 production certificate, and it’s password
  • An APNS token of an iOS app, that has subscribed to push notifications.
  • A subscription Key to this RapidAPI service.

Create a new project in Visual Studio, and add your p12 certificate to the project. Change it’s build properties to “copy always”.

From the Package management panel, Install Rest Sharp via Nuget with “Install-Package RestSharp”

Add the following code;

public static string Push(string destination, string message, string certFile, string certPassword, string rapidApiKey)
        {
            var certificate = File.ReadAllBytes(certFile);
            var client = new RestClient("https://rapidapi.p.rapidapi.com/Prod");
            var request = new RestRequest(Method.POST);
            request.AddHeader("x-rapidapi-key", rapidApiKey);
            request.AddHeader("x-rapidapi-host", "simplified-apns-apple-push-notification-service.p.rapidapi.com");
            request.AddJsonBody(new
            {
                destination,
                message,
                certificate,
                certPassword
            });
            var response = client.Execute(request);
            return response.Content;
        }

The calling code will be up to you, but it will be in the form;

        var destination = "8ec378164725d019fce12c420cea7......";
        var message = "hello, this is rapidAPI!";
        var certPassword = "XXXXX";
        var certFile = "XXXXX.p12";
        var rapidApiKey = "PUB#XXXXXXXX";
        var pushResponse = Push(destination, message, certFile, certPassword, rapidApiKey);
        Console.WriteLine(pushResponse);
Categories: Uncategorized

Deleting a large number of records from a database without locking it (for ages) #SQL

If you have a large database, with millions of rows, and you need to run an batch operation on it, like deleting lots of old records, then you’ll quickly find that the operation often will lock the table, and prevent users get at their data – as well as bloating the transaction log table.

So, the trick is to break it down into manageable chunks. Let’s say the operation I want to run is this;

delete from log where success=0

If the “log” table has millions of rows, then this will undoubtedly lock the log table, as the statement is running. Preventing new logs from being written.

If I then write something like:

delete top (100) from log where success=0

This completes in a jiffy, and deletes 100 rows from the log table. The actual 100 rows that get deleted are beyond your control, it’s just the first 100 that it finds. But that isn’t really a problem.

So, let’s write this as a loop as follows;

declare @FirstPass Bit
select @FirstPass = 1;
while @@ROWCOUNT = 100 or @FirstPass = 1
begin
set @FirstPass = 0;
delete top (100) from log where success=0
end

This just means that it will run this command over and over again until it no longer has rows that it can delete.

Now, to improve upon this a bit more, I’m going to add the lines;

  WAITFOR DELAY  '00:00:01';  
  RAISERROR('ok',0,1) WITH NOWAIT;

Which will put a 1 second delay in the loop, to make sure we’re not hogging all the Database’s processing power, and the “RaiseError” just flushes the output to the messages window, so we can see that everything is running smoothly.

Categories: Uncategorized

#APNS using HTTP/2 in C# using #AWS Lambda

By March 31st 2021, all users using the Apple Push Notification Service (APNS) must update to Apple’s new API, which is based on HTTP/2. If you don’t update, then it’s likely that your push notifications won’t get through.

If you are using C#, then you can use the dotAPNS NUGet package, which, from the client perspective is a tiny change, however, it does require .NET Core to run, which if your project is in .NET standard, then this could cause problems.

So, in this case, I decided to create a stand-alone .NET Core app using AWS Lambda and AWS API Gateway, which would be a middleware API between my main app and the APNS API.

My App -> AWS LAMBDA -> APNS

So, I created an AWS Lambda App in Visual Studio, and made sure I could publish to AWS Lambda. Which also gives you an API Gateway URL, in the format;

<ID>.execute-api.<Region>.amazonaws.com/Prod

I also needed to update the serverless.template file as follows

         "Events": {
           "RootGet": {
             "Type": "Api",
             "Properties": {
               "Path": "/",
               "Method": "GET"
             }
           },
           "RootPost": {
             "Type": "Api",
             "Properties": {
               "Path": "/",
               "Method": "POST"
             }
           }

And changed the Handler to

ApnsHttp2Serverless::ApnsHttp2Serverless.Functions::HttpRequest

(Where ApnsHttp2Serverless was the name of my project)

Now, my code to send the push notification is as follows;

private ApnsResponse Send(
             byte[] certificate, 
             string certPassword, 
             string message, 
             string destination)
 {
     var x509 = new X509Certificate2(certificate, certPassword);
     var applePushNotificationService = ApnsClient.CreateUsingCert(x509);
     var push = new ApplePush(ApplePushType.Alert)
     .AddAlert(message)
     .AddToken(destination);
     return applePushNotificationService.Send(push).Result;
 }

Which is called from the lambda as follows;

public APIGatewayProxyResponse HttpRequest(APIGatewayProxyRequest request, ILambdaContext context)
 {
     context.Logger.LogLine(request.Body);
     var jRequest = JObject.Parse(request.Body);
     var certificate = jRequest["certificate"].ToObject();
     var certPassword = jRequest["certPassword"].ToObject();
     var message = jRequest["message"].ToObject();
     var destination = jRequest["destination"].ToObject();
     var sendResult = Send(certificate, certPassword, message, destination);
     var response = new APIGatewayProxyResponse
     {
     StatusCode = (int)HttpStatusCode.OK,
     Body = JsonConvert.SerializeObject(sendResult,Formatting.Indented),
     Headers = new Dictionary { { "Content-Type", "application/json" } }
     };
     return response;
 }

So, I pushed this code to AWS Lambda, and wrote the client as follows:

public static string Push(string destination, string message, string certFile, string certPassword)
 {
     var certificate = File.ReadAllBytes(certFile);
     var oPayload = new
     {
         destination,
         message,
         certificate,
         certPassword
     };
     var strPayload = JsonConvert.SerializeObject(oPayload, Formatting.Indented);
     var wc = new WebClient();
     var response = wc.UploadString("https://....execute-api.eu-west-1.amazonaws.com/Prod", strPayload);
     return response;
 }

So, Assuming you have the destination ID, and your certs set up correctly, this just works!

For anyone who is interested, here is the GitHub Repo of the AWS Lambda function:

https://github.com/infiniteloopltd/ApnsHttp2

And for those who happen to use PHP as the trigger to send push notifications, here is the client code in PHP:

<?php
$data        = file_get_contents('cert.p12');
$cert64      = base64_encode($data);
$destination = "-apns-token-";
$password    = "-cert-password-";
$url         = "https://xxxxxx.execute-api.eu-west-1.amazonaws.com/Prod";
$ch          = curl_init($url);
$oPayload    = array(
    'destination' => $destination,
    'message' => 'hello there!',
    'certificate' => $cert64,
    'certPassword' => $password
);
$payload     = json_encode($oPayload);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
if ($content === false) {
    echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch);
echo $content;
?>

Categories: Uncategorized

Overriding the Date in a WebClient Request in C#

The WebClient object in C# greatly simplifies the actions of making HTTP GET and POST requests, however, when you need to edit an “Under the hood” property, then you find that WebClient has hidden this functionality from you.

In this example, I want to override the Date property of the HTTP request, effectively sending a request to the server, but saying it was sent at a different time. This is not a property you often want to mess with, but you can do it as follows;

private class SpecializedWebClient : WebClient
{
    public DateTime Date { get; set; }
    protected override WebRequest GetWebRequest(Uri address)
    {
	var request = base.GetWebRequest(address) as HttpWebRequest;
	if (request != null) request.Date = Date;
	return request;
    }
}

I hope someone finds this useful!

Categories: Uncategorized

Convert French Siret/Siren to VAT (TVA) in C#

This is probably well known to french people, but you can convert a french company ID (Siret or Siren) to a french VAT number with some simple code, as follows in c#

The relevant function is as follows;

public static string VatFromSiret(string siret)
{
if (siret.Length > 9) siret = siret.Substring(0, 9); // siren
var numSiret = Convert.ToInt32(siret);
var validation = (12 + 3 * (numSiret % 97)) % 97;
return "FR" + validation + siret;
}

Here is the Github repo, for anyone who’s interested;

https://github.com/infiniteloopltd/VatFromSiret/

Categories: Uncategorized

Encryption at rest #MySQL, before and after

If you don’t encrypt data at rest in MySQL, then potentially secure information can be easily extracted from the underlying “ibd” files. This scenario may occur, if someone had access to the filesystem of your server, but not necessarily access to MySQL itself.

Here, I’ve simply created a new database, called “superSecure”, with one table called “Passwords”, which has one column called “Password”, and one row containing the text “YELLOW_SUBMARINE”, by running a simple “cat” commad on the ibd file, you can clearly see the text “YELLOW_SUBMARINE” in the text.

However, with these commands, we can encrypt the underlying data;

INSTALL PLUGIN keyring_file SONAME 'keyring_file.so';
SET GLOBAL keyring_file_data = '/var/lib/mysql-keyring/keyring';
ALTER TABLE PASSWORDS ENCRYPTION='Y';

Once these commands are complete; and we try to view the ibd file again,

There is no plain text that can be viewed in the file.

Evidently, this is not foolproof, but it’s one simple way to help secure your data.

Categories: Uncategorized

Microsoft Translation #API using #Azure #CognitiveServices

When it comes to translation APIs, then Google translate is perhaps the first that comes to mind, but there is also Microsoft Azure translation API, under their cognitive Services umbrella.

Here is some simple code to implement the API, – I’ve omitted my API keys, and assuming you are using the WesternEurope (Ireland) endpoint.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
                                       SecurityProtocolType.Tls |
                                       SecurityProtocolType.Tls11 |
                                       SecurityProtocolType.Tls12; 

const string strUrl = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=es&from=en";
var wc = new WebClient();
wc.Headers["Ocp-Apim-Subscription-Key"] = key;
wc.Headers["Ocp-Apim-Subscription-Region"] = "westeurope";
wc.Encoding = Encoding.UTF8;
var jPost = new [] { new { Text = "Hello, what is your name?"}};
var strPost = JsonConvert.SerializeObject(jPost, Formatting.Indented);
wc.Headers[HttpRequestHeader.ContentType] = "application/json";
var json = "";
try
{
    json = wc.UploadString(strUrl, "POST", strPost);
  
}
catch (WebException exception)
{
    string strResult = "";
    if (exception.Response != null)
    {
        var responseStream = exception.Response.GetResponseStream();
        if (responseStream != null)
        {
            using (var reader = new StreamReader(responseStream))
            {
                strResult = reader.ReadToEnd();
            }
        }
    }
    throw new Exception(strResult);
}

var jResponse = JArray.Parse(json);
var translation = jResponse.First["translations"].First["text"].ToString();

It also requires the Newtonsoft.JSON Nuget package.

Hope this is useful to someone.

Categories: Uncategorized