{"id":2097,"date":"2016-08-08T08:16:05","date_gmt":"2016-08-08T15:16:05","guid":{"rendered":"https:\/\/blog.mozilla.org\/security\/?p=2097"},"modified":"2016-09-30T02:46:21","modified_gmt":"2016-09-30T09:46:21","slug":"mwos-2015-lets-encrypt-automation-tooling","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/","title":{"rendered":"MWoS 2015: Let\u2019s Encrypt Automation Tooling"},"content":{"rendered":"<p><a href=\"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"size-medium wp-image-1919 alignright\" src=\"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2-252x331.png\" alt=\"winterOfSecurity_logo_dark_vertical2\" width=\"252\" height=\"331\" srcset=\"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2-252x331.png 252w, https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2-600x787.png 600w, https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2.png 1716w\" sizes=\"(max-width: 252px) 100vw, 252px\" \/><\/a>The <a href=\"https:\/\/wiki.mozilla.org\/Security\/Automation\/WinterOfSecurity2015\">Mozilla Winter of Security of 2015<\/a> has ended, and the participating teams of students are completing their projects.<\/p>\n<p>The <a href=\"https:\/\/wiki.mozilla.org\/Security\/Automation\/Winter_Of_Security_2015\/Certificate_Automation_tooling_for_Lets_Encrypt\">Certificate Automation tooling for Let&#8217;s Encrypt project<\/a> wrapped up this month, having produced an experimental proof-of-concept patch for the Nginx webserver to tightly integrate the ACME automated certificate management protocol into the server operation.<\/p>\n<p>The MWoS team, my co-mentor Richard Barnes, and I would like to thank Klaus Krapfenbauer, his advisor Martin Schmiedecker, and the Technical University of Vienna for all the excellent research and work on this project.<\/p>\n<p>Below is Klaus&#8217; end-of-project presentation on AirMozilla, as well as further details on the project.<\/p>\n<h3>MWoS Let&#8217;s Encrypt Certificate Automation presentation on <a href=\"https:\/\/air.mozilla.org\/mwos-2015-lets-encrypt-automation-tooling\/\">AirMozilla<\/a><\/h3>\n<p><iframe loading=\"lazy\" src=\"https:\/\/air.mozilla.org\/mwos-2015-lets-encrypt-automation-tooling\/video\/\" width=\"640\" height=\"380\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<h3>Developing an ACME Module for Nginx<\/h3>\n<p><strong>Author: Klaus Krapfenbauer<\/strong><\/p>\n<p><i>Note: The module is an incomplete proof-of-concept, available at <\/i><a href=\"https:\/\/github.com\/mozilla\/mwos-letsencrypt-2015\"><i>https:\/\/github.com\/mozilla\/mwos-letsencrypt-2015<\/i><\/a><\/p>\n<p><!--more--><\/p>\n<p>The <a href=\"https:\/\/wiki.mozilla.org\/Security\/Automation\/Winter_Of_Security_2015\">2015-2016 Mozilla Winter of Security<\/a> included a project to implement an ACME client within a well-known web server, to show the value of automated HTTPS configuration when used with <a href=\"https:\/\/letsencrypt.org\/\">Let\u2019s Encrypt<\/a>. Projects like <a href=\"https:\/\/caddyserver.com\/\">Caddy Server<\/a> showed the tremendous ease-of-use that could be attained, so for this project we sought to patch-in such automation to a mainstay web server: Nginx.<\/p>\n<p>The goal of the project is to build a module for a web server to make securing your web site even easier. Instead of configuring the web server, getting the certificate (e.g. with the <a href=\"https:\/\/certbot.eff.org\/\">Let\u2019s Encrypt Certbot<\/a>) and installing the certificate on the web server, you just need to configure your web server. The rest of the work is done by the built-in ACME module in the web server.<\/p>\n<h2>Nginx<\/h2>\n<p>This project didn\u2019t specify which particular web server we should develop on. We evaluated several, including Apache, Nginx, and Stunnel. Since the goal is to help as many people as possible in securing their web sites we narrowed to the two most widely-used: Nginx and Apache. Ultimately, we decided to work with Nginx since it has a younger code base to develop with.<\/p>\n<p>Nginx has a module system with different types of modules for different purposes. There are load-balancer modules which pass the traffic to multiple backend servers, filter modules which convert the data of a website (for example encrypt it like the SSL\/TLS module) and handler modules which create the content of a web request (e.g. the http handler loads the html file from the disk and serves it). In addition to their purpose the module types also differ in how they hook into the server core, which makes the choice crucial when you start to implement a Nginx module. In our case none of the types were suitable, which introduced some difficulties, discussed later.<\/p>\n<h2>The ACME module<\/h2>\n<p>The Nginx module should be a replacement of the traditional workflow involving the ACME Certbot. Therefore the features of the module should resemble the features of the Certbot. This includes:<\/p>\n<ul>\n<li>Generate and store a key-pair<\/li>\n<li>Register an account on an ACME server<\/li>\n<li>Create an authorization for a domain<\/li>\n<li>Solve the HTTP challenge for the domain authorization\n<ul>\n<li>At a later date, support the other challenge types<\/li>\n<\/ul>\n<\/li>\n<li>Retrieve the certificate from the ACME server<\/li>\n<li>Renew a certificate<\/li>\n<li>Configure the Nginx SSL\/TLS module to use the certificate<\/li>\n<\/ul>\n<p>To provide the necessary information for all the steps in the ACME protocol, we introduced new Nginx configuration directives:<\/p>\n<ul>\n<li>A directive to activate the module<\/li>\n<li>Directive(s) for the recovery contact of the ACME account (optional)\n<ul>\n<li>An array of URIs like \u201cmailto:\u201d or \u201ctel:\u201d<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Everything else is gathered from the default Nginx directives. For example, the domain for which the certificate is issued is taken from the Nginx configuration directive \u201cserver_name\u201d.<\/p>\n<div id=\"attachment_2098\" style=\"width: 490px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.mozilla.org\/security\/files\/2016\/08\/Untitled-drawing.png\"><img aria-describedby=\"caption-attachment-2098\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-2098 size-full\" src=\"https:\/\/blog.mozilla.org\/security\/files\/2016\/08\/Untitled-drawing.png\" alt=\"An architecture diagram showing the different resources available to Nginx, and their relationships with the ACME module developed, as well as the ACME server: Let's Encrypt.\" width=\"480\" height=\"493\" srcset=\"https:\/\/blog.mozilla.org\/security\/files\/2016\/08\/Untitled-drawing.png 480w, https:\/\/blog.mozilla.org\/security\/files\/2016\/08\/Untitled-drawing-252x259.png 252w, https:\/\/blog.mozilla.org\/security\/files\/2016\/08\/Untitled-drawing-32x32.png 32w, https:\/\/blog.mozilla.org\/security\/files\/2016\/08\/Untitled-drawing-50x50.png 50w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><\/a><p id=\"caption-attachment-2098\" class=\"wp-caption-text\">Architecture of the ACME Module for Nginx<\/p><\/div>\n<p>As the ACME module is an extension of the Nginx server itself, it\u2019s a part of the software and therefore uses the Nginx config file for its own configuration and stores the certificates in the Nginx config directory. The ACME module communicates with the ACME server (e.g. Let\u2019s Encrypt, but it could be any other server speaking the ACME protocol) for gathering the certificate, then configures the SSL\/TLS module to use this certificate. The SSL\/TLS module then does the encryption work for the website\u2019s communication to the end user\u2019s browser.<\/p>\n<p>Let\u2019s look at the workflow of setting up a secure website. In a world without ACME, anyone who wanted to setup an encrypted website had to:<\/p>\n<ol>\n<li>Create a CSR (certificate signing request) with all the information needed<\/li>\n<li>Send the CSR over to a CA (certificate authority)<\/li>\n<li>Pay the CA for getting a signed certificate<\/li>\n<li>Wait for their reply containing the certificate (this could take hours)<\/li>\n<li>Download the certificate and put it in the right place on the server<\/li>\n<li>Configure the server to use the certificate<\/li>\n<\/ol>\n<p>With the ACME protocol and the Let\u2019s Encrypt CA you just have to:<\/p>\n<ol>\n<li>Install an ACME client<\/li>\n<li>Use the ACME client to:\n<ol>\n<li>Enter all your information for the certificate<\/li>\n<li>Get a certificate<\/li>\n<li>Automatically configure the server<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>That\u2019s already a huge improvement, but with the ACME module for Nginx it\u2019s even more simple. You just have to:<\/p>\n<ol>\n<li>Activate the ACME module in the server\u2019s configuration<\/li>\n<\/ol>\n<p>Pretty much everything else is handled by the ACME module. So it does all the steps the Let\u2019s Encrypt client does, but fully automated during the server startup. This is how easy it can and should be to encourage website admins to secure their sites.<\/p>\n<p>The minimal configuration work for the ACME module is to just add the \u201cacme\u201d directive to the server context in the Nginx config for which you would like to activate it. For example:<\/p>\n<pre>\u2026\r\nhttp {\r\n\u2026\r\n  server {\r\n    listen 443 ssl;\r\n    server_name example.com;\r\n    acme;\r\n    \u2026\r\n    &lt;recommended SSL hardening config directives&gt;\r\n    \u2026\r\n    location \/ {\r\n      \u2026\r\n    }\r\n  }\r\n}\r\n\u2026\r\n<\/pre>\n<h2>Experienced challenges<\/h2>\n<p>Designing and developing the ACME module was quite challenging.<\/p>\n<p>As mentioned earlier, there are different types of modules which enhance different portions of the Nginx core server. The default Nginx module types are: handler modules (which create content on their own), filter modules (which convert website data &#8211; like the SSL\/TLS module does) and load-balancer modules (which route requests to backend servers). Unfortunately, the ACME module and its inherent workflow does not fit any of these types. Our module breaks these conventions: it has its own configuration directives, and requires hooks into both the core and other modules. Nginx\u2019s module system was not designed to accommodate our module\u2019s needs, therefore we had a very limited choice on <i>when<\/i> we could perform the ACME protocol communication.<\/p>\n<p>The ACME module serves to configure the existing SSL\/TLS module, which performs the actual encryption of the website. Our module needs to control the SSL\/TLS module to some degree in order to provide the ACME-retrieved encryption certificates. Unfortunately, the SSL\/TLS module does a check for the existence and the validity of the certificates during the Nginx configuration parsing phase while the server is starting. This means the ACME module must complete its tasks before the configuration is parsed. Our decision, due to those limitations, was to handle all the certificate gathering at the time when the &#8220;acme&#8221; configuration directive is parsed in the configuration during server startup. After getting the certificates, the ACME module then updates the in-memory configuration of the SSL\/TLS module to use those new certificates.<\/p>\n<p>Another architectural problem arose when implementing the ACME HTTP challenge-response. \u00a0To authorize a domain using the ACME HTTP challenge, the server needs to respond with a particular token at a well known URL path in its domain. Basically, it must publish this token like \u00a0a web server publishes any other site. Unfortunately, at the time the ACME module is processing, Nginx has not yet started: There\u2019s no web server. If the ACME module exits, permitting web server functions to begin (and keeping in mind the SSL\/TLS module certificate limitations from before), there\u2019s no simple mechanism to resume the ACME functions later. Architecturally, this makes sense for Nginx, but it is inconvenient for this project. Faced with this dilemma, for the purposes of this proof-of-concept, we decided to launch an independent, tiny web server to service the ACME challenge before Nginx itself properly starts.<\/p>\n<h2>Conclusion<\/h2>\n<p>As discussed, the limitations of a Nginx module prompted some suboptimal architectural design decisions. As in many software projects, the problem is that we want something from the underlying framework which it wasn\u2019t designed to do. The current architectural design of the ACME module should be considered a proof-of-concept.<\/p>\n<p>There are potential changes that would improve the architecture of the module and the communication between the Nginx core, the SSL\/TLS module and the ACME module. These changes, of course, have pros and cons which merit discussion.<\/p>\n<p>One change would be deferring the retrieval of the certificate to a time after the configuration is parsed. This would require spoofing the SSL\/TLS module with a temporary certificate until the newly retrieved certificate is ready. This is a corner-case issue that arises just for the first server start when there is no previously retrieved certificate already stored.<\/p>\n<p>Another change is the challenge-response: A web server inside a web server (whether with a third party library or not) is not clean. Therefore perhaps the TLS-SNI or another challenge type in the ACME protocol could be more suitable, or perhaps there is some method to start Nginx while still permitting the module to continue work.<\/p>\n<p>Finally, the communication to the SSL\/TLS module is very hacky.<\/p>\n<h2>Current status of the project &amp; future plans<\/h2>\n<p>The current status of the module can be roughly described as a proof-of-concept in a late development stage. The module creates an ephemeral key-pair, registers with the ACME server, requests the authentication challenge for the domain and starts to answer the challenge. As the proof of concept isn\u2019t finished yet, we intend to carry on with the project.<\/p>\n<h2>Many thanks<\/h2>\n<p>This project was an exciting opportunity to help realize the vision of securing the whole web. Personally, I\u2019d like to give special thanks to J.C. Jones and Richard Barnes from the Mozilla Security Engineering Team who accompanied and supported me during the project. Also special thanks to Martin Schmiedecker, my professor and mentor at SBA Research at the Vienna University of Technology, Austria. Of course I also want to thank the whole Mozilla organization for holding the Mozilla Winter of Security and enabling students around the world to participate in some great IT projects. Last but not least, many thanks to the Let\u2019s Encrypt project for allowing me to participate and play a tiny part in such a great security project.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Mozilla Winter of Security of 2015 has ended, and the participating teams of students are completing their projects. The Certificate Automation tooling for Let&#8217;s Encrypt project wrapped up this &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/\">Read more<\/a><\/p>\n","protected":false},"author":1349,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[69,45499],"tags":[45506,650,45501,45499],"coauthors":[45540],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>MWoS 2015: Let\u2019s Encrypt Automation Tooling - Mozilla Security Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"J.C. Jones\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/\",\"url\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/\",\"name\":\"MWoS 2015: Let\u2019s Encrypt Automation Tooling - Mozilla Security Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/security\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2-252x331.png\",\"datePublished\":\"2016-08-08T15:16:05+00:00\",\"dateModified\":\"2016-09-30T09:46:21+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/security\/#\/schema\/person\/f2bfcea9a0c404ce2431925922bedbde\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#primaryimage\",\"url\":\"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2.png\",\"contentUrl\":\"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2.png\",\"width\":1716,\"height\":2252},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/security\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"MWoS 2015: Let\u2019s Encrypt Automation Tooling\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.mozilla.org\/security\/#website\",\"url\":\"https:\/\/blog.mozilla.org\/security\/\",\"name\":\"Mozilla Security Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.mozilla.org\/security\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.mozilla.org\/security\/#\/schema\/person\/f2bfcea9a0c404ce2431925922bedbde\",\"name\":\"J.C. Jones\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/security\/#\/schema\/person\/image\/d063fc46e7671301c178b2781210dff7\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/64eb1412c9354cf356df31936368cdac?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/64eb1412c9354cf356df31936368cdac?s=96&d=identicon&r=g\",\"caption\":\"J.C. Jones\"},\"description\":\"Keeping people safe on the 'net. Cryptography Engineering lead for Firefox.\",\"sameAs\":[\"https:\/\/tacticalsecret.com\/\",\"https:\/\/x.com\/JamesPugJones\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MWoS 2015: Let\u2019s Encrypt Automation Tooling - Mozilla Security Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/","twitter_misc":{"Written by":"J.C. Jones","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/","url":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/","name":"MWoS 2015: Let\u2019s Encrypt Automation Tooling - Mozilla Security Blog","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/security\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#primaryimage"},"image":{"@id":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2-252x331.png","datePublished":"2016-08-08T15:16:05+00:00","dateModified":"2016-09-30T09:46:21+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/security\/#\/schema\/person\/f2bfcea9a0c404ce2431925922bedbde"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#primaryimage","url":"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2.png","contentUrl":"https:\/\/blog.mozilla.org\/security\/files\/2015\/03\/winterOfSecurity_logo_dark_vertical2.png","width":1716,"height":2252},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/security\/2016\/08\/08\/mwos-2015-lets-encrypt-automation-tooling\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/security\/"},{"@type":"ListItem","position":2,"name":"MWoS 2015: Let\u2019s Encrypt Automation Tooling"}]},{"@type":"WebSite","@id":"https:\/\/blog.mozilla.org\/security\/#website","url":"https:\/\/blog.mozilla.org\/security\/","name":"Mozilla Security Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.mozilla.org\/security\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.mozilla.org\/security\/#\/schema\/person\/f2bfcea9a0c404ce2431925922bedbde","name":"J.C. Jones","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/security\/#\/schema\/person\/image\/d063fc46e7671301c178b2781210dff7","url":"https:\/\/secure.gravatar.com\/avatar\/64eb1412c9354cf356df31936368cdac?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/64eb1412c9354cf356df31936368cdac?s=96&d=identicon&r=g","caption":"J.C. Jones"},"description":"Keeping people safe on the 'net. Cryptography Engineering lead for Firefox.","sameAs":["https:\/\/tacticalsecret.com\/","https:\/\/x.com\/JamesPugJones"]}]}},"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/posts\/2097"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/users\/1349"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/comments?post=2097"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/posts\/2097\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/media?parent=2097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/categories?post=2097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/tags?post=2097"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mozilla.org\/security\/wp-json\/wp\/v2\/coauthors?post=2097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}