{"id":589,"date":"2014-11-19T17:49:47","date_gmt":"2014-11-19T16:49:47","guid":{"rendered":"https:\/\/www.yelloworb.com\/orbblog\/?p=589"},"modified":"2014-11-19T20:51:57","modified_gmt":"2014-11-19T19:51:57","slug":"how-to-create-a-reasonably-secure-arduino-client-that-post-data-into-a-rails-application-part-i","status":"publish","type":"post","link":"https:\/\/www.yelloworb.com\/orbblog\/how-to-create-a-reasonably-secure-arduino-client-that-post-data-into-a-rails-application-part-i\/","title":{"rendered":"How-to create a reasonably secure Arduino client that post data into a Rails application &#8211; part I"},"content":{"rendered":"<p>Arduinos get more and more connected and I use an Arduino together with a GSM\/GPRS shield to build the <a href=\"http:\/\/www.blast.nu\/products\" target=\"_blank\">wind stations<\/a>.<\/p>\n<p>But the Arduino is a very limited platform and some (as the <a href=\"http:\/\/arduino.cc\/en\/Main\/ArduinoBoardNano\" target=\"_blank\">Nano<\/a>) has as little as 1k RAM! Then it becomes a real challenge to do web and HTTP communication. Here I will summarise the experience gathered during the construction of a tiny secure REST client for the Arduino.<\/p>\n<p>Why REST?<br \/>\nRuby on Rails is the framework I prefer when it comes to write web applications. It is powerful still quite fast to work with. Rails uses REST a lot and it is definite the easiest way to considering the server-side. Though HTML is quite talkative so lots of strings(which take RAM) will be needed in the Arduino, or clever use of PROGMEM with which we can put the strings in ROM.<\/p>\n<p>Secure?<br \/>\nWhat I mainly want to achieve is to make it hard for someone to send\/post false information into the Rails application. For the wind stations it does not matter so much but say we use an Arduino for some kind of real world game. Then some clever hacker could quite easily figure out the URL to make a post and then just start posting in actions or whatever the Arduino controls. So we want to make sure those post requests we receive comes from a unit we have put the software inside.<\/p>\n<p>HMAC<br \/>\nBut what kind of authentication should one use? Have read around a bit and regarding REST so seems HMAC(Hash based Message AuthentiCation) a good option and recommended(<a href=\"http:\/\/restcookbook.com\/Basics\/loggingin\/\" target=\"_blank\">http:\/\/restcookbook.com\/Basics\/loggingin\/<\/a>). Also found an Arduino lib that supports HMAC called <a href=\"https:\/\/github.com\/Cathedrow\/Cryptosuite\" target=\"_blank\">Cryptosuite<\/a>. It seems at first glance to be really memory efficient (uses PROGMEM) but when reading through the code it seems to use about 196 bytes of RAM which is still quite a lot in these circumstances.<\/p>\n<p>Rails application<br \/>\nLets start with the Rails application. <a href=\"http:\/\/github.com\/mgomes\/api_auth\" target=\"_blank\">API_AUTH<\/a> seems to be a good library to get HMAC support for Rails applications so that was my choice.<\/p>\n<p>Create a new Rails project:<\/p>\n<pre><code class=\"\" data-line=\"\">&gt;rail new ArduinoAuthenticatedClientExample<\/code><\/pre>\n<p>Then using you favourite text editor add API_AUTH to the Gemfile:<\/p>\n<pre><code class=\"\" data-line=\"\">gem &#039;api-auth&#039;<\/code><\/pre>\n<p>After that do a bundle update to get all gems installed.<\/p>\n<pre><code class=\"\" data-line=\"\">&gt; bundle update<\/code><\/pre>\n<p>Our model is quite simple, we have probes(an Arduino) that can post temperature readings(Measures). So lets create these two:<\/p>\n<pre><code class=\"\" data-line=\"\">&gt; rails generate scaffold Probe name:string secret:string\n&gt; rails generate scaffold Measure temperature:float<\/code><\/pre>\n<p>We need to setup the relationships between these models, a probe has many measures and measures belongs to probes. In app\/models\/probe.rb add:<\/p>\n<pre><code class=\"\" data-line=\"\">has_many :measures<\/code><\/pre>\n<p>and in app\/models\/measure.rb add:<\/p>\n<pre><code class=\"\" data-line=\"\">belongs_to:probe<\/code><\/pre>\n<p>Now give the following command to generate the migration and have it create the needed index in measures:<\/p>\n<pre><code class=\"\" data-line=\"\">rails generate migration AddProbeRefToMeasures user:references<\/code><\/pre>\n<p>Now it is time to update the database:<\/p>\n<pre><code class=\"\" data-line=\"\">rake db:migrate<\/code><\/pre>\n<p>Add the following code to app\/controllers\/measures_controller.rb so that all REST calls that modify the model needs to be authenticated using HMAC:<\/p>\n<pre><code class=\"\" data-line=\"\"># require any kind of change and creation of a measure to come through our authenticated api using HMAC \n  # and we skip the CSRF check for these requests\n  before_action :require_authenticated_api, only: [:edit, :update, :destroy, :create]\n  skip_before_action :verify_authenticity_token, only: [:edit, :update, :destroy, :create]\n\n  def require_authenticated_api\n    @current_probe = Probe.find_by_id(ApiAuth.access_id(request))\n    logger.info request.raw_post # needed due to a bug in api_auth\n    # if a probe could not be found via the access id or the one found did not authenticate with the data in the request\n    # fail the call\n    if @current_probe.nil? || !ApiAuth.authentic?(request, @current_probe.secret) \n      flash[:error] = &quot;Authentication required&quot;\n      redirect_to measures_url, :status =&gt; :unauthorized\n    end\n  end \n<\/code><\/pre>\n<p>We added a flash error message in the code above so we need to add support in app\/views\/layouts\/application.html-erb to get that presented:<\/p>\n<pre><code class=\"\" data-line=\"\">&lt; % flash.each do |name, msg| -%&gt;\n      &lt; %= content_tag :div, msg, class: name %&gt;\n    &lt; % end -%&gt;<\/code><\/pre>\n<p>We want the secret keys generated automatically rather then entered by the user. So in app\/controllers\/probes_controller.rb, in the create method change so the first lines looks like this:<\/p>\n<pre><code class=\"\" data-line=\"\">    @probe = Probe.new(probe_params)\n    @probe.secret = ApiAuth.generate_secret_key<\/code><\/pre>\n<p>And we want to remove the input field. Change in app\/views\/probes\/_form.html.erb so<\/p>\n<pre><code class=\"\" data-line=\"\">&lt; %= f.text_field :secret %&gt;<\/code><\/pre>\n<p>becomes<\/p>\n<pre><code class=\"\" data-line=\"\">&lt; %= @probe.secret %&gt;<\/code><\/pre>\n<p>Now we are almost done but we want to add some more security. We do not want anyone be able to change the secret keys and actually we would like to add user authentication so that like an admin is the only one who ca see the secrets but that is not a task for this tutorial. If you need that see for example the <a href=\"https:\/\/github.com\/plataformatec\/devise#getting-started\" target=\"_blank\">Devise getting started guide<\/a>. Add the following to app\/models\/probe.rb so that the secret only can be read and not modified:<\/p>\n<pre><code class=\"\" data-line=\"\">attr_readonly :secret<\/code><\/pre>\n<p>Now you can run the server and start creating probes. Do<\/p>\n<pre><code class=\"\" data-line=\"\">&gt; rails server<\/code><\/pre>\n<p>and create a probe or two by going to <a href=\"http:\/\/localhost:3000\/probes\/\" target=\"_blank\">http:\/\/localhost:3000\/probes\/<\/a><\/p>\n<p>To test that is&#8217;s working create a simple client:<\/p>\n<pre><code class=\"\" data-line=\"\">require &#039;openssl&#039;\nrequire &#039;rest_client&#039;\nrequire &#039;date&#039;\nrequire &#039;api_auth&#039;\n\n@probe_id = &quot;2&quot;\n@secret_key = &quot;rNwtKjjVZ4UUTQWvL+ZpK1PVjXz5N1uKpYRCfLfTD+ySTMaeswfPhkokN\/ttjX3J78KNqclcYLHSw\/mzHeJDow==&quot;\n    \nheaders = { &#039;Content-Type&#039; =&gt; &quot;text\/yaml&quot;, &#039;Timestamp&#039; =&gt; DateTime.now.httpdate}\n\n@request = RestClient::Request.new(:url =&gt; &quot;http:\/\/localhost:3000\/measures.json&quot;,\n        :payload =&gt; {:measure =&gt; { :temperature =&gt; 12}},\n        :headers =&gt; headers,\n        :method =&gt; :post)\n        \n@signed_request = ApiAuth.sign!(@request, @probe_id, @secret_key)    \n\nresponse = @signed_request.execute()\nputs &quot;Response &quot; + response.inspect<\/code><\/pre>\n<p>And run that and you should get something like:<\/p>\n<pre><code class=\"\" data-line=\"\">Response &quot;{\\&quot;id\\&quot;:19,\\&quot;temperature\\&quot;:12.0,\\&quot;created_at\\&quot;:\\&quot;2014-09-30T15:04:26.286Z\\&quot;,\\&quot;updated_at\\&quot;:\\&quot;2014-09-30T15:04:26.286Z\\&quot;}&quot;<\/code><\/pre>\n<p>In <a href=\"https:\/\/www.yelloworb.com\/orbblog\/how-to-create-a-reasonably-secure-arduino-client-that-post-data-into-a-rails-application-part-ii\/\" title=\"How-to create a reasonably secure Arduino client that post data into a Rails application \u2013 part II\">part II<\/a> I describe how to create the client on the Arduino.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Arduinos get more and more connected and I use an Arduino together with a GSM\/GPRS shield to build the wind stations. But the Arduino is a very limited platform and some (as the Nano) has as little as 1k RAM! Then it becomes a real challenge to do web and HTTP communication. Here I will [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[67,68,28],"tags":[],"class_list":["post-589","post","type-post","status-publish","format-standard","hentry","category-arduino","category-rails","category-software-development"],"_links":{"self":[{"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/posts\/589","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/comments?post=589"}],"version-history":[{"count":14,"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/posts\/589\/revisions"}],"predecessor-version":[{"id":637,"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/posts\/589\/revisions\/637"}],"wp:attachment":[{"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/media?parent=589"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/categories?post=589"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yelloworb.com\/orbblog\/wp-json\/wp\/v2\/tags?post=589"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}