aws ssl, aws_certificate_manager, acm

Paying a ton of money to a digital certificate, which costs nothing to generate, has always bugged me. Fortunately it isn’t just me and recently I heard about Let’s Encrypt.

I was just planning to give it a go but I noticed a new service on AWS Management Console:

Apparently AWS is now issuing free SSL certificates, which was too tempting to pass on so I decided to dive in.

Enter AWS Certificate Manager

Requesting a certificate just takes seconds as it’s a 3-step process:

First, enter the list of domains you want the certificates for:

Wildcard SSL certificates don’t cover the zone apex so I had to enter both. (Hey it’s free so no complaints here!)

Then review and confirm and request has been made:

A verification email has been sent to the email addresses listed in the confirmation step.

At this point I could define MX records and use Google Apps to create a new user and receive the verification email. The problem is I don’t want all this hassle and certainly don’t need another email account to monitor.

SES to the rescue

I always considered SES as a simple SMTP service to send emails but while dabbling with alternatives I realized that now we can receive emails too!

To receive emails you need to verify your domain first. Also an MX record pointing to AWS SMTP server must be added. Fortunately since everything here is AWS it can be done automatically using Route53:

After this we can move on, we’ll receive a confirmation email once the domain has been verified:

In the next step we decide what to do with the incoming mails. We can bounce them, call a Lambda function, create a SNS notification etc. These all sound fun to experiment with but in this case I’ll opt for simplicity and just drop them to a S3 bucket.

Great thing is I can even assign a prefix so I can a single bucket to collect emails from a bunch of different addresses all separated into their own folders.

In step 3, we can specify more options. Another pleasant surprise was to see spam and virus protection:

After reviewing everything and confirming we are ready to receive emails to our bucket. In fact nice folks at AWS are so considerate that they even sent us a test email already:

Back to certificates

OK, after a short detour we are back on getting our SSL certificate. As I didn’t have my mailbox setup during the validation step I had to go to actions menu and select Resend validation email.

And after requesting it I immediately received the email containing a link to verify ownership of the domain.

After the approval process we get ourselves a nice free wildcard SSL certificate:

Test drive

To leverage the new certificate we need to use CloudFront to create a distribution. Here again we benefit from the integrated services. The certificate we have been issued can be selected from the dropdown list:

So after entering simple basics like the domain name and default page I created the distribution and pointed the Route53 records to this distribution instead of the S3 bucket.

And finally, after waiting (quite a bit) for the CloudFront distribution to be deployed we can see that little green padlock we’ve been looking forward to see!:

UPDATE 1 [03/03/2016]

Yesterday I was so excited about discovering this I didn’t look any further like downloading the certificate and using it on your servers.

Today unfortunately I realized that the usability is quite limited: It only works with AWS Elastic Load Balancer and CloudFront. I was hoping to use it with API Gateway but even that’s another AWS service it’s not integrated with ACM yet.

I do hope they make the cert bits available so we can have full control over them and deploy to wherever we want. So I guess Let’s Encrpt is a better option for now considering this limitation.

Resources

dev csharp, gadget, fitbit, aria
"What gets measured, gets managed." - Peter Drucker

It’s important to have goals, especially SMART goals. The “M” in S.M.A.R.T. stands for Measurable. Having enough data about a process helps tremendously to improve that process. To this effect, I started to collect exercise data from my Microsoft band which I blogged about here.

Weight tracking is also crucial for me. I used to record my weight manually on a piece of paper but, for the obvious reasons, I abandoned it quickly and decided to give Fitbit Aria a shot.

Fitbit Aria Wi-Fi Smart Scale

Aria is basically a scale that can connect to your Wi-Fi network and send your weight results to Fitbit automatically which can then be viewed via Fitbit web application.

Setup

Since it doesn’t have a keyboard or any other way to interact directly setup is carried out by running a program on your computer

It’s mostly just following the steps on the setup tool. You basically let it connect to your Wi-Fi network so that it can synchronize with Fitbit servers.

Putting the scale into setup mode proved to be tricky in the past though. Also it was not easy to change Wi-Fi so I had to reset the go back to factory settings and ran the setup tool again.

Getting the data via API

Here comes the fun part! Similar to my MS Band workout demo, I developed a WPF program to get my data from Fitbit’s API. Ultimately the goal is to combine all these data in one application and make sense of it.

Like MS Health API, FitBit uses OAuth 2.0 authorization and requires a registered application.

The endpoint that returns weight data accepts a few various formats depending on your needs. As I wanted a range instead of a single day I used the following format:

https://api.fitbit.com/1/user/{user ID}/body/log/weight/date/{startDate}/{endDate}.json

This call returns an array of the following JSON objects:

{
	"bmi": xx.xx,
	"date": "yyyy-mm-dd",
	"fat": xx.xxxxxxxxxxxxxxx,
	"logId": xxxxxxxxxxxxx,
	"source": "Aria",
	"time": "hh:mm:ss",
	"weight": xx.xx
}

Sample application

The bulk of the application is very similar to MS Band sample: It first opens an authorization window and once the client consents for the app to be granted some privileges it uses the access token to retrieve the actual data.

There are a few minor differences though:

  • Unlike MS Health API it requires Authorization header in the authorization code request calls which is basically Base64 encoded client ID and client secret
string base64String = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Settings.Default.ClientID}:{Settings.Default.ClientSecret}"));
request.AddHeader("Authorization", $"Basic {base64String}");
  • It requires a POST request to redeem URL. Apparently RestSharp has a weird behaviour. You’d think a method called AddBody could be used to send the request body, right? Not quite! It doesn’t transmit the header so I kept getting a missing field error. So instead I used AddParameter:
string requestBody = $"client_id={Settings.Default.ClientID}&grant_type=authorization_code&redirect_uri={_redirectUri}&code={code}";
request.AddParameter("application/x-www-form-urlencoded", requestBody, ParameterType.RequestBody);

I found a lot of SO questions and a hillarious blog post addressing the issue. It’s good to know I wasn’t alone in this!

The rest is very straightforward. Make the request, parse JSON and assign the list to the chart:

public void GetWeightData()
{
    var endDate = DateTime.Today.ToString("yyyy-MM-dd");
    var startDate = DateTime.Today.AddDays(-30).ToString("yyyy-MM-dd");
    var url = $"https://api.fitbit.com/1/user/XXXXXX/body/log/weight/date/{startDate}/{endDate}.json";
    var response = SendRequest(url);

    ParseWeightData(response);
}

public void ParseWeightData(string rawContent)
{
    var weightJsonArray = JObject.Parse(rawContent)["weight"].ToArray();
    foreach (var weightJson in weightJsonArray)
    {
        var weight = new FitbitWeightResult();
        weight.Weight = weightJson["weight"]?.Value<decimal>() ?? 0;
        weight.Date = weightJson["date"].Value<DateTime>();
        WeightResultList.Add(weight);
    }
}

And the output is:

Conclusion

So far I managed to collect walking data from MS Band, weight data from Fitbit Aria. In this demo I limited the scope with weight data only but Fitbit API can be used to track sleep, exercise and nutrition.

I currently use My Fitness Pal to log what I eat. They too have an API but even though I requested twice they haven’t given me a key yet! Good news is Fitbit has a key and I can get my MFP logs through Fitbit API. I also log my sleep on Fitbit manually so next step is to combine all these in one application to have a nice overview.

Resources

dev csharp, gadget, microsoft_band

I bought this about 6 months ago and in this post I’ll talk about my experiences so far. They released version 2 of it in last November so I thought I should write about it before it gets terribly outdated!

Choosing the correct size

It comes in 3 sizes: Small, Medium and Large and finding the correct size is the first challenge. They seem to have improved the sizing guide for version 2. In the original one they didn’t mention the appropriate size for wrist’s circumference.

To have the same effect I followed someone’s advice on a forum regarding the circumferences. Downloaded a printable ruler to measure mine. It was at the border of medium and laarge and I decided to go with medium but even at the largest setting it’s not comfortable and irritates my skin. Most of the time I have to wear it on top of a large plaster

Wearing notes

I hope they fixed it in v2 but the first generation Band is quite bulky and uncomfortable. To be honest most of the time I just kept wearing it because I had spent £170 and didn’t come to terms with making a terrible investment. I wear it when I’m walking but as soon as I arrive at home or work I take it off because it’s almost impossible to type something with it.

Band in action

For solely getting fitness data purposes you can use it without pairing with your phone but pairing is helpful as you can read your texts on it, see emails and answer calls.

I also installed the Microsoft Health app and started using Microsoft Health dashboard:

Troubleshooting

As soon as I started using it I noticed a discrepancy with the step count on the Microsoft Health dashboard. Turns out by default it was using phone’s motion tracker as well so it was doubling my steps. After I turned it off started getting the exact same results as on Band.

Turn off motion tracking to get accurate results

Developing with Band and Cloud API

Recording data about something helps tremendously to make it manageable. That’s why I like using these health & fitness gadgets. But of course it doesn’t mean much if you don’t make sense of that data.

In my sample application I used Microsoft Health Cloud API to get the Band’s data. In order this to work Band needs to sync with Microsoft Health app on my phone and the app syncs with my MS account.

The API has a great guide here that can be downloaded as a PDF. It outlines all the necessary steps very clearly and in detail.

Long story short, firstly you need to go to Microsoft Account Developer Center and register an application. This will give you a client ID and client secret that will be used for OAuth 2.0 authentication.

API uses OAuth 2.0 authentication. After the token has been acquired, using the actual API is quite simple, in my example app I used /Summaries endpoint to get the daily step counts.

Implementation

The sample application is a simple WPF desktop application. Upon launch it checks if the user has an access token stored, if not then it shows the OAuth window and the user need to login to their account.

To let the user login to their Microsoft account I added a web browser control to a window and navigated to authorization page:

string authUri = $"{baseUrl}/oauth20_authorize.srf?client_id={Settings.Default.ClientID}&scope={_scope}&response_type=code&redirect_uri={_redirectUri}";
webBrowser.Navigate(authUri);

Once the authorization is complete, the web browser is redirected to with a query parameter code. This is not the actual token we need. Now, we need to go to another URL (oauth20_token.srf) with this code and client secret as parameters and redeem the actual access token:

private void webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    if (e.Uri.Query.Contains("code=") && e.Uri.Query.Contains("lc="))
    {
        string code = e.Uri.Query.Substring(1).Split('&')[0].Split('=')[1];

        string authUriRedeem = $"/oauth20_token.srf?client_id={Settings.Default.ClientID}&redirect_uri={_redirectUri}&client_secret={Settings.Default.ClientSecret}&code={code}&grant_type=authorization_code";

        var client = new RestClient(baseUrl);
        var request = new RestRequest(authUriRedeem, Method.GET);
        var response = (RestResponse)client.Execute(request);
        var content = response.Content;

        // Parse content and get auth code
        Settings.Default.AccessToken = JObject.Parse(content)["access_token"].Value<string>();
        Settings.Default.Save();

        Close();
    }
}

After we get the authorization out of the way we can actually call the API and get some results. It’s a simple GET call (https://api.microsofthealth.net/v1/me/Summaries/daily) and the response JSON is pretty straightforward. The only thing to keep in mind is to add the access token to Authorization header:

request.AddHeader("Authorization", $"bearer {Settings.Default.AccessToken}");

Here’s a sample output for a daily summary:

{
	"userId": "67491ecc-c408-47b6-a3ad-041edb410524",
	"startTime": "2016-01-18T00:00:00.000+00:00",
	"endTime": "2016-01-19T00:00:00.000+00:00",
	"parentDay": "2016-01-18T00:00:00.000+00:00",
	"isTransitDay": false,
	"period": "Daily",
	"duration": "P1D",
	"stepsTaken": 2784,
	"caloriesBurnedSummary": {
		"period": "Daily",
		"totalCalories": 1119
	},
	"heartRateSummary": {
		"period": "Daily",
		"averageHeartRate": 77,
		"peakHeartRate": 88,
		"lowestHeartRate": 68
	},
	"distanceSummary": {
		"period": "Daily",
		"totalDistance": 232468,
		"totalDistanceOnFoot": 232468
}

Since we now have the data, we can visualize it:

If you want to play with the sample code don’t forget to register an app and update the settings with your client ID and secret

Next

I guess the most fun would be to develop something that actually runs on the device. My next goal with my Band is to develop a custom tile using its SDK. I hope I can finish it while a first-gen device is still fairly relevant.

Resources