<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Geoffroy Couprie, Author at Clever Cloud</title>
	<atom:link href="https://stagingv6.cleverapps.io/blog/author/geoffroy-couprieclever-cloud-com/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>From Code to Product</description>
	<lastBuildDate>Mon, 02 Oct 2023 14:33:25 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>Geoffroy Couprie, Author at Clever Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Biscuit tutorial</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2021/04/15/biscuit-tutorial/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Thu, 15 Apr 2021 11:25:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authorization]]></category>
		<category><![CDATA[biscuit]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2021/04/15/biscuit-tutorial/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" fetchpriority="high" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>In the <a href="https://stagingv6.cleverapps.io/blog/engineering/2021/04/12/introduction-to-biscuit/">previous article</a>, I introduced Biscuit, our authentication and authorization token, and mentioned its Datalog based language for authorization policies. Let&#39;s see how it works!</p>
<span id="more-2833"></span>

<h2 id="from-a-personal-blog-to-an-entire-newspaper">From a personal blog to an entire newspaper</h2>
<p>As an example, we will build up authorization policies, going from a small, personal blog, to a professional journal with multiple teams, editors, etc.</p>
<p>Since those policies will be written in Datalog, let&#39;s take a short look at that language first.</p>
<h3 id="side-note-introduction-to-datalog">Side note: introduction to Datalog</h3>
<p>Datalog is a declarative logic language that is a subset of Prolog. A Datalog program contains &quot;facts&quot;, which represent data, and &quot;rules&quot;, which can generate new facts from existing ones.</p>
<p>As an example, we could define the following facts, describing some relationships:</p>
<pre><code class="language-prolog">parent(&quot;Alice&quot;, &quot;Bob&quot;);
parent(&quot;Bob&quot;, &quot;Charles&quot;);
parent(&quot;Charles&quot;, &quot;Denise&quot;);
</code></pre>
<p>This means that Alice is Bob&#39;s parent, and so on.</p>
<p>This could be seen as a table in a relational database:</p>
<table class="table">
<thead>
<tr>
<th>parent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Bob</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Charles</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>We can then define rules to query our data:</p>
<pre><code class="language-prolog">parent_of_charles($name) &lt;-
  parent($name, &quot;Charles&quot;);
</code></pre>
<p>This could be written in SQL as:</p>
<pre><code class="language-sql">SELECT DISTINCT name from parent where child = &quot;Charles&quot;;
</code></pre>
<p>(we use <code>DISTINCT</code> because Datalog will always remove redundant results)</p>
<p>We can also use rules to create new facts, like this one: (variables are introduced with the <code>$</code> sign)</p>
<pre><code class="language-prolog">grandparent($grandparent, $child) &lt;-
  parent($grandparent, $parent),
  parent($parent, $child);
</code></pre>
<p>You can read it as follows:</p>
<pre><code class="language-text">create the fact grandparent($grandparent, $child)
  IF
    there is a fact parent($grandparent, $parent)
    AND there is a fact parent($parent, $child)
    with matching $parent variable
</code></pre>
<p>or in SQL:</p>
<pre><code class="language-sql">INSERT INTO grandparent( name, grandchild )
  SELECT A.name as name, B.child as grandchild
  FROM parent A, parent B
  WHERE A.child = B.name;
</code></pre>
<p>Applying this rule will look at combinations of the <code>parent</code> facts as defined on the right side of the arrow (the &quot;body&quot; of the rule), and try to match them to the variables (<code>$grandparent</code>, <code>$parent</code>, <code>$child</code>):</p>
<ul>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code> matches because we can
replace <code>$grandparent</code> with <code>&quot;Alice&quot;</code>, <code>$parent</code> with <code>&quot;Bob&quot;</code>, <code>$child</code> with <code>&quot;Charles&quot;</code></li>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Charles&quot;, &quot;Denise&quot;)</code> does not match because
we would get different values for the <code>$parent</code> variable</li>
</ul>
<p>For each matching combination of facts in the body, we will then generate a fact, as defined on the left side of the arrow, the <em>head</em> of the rule. For <code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code>, we would generate <code>grandparent(&quot;Alice&quot;, &quot;Charles&quot;)</code>. A fact can be generated from multiple rules, but we will get only one instance of it.</p>
<p>Going through all the combinations, we will generate:</p>
<pre><code class="language-prolog">grandparent(&quot;Alice&quot;, &quot;Charles&quot;);
grandparent(&quot;Bob&quot;, &quot;Denise&quot;);
</code></pre>
<p>which can be seen as:</p>
<table class="table">
<thead>
<tr>
<th>grandparent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>Interactions with a Datalog program are done through queries: <strong>a query contains a rule</strong> that we apply over the system, and <strong>it returns the generated facts</strong>.</p>
<h3 id="first-steps-personal-blog">First steps: personal blog</h3>
<p>*note: you can follow along the various steps of this tutorial in the <a href="https://play-with-biscuit.cleverapps.io/blog.html">online playground</a>.</p>
<p>When we are the only user of that blog, we do not need much (honestly we could get away with just a random string in a cookie, but bear with me). We only need a way to identify ourselves to the blog engine&#39;s admin panel. So we could just consider the Biscuit token as a fancy JWT, that will only contain data (so, in Datalog, facts).</p>
<p>Our token will contain this fact: <code>user(#authority, &quot;user_1234&quot;)</code>.</p>
<p>Here, <code>&quot;user_1234&quot;</code> is our user id, and <code>#authority</code> is a special symbol that can only be added to facts in the first block of a token (or added by the verifier). A block contains facts (data), rules (to generate facts) and checks (queries used to validate the facts). Attenuation is done by adding more blocks. Since <code>#authority</code> facts are about the basic rights of a token, adding <code>#authority</code> facts would increase the number of rights. So we forbid adding <code>#authority</code> facts in additional blocks. Symbols, as indicated by the <code>#</code> prefix, are special strings that are internally replaced with integers, to compress tokens and accelerate evaluation.</p>
<p>The token can be serialized to a byte array (encoded with Protobuf) and then to base64 if we want to carry it in a cookie.</p>
<p>On the blog engine&#39;s side, we will only have this single line:</p>
<pre><code class="language-prolog">allow if user(#authority, &quot;user_1234&quot;);
</code></pre>
<p>Biscuit can enforce authorization in 2 ways:</p>
<ul>
<li>checks, starting with <code>check if</code></li>
<li>allow/deny policies, starting with <code>allow if</code> or <code>deny if</code></li>
</ul>
<p>They work a bit like rules: if there&#39;s at least one combination of fact in the body (after the <code>if</code>) that fits, then it matches. They will not produce any fact.</p>
<p>To validate a token:</p>
<ul>
<li>all of the checks must match. If one does not, fail</li>
<li>allow/deny policies are tried in order until one matches<ul>
<li>if allow matches, succeed</li>
<li>if deny matches, fail</li>
</ul>
</li>
<li>if none match, fail</li>
</ul>
<p>Here the allow test will succeed if the token contains the fact <code>user(#authority, &quot;user_1234&quot;)</code></p>
<p>It is not very useful yet, but maybe we can add more features?</p>
<h3 id="next-multi-blog-platform">Next: multi-blog platform</h3>
<p>After a few friends have seen your marvelous website, they ask if you could host their blogs on the same platform. So now you need more flexible authorization rules. We could keep the small tokens with the user id, but add more intelligence on the server&#39;s side.</p>
<p>First we need to indicate who owns which blog, with the format <code>owner(#authority, $user_id, $blog_id)</code>. You can load this data when creating the verifier, from your database, from static files, etc.</p>
<pre><code class="language-prolog">owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>Here we own <code>&quot;blog1&quot;</code> and <code>&quot;blog3&quot;</code>, and <code>&quot;user_5678&quot;</code> owns <code>&quot;blog2&quot;</code>.</p>
<p>Now we need to actually validate the request, to see who has access to what. The request is represented through the <code>#ambient</code> facts, added to the verifier: you indicate to the verifier facts representing the current request like which resource is accessed, which operation (read, write, etc), the current time, the source IP address, etc. As an example, a <code>PUT /blog1/article1</code> to modify an article could be translated as:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
</code></pre>
<p>In the verifier, we add a rule to indicate that the owner of a blog has full rights on it:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);
</code></pre>
<p>If this rules finds a matching set of facts, it will produce a <code>right(...)</code> fact.</p>
<p>The verifier will also use an allow policy for the presence of that <code>right</code> (you will see why we separate them in the next section):</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);

// unauthenticated users have read access
allow if
  operation(#ambient, #read);

// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>So if we tried to do a <code>PUT /blog1/article1</code> with the token containing <code>user(#authority, &quot;user_1234&quot;)</code>, we would end up with the following facts:</p>
<pre><code class="language-prolog">user(#authority, &quot;user_1234&quot;);
blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>If we applied the verifier&#39;s rule, we would end up with:</p>
<pre><code class="language-prolog">right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update) &lt;-
    owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;),
    article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
    user(#authority, &quot;user_1234&quot;),
    operation(#ambient, #update);
</code></pre>
<p>So we end up with the new fact <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update)</code>.</p>
<p>Now the verifier applies the check:</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, &quot;blog1&quot;),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  operation(#ambient, #update),
  right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update);
</code></pre>
<p>And the test succeeds! If we had tried the request with a token containing <code>user(#authority, &quot;user_5678&quot;)</code>, the rule would not have produced the <code>right()</code> fact, and it would have failed.</p>
<p>Now if we did a <code>GET /blog1/article1</code> request, without being the owner of the blog, we would have matched <code>allow if operation(#ambient, #read)</code>.</p>
<p>But maybe we don&#39;t want to have all articles available by default, maybe some of them are still in writing, so let&#39;s remove that allow policy. We want to mark an article as publicly readable by creating the fact <code>readable(#authority, $blog_id, $article_id)</code>. We can do that with this test:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);
</code></pre>
<p>So if we did a <code>GET /blog1/article1</code> request with that article marked as readable, we would get the facts:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #read);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>The test would apply as follows:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>And we got access. In a few lines, we created basic rules to protect our blog platform. But users need more features!</p>
<h3 id="add-reviewers">add reviewers</h3>
<p>Often, we&#39;d like to ask friends and colleagues to review articles before they are published. In our system, it could be done in two ways:</p>
<ul>
<li>mint a token containing only <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #read)</code></li>
<li>derive the user&#39;s token, adding a check restricting to the article</li>
</ul>
<p>In the second case, the token would look like this:</p>
<pre><code class="language-text">Block 0 (authority):
  facts: [ user(#authority, &quot;user_1234&quot;) ]
  rules: []
  checks: []

Block 1:
  facts: []
  rules: []
  check: [
    check if article(#ambient, &quot;blog1&quot;, &quot;article1&quot;), operation(#ambient, #read)
  ]
</code></pre>
<p>if we tried to do a <code>PUT /blog1/article1</code>, the verifier&#39;s checks would succeed, but the token&#39;s check would fail, because it does not find the <code>operation(#ambient, #read)</code> fact. But for a <code>GET /blog1/article1</code>, all checks would succeed. The reviewer will not be able to remove the block while keeping a valid signature, so any alteration will result in a failed request.</p>
<h3 id="premium-accounts">premium accounts</h3>
<p>Now some of the blog authors want to make living out of it (come on, it&#39;s 2021, do a newsletter instead) and mark some articles as &quot;premium&quot;, so that only some users can access them.</p>
<p>We can do that by having <code>premium_user(#authority, $user_id, $blog_id)</code> facts and adding a rule on the verifier&#39;s side:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);
</code></pre>
<p>We could even add a feature like <a href="https://lwn.net/">LWN.net</a> where a paying user can share a premium article, by deriving their tokens to only accept that article.</p>
<h3 id="were-a-big-newspaper-now-we-want-roles-and-teams">We&#39;re a big newspaper now, we want roles and teams</h3>
<p>Againt all odds, our blog platform is a smashing success. We need to recruit journalists, editors, copywriters... So now we might need more flexible rights management, maybe some teams and roles?</p>
<p>Let&#39;s define more facts and rules to encode that. As an example, let&#39;s define a &quot;contributor&quot; role that can only read or write articles, while owners are the only ones who can create or delete.</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  contributor(#authority, $user_id, $blog_id),
  [#read, #update].contains($operation);
</code></pre>
<p>What you can see on the last line is an <em>expression</em>: Biscuit&#39;s Datalog implementation can require additional conditions on some values, like a string matching a regular expression, or a date being lower than an expiration date, or here, presence in a set. This rule will only produce if the operation is <code>#read</code> or <code>#update</code>.</p>
<p>Now, we want to define contributor teams to manage them more easily. So we will introduce the <code>team(#authority, $team_id)</code>, <code>member(#authority, $user_id, $team_id)</code> and <code>team_role(#authority, $team_id, $blog_id, #contributor)</code> facts.</p>
<p>Additionally, we insert this rule in the verifier:</p>
<pre><code class="language-prolog">contributor(#authority, $user_id, $blog_id) &lt;-
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor);
</code></pre>
<p>This rule will generate the <code>contributor</code> fact for a blog if we are member of a team that has the &quot;contributor&quot; team role.</p>
<p>We could also fold the two precedent rules in one:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);
</code></pre>
<p>And that&#39;s it! With a few rules, we can model more and more complex authorization patterns, some of them relying on user provided policies, without compromising the previous features. Rules are additive, so there&#39;s no need for a long chain of if/else and special cases hardcoded in some endpoints. Everything can be managed in one place.</p>
<p>To sum up the rules of our system:</p>
<pre><code class="language-prolog">// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>And here is an example Rust program reproducing this authorization system:</p>
<pre><code class="language-rust">use biscuit::{crypto::KeyPair, error, token::Biscuit, parser::parse_source};
use biscuit_auth as biscuit;

fn main() -&gt; Result&lt;(), error::Token&gt; {
    let start = std::time::Instant::now();

    // First, let&#39;s create the root key for the system
    // its public part will be used to verify the token
    let mut rng = rand::thread_rng();
    let root = KeyPair::new();

    // Token creation
    // we will add a single fact indicating identity
    let mut builder = Biscuit::builder(&amp;root);
    builder.add_authority_fact(&quot;user(#authority, \&quot;user_1234\&quot;)&quot;)?;

    let token = builder.build()?;
    println!(&quot;{}&quot;, token.print());
    let token_bytes = token.to_vec()?;
    let serialized = base64::encode_config(&amp;token_bytes, base64::URL_SAFE);
    println!(&quot;serialized ({} bytes): {}&quot;, token_bytes.len(), serialized);

    let deserialized_token = Biscuit::from(&amp;token_bytes)?;
    // Token verification
    // first, we validate the signature with the root public key
    let mut verifier = deserialized_token.verify(root.public())?;

    // simulate verification for PUT /blog1/article1
    verifier.add_fact(&quot;blog(#ambient, \&quot;blog1\&quot;)&quot;)?;
    verifier.add_fact(&quot;article(#ambient, \&quot;blog1\&quot;, \&quot;article1\&quot;)&quot;)?;
    verifier.add_fact(&quot;operation(#ambient, #update)&quot;)?;

    // add ownership information
    // we only need to load facts related to the blog and article we&#39;re accessing
    verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog1\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_5678\&quot;, \&quot;blog2\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog3\&quot;)&quot;)?;

    let (_remaining_input, mut policies) = parse_source(&quot;
// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $usr_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
    &quot;).unwrap();

    for (_span, fact) in policies.facts.drain(..) {
        verifier.add_fact(fact)?;
    }

    for (_span, rule) in policies.rules.drain(..) {
        verifier.add_rule(rule)?;
    }

    for (_span, check) in policies.checks.drain(..) {
        verifier.add_check(check)?;
    }

    for (_span, policy) in policies.policies.drain(..) {
        verifier.add_policy(policy)?;
    }

    let res = verifier.verify()?;
    let dur = std::time::Instant::now() - start;
    //println!(&quot;res: {:?}&quot;, res);
    println!(&quot;{}&quot;, verifier.print_world());

    println!(&quot;ran in {:?}&quot;, dur);
    Ok(())
}
</code></pre>
<p>The entire program (key generation, token creation, serialization, deserialization, signature validation and facts verification) <strong>runs in 0.5 ms</strong>. So even with all of these features, Biscuit is fast enough to get out of your way.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>You can already start using Biscuit in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<script>
$("table").addClass("table-bordered");
</script>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>In the <a href="https://stagingv6.cleverapps.io/blog/engineering/2021/04/12/introduction-to-biscuit/">previous article</a>, I introduced Biscuit, our authentication and authorization token, and mentioned its Datalog based language for authorization policies. Let&#39;s see how it works!</p>
<span id="more-2833"></span>

<h2 id="from-a-personal-blog-to-an-entire-newspaper">From a personal blog to an entire newspaper</h2>
<p>As an example, we will build up authorization policies, going from a small, personal blog, to a professional journal with multiple teams, editors, etc.</p>
<p>Since those policies will be written in Datalog, let&#39;s take a short look at that language first.</p>
<h3 id="side-note-introduction-to-datalog">Side note: introduction to Datalog</h3>
<p>Datalog is a declarative logic language that is a subset of Prolog. A Datalog program contains &quot;facts&quot;, which represent data, and &quot;rules&quot;, which can generate new facts from existing ones.</p>
<p>As an example, we could define the following facts, describing some relationships:</p>
<pre><code class="language-prolog">parent(&quot;Alice&quot;, &quot;Bob&quot;);
parent(&quot;Bob&quot;, &quot;Charles&quot;);
parent(&quot;Charles&quot;, &quot;Denise&quot;);
</code></pre>
<p>This means that Alice is Bob&#39;s parent, and so on.</p>
<p>This could be seen as a table in a relational database:</p>
<table class="table">
<thead>
<tr>
<th>parent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Bob</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Charles</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>We can then define rules to query our data:</p>
<pre><code class="language-prolog">parent_of_charles($name) &lt;-
  parent($name, &quot;Charles&quot;);
</code></pre>
<p>This could be written in SQL as:</p>
<pre><code class="language-sql">SELECT DISTINCT name from parent where child = &quot;Charles&quot;;
</code></pre>
<p>(we use <code>DISTINCT</code> because Datalog will always remove redundant results)</p>
<p>We can also use rules to create new facts, like this one: (variables are introduced with the <code>$</code> sign)</p>
<pre><code class="language-prolog">grandparent($grandparent, $child) &lt;-
  parent($grandparent, $parent),
  parent($parent, $child);
</code></pre>
<p>You can read it as follows:</p>
<pre><code class="language-text">create the fact grandparent($grandparent, $child)
  IF
    there is a fact parent($grandparent, $parent)
    AND there is a fact parent($parent, $child)
    with matching $parent variable
</code></pre>
<p>or in SQL:</p>
<pre><code class="language-sql">INSERT INTO grandparent( name, grandchild )
  SELECT A.name as name, B.child as grandchild
  FROM parent A, parent B
  WHERE A.child = B.name;
</code></pre>
<p>Applying this rule will look at combinations of the <code>parent</code> facts as defined on the right side of the arrow (the &quot;body&quot; of the rule), and try to match them to the variables (<code>$grandparent</code>, <code>$parent</code>, <code>$child</code>):</p>
<ul>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code> matches because we can
replace <code>$grandparent</code> with <code>&quot;Alice&quot;</code>, <code>$parent</code> with <code>&quot;Bob&quot;</code>, <code>$child</code> with <code>&quot;Charles&quot;</code></li>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Charles&quot;, &quot;Denise&quot;)</code> does not match because
we would get different values for the <code>$parent</code> variable</li>
</ul>
<p>For each matching combination of facts in the body, we will then generate a fact, as defined on the left side of the arrow, the <em>head</em> of the rule. For <code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code>, we would generate <code>grandparent(&quot;Alice&quot;, &quot;Charles&quot;)</code>. A fact can be generated from multiple rules, but we will get only one instance of it.</p>
<p>Going through all the combinations, we will generate:</p>
<pre><code class="language-prolog">grandparent(&quot;Alice&quot;, &quot;Charles&quot;);
grandparent(&quot;Bob&quot;, &quot;Denise&quot;);
</code></pre>
<p>which can be seen as:</p>
<table class="table">
<thead>
<tr>
<th>grandparent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>Interactions with a Datalog program are done through queries: <strong>a query contains a rule</strong> that we apply over the system, and <strong>it returns the generated facts</strong>.</p>
<h3 id="first-steps-personal-blog">First steps: personal blog</h3>
<p>*note: you can follow along the various steps of this tutorial in the <a href="https://play-with-biscuit.cleverapps.io/blog.html">online playground</a>.</p>
<p>When we are the only user of that blog, we do not need much (honestly we could get away with just a random string in a cookie, but bear with me). We only need a way to identify ourselves to the blog engine&#39;s admin panel. So we could just consider the Biscuit token as a fancy JWT, that will only contain data (so, in Datalog, facts).</p>
<p>Our token will contain this fact: <code>user(#authority, &quot;user_1234&quot;)</code>.</p>
<p>Here, <code>&quot;user_1234&quot;</code> is our user id, and <code>#authority</code> is a special symbol that can only be added to facts in the first block of a token (or added by the verifier). A block contains facts (data), rules (to generate facts) and checks (queries used to validate the facts). Attenuation is done by adding more blocks. Since <code>#authority</code> facts are about the basic rights of a token, adding <code>#authority</code> facts would increase the number of rights. So we forbid adding <code>#authority</code> facts in additional blocks. Symbols, as indicated by the <code>#</code> prefix, are special strings that are internally replaced with integers, to compress tokens and accelerate evaluation.</p>
<p>The token can be serialized to a byte array (encoded with Protobuf) and then to base64 if we want to carry it in a cookie.</p>
<p>On the blog engine&#39;s side, we will only have this single line:</p>
<pre><code class="language-prolog">allow if user(#authority, &quot;user_1234&quot;);
</code></pre>
<p>Biscuit can enforce authorization in 2 ways:</p>
<ul>
<li>checks, starting with <code>check if</code></li>
<li>allow/deny policies, starting with <code>allow if</code> or <code>deny if</code></li>
</ul>
<p>They work a bit like rules: if there&#39;s at least one combination of fact in the body (after the <code>if</code>) that fits, then it matches. They will not produce any fact.</p>
<p>To validate a token:</p>
<ul>
<li>all of the checks must match. If one does not, fail</li>
<li>allow/deny policies are tried in order until one matches<ul>
<li>if allow matches, succeed</li>
<li>if deny matches, fail</li>
</ul>
</li>
<li>if none match, fail</li>
</ul>
<p>Here the allow test will succeed if the token contains the fact <code>user(#authority, &quot;user_1234&quot;)</code></p>
<p>It is not very useful yet, but maybe we can add more features?</p>
<h3 id="next-multi-blog-platform">Next: multi-blog platform</h3>
<p>After a few friends have seen your marvelous website, they ask if you could host their blogs on the same platform. So now you need more flexible authorization rules. We could keep the small tokens with the user id, but add more intelligence on the server&#39;s side.</p>
<p>First we need to indicate who owns which blog, with the format <code>owner(#authority, $user_id, $blog_id)</code>. You can load this data when creating the verifier, from your database, from static files, etc.</p>
<pre><code class="language-prolog">owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>Here we own <code>&quot;blog1&quot;</code> and <code>&quot;blog3&quot;</code>, and <code>&quot;user_5678&quot;</code> owns <code>&quot;blog2&quot;</code>.</p>
<p>Now we need to actually validate the request, to see who has access to what. The request is represented through the <code>#ambient</code> facts, added to the verifier: you indicate to the verifier facts representing the current request like which resource is accessed, which operation (read, write, etc), the current time, the source IP address, etc. As an example, a <code>PUT /blog1/article1</code> to modify an article could be translated as:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
</code></pre>
<p>In the verifier, we add a rule to indicate that the owner of a blog has full rights on it:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);
</code></pre>
<p>If this rules finds a matching set of facts, it will produce a <code>right(...)</code> fact.</p>
<p>The verifier will also use an allow policy for the presence of that <code>right</code> (you will see why we separate them in the next section):</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);

// unauthenticated users have read access
allow if
  operation(#ambient, #read);

// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>So if we tried to do a <code>PUT /blog1/article1</code> with the token containing <code>user(#authority, &quot;user_1234&quot;)</code>, we would end up with the following facts:</p>
<pre><code class="language-prolog">user(#authority, &quot;user_1234&quot;);
blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>If we applied the verifier&#39;s rule, we would end up with:</p>
<pre><code class="language-prolog">right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update) &lt;-
    owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;),
    article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
    user(#authority, &quot;user_1234&quot;),
    operation(#ambient, #update);
</code></pre>
<p>So we end up with the new fact <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update)</code>.</p>
<p>Now the verifier applies the check:</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, &quot;blog1&quot;),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  operation(#ambient, #update),
  right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update);
</code></pre>
<p>And the test succeeds! If we had tried the request with a token containing <code>user(#authority, &quot;user_5678&quot;)</code>, the rule would not have produced the <code>right()</code> fact, and it would have failed.</p>
<p>Now if we did a <code>GET /blog1/article1</code> request, without being the owner of the blog, we would have matched <code>allow if operation(#ambient, #read)</code>.</p>
<p>But maybe we don&#39;t want to have all articles available by default, maybe some of them are still in writing, so let&#39;s remove that allow policy. We want to mark an article as publicly readable by creating the fact <code>readable(#authority, $blog_id, $article_id)</code>. We can do that with this test:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);
</code></pre>
<p>So if we did a <code>GET /blog1/article1</code> request with that article marked as readable, we would get the facts:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #read);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>The test would apply as follows:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>And we got access. In a few lines, we created basic rules to protect our blog platform. But users need more features!</p>
<h3 id="add-reviewers">add reviewers</h3>
<p>Often, we&#39;d like to ask friends and colleagues to review articles before they are published. In our system, it could be done in two ways:</p>
<ul>
<li>mint a token containing only <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #read)</code></li>
<li>derive the user&#39;s token, adding a check restricting to the article</li>
</ul>
<p>In the second case, the token would look like this:</p>
<pre><code class="language-text">Block 0 (authority):
  facts: [ user(#authority, &quot;user_1234&quot;) ]
  rules: []
  checks: []

Block 1:
  facts: []
  rules: []
  check: [
    check if article(#ambient, &quot;blog1&quot;, &quot;article1&quot;), operation(#ambient, #read)
  ]
</code></pre>
<p>if we tried to do a <code>PUT /blog1/article1</code>, the verifier&#39;s checks would succeed, but the token&#39;s check would fail, because it does not find the <code>operation(#ambient, #read)</code> fact. But for a <code>GET /blog1/article1</code>, all checks would succeed. The reviewer will not be able to remove the block while keeping a valid signature, so any alteration will result in a failed request.</p>
<h3 id="premium-accounts">premium accounts</h3>
<p>Now some of the blog authors want to make living out of it (come on, it&#39;s 2021, do a newsletter instead) and mark some articles as &quot;premium&quot;, so that only some users can access them.</p>
<p>We can do that by having <code>premium_user(#authority, $user_id, $blog_id)</code> facts and adding a rule on the verifier&#39;s side:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);
</code></pre>
<p>We could even add a feature like <a href="https://lwn.net/">LWN.net</a> where a paying user can share a premium article, by deriving their tokens to only accept that article.</p>
<h3 id="were-a-big-newspaper-now-we-want-roles-and-teams">We&#39;re a big newspaper now, we want roles and teams</h3>
<p>Againt all odds, our blog platform is a smashing success. We need to recruit journalists, editors, copywriters... So now we might need more flexible rights management, maybe some teams and roles?</p>
<p>Let&#39;s define more facts and rules to encode that. As an example, let&#39;s define a &quot;contributor&quot; role that can only read or write articles, while owners are the only ones who can create or delete.</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  contributor(#authority, $user_id, $blog_id),
  [#read, #update].contains($operation);
</code></pre>
<p>What you can see on the last line is an <em>expression</em>: Biscuit&#39;s Datalog implementation can require additional conditions on some values, like a string matching a regular expression, or a date being lower than an expiration date, or here, presence in a set. This rule will only produce if the operation is <code>#read</code> or <code>#update</code>.</p>
<p>Now, we want to define contributor teams to manage them more easily. So we will introduce the <code>team(#authority, $team_id)</code>, <code>member(#authority, $user_id, $team_id)</code> and <code>team_role(#authority, $team_id, $blog_id, #contributor)</code> facts.</p>
<p>Additionally, we insert this rule in the verifier:</p>
<pre><code class="language-prolog">contributor(#authority, $user_id, $blog_id) &lt;-
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor);
</code></pre>
<p>This rule will generate the <code>contributor</code> fact for a blog if we are member of a team that has the &quot;contributor&quot; team role.</p>
<p>We could also fold the two precedent rules in one:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);
</code></pre>
<p>And that&#39;s it! With a few rules, we can model more and more complex authorization patterns, some of them relying on user provided policies, without compromising the previous features. Rules are additive, so there&#39;s no need for a long chain of if/else and special cases hardcoded in some endpoints. Everything can be managed in one place.</p>
<p>To sum up the rules of our system:</p>
<pre><code class="language-prolog">// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>And here is an example Rust program reproducing this authorization system:</p>
<pre><code class="language-rust">use biscuit::{crypto::KeyPair, error, token::Biscuit, parser::parse_source};
use biscuit_auth as biscuit;

fn main() -&gt; Result&lt;(), error::Token&gt; {
    let start = std::time::Instant::now();

    // First, let&#39;s create the root key for the system
    // its public part will be used to verify the token
    let mut rng = rand::thread_rng();
    let root = KeyPair::new();

    // Token creation
    // we will add a single fact indicating identity
    let mut builder = Biscuit::builder(&amp;root);
    builder.add_authority_fact(&quot;user(#authority, \&quot;user_1234\&quot;)&quot;)?;

    let token = builder.build()?;
    println!(&quot;{}&quot;, token.print());
    let token_bytes = token.to_vec()?;
    let serialized = base64::encode_config(&amp;token_bytes, base64::URL_SAFE);
    println!(&quot;serialized ({} bytes): {}&quot;, token_bytes.len(), serialized);

    let deserialized_token = Biscuit::from(&amp;token_bytes)?;
    // Token verification
    // first, we validate the signature with the root public key
    let mut verifier = deserialized_token.verify(root.public())?;

    // simulate verification for PUT /blog1/article1
    verifier.add_fact(&quot;blog(#ambient, \&quot;blog1\&quot;)&quot;)?;
    verifier.add_fact(&quot;article(#ambient, \&quot;blog1\&quot;, \&quot;article1\&quot;)&quot;)?;
    verifier.add_fact(&quot;operation(#ambient, #update)&quot;)?;

    // add ownership information
    // we only need to load facts related to the blog and article we&#39;re accessing
    verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog1\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_5678\&quot;, \&quot;blog2\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog3\&quot;)&quot;)?;

    let (_remaining_input, mut policies) = parse_source(&quot;
// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $usr_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
    &quot;).unwrap();

    for (_span, fact) in policies.facts.drain(..) {
        verifier.add_fact(fact)?;
    }

    for (_span, rule) in policies.rules.drain(..) {
        verifier.add_rule(rule)?;
    }

    for (_span, check) in policies.checks.drain(..) {
        verifier.add_check(check)?;
    }

    for (_span, policy) in policies.policies.drain(..) {
        verifier.add_policy(policy)?;
    }

    let res = verifier.verify()?;
    let dur = std::time::Instant::now() - start;
    //println!(&quot;res: {:?}&quot;, res);
    println!(&quot;{}&quot;, verifier.print_world());

    println!(&quot;ran in {:?}&quot;, dur);
    Ok(())
}
</code></pre>
<p>The entire program (key generation, token creation, serialization, deserialization, signature validation and facts verification) <strong>runs in 0.5 ms</strong>. So even with all of these features, Biscuit is fast enough to get out of your way.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>You can already start using Biscuit in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<script>
$("table").addClass("table-bordered");
</script>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Biscuit, the foundation for your authorization systems</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2021/04/12/introduction-to-biscuit/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Mon, 12 Apr 2021 09:45:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authorization]]></category>
		<category><![CDATA[biscuit]]></category>
		<category><![CDATA[cryptography]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2021/04/12/introduction-to-biscuit/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>After 2 years of development, I am proud to share with you the official release of Biscuit, the authentication and authorization token we develop to manage access to our systems.</p>
<span id="more-2832"></span>

<p>Where does it fit in the current authentication projects landscape (and why all of those cake themed names)?</p>
<ul>
<li>Cookies are a storage area in browsers, which can contain a session identifier
(the session data is then in a database, indexed by those identifiers), or
authentication tokens. They&#39;re good with lots of chocolate chips.</li>
<li><a href="https://jwt.io/">JSON Web Tokens</a> or JWT
(<a href="https://tools.ietf.org/html/rfc7519#section-1">pronounced &quot;jot&quot;</a>) contain
cryptographically signed data. Since the signature guarantees it has not been
modified, a web application could store session data in a JWT and send it in
a cookie, and read it from HTTP requests. The signature can be done with
secret key cryptography (HMAC algorithm), or public key cryptography (RSA,
ECDSA). They can even be encrypted, and stored in a cookie, but they cannot be
eaten.</li>
<li><a href="https://research.google/pubs/pub41892/">Macaroons</a> are cryptographically
signed (HMAC) tokens focused on authorization. They embed <em>caveats</em>, conditions
that the request must fit. They support attenuation: the holder of a token can
create a new valid token by adding a caveat, further restricting the token. A
macaroon can be stored in a cookie. It is also an Italian almond or coconut-based cake (do not confuse it with the French <em>macaron</em> which is also an almond
based cake)</li>
<li><a href="https://www.openpolicyagent.org/">Open Policy Agent</a> is a server-side logic
language used to encode authorization policies</li>
</ul>
<p>Biscuit unifies these various approaches:</p>
<ul>
<li>it can be signed with public key or secret key cryptography like JWT</li>
<li>it can be attenuated like Macaroons</li>
<li>it comes with a powerful logic language to write authorization policies, like OPA, but those policies can also be carried by the token</li>
</ul>
<p>By assembling those techniques, it opens up an array of authorization patterns that were not possible before.</p>
<p><img src="https://cdn.clever-cloud.com/uploads/2021/08/token_disambiguation.jpg" alt=""></p>
<p>When we started working on Biscuit, we were battling common issues in modern web applications:</p>
<ul>
<li>In a microservices system, how do you handle authorization from an initial
request, as it goes from service to service?</li>
<li>How do you reconcile an application&#39;s authorization policies (often some basic
roles and groups) with a client&#39;s organization chart?</li>
</ul>
<p>The microservices case is tricky: the initial request may come from a user for which we can look up a list of rights, but some services in the request tree may not even have a concept of user: at Clever Cloud, the service that launches virtual machines never hears about who requested a new deployment. With JWT, you could generate a temporary token in the user-facing API, and carry that from service to service. But then, any service holding that token has the entire set of rights for that request. Also, we need to make sure the authorization policies are evaluated in the same way in all services. With Macaroons, a service can attenuate the token before sending it to the next service, by adding a <em>caveat</em>, a condition over the current request (expiration date, limiting to read operations, restricting file paths to a prefix...). Unfortunately, Macaroon validation requires knowing the secret key used to generate the initial token.</p>
<p>Macaroons use a design based on chaining HMAC calculations: start from the initial secret, sign the first caveat, then for each new caveat, sign it using the previous signature as key. If you know the initial secret key, you can reconstruct the entire chain and verify that you obtain the same initial signature. But distributing that key in every service is a security risk: if someone gets access to this key, they can create a token with any authorization level they want. On the other side, JWT only requires verifiers to know a public key, and the private key can be kept in the service creating the token.</p>
<p>That was one of the motivating goals for Biscuit: <strong>what if we could attenuate the token, but still be able to verify it with public key cryptography?</strong></p>
<p>As it turns out, a cryptographic concept called <em>aggregated signatures</em> can help us: we take multiple messages, each individually signed with a different public key, and we aggregate all of those signatures into one main signature. From that aggregated signature, it is impossible to remove one of the messages and keep a valid signature, but we can always add more signed messages. We can verify the aggregated signatures if we know the public keys for each message. From this, we reproduce the Macaroon design, with public key cryptography.</p>
<p>To provide attenuation, we could have reused the Macaroons approach with caveats, but its user experience was challenging: a caveat is basically a byte array for which you must design your own system to encode and test conditions.</p>
<p>For Biscuit, we chose a more general approach. We provide a logic language based on Datalog to write authorization policies. It can store data, like JWT, or small conditions like Macaroons, but it is also able to represent more complex rules like role-based access control, delegation, hierarchies. Those authorization policies can be carried by the token or provided on the verification side. They are encoded in a small binary format for transport. Additionally, it is fast to evaluate: generally, the entire process of checking the signature, deserializing the token and testing the authorization policies is done under 1 ms.</p>
<figure>
<img alt="Example Datalog rule" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-datalog-example.png"/>
  <figcaption>Example Datalog rule</figcaption>
</figure>

<p>With this language (that can be learned in minutes), you get a unified way of representing complex business rules, in a testable and portable format. You can explore how policies work in a simulate environment, even write unit tests for them, then deploy them as dry-run tests and see how they would react on real world requests. Instead of a binary allow/deny result, you can gain fine-grained info, and query structured data. As an example, a request to list files would be accepted if we have the rights for it, and we can also get the filtered list of files we can access, even taking into account the attenuation rules carried by the token.</p>
<p>Multiple rule systems can be combined, which is useful for the second problem, about the mismatch between an application&#39;s policies and its user&#39;s needs:</p>
<ul>
<li>an application using GitHub or Twitter OAuth and requesting too many rights
because to get a subset of rights like read access to a repository, you get
it for all repositories</li>
<li>a SaaS application or hosting company for which all users from one client
share one account</li>
<li>or roles and groups that do not match work segmentation for users</li>
</ul>
<p>Traditionally, this is solved in two ways:</p>
<ul>
<li>the service includes more and more complicated authorization policies and the
user management panel becomes a complicated mess</li>
<li>it connects itself to external authorization systems, like Active Directory
or Keycloak, and let the user manage them</li>
</ul>
<p>With Biscuit, there&#39;s another way. Authorization policies can be provided by the verification service, but they can also be carried by the token. The service can specify its policies, and the user can attenuate tokens with their own policies. And they will all be evaluated in the same way, while guaranteeing that the token cannot get more rights with user policies. So from an initial token, an entire parallel authorization design can be developed that will still be compatible with the original one.</p>
<p>You can also take an existing token, and restrict its access to a minimal set of resources, like you would need for your CI/CD systems. There&#39;s a lot of new patterns that will become possible with Biscuit, and we&#39;ll have to explore it more in the future. Right now, let&#39;s look at an existing use case.</p>
<h2 id="example">Example</h2>
<p>At Clever Cloud, we are heavy users of <a href="https://pulsar.apache.org/">Apache Pulsar</a>. To provide this service to our users, we needed a flexible way to make it multitenant. By integrating Biscuit as an authorization plugin, using the Java implementation of Biscuit, we can provide a separate namespace for each user, but that token has full rights on that namespace. From there, the token can be attenuated to new tokens with various policies:</p>
<ul>
<li>limiting access to a topic name prefix</li>
<li>allowing subscription on only one topic</li>
<li>allowing message production on only one topic</li>
<li>adding an expiration time</li>
</ul>
<p>The authorization plugin only needs to check the token&#39;s initial rights to the namespace, and verify that the request matches the various checks added in attenuation.</p>
<p>As an example, we use that internally for a remote administration agent. Each new instance of the agent gets a new token derived from the original one, restricted to listening on its own topic (the topic name is a UUID). Then, when it receives a message, it also gets a short-lived token that can be used to send answers to a single temporary topic.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>The next article will dive into how to write policies and how to integrate it into your application. You can already test that language in the <a href="https://play-with-biscuit.cleverapps.io/">online playground</a>.</p>
<p>You can start using Biscuit right now in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<p>We are just at the beginning of this exciting new technology, so we are still learning how to use it, exploring new design and authorization patterns. I can&#39;t wait to see the fun applications you will come up with Biscuit!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>After 2 years of development, I am proud to share with you the official release of Biscuit, the authentication and authorization token we develop to manage access to our systems.</p>
<span id="more-2832"></span>

<p>Where does it fit in the current authentication projects landscape (and why all of those cake themed names)?</p>
<ul>
<li>Cookies are a storage area in browsers, which can contain a session identifier
(the session data is then in a database, indexed by those identifiers), or
authentication tokens. They&#39;re good with lots of chocolate chips.</li>
<li><a href="https://jwt.io/">JSON Web Tokens</a> or JWT
(<a href="https://tools.ietf.org/html/rfc7519#section-1">pronounced &quot;jot&quot;</a>) contain
cryptographically signed data. Since the signature guarantees it has not been
modified, a web application could store session data in a JWT and send it in
a cookie, and read it from HTTP requests. The signature can be done with
secret key cryptography (HMAC algorithm), or public key cryptography (RSA,
ECDSA). They can even be encrypted, and stored in a cookie, but they cannot be
eaten.</li>
<li><a href="https://research.google/pubs/pub41892/">Macaroons</a> are cryptographically
signed (HMAC) tokens focused on authorization. They embed <em>caveats</em>, conditions
that the request must fit. They support attenuation: the holder of a token can
create a new valid token by adding a caveat, further restricting the token. A
macaroon can be stored in a cookie. It is also an Italian almond or coconut-based cake (do not confuse it with the French <em>macaron</em> which is also an almond
based cake)</li>
<li><a href="https://www.openpolicyagent.org/">Open Policy Agent</a> is a server-side logic
language used to encode authorization policies</li>
</ul>
<p>Biscuit unifies these various approaches:</p>
<ul>
<li>it can be signed with public key or secret key cryptography like JWT</li>
<li>it can be attenuated like Macaroons</li>
<li>it comes with a powerful logic language to write authorization policies, like OPA, but those policies can also be carried by the token</li>
</ul>
<p>By assembling those techniques, it opens up an array of authorization patterns that were not possible before.</p>
<p><img src="https://cdn.clever-cloud.com/uploads/2021/08/token_disambiguation.jpg" alt=""></p>
<p>When we started working on Biscuit, we were battling common issues in modern web applications:</p>
<ul>
<li>In a microservices system, how do you handle authorization from an initial
request, as it goes from service to service?</li>
<li>How do you reconcile an application&#39;s authorization policies (often some basic
roles and groups) with a client&#39;s organization chart?</li>
</ul>
<p>The microservices case is tricky: the initial request may come from a user for which we can look up a list of rights, but some services in the request tree may not even have a concept of user: at Clever Cloud, the service that launches virtual machines never hears about who requested a new deployment. With JWT, you could generate a temporary token in the user-facing API, and carry that from service to service. But then, any service holding that token has the entire set of rights for that request. Also, we need to make sure the authorization policies are evaluated in the same way in all services. With Macaroons, a service can attenuate the token before sending it to the next service, by adding a <em>caveat</em>, a condition over the current request (expiration date, limiting to read operations, restricting file paths to a prefix...). Unfortunately, Macaroon validation requires knowing the secret key used to generate the initial token.</p>
<p>Macaroons use a design based on chaining HMAC calculations: start from the initial secret, sign the first caveat, then for each new caveat, sign it using the previous signature as key. If you know the initial secret key, you can reconstruct the entire chain and verify that you obtain the same initial signature. But distributing that key in every service is a security risk: if someone gets access to this key, they can create a token with any authorization level they want. On the other side, JWT only requires verifiers to know a public key, and the private key can be kept in the service creating the token.</p>
<p>That was one of the motivating goals for Biscuit: <strong>what if we could attenuate the token, but still be able to verify it with public key cryptography?</strong></p>
<p>As it turns out, a cryptographic concept called <em>aggregated signatures</em> can help us: we take multiple messages, each individually signed with a different public key, and we aggregate all of those signatures into one main signature. From that aggregated signature, it is impossible to remove one of the messages and keep a valid signature, but we can always add more signed messages. We can verify the aggregated signatures if we know the public keys for each message. From this, we reproduce the Macaroon design, with public key cryptography.</p>
<p>To provide attenuation, we could have reused the Macaroons approach with caveats, but its user experience was challenging: a caveat is basically a byte array for which you must design your own system to encode and test conditions.</p>
<p>For Biscuit, we chose a more general approach. We provide a logic language based on Datalog to write authorization policies. It can store data, like JWT, or small conditions like Macaroons, but it is also able to represent more complex rules like role-based access control, delegation, hierarchies. Those authorization policies can be carried by the token or provided on the verification side. They are encoded in a small binary format for transport. Additionally, it is fast to evaluate: generally, the entire process of checking the signature, deserializing the token and testing the authorization policies is done under 1 ms.</p>
<figure>
<img alt="Example Datalog rule" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-datalog-example.png"/>
  <figcaption>Example Datalog rule</figcaption>
</figure>

<p>With this language (that can be learned in minutes), you get a unified way of representing complex business rules, in a testable and portable format. You can explore how policies work in a simulate environment, even write unit tests for them, then deploy them as dry-run tests and see how they would react on real world requests. Instead of a binary allow/deny result, you can gain fine-grained info, and query structured data. As an example, a request to list files would be accepted if we have the rights for it, and we can also get the filtered list of files we can access, even taking into account the attenuation rules carried by the token.</p>
<p>Multiple rule systems can be combined, which is useful for the second problem, about the mismatch between an application&#39;s policies and its user&#39;s needs:</p>
<ul>
<li>an application using GitHub or Twitter OAuth and requesting too many rights
because to get a subset of rights like read access to a repository, you get
it for all repositories</li>
<li>a SaaS application or hosting company for which all users from one client
share one account</li>
<li>or roles and groups that do not match work segmentation for users</li>
</ul>
<p>Traditionally, this is solved in two ways:</p>
<ul>
<li>the service includes more and more complicated authorization policies and the
user management panel becomes a complicated mess</li>
<li>it connects itself to external authorization systems, like Active Directory
or Keycloak, and let the user manage them</li>
</ul>
<p>With Biscuit, there&#39;s another way. Authorization policies can be provided by the verification service, but they can also be carried by the token. The service can specify its policies, and the user can attenuate tokens with their own policies. And they will all be evaluated in the same way, while guaranteeing that the token cannot get more rights with user policies. So from an initial token, an entire parallel authorization design can be developed that will still be compatible with the original one.</p>
<p>You can also take an existing token, and restrict its access to a minimal set of resources, like you would need for your CI/CD systems. There&#39;s a lot of new patterns that will become possible with Biscuit, and we&#39;ll have to explore it more in the future. Right now, let&#39;s look at an existing use case.</p>
<h2 id="example">Example</h2>
<p>At Clever Cloud, we are heavy users of <a href="https://pulsar.apache.org/">Apache Pulsar</a>. To provide this service to our users, we needed a flexible way to make it multitenant. By integrating Biscuit as an authorization plugin, using the Java implementation of Biscuit, we can provide a separate namespace for each user, but that token has full rights on that namespace. From there, the token can be attenuated to new tokens with various policies:</p>
<ul>
<li>limiting access to a topic name prefix</li>
<li>allowing subscription on only one topic</li>
<li>allowing message production on only one topic</li>
<li>adding an expiration time</li>
</ul>
<p>The authorization plugin only needs to check the token&#39;s initial rights to the namespace, and verify that the request matches the various checks added in attenuation.</p>
<p>As an example, we use that internally for a remote administration agent. Each new instance of the agent gets a new token derived from the original one, restricted to listening on its own topic (the topic name is a UUID). Then, when it receives a message, it also gets a short-lived token that can be used to send answers to a single temporary topic.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>The next article will dive into how to write policies and how to integrate it into your application. You can already test that language in the <a href="https://play-with-biscuit.cleverapps.io/">online playground</a>.</p>
<p>You can start using Biscuit right now in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<p>We are just at the beginning of this exciting new technology, so we are still learning how to use it, exploring new design and authorization patterns. I can&#39;t wait to see the fun applications you will come up with Biscuit!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>In Defense of Optimization Work</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2018/09/27/in-defense-of-optimization-work/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Thu, 27 Sep 2018 17:15:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[performance]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2018/09/27/in-defense-of-optimization-work/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>It is common knowledge that <a href="https://blog.codinghorror.com/hardware-is-cheap-programmers-are-expensive/">hardware is cheap, and programmers are expensive</a>, and that most performance issues can be easily solved by throwing more and bigger hardware at it. But is it really cheaper in the long run? Is there still some room for optimization work?</p>
<span id="more-2814"></span>

<blockquote>
<p>&quot;The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.&quot;</p>
</blockquote>
<div class="quote-credits">
Donald Knuth, [or Tony Hoare according to Donald Knuth, or Edsger W. Dijkstra according to Tony Hoare](https://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/)
</div>

<p>Yes, we engineers like to optimize, spend time shaving off bytes and microseconds from our systems. And it is often at odds with the requirement to build features and squash bugs instead. Before we get into the cost comparison of optimization work VS hardware, allow me to reframe the issue: performance is not a goal isolated from other engineering business issues. Like security, it is a transversal problem:</p>
<ul>
<li>performance is a reliability issue, because it will trigger bigger and more frequent production issues</li>
<li>performance is a user experience issue, it affects directly how your users will work with your systems</li>
<li>performance is a cost issue</li>
</ul>
<p>And like security, it is not something we can ignore on a whim, it is part of the job.</p>
<p>Moreover, while we hear about hero stories of optimizations involving kernel ork or writing assembly manually, most performance work is actually quite simple, and boils down to tasks like:</p>
<ul>
<li>adding a cache</li>
<li>adding database indexes</li>
<li>doing some work inside a database query instead of loading all the data and analyzing manually</li>
</ul>
<p>It is actually rare (in web services) to have some optimization work that requires someone to write assembly manually or other fun tasks like this.</p>
<h2 id="the-cost-of-not-optimizing-code">The cost of not optimizing code</h2>
<p>If we take $100,000 as average programmer salary (in the US), it comes down to around $400 per day, so $50 per hour (20-21 days per month, 8 hours per day). So spending an afternoon optimizing code would amount to $200.</p>
<p>Using bigger or more hardware looks like a small cost comparatively. Let’s assume adding another machine would cost $20 to $50 per month. Let’s choose $20/month. The naive calculation would show that we recoup the costs of optimization work after 10 months. So at this point, thinking 10 months in advance might not be too interesting, and the cost of the machine is not too high. But after those 10 months, it starts costing more than having an engineer look at it.</p>
<p>Because here is the first difference: an optimization task is a fixed cost, done once, while the hardware cost is compounded (if the hardware is bought instead of rented, it will be amortized until the date of replacement). We easily trick ourselves into comparing the local, monthly cost, without looking at it on the long term.</p>
<p>But there is another aspect of the problem: performance issues are linked to business growth. Often not directly, but through some usage metric, like a number of messages sent, or a number of searches per second. Those grow with the number of customers. But they also grow with customer usage: if everything goes well, customers will use the product more and more. Do not expect performance issues to follow business growth linearly.</p>
<p>Let&#39;s take as example one of the metrics to evaluate a startup&#39;s growth: <a href="http://www.paulgraham.com/growth.html">the growth rate should be around 5-7% per week</a></p>
<p>Let&#39;s use the number of users as growth metric, and ignore usage growth.</p>
<p>Assuming that one node of the application is at full capacity with the current number of customers N, we add another node.</p>
<p>At 5% per week, we’re around 21% growth per month (21.550625% exactly, and that&#39;s calculated as a geometric progression). We will double the number of customers in just 15 weeks!</p>
<p>We can see the costs in the following graph. Red points represent the monthly cost, while blue points indicate how much we spent so far.</p>
<figure>
  <a href="https://www2.cleverapps.io/app/uploads/2021/08/growth-graph.png" rel="noopener noreferrer" target="_blank">
    <img style="width:100%" src="https://www2.cleverapps.io/app/uploads/2021/08/growth-graph.png">
  </a>
  <figcaption>Red points: monthly cost — Blue points: what we've spent so far</figcaption>
</figure>

<p>So we would spend: 1 more machine for the first 4 months, then we need to add one more. We will reach 3N at week 24 (6 months). We already spent $200 more than one machine. So this engineering time would pay for itself in 6 months, not 10. At week 40, we have already spent $560. Next week we will add another machine, because we will reach 7N.</p>
<p>After a year, we reached 12N, and paid $1140. We likely got other performance issues linked to the number of machines running, on-call issues, time spent updating them, etc. (But for all of those issues, we have Clever Cloud!) So we probably have more than 12 machines doing the work, and we spent considerable engineering time making them work.</p>
<p>Here&#39;s the equation: for a growth rate G, a number of months M, and a monthly cost C for one machine:</p>
<figure>
  <img style=" width: 180px;margin:0 auto;display: block;" src="https://www2.cleverapps.io/app/uploads/2021/08/growth-equation.png">
</figure>

<p>You can also test it in Wolfram Alpha <a href="http://www.wolframalpha.com/input/?i=sum+20+*+floor(1.05%5E(4m))+from+m+%3D+0+to+12N">(here for $20/month and growth at 5%)</a></p>
<p>To sum up, choosing the current settings as:</p>
<ul>
<li>$200 of work (4h at $50/h)</li>
<li>$20/month for a machine</li>
<li>5% growth per week</li>
</ul>
<p>We would spend $200 in new machines over the next 6 months, which is pretty short term. But there’s another way to look at it. We still need to fix the performance issue, but adding more hardware would buy us time. For the next 4 months, we would pay only $20 per month to delay the issue, and let our engineers work properly on it instead of putting out fires. Even better, now we have the means to plan hardware costs following business growth.</p>
<blockquote>
<p>&quot;Hardware is cheap, programmers are expensive;&quot;</p>
</blockquote>
<p style="margin-top: -60px; margin-bottom: 70px; text-align: center; font-style: italic; text-align: center;">…but performance debt comes with interests <span style="font-style:normal">(/¯–‿･)/¯</span></p>

<figure>
  <img style=" width: 450px;margin:0 auto;display: block;max-width:100%" src="https://www2.cleverapps.io/app/uploads/2021/08/goodbook.jpeg">
  <figcaption>The author, posing with what seems to be a good book.</figcaption>
</figure>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/in-defense-of-optimization-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>It is common knowledge that <a href="https://blog.codinghorror.com/hardware-is-cheap-programmers-are-expensive/">hardware is cheap, and programmers are expensive</a>, and that most performance issues can be easily solved by throwing more and bigger hardware at it. But is it really cheaper in the long run? Is there still some room for optimization work?</p>
<span id="more-2814"></span>

<blockquote>
<p>&quot;The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.&quot;</p>
</blockquote>
<div class="quote-credits">
Donald Knuth, [or Tony Hoare according to Donald Knuth, or Edsger W. Dijkstra according to Tony Hoare](https://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/)
</div>

<p>Yes, we engineers like to optimize, spend time shaving off bytes and microseconds from our systems. And it is often at odds with the requirement to build features and squash bugs instead. Before we get into the cost comparison of optimization work VS hardware, allow me to reframe the issue: performance is not a goal isolated from other engineering business issues. Like security, it is a transversal problem:</p>
<ul>
<li>performance is a reliability issue, because it will trigger bigger and more frequent production issues</li>
<li>performance is a user experience issue, it affects directly how your users will work with your systems</li>
<li>performance is a cost issue</li>
</ul>
<p>And like security, it is not something we can ignore on a whim, it is part of the job.</p>
<p>Moreover, while we hear about hero stories of optimizations involving kernel ork or writing assembly manually, most performance work is actually quite simple, and boils down to tasks like:</p>
<ul>
<li>adding a cache</li>
<li>adding database indexes</li>
<li>doing some work inside a database query instead of loading all the data and analyzing manually</li>
</ul>
<p>It is actually rare (in web services) to have some optimization work that requires someone to write assembly manually or other fun tasks like this.</p>
<h2 id="the-cost-of-not-optimizing-code">The cost of not optimizing code</h2>
<p>If we take $100,000 as average programmer salary (in the US), it comes down to around $400 per day, so $50 per hour (20-21 days per month, 8 hours per day). So spending an afternoon optimizing code would amount to $200.</p>
<p>Using bigger or more hardware looks like a small cost comparatively. Let’s assume adding another machine would cost $20 to $50 per month. Let’s choose $20/month. The naive calculation would show that we recoup the costs of optimization work after 10 months. So at this point, thinking 10 months in advance might not be too interesting, and the cost of the machine is not too high. But after those 10 months, it starts costing more than having an engineer look at it.</p>
<p>Because here is the first difference: an optimization task is a fixed cost, done once, while the hardware cost is compounded (if the hardware is bought instead of rented, it will be amortized until the date of replacement). We easily trick ourselves into comparing the local, monthly cost, without looking at it on the long term.</p>
<p>But there is another aspect of the problem: performance issues are linked to business growth. Often not directly, but through some usage metric, like a number of messages sent, or a number of searches per second. Those grow with the number of customers. But they also grow with customer usage: if everything goes well, customers will use the product more and more. Do not expect performance issues to follow business growth linearly.</p>
<p>Let&#39;s take as example one of the metrics to evaluate a startup&#39;s growth: <a href="http://www.paulgraham.com/growth.html">the growth rate should be around 5-7% per week</a></p>
<p>Let&#39;s use the number of users as growth metric, and ignore usage growth.</p>
<p>Assuming that one node of the application is at full capacity with the current number of customers N, we add another node.</p>
<p>At 5% per week, we’re around 21% growth per month (21.550625% exactly, and that&#39;s calculated as a geometric progression). We will double the number of customers in just 15 weeks!</p>
<p>We can see the costs in the following graph. Red points represent the monthly cost, while blue points indicate how much we spent so far.</p>
<figure>
  <a href="https://www2.cleverapps.io/app/uploads/2021/08/growth-graph.png" rel="noopener noreferrer" target="_blank">
    <img style="width:100%" src="https://www2.cleverapps.io/app/uploads/2021/08/growth-graph.png">
  </a>
  <figcaption>Red points: monthly cost — Blue points: what we've spent so far</figcaption>
</figure>

<p>So we would spend: 1 more machine for the first 4 months, then we need to add one more. We will reach 3N at week 24 (6 months). We already spent $200 more than one machine. So this engineering time would pay for itself in 6 months, not 10. At week 40, we have already spent $560. Next week we will add another machine, because we will reach 7N.</p>
<p>After a year, we reached 12N, and paid $1140. We likely got other performance issues linked to the number of machines running, on-call issues, time spent updating them, etc. (But for all of those issues, we have Clever Cloud!) So we probably have more than 12 machines doing the work, and we spent considerable engineering time making them work.</p>
<p>Here&#39;s the equation: for a growth rate G, a number of months M, and a monthly cost C for one machine:</p>
<figure>
  <img style=" width: 180px;margin:0 auto;display: block;" src="https://www2.cleverapps.io/app/uploads/2021/08/growth-equation.png">
</figure>

<p>You can also test it in Wolfram Alpha <a href="http://www.wolframalpha.com/input/?i=sum+20+*+floor(1.05%5E(4m))+from+m+%3D+0+to+12N">(here for $20/month and growth at 5%)</a></p>
<p>To sum up, choosing the current settings as:</p>
<ul>
<li>$200 of work (4h at $50/h)</li>
<li>$20/month for a machine</li>
<li>5% growth per week</li>
</ul>
<p>We would spend $200 in new machines over the next 6 months, which is pretty short term. But there’s another way to look at it. We still need to fix the performance issue, but adding more hardware would buy us time. For the next 4 months, we would pay only $20 per month to delay the issue, and let our engineers work properly on it instead of putting out fires. Even better, now we have the means to plan hardware costs following business growth.</p>
<blockquote>
<p>&quot;Hardware is cheap, programmers are expensive;&quot;</p>
</blockquote>
<p style="margin-top: -60px; margin-bottom: 70px; text-align: center; font-style: italic; text-align: center;">…but performance debt comes with interests <span style="font-style:normal">(/¯–‿･)/¯</span></p>

<figure>
  <img style=" width: 450px;margin:0 auto;display: block;max-width:100%" src="https://www2.cleverapps.io/app/uploads/2021/08/goodbook.jpeg">
  <figcaption>The author, posing with what seems to be a good book.</figcaption>
</figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spectre and Meltdown</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2018/01/04/dealing-with-spectre-and-meltdown/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Thu, 04 Jan 2018 11:59:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Update]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2018/01/04/dealing-with-spectre-and-meltdown/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Yesterday two issues affecting CPUs have been released to the public.</p>
<p><strong>TL;DR</strong>: the attacks are named Meltdown and Spectre. They allow reading the memory of the OS or of other processes, to steal secrets or get information for other exploits. A part of the solution can greatly affect performance of running code. In particular, this attack allows to easily cross container boundaries, and in some cases (not our case) even VM boundaries.</p>
<p>In addition to servers, consumer machines are affected, especially through browsers, so you should definitely update your operating system as well as your browsers.</p>
<span id="more-2812"></span>

<h2 id="what-it-means-for-clever-cloud-users">What it means for Clever Cloud users</h2>
<p>Your applications will be (or already have been) automatically restarted (just like any other maintenance deployments). The addons will be patched and restarted in place in the following hours. This will generate limited downtime on addons (usually around a minute, depending on the addon start up time).</p>
<p>In addition to restarting virtual machines, we will also need to restart physical machines, as the attacks theoretically allows VM boundaries crossing. This attack is not usable (yet?) on Clever Cloud due to our virtualization choices and our OS hardening, but we will deploy patches preemptively. Physical machines updates will take place in the following days and will not impact applications. We are currently working on finding the best solution for addons, but it will definitely incur additional downtime for addons.</p>
<p>The patches, while mitigating the issues, also come with performance regressions. It heavily depends on the workload as well as the exact CPU model. The CPUs we use are among the less affected by the performance issues, but a slowdown of at least 5% is to be expected.</p>
<h2 id="technical-details">Technical details</h2>
<p>The Meltdown attack and the Spectre categories of attack are related to a performance feature of modern processors: branch prediction and speculative execution. Meltdown shows that when an instruction can cause a trap, like the privilege check for user → kernel access), the processor will perform speculative execution: it starts executing the code in case there’s no trap, but rollbacks if there was a trap. This attack happens at the boundary between user code and kernel. Before the processor has completely checked that we have the authorization to run privileged code, it starts executing it. When it turns out we were not authorized, it rolls back the results of that code, but not completely, it can leave some data in the cache. Combined with a technique called “cache timing attack”, it is then possible to guess the content of the data that was loaded in cache, bit by bit. Branch prediction has a related behaviour: when encountering a branch (example: an if/else expression), the processor will start executing one of the branches before it calculates the condition, to avoid waiting too much. It guesses which side of the condition is most likely thanks to its branch predictor. Spectre uses branch prediction to cause speculative execution to read out of a buffer’s bounds (among other consequences) in the kernel or another process, then guess the results from the cache.</p>
<p>The Meltdown attack is specific to Intel processors, it allows reading from the OS’s memory. There are patches available (the kPTI feature, also named KAISER <a href="https://lkml.org/lkml/2017/12/4/709">https://lkml.org/lkml/2017/12/4/709</a>). Those patches have a great impact on syscall performance (<a href="https://www.phoronix.com/scan.php?page=article&amp;item=linux-415-x86pti&amp;num=1">https://www.phoronix.com/scan.php?page=article&amp;item=linux-415-x86pti&amp;num=1</a>), with programs running 5% to 30% slower depending on the workload. The Intel Haswell processors with the PCID (Process Context Identifiers) feature get the lowest performance hit (5%). We use those processors on Clever Cloud.</p>
<p>Spectre affects processors from Intel, AMD and ARM, it allows reading from the memory of other processes. It looks more like a new attack category, for which we will have to fix the issue individually in each affected software. The only global solution for Spectre is a radical change in processor architecture, and this is unlikely to happen soon. We will follow closely any new related vulnerability and promptly patch our infrastructure.</p>
<h3 id="for-further-information">For further information</h3>
<ul>
<li>Papers and explanations about Meltdown and Spectre: <a href="https://spectreattack.com/">https://spectreattack.com/</a></li>
<li>Proofs of concept from Google’s Project Zero team: <a href="https://googleprojectzero.blogspot.fr/2018/01/reading-privileged-memory-with-side.html">https://googleprojectzero.blogspot.fr/2018/01/reading-privileged-memory-with-side.html</a></li>
<li>French twitter thread explaining the attacks: <a href="https://twitter.com/fenarinarsa/status/948697105996156928">https://twitter.com/fenarinarsa/status/948697105996156928</a></li>
<li>English twitter thread explaining the attacks: <a href="https://twitter.com/nicoleperlroth/status/948684376249962496">https://twitter.com/nicoleperlroth/status/948684376249962496</a></li>
</ul>
<p>This post has been written by <a href="https://twitter.com/gcouprie">@gcouprie</a> and <a href="https://twitter.com/clementd">@clementd</a>.<br>Spectre and meltdown logos of are designed by <a href="https://vividfox.me">Natascha Eibl</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/spectre-meltdown-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Yesterday two issues affecting CPUs have been released to the public.</p>
<p><strong>TL;DR</strong>: the attacks are named Meltdown and Spectre. They allow reading the memory of the OS or of other processes, to steal secrets or get information for other exploits. A part of the solution can greatly affect performance of running code. In particular, this attack allows to easily cross container boundaries, and in some cases (not our case) even VM boundaries.</p>
<p>In addition to servers, consumer machines are affected, especially through browsers, so you should definitely update your operating system as well as your browsers.</p>
<span id="more-2812"></span>

<h2 id="what-it-means-for-clever-cloud-users">What it means for Clever Cloud users</h2>
<p>Your applications will be (or already have been) automatically restarted (just like any other maintenance deployments). The addons will be patched and restarted in place in the following hours. This will generate limited downtime on addons (usually around a minute, depending on the addon start up time).</p>
<p>In addition to restarting virtual machines, we will also need to restart physical machines, as the attacks theoretically allows VM boundaries crossing. This attack is not usable (yet?) on Clever Cloud due to our virtualization choices and our OS hardening, but we will deploy patches preemptively. Physical machines updates will take place in the following days and will not impact applications. We are currently working on finding the best solution for addons, but it will definitely incur additional downtime for addons.</p>
<p>The patches, while mitigating the issues, also come with performance regressions. It heavily depends on the workload as well as the exact CPU model. The CPUs we use are among the less affected by the performance issues, but a slowdown of at least 5% is to be expected.</p>
<h2 id="technical-details">Technical details</h2>
<p>The Meltdown attack and the Spectre categories of attack are related to a performance feature of modern processors: branch prediction and speculative execution. Meltdown shows that when an instruction can cause a trap, like the privilege check for user → kernel access), the processor will perform speculative execution: it starts executing the code in case there’s no trap, but rollbacks if there was a trap. This attack happens at the boundary between user code and kernel. Before the processor has completely checked that we have the authorization to run privileged code, it starts executing it. When it turns out we were not authorized, it rolls back the results of that code, but not completely, it can leave some data in the cache. Combined with a technique called “cache timing attack”, it is then possible to guess the content of the data that was loaded in cache, bit by bit. Branch prediction has a related behaviour: when encountering a branch (example: an if/else expression), the processor will start executing one of the branches before it calculates the condition, to avoid waiting too much. It guesses which side of the condition is most likely thanks to its branch predictor. Spectre uses branch prediction to cause speculative execution to read out of a buffer’s bounds (among other consequences) in the kernel or another process, then guess the results from the cache.</p>
<p>The Meltdown attack is specific to Intel processors, it allows reading from the OS’s memory. There are patches available (the kPTI feature, also named KAISER <a href="https://lkml.org/lkml/2017/12/4/709">https://lkml.org/lkml/2017/12/4/709</a>). Those patches have a great impact on syscall performance (<a href="https://www.phoronix.com/scan.php?page=article&amp;item=linux-415-x86pti&amp;num=1">https://www.phoronix.com/scan.php?page=article&amp;item=linux-415-x86pti&amp;num=1</a>), with programs running 5% to 30% slower depending on the workload. The Intel Haswell processors with the PCID (Process Context Identifiers) feature get the lowest performance hit (5%). We use those processors on Clever Cloud.</p>
<p>Spectre affects processors from Intel, AMD and ARM, it allows reading from the memory of other processes. It looks more like a new attack category, for which we will have to fix the issue individually in each affected software. The only global solution for Spectre is a radical change in processor architecture, and this is unlikely to happen soon. We will follow closely any new related vulnerability and promptly patch our infrastructure.</p>
<h3 id="for-further-information">For further information</h3>
<ul>
<li>Papers and explanations about Meltdown and Spectre: <a href="https://spectreattack.com/">https://spectreattack.com/</a></li>
<li>Proofs of concept from Google’s Project Zero team: <a href="https://googleprojectzero.blogspot.fr/2018/01/reading-privileged-memory-with-side.html">https://googleprojectzero.blogspot.fr/2018/01/reading-privileged-memory-with-side.html</a></li>
<li>French twitter thread explaining the attacks: <a href="https://twitter.com/fenarinarsa/status/948697105996156928">https://twitter.com/fenarinarsa/status/948697105996156928</a></li>
<li>English twitter thread explaining the attacks: <a href="https://twitter.com/nicoleperlroth/status/948684376249962496">https://twitter.com/nicoleperlroth/status/948684376249962496</a></li>
</ul>
<p>This post has been written by <a href="https://twitter.com/gcouprie">@gcouprie</a> and <a href="https://twitter.com/clementd">@clementd</a>.<br>Spectre and meltdown logos of are designed by <a href="https://vividfox.me">Natascha Eibl</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Hot reloading configuration: why and how?</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2017/07/24/hot-reloading-configuration-why-and-how/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Mon, 24 Jul 2017 14:25:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[Sōzu]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2017/07/24/hot-reloading-configuration-why-and-how/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we are working on <a href="https://www.sozu.io">Sōzu</a>, an HTTP reverse proxy that can change its configuration at runtime, without restarting the process. Why would we need that, you might ask?</p>
<span id="more-2811"></span>

<p>In our architecture, all the applications sit behind a few load balancers with public IP addresses to which our clients point their DNS entries. We used HAProxy for these load balancers, a well known HTTP reverse proxy. Like a lot of other companies, our solution to serve a lot of applications, each with many backend servers, is to generate a configuration file for HAProxy and ask the current process to spawn new workers to handle the new configuration.</p>
<p>Unfortunately, this approach can lose new TCP connections on configuration updates: the old workers might stop accepting connections, but their listen queue might still contain new connections that will not be transferred to the new workers. Worse: if you change the configuration again while the old workers have not stopped handling their current connections, they would be killed, and the live connections would stop right there. Or the processes could just pile up and hog resources.</p>
<p>We use an immutable infrastructure approach. For every new version of an application, instead of modifying the backend servers in place, we spawn new ones. This means that we must update the HAProxy configuration to route an application to the new backend servers. And so, we must update the global configuration on every new commit from any of our clients. With multiple configuration changes every second, we&#39;re bound to lose some connections.</p>
<h2 id="hot-configuration-reloading-vs-restarting-processes">Hot configuration reloading VS restarting processes</h2>
<p>That&#39;s why we set out to build a new reverse proxy that could handle configuration changes without losing connections.</p>
<p>First, we decided configuration updates should happen without restarts. The ability to change the configuration of a running process is essential because launching new workers, transferring the current state between them, and removing old workers gracefully, is a task with a high impact on server load and latency. You&#39;re essentially doubling the server&#39;s resource usage, and launching a lot of new processes every time.</p>
<p>This is a cost we have to pay for executable upgrades, though, but those happen less frequently. For that case, we provide ways to do upgrades without downtimes, either automatically, or with more hand holding (you decide when to launch each step) if you want.</p>
<h2 id="shared-and-synchronized-configuration-vs-data-locality">Shared and synchronized configuration VS data locality</h2>
<p>To handle configuration changes, Sōzu uses a master/workers architecture, with the master receiving configuration changes and transmitting it to clients. Each worker has its own copy of the configuration: if workers had something like a shared memory segment for this, we would need to add cross process synchronization, and make sure that accessing this data is safe, fiddle with pointers, etc. The whole configuration state is not very large (certificates and keys are the biggest part), so we can keep copies in every process. This makes for better data locality and is easier to handle overall.</p>
<h2 id="configuration-changes-push-vs-pull">Configuration changes: push VS pull</h2>
<p>To get configuration updates, there are basically two solutions:</p>
<ul>
<li>The proxy polls new configuration from files or from tools like Kubernetes, etcd, Consul...</li>
<li>The proxy exposes a communication channel to get the new configuration</li>
</ul>
<p>The first solution is essentially what Traefik, the reverse proxy built in Go, does. We chose the second solution because we thought it is not the proxy&#39;s reponsibility to communicate with those tools. After all, it is just a pipe, it should not have to understand all the existing configuration protocols. So we expose a channel, and we build tools to bridge between the configuration backend and Sōzu.</p>
<p>That way, we do not impose the configuration format, the proxy binary stays small, and anyone can write their own tool to drive it, in any language they want.</p>
<p>The channel is a Unix socket. We decided on this instead of exposing a TCP port on localhost because anybody on the machine could connect to it, while a Unix socket has its access protected by filesystem rights.</p>
<p>The protocol is quite simple: JSON objects representing the proxy orders and their answers, separated by null characters. Writing new tools is as easy as writing directly to a file, you can even make tools in bash. If you want more control, we provide libraries in Rust to wrap this channel. Other libraries will appear soon to do it easily from other languages.</p>
<h2 id="working-with-configuration-diffs-vs-replacing-the-configuration">Working with configuration diffs VS replacing the configuration</h2>
<p>An easy way to implement runtime configuration changes might be to replace the whole configuration every time there&#39;s a change, and start handling the new routing right away. We choose another way: Sōzu works with configuration diffs. The messages you send through the Unix socket contain information like &quot;add this specific certificate&quot;, &quot;add this backend server to this application&quot;, &quot;remove this domain name for this application&quot;. This is useful because when you replace the whole configuration at once, you lose information.</p>
<p>You might have to remove some openssl contexts still storing old certificates. Or you might want to know when you can drop a backend server: if you tell Sōzu to remove a backend server for an application, it will first tell you that it acknowledges the change and will stop routing new traffic to this server, but will also tell you if there are still connections going on to this server. It will notify you once the connections are gone, so you can safely drop that server.</p>
<p>This also means configuration changes are smaller: instead of loading a complete configuration, you just send a few small messages.</p>
<p>To accomodate for this solution, the configuration protocol is more than request-response: there are 3 possible answers: Error, Ok or Processing. If the proxy answers Processing, that means the actual result might come later. It can send other Processing messages, to keep you posted on the number of current connections or other issues, and send you Ok or Error after a while.</p>
<h2 id="design-goals-for-a-tool-with-hot-reconfiguration">Design goals for a tool with hot reconfiguration</h2>
<p>We worked for a while on this and had time to explore the requirements for a tool with hot reconfiguration. There are three important points:</p>
<ul>
<li>You have to bake runtime reconfiguration in from the beginning. You cannot retrofit
that correctly in an actual system by messing with backend config switches or other hacks</li>
<li>Do runtime reconfiguration, not process restarts. You might get away with it or
blue/green deployments if your configuration does not change often and connections
are short lived. Our experience shows it does not happen like this</li>
<li>Work with configuration diffs instead of replacing the configuration. Otherwise,
you&#39;re losing important information for your infrastructure</li>
</ul>
<p>We hope this architecture will make it easily to make long lived and reliable systems, and we hope people will build awesome tools around <a href="https://github.com/sozu-proxy/sozu">Sōzu</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/hot-conf-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we are working on <a href="https://www.sozu.io">Sōzu</a>, an HTTP reverse proxy that can change its configuration at runtime, without restarting the process. Why would we need that, you might ask?</p>
<span id="more-2811"></span>

<p>In our architecture, all the applications sit behind a few load balancers with public IP addresses to which our clients point their DNS entries. We used HAProxy for these load balancers, a well known HTTP reverse proxy. Like a lot of other companies, our solution to serve a lot of applications, each with many backend servers, is to generate a configuration file for HAProxy and ask the current process to spawn new workers to handle the new configuration.</p>
<p>Unfortunately, this approach can lose new TCP connections on configuration updates: the old workers might stop accepting connections, but their listen queue might still contain new connections that will not be transferred to the new workers. Worse: if you change the configuration again while the old workers have not stopped handling their current connections, they would be killed, and the live connections would stop right there. Or the processes could just pile up and hog resources.</p>
<p>We use an immutable infrastructure approach. For every new version of an application, instead of modifying the backend servers in place, we spawn new ones. This means that we must update the HAProxy configuration to route an application to the new backend servers. And so, we must update the global configuration on every new commit from any of our clients. With multiple configuration changes every second, we&#39;re bound to lose some connections.</p>
<h2 id="hot-configuration-reloading-vs-restarting-processes">Hot configuration reloading VS restarting processes</h2>
<p>That&#39;s why we set out to build a new reverse proxy that could handle configuration changes without losing connections.</p>
<p>First, we decided configuration updates should happen without restarts. The ability to change the configuration of a running process is essential because launching new workers, transferring the current state between them, and removing old workers gracefully, is a task with a high impact on server load and latency. You&#39;re essentially doubling the server&#39;s resource usage, and launching a lot of new processes every time.</p>
<p>This is a cost we have to pay for executable upgrades, though, but those happen less frequently. For that case, we provide ways to do upgrades without downtimes, either automatically, or with more hand holding (you decide when to launch each step) if you want.</p>
<h2 id="shared-and-synchronized-configuration-vs-data-locality">Shared and synchronized configuration VS data locality</h2>
<p>To handle configuration changes, Sōzu uses a master/workers architecture, with the master receiving configuration changes and transmitting it to clients. Each worker has its own copy of the configuration: if workers had something like a shared memory segment for this, we would need to add cross process synchronization, and make sure that accessing this data is safe, fiddle with pointers, etc. The whole configuration state is not very large (certificates and keys are the biggest part), so we can keep copies in every process. This makes for better data locality and is easier to handle overall.</p>
<h2 id="configuration-changes-push-vs-pull">Configuration changes: push VS pull</h2>
<p>To get configuration updates, there are basically two solutions:</p>
<ul>
<li>The proxy polls new configuration from files or from tools like Kubernetes, etcd, Consul...</li>
<li>The proxy exposes a communication channel to get the new configuration</li>
</ul>
<p>The first solution is essentially what Traefik, the reverse proxy built in Go, does. We chose the second solution because we thought it is not the proxy&#39;s reponsibility to communicate with those tools. After all, it is just a pipe, it should not have to understand all the existing configuration protocols. So we expose a channel, and we build tools to bridge between the configuration backend and Sōzu.</p>
<p>That way, we do not impose the configuration format, the proxy binary stays small, and anyone can write their own tool to drive it, in any language they want.</p>
<p>The channel is a Unix socket. We decided on this instead of exposing a TCP port on localhost because anybody on the machine could connect to it, while a Unix socket has its access protected by filesystem rights.</p>
<p>The protocol is quite simple: JSON objects representing the proxy orders and their answers, separated by null characters. Writing new tools is as easy as writing directly to a file, you can even make tools in bash. If you want more control, we provide libraries in Rust to wrap this channel. Other libraries will appear soon to do it easily from other languages.</p>
<h2 id="working-with-configuration-diffs-vs-replacing-the-configuration">Working with configuration diffs VS replacing the configuration</h2>
<p>An easy way to implement runtime configuration changes might be to replace the whole configuration every time there&#39;s a change, and start handling the new routing right away. We choose another way: Sōzu works with configuration diffs. The messages you send through the Unix socket contain information like &quot;add this specific certificate&quot;, &quot;add this backend server to this application&quot;, &quot;remove this domain name for this application&quot;. This is useful because when you replace the whole configuration at once, you lose information.</p>
<p>You might have to remove some openssl contexts still storing old certificates. Or you might want to know when you can drop a backend server: if you tell Sōzu to remove a backend server for an application, it will first tell you that it acknowledges the change and will stop routing new traffic to this server, but will also tell you if there are still connections going on to this server. It will notify you once the connections are gone, so you can safely drop that server.</p>
<p>This also means configuration changes are smaller: instead of loading a complete configuration, you just send a few small messages.</p>
<p>To accomodate for this solution, the configuration protocol is more than request-response: there are 3 possible answers: Error, Ok or Processing. If the proxy answers Processing, that means the actual result might come later. It can send other Processing messages, to keep you posted on the number of current connections or other issues, and send you Ok or Error after a while.</p>
<h2 id="design-goals-for-a-tool-with-hot-reconfiguration">Design goals for a tool with hot reconfiguration</h2>
<p>We worked for a while on this and had time to explore the requirements for a tool with hot reconfiguration. There are three important points:</p>
<ul>
<li>You have to bake runtime reconfiguration in from the beginning. You cannot retrofit
that correctly in an actual system by messing with backend config switches or other hacks</li>
<li>Do runtime reconfiguration, not process restarts. You might get away with it or
blue/green deployments if your configuration does not change often and connections
are short lived. Our experience shows it does not happen like this</li>
<li>Work with configuration diffs instead of replacing the configuration. Otherwise,
you&#39;re losing important information for your infrastructure</li>
</ul>
<p>We hope this architecture will make it easily to make long lived and reliable systems, and we hope people will build awesome tools around <a href="https://github.com/sozu-proxy/sozu">Sōzu</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Async, Futures, AMQP, pick three</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2017/03/28/lapin-new-rust-amqp-library/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Tue, 28 Mar 2017 19:34:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Rust]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2017/03/28/lapin-new-rust-amqp-library/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>A few weeks ago, we set out to develop an <a href="https://github.com/geal/lapin">AMQP client library in Rust</a>, and I&#39;m happy to release it now! We will integrate it in more and more of our tools in the future.</p>
<span id="more-2810"></span>

<h2 id="design-a-futures-based-api-and-a-low-level-api">Design: a futures based API and a low level API</h2>
<p>One of our goals was to leverage <a href="http://tokio.rs">tokio</a> and <a href="https://github.com/alexcrichton/futures-rs">futures</a> to make an API that is easy to use, but also allowing for lower level implementations using directly an event loop with something like <a href="https://github.com/carllerche/mio/">mio</a>.</p>
<p>This was a bit challenging, but we ended up with two crates:</p>
<ul>
<li><a href="https://crates.io/crates/lapin-async">lapin-async</a>, the low level library</li>
<li><a href="https://crates.io/crates/lapin-futures">lapin-futures</a> wrapping lapin-async in futures</li>
</ul>
<p>The resulting code can work with tokio-core&#39;s event reactor, or even <a href="https://github.com/alexcrichton/futures-rs/tree/master/futures-cpupool">futures-cpupool</a>.</p>
<p>The libraries use, for the network frame format: <a href="https://github.com/Geal/nom">nom</a>, the Rust parser combinators library; <a href="https://github.com/geal/cookie-factory">cookie-factory</a>, the experimental serialization library with the same approach as nom. It is a great example of employing <a href="https://github.com/Geal/lapin/blob/master/futures/src/transport.rs">nom inside a tokio transport</a>, and integrating a complex protocol&#39;s state machine directly with <a href="https://github.com/tokio-rs/tokio-io">tokio-io</a>. We will release a tutorial on how to write such a protocol soon.</p>
<p>The libraries are also designed to be completely independent from the network stream: you can use a basic TCP stream, a TLS stream or a unix socket, and you won&#39;t be blocked by rust-openssl version conflicts between many libraries (which was a big issue for us).</p>
<h2 id="using-the-futures-api-publishing-a-message">Using the futures API: publishing a message</h2>
<p>Every method returns a future, to let you chain them: the <code>connect</code> result will give a correct client once the complete AMQP handshake was performed, the channel will be available once the server has answered, etc. But the nature of AMQP makes parallel work on the same connection easy.</p>
<pre><code class="language-rust">extern crate futures;
extern crate tokio_core;
extern crate lapin_futures as lapin;

use std::default::Default;
use futures::Stream;
use futures::future::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicPublishOptions,QueueDeclareOptions};

fn main() {

  // create the reactor
  let mut core = Core::new().unwrap();
  let handle = core.handle();
  let addr = &quot;127.0.0.1:5672&quot;.parse().unwrap();

  core.run(

    TcpStream::connect(&amp;addr, &amp;handle).and_then(|stream| {

      // connect() returns a future of an AMQP Client
      // that resolves once the handshake is done
      lapin::client::Client::connect(
        stream,
        &amp;ConnectionOptions{
          username: &quot;guest&quot;,
          password: &quot;guest&quot;,
          ..Default::default()
        }
      )
    }).and_then(|client| {

      // create_channel returns a future that is resolved
      // once the channel is successfully created
      client.create_channel()
    }).and_then(|channel| {
      let id = channel.id;
      info!(&quot;created channel with id: {}&quot;, id);

      channel.queue_declare(&quot;hello&quot;, &amp;QueueDeclareOptions::default()).and_then(move |_| {
        info!(&quot;channel {} declared queue {}&quot;, id, &quot;hello&quot;);

        channel.basic_publish(
          &quot;hello&quot;,
          b&quot;hello from tokio&quot;,
          &amp;BasicPublishOptions::default(),
          BasicProperties::default().with_user_id(&quot;guest&quot;.to_string()).with_reply_to(&quot;foobar&quot;.to_string())
        )
      })
    })
  ).unwrap();
}
</code></pre>
<p>Every struct of the API, be it a client, channel or consumer, holds a synchronized reference to the underlying transport, so you could call it from any thread.</p>
<h2 id="using-the-futures-api-creating-a-consumer">Using the futures API: creating a consumer</h2>
<p>When you call the <code>basic_consume</code> method, it returns a future of a <code>Consumer</code>. It implements <code>Stream</code>, so this can reuse all the related combinators from the futures library.</p>
<pre><code class="language-rust">extern crate futures;
extern crate tokio_core;
extern crate lapin_futures as lapin;

use futures::Stream;
use futures::future::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicConsumeOptions,QueueDeclareOptions};

fn main() {

  // create the reactor
  let mut core = Core::new().unwrap();
  let handle = core.handle();
  let addr = &quot;127.0.0.1:5672&quot;.parse().unwrap();

  core.run(

    TcpStream::connect(&amp;addr, &amp;handle).and_then(|stream| {
      lapin::client::Client::connect(stream, &amp;ConnectionOptions::default())
    }).and_then(|client| {

      client.create_channel()
    }).and_then(|channel| {

      let id = channel.id;
      info!(&quot;created channel with id: {}&quot;, id);

      let ch = channel.clone();
      channel.queue_declare(&quot;hello&quot;, &amp;QueueDeclareOptions::default()).and_then(move |_| {
        info!(&quot;channel {} declared queue {}&quot;, id, &quot;hello&quot;);

        channel.basic_consume(&quot;hello&quot;, &quot;my_consumer&quot;, &amp;BasicConsumeOptions::default())
      }).and_then(|stream| {
        info!(&quot;got consumer stream&quot;);

        stream.for_each(|message| {
          debug!(&quot;got message: {:?}&quot;, message);
          info!(&quot;decoded message: {:?}&quot;, std::str::from_utf8(&amp;message.data).unwrap());

          ch.basic_ack(message.delivery_tag);
          Ok(())
        })
      })
    })
  ).unwrap();
}
</code></pre>
<h2 id="looking-under-the-hood-lapin-async">Looking under the hood: lapin-async</h2>
<p>The lapin-async library is meant for use with an event loop that will tell you when you can read or write on the underlying stream. As such, it does not own the network stream, nor the buffers used to read and write. You handle your IO, then pass the buffers to the protocol&#39;s state machine. It will update its state, tell you how much data it consumed, give you data to send to the network. And then you can query it for state changes.</p>
<p>There are various reasons for an architecture like this one:</p>
<ul>
<li>a library that owns the IO stream usually does not play well with event loops</li>
<li>the developer might want to make their own optimizations with sockets and buffers</li>
<li>separating the IO makes the library easy to test: you can pass buffers (or even
complete structs) to the state machine and verify the expected state easily</li>
</ul>
<p>More generally, a protocol library should not dictate how the application handles its networking.</p>
<p>As an example of how it could run:</p>
<pre><code class="language-rust">let mut stream = TcpStream::connect(&quot;127.0.0.1:5672&quot;).unwrap();
stream.set_nonblocking(true);

let capacity = 8192;
let mut send_buffer    = Buffer::with_capacity(capacity as usize);
let mut receive_buffer = Buffer::with_capacity(capacity as usize);

let mut conn: Connection = Connection::new();
assert_eq!(conn.connect().unwrap(), ConnectionState::Connecting(ConnectingState::SentProtocolHeader));
loop {
  match conn.run(&amp;mut stream, &amp;mut send_buffer, &amp;mut receive_buffer) {
    Err(e) =&gt; panic!(&quot;could not connect: {:?}&quot;, e),
    Ok(ConnectionState::Connected) =&gt; break,
    Ok(state) =&gt; info!(&quot;now at state {:?}, continue&quot;, state),
  }
  thread::sleep(time::Duration::from_millis(100));
}
info!(&quot;CONNECTED&quot;);
</code></pre>
<p>the <code>run</code> method is a helper that will read from the network, parse frames, update internal state with the frames, write new frames to the network. We loop until the state switches to &quot;connected&quot;. Most of the behaviour is on that model.</p>
<p>While the lapin-async library has most of the functionality, it is still a lot of manual work to manage, and you should prefer the futures based library.</p>
<h2 id="a-young-library">A young library</h2>
<p>This is an early release, and it is missing a lot of features, but the design makes them easy to implement.</p>
<p>Right now, the only authentication method is &quot;plain&quot;, you can create and close channels, create queues (without options), and use the <a href="https://docs.rs/lapin-futures/0.3.0/lapin_futures/channel/struct.Channel.html">methods from the &quot;basic&quot; AMQP class</a>. RabbitMQ&#39;s <a href="https://www.rabbitmq.com/confirms.html">&quot;publisher confirms&quot; extension</a> is also available.</p>
<p>It is mainly missing the &quot;nack&quot; extension, and the exchange and transaction handling methods.</p>
<p>More features will come in the following weeks, and if you want to <a href="https://github.com/geal/lapin">contribute</a>, you&#39;re very welcome :)</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/lapin-banner-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>A few weeks ago, we set out to develop an <a href="https://github.com/geal/lapin">AMQP client library in Rust</a>, and I&#39;m happy to release it now! We will integrate it in more and more of our tools in the future.</p>
<span id="more-2810"></span>

<h2 id="design-a-futures-based-api-and-a-low-level-api">Design: a futures based API and a low level API</h2>
<p>One of our goals was to leverage <a href="http://tokio.rs">tokio</a> and <a href="https://github.com/alexcrichton/futures-rs">futures</a> to make an API that is easy to use, but also allowing for lower level implementations using directly an event loop with something like <a href="https://github.com/carllerche/mio/">mio</a>.</p>
<p>This was a bit challenging, but we ended up with two crates:</p>
<ul>
<li><a href="https://crates.io/crates/lapin-async">lapin-async</a>, the low level library</li>
<li><a href="https://crates.io/crates/lapin-futures">lapin-futures</a> wrapping lapin-async in futures</li>
</ul>
<p>The resulting code can work with tokio-core&#39;s event reactor, or even <a href="https://github.com/alexcrichton/futures-rs/tree/master/futures-cpupool">futures-cpupool</a>.</p>
<p>The libraries use, for the network frame format: <a href="https://github.com/Geal/nom">nom</a>, the Rust parser combinators library; <a href="https://github.com/geal/cookie-factory">cookie-factory</a>, the experimental serialization library with the same approach as nom. It is a great example of employing <a href="https://github.com/Geal/lapin/blob/master/futures/src/transport.rs">nom inside a tokio transport</a>, and integrating a complex protocol&#39;s state machine directly with <a href="https://github.com/tokio-rs/tokio-io">tokio-io</a>. We will release a tutorial on how to write such a protocol soon.</p>
<p>The libraries are also designed to be completely independent from the network stream: you can use a basic TCP stream, a TLS stream or a unix socket, and you won&#39;t be blocked by rust-openssl version conflicts between many libraries (which was a big issue for us).</p>
<h2 id="using-the-futures-api-publishing-a-message">Using the futures API: publishing a message</h2>
<p>Every method returns a future, to let you chain them: the <code>connect</code> result will give a correct client once the complete AMQP handshake was performed, the channel will be available once the server has answered, etc. But the nature of AMQP makes parallel work on the same connection easy.</p>
<pre><code class="language-rust">extern crate futures;
extern crate tokio_core;
extern crate lapin_futures as lapin;

use std::default::Default;
use futures::Stream;
use futures::future::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicPublishOptions,QueueDeclareOptions};

fn main() {

  // create the reactor
  let mut core = Core::new().unwrap();
  let handle = core.handle();
  let addr = &quot;127.0.0.1:5672&quot;.parse().unwrap();

  core.run(

    TcpStream::connect(&amp;addr, &amp;handle).and_then(|stream| {

      // connect() returns a future of an AMQP Client
      // that resolves once the handshake is done
      lapin::client::Client::connect(
        stream,
        &amp;ConnectionOptions{
          username: &quot;guest&quot;,
          password: &quot;guest&quot;,
          ..Default::default()
        }
      )
    }).and_then(|client| {

      // create_channel returns a future that is resolved
      // once the channel is successfully created
      client.create_channel()
    }).and_then(|channel| {
      let id = channel.id;
      info!(&quot;created channel with id: {}&quot;, id);

      channel.queue_declare(&quot;hello&quot;, &amp;QueueDeclareOptions::default()).and_then(move |_| {
        info!(&quot;channel {} declared queue {}&quot;, id, &quot;hello&quot;);

        channel.basic_publish(
          &quot;hello&quot;,
          b&quot;hello from tokio&quot;,
          &amp;BasicPublishOptions::default(),
          BasicProperties::default().with_user_id(&quot;guest&quot;.to_string()).with_reply_to(&quot;foobar&quot;.to_string())
        )
      })
    })
  ).unwrap();
}
</code></pre>
<p>Every struct of the API, be it a client, channel or consumer, holds a synchronized reference to the underlying transport, so you could call it from any thread.</p>
<h2 id="using-the-futures-api-creating-a-consumer">Using the futures API: creating a consumer</h2>
<p>When you call the <code>basic_consume</code> method, it returns a future of a <code>Consumer</code>. It implements <code>Stream</code>, so this can reuse all the related combinators from the futures library.</p>
<pre><code class="language-rust">extern crate futures;
extern crate tokio_core;
extern crate lapin_futures as lapin;

use futures::Stream;
use futures::future::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicConsumeOptions,QueueDeclareOptions};

fn main() {

  // create the reactor
  let mut core = Core::new().unwrap();
  let handle = core.handle();
  let addr = &quot;127.0.0.1:5672&quot;.parse().unwrap();

  core.run(

    TcpStream::connect(&amp;addr, &amp;handle).and_then(|stream| {
      lapin::client::Client::connect(stream, &amp;ConnectionOptions::default())
    }).and_then(|client| {

      client.create_channel()
    }).and_then(|channel| {

      let id = channel.id;
      info!(&quot;created channel with id: {}&quot;, id);

      let ch = channel.clone();
      channel.queue_declare(&quot;hello&quot;, &amp;QueueDeclareOptions::default()).and_then(move |_| {
        info!(&quot;channel {} declared queue {}&quot;, id, &quot;hello&quot;);

        channel.basic_consume(&quot;hello&quot;, &quot;my_consumer&quot;, &amp;BasicConsumeOptions::default())
      }).and_then(|stream| {
        info!(&quot;got consumer stream&quot;);

        stream.for_each(|message| {
          debug!(&quot;got message: {:?}&quot;, message);
          info!(&quot;decoded message: {:?}&quot;, std::str::from_utf8(&amp;message.data).unwrap());

          ch.basic_ack(message.delivery_tag);
          Ok(())
        })
      })
    })
  ).unwrap();
}
</code></pre>
<h2 id="looking-under-the-hood-lapin-async">Looking under the hood: lapin-async</h2>
<p>The lapin-async library is meant for use with an event loop that will tell you when you can read or write on the underlying stream. As such, it does not own the network stream, nor the buffers used to read and write. You handle your IO, then pass the buffers to the protocol&#39;s state machine. It will update its state, tell you how much data it consumed, give you data to send to the network. And then you can query it for state changes.</p>
<p>There are various reasons for an architecture like this one:</p>
<ul>
<li>a library that owns the IO stream usually does not play well with event loops</li>
<li>the developer might want to make their own optimizations with sockets and buffers</li>
<li>separating the IO makes the library easy to test: you can pass buffers (or even
complete structs) to the state machine and verify the expected state easily</li>
</ul>
<p>More generally, a protocol library should not dictate how the application handles its networking.</p>
<p>As an example of how it could run:</p>
<pre><code class="language-rust">let mut stream = TcpStream::connect(&quot;127.0.0.1:5672&quot;).unwrap();
stream.set_nonblocking(true);

let capacity = 8192;
let mut send_buffer    = Buffer::with_capacity(capacity as usize);
let mut receive_buffer = Buffer::with_capacity(capacity as usize);

let mut conn: Connection = Connection::new();
assert_eq!(conn.connect().unwrap(), ConnectionState::Connecting(ConnectingState::SentProtocolHeader));
loop {
  match conn.run(&amp;mut stream, &amp;mut send_buffer, &amp;mut receive_buffer) {
    Err(e) =&gt; panic!(&quot;could not connect: {:?}&quot;, e),
    Ok(ConnectionState::Connected) =&gt; break,
    Ok(state) =&gt; info!(&quot;now at state {:?}, continue&quot;, state),
  }
  thread::sleep(time::Duration::from_millis(100));
}
info!(&quot;CONNECTED&quot;);
</code></pre>
<p>the <code>run</code> method is a helper that will read from the network, parse frames, update internal state with the frames, write new frames to the network. We loop until the state switches to &quot;connected&quot;. Most of the behaviour is on that model.</p>
<p>While the lapin-async library has most of the functionality, it is still a lot of manual work to manage, and you should prefer the futures based library.</p>
<h2 id="a-young-library">A young library</h2>
<p>This is an early release, and it is missing a lot of features, but the design makes them easy to implement.</p>
<p>Right now, the only authentication method is &quot;plain&quot;, you can create and close channels, create queues (without options), and use the <a href="https://docs.rs/lapin-futures/0.3.0/lapin_futures/channel/struct.Channel.html">methods from the &quot;basic&quot; AMQP class</a>. RabbitMQ&#39;s <a href="https://www.rabbitmq.com/confirms.html">&quot;publisher confirms&quot; extension</a> is also available.</p>
<p>It is mainly missing the &quot;nack&quot; extension, and the exchange and transaction handling methods.</p>
<p>More features will come in the following weeks, and if you want to <a href="https://github.com/geal/lapin">contribute</a>, you&#39;re very welcome :)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Falling for Rust</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2016/11/02/falling-for-rust/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Wed, 02 Nov 2016 16:02:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Rust]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2016/11/02/falling-for-rust/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>If you ever talked to me, or looked at my Twitter feed, you may have noticed that I campaign loudly for the Rust programming language. I am not going to stop. In fact, it will only go crescendo!</p>
<span id="more-2809"></span>

<p>I got involved with that language <a href="https://github.com/Geal/rust-csv/commit/adaf9f09a3b3aa4889dc0213c88a83ae02219115">a while ago</a>, when I was looking for a safe alternative to C, for my research for the <a href="http://videolan.org/">Videolan</a> project. It was an interesting time, since the language changed often. I basically had to rewrite most of my code every two weeks. But since the release of Rust 1.0 in May 2015, it has gone from being an experimental tool to a serious contender for other system programming platforms.</p>
<p>I&#39;m no longer the only one talking about Rust in the office, and the funny thing is that I&#39;m not the first one to put some Rust in production! <a href="https://github.com/Keruspe">Marc-Antoine</a> started rewriting some management tools from bash to Rust, and they were working so well that they quickly ended up running on the platform.</p>
<h2 id="why-we-are-betting-on-rust-for-the-future">Why we are betting on Rust for the future</h2>
<p>We have always used heterogeneous technologies to manage the platform, mainly because we must know how they behave to host them properly. We test and use everything, and running them on our platform gives use the long term view.</p>
<p>For us, Rust gave substantial benefits from the beginning, and showed it is adapted to the way we run production code.</p>
<h2 id="static-binaries">Static binaries</h2>
<p>Like C, C++ and Go, Rust can build single file binaries that you will upload on a server and run directly, without any installed dependencies except a libc. This is significant, because when you want to reduce the base disk size and the boot time of a virtual machine, installing a lot of dependencies, like a Python virtual machine and its standard library, quickly takes its toll.</p>
<p>We built an immutable infrastructure: we do not modify virtual machines directly, instead we modify the base image and start new machines from scratch. So we&#39;re not too concerned about updating a dynamic library separately from the executable loading it.</p>
<h2 id="reliability">Reliability</h2>
<p>Memory safety is one of the biggest arguments of Rust, but it goes further than that. There&#39;s a big emphasis on providing safe patterns everywhere. As an example, data is immutable by default, you need to explicitely add &quot;mut&quot; to a variable to be able to change it. Most APIs will return an &quot;Option&quot; or &quot;Result&quot; type to safely wrap an actual result or an error, and there are lots of ways to manipulate them easily. Ignoring an error means explicitely adding an &quot;unwrap()&quot; call to that function&#39;s result.</p>
<p>All this means that by default, you write Rust code that should not crash, and that should not modify data unless explicitely stated. Add in a good type system to represent correctly and check assumptions. And some unit tests, because we know type systems don&#39;t replace them (although you don&#39;t need to write as many unit tests as in languages with simpler type systems).</p>
<p>You then get code that will rarely fail, and in which you can easily find the parts that break assumptions (example: grep for unsafe and unwrap). There will still be bugs, but you will work more on functional parts than on plumbing.</p>
<h2 id="stability">Stability</h2>
<p>Rust has no garbage collection. Most of the time, you won&#39;t care about this, because the benefit of using a language with a garbage collector outweights any of the usual concerns, like performance. Not caring about memory allocation lets you write code without fear of most memory vulnerabilities, and avoid most instances of memory leaks (sadly, not all of them). The real issue in production: the garbage collector disturbs the program&#39;s behaviour by regularly executing a task that goes through the memory to detect what to deallocate. Of course, it&#39;s not always as simple as a mark and sweep, but GC will still take some CPU time and introduce latency in other tasks. In situations of intense memory pressures (like, a lot of requests to handle), keeping lots of unusable memory around or stopping other tasks can trigger catastrophic failures. When the issue appears, people will typically spend a lot of time tweaking GC settings or rewriting code to avoid it. Either way, it&#39;s a lot of work.</p>
<p>Rust avoids garbage collection by handling memory allocation precisely at compile time. You get the same benefits without the runtime cost. The result? an application with predictable CPU and RAM usage. Typically, the RAM usage graphs will be flat, compared to the sawtooth graphs with garbage collectors. Predictability is a key feature for stable production systems: you can make more assumptions about the runtime behaviour and plan for resource usage.</p>
<p>On that point, you get another benefit: it is easy to make boundaries on resource usage. If I know roughly how much memory I need for X concurrent requests, and if I know the capacity of my server, I can put a soft limit on the number of concurrent requests, at which I set up an alert, and a hard limit, because I know that past that limit, the server will just stop answering properly.</p>
<h2 id="not-worrying-about-it">Not worrying about it</h2>
<p>For us, these benefits make a strong case for Rust as a reliable building block for a production platform. This is the piece of code we don&#39;t have to worry about, and it will enable others to run safely.</p>
<h2 id="you-can-do-it-too">You can do it, too!</h2>
<p>Right now, we are replacing small parts of the infrastructure, and we will soon unveil more interesting tools. In the meantime, we added <a href="https://stagingv6.cleverapps.io/doc/rust/rust/">Rust support in beta on our platform</a>: now you can deploy Rust web applications in a few commands.</p>
<p>Go ahead and put Rust in production!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/falling-rust-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>If you ever talked to me, or looked at my Twitter feed, you may have noticed that I campaign loudly for the Rust programming language. I am not going to stop. In fact, it will only go crescendo!</p>
<span id="more-2809"></span>

<p>I got involved with that language <a href="https://github.com/Geal/rust-csv/commit/adaf9f09a3b3aa4889dc0213c88a83ae02219115">a while ago</a>, when I was looking for a safe alternative to C, for my research for the <a href="http://videolan.org/">Videolan</a> project. It was an interesting time, since the language changed often. I basically had to rewrite most of my code every two weeks. But since the release of Rust 1.0 in May 2015, it has gone from being an experimental tool to a serious contender for other system programming platforms.</p>
<p>I&#39;m no longer the only one talking about Rust in the office, and the funny thing is that I&#39;m not the first one to put some Rust in production! <a href="https://github.com/Keruspe">Marc-Antoine</a> started rewriting some management tools from bash to Rust, and they were working so well that they quickly ended up running on the platform.</p>
<h2 id="why-we-are-betting-on-rust-for-the-future">Why we are betting on Rust for the future</h2>
<p>We have always used heterogeneous technologies to manage the platform, mainly because we must know how they behave to host them properly. We test and use everything, and running them on our platform gives use the long term view.</p>
<p>For us, Rust gave substantial benefits from the beginning, and showed it is adapted to the way we run production code.</p>
<h2 id="static-binaries">Static binaries</h2>
<p>Like C, C++ and Go, Rust can build single file binaries that you will upload on a server and run directly, without any installed dependencies except a libc. This is significant, because when you want to reduce the base disk size and the boot time of a virtual machine, installing a lot of dependencies, like a Python virtual machine and its standard library, quickly takes its toll.</p>
<p>We built an immutable infrastructure: we do not modify virtual machines directly, instead we modify the base image and start new machines from scratch. So we&#39;re not too concerned about updating a dynamic library separately from the executable loading it.</p>
<h2 id="reliability">Reliability</h2>
<p>Memory safety is one of the biggest arguments of Rust, but it goes further than that. There&#39;s a big emphasis on providing safe patterns everywhere. As an example, data is immutable by default, you need to explicitely add &quot;mut&quot; to a variable to be able to change it. Most APIs will return an &quot;Option&quot; or &quot;Result&quot; type to safely wrap an actual result or an error, and there are lots of ways to manipulate them easily. Ignoring an error means explicitely adding an &quot;unwrap()&quot; call to that function&#39;s result.</p>
<p>All this means that by default, you write Rust code that should not crash, and that should not modify data unless explicitely stated. Add in a good type system to represent correctly and check assumptions. And some unit tests, because we know type systems don&#39;t replace them (although you don&#39;t need to write as many unit tests as in languages with simpler type systems).</p>
<p>You then get code that will rarely fail, and in which you can easily find the parts that break assumptions (example: grep for unsafe and unwrap). There will still be bugs, but you will work more on functional parts than on plumbing.</p>
<h2 id="stability">Stability</h2>
<p>Rust has no garbage collection. Most of the time, you won&#39;t care about this, because the benefit of using a language with a garbage collector outweights any of the usual concerns, like performance. Not caring about memory allocation lets you write code without fear of most memory vulnerabilities, and avoid most instances of memory leaks (sadly, not all of them). The real issue in production: the garbage collector disturbs the program&#39;s behaviour by regularly executing a task that goes through the memory to detect what to deallocate. Of course, it&#39;s not always as simple as a mark and sweep, but GC will still take some CPU time and introduce latency in other tasks. In situations of intense memory pressures (like, a lot of requests to handle), keeping lots of unusable memory around or stopping other tasks can trigger catastrophic failures. When the issue appears, people will typically spend a lot of time tweaking GC settings or rewriting code to avoid it. Either way, it&#39;s a lot of work.</p>
<p>Rust avoids garbage collection by handling memory allocation precisely at compile time. You get the same benefits without the runtime cost. The result? an application with predictable CPU and RAM usage. Typically, the RAM usage graphs will be flat, compared to the sawtooth graphs with garbage collectors. Predictability is a key feature for stable production systems: you can make more assumptions about the runtime behaviour and plan for resource usage.</p>
<p>On that point, you get another benefit: it is easy to make boundaries on resource usage. If I know roughly how much memory I need for X concurrent requests, and if I know the capacity of my server, I can put a soft limit on the number of concurrent requests, at which I set up an alert, and a hard limit, because I know that past that limit, the server will just stop answering properly.</p>
<h2 id="not-worrying-about-it">Not worrying about it</h2>
<p>For us, these benefits make a strong case for Rust as a reliable building block for a production platform. This is the piece of code we don&#39;t have to worry about, and it will enable others to run safely.</p>
<h2 id="you-can-do-it-too">You can do it, too!</h2>
<p>Right now, we are replacing small parts of the infrastructure, and we will soon unveil more interesting tools. In the meantime, we added <a href="https://stagingv6.cleverapps.io/doc/rust/rust/">Rust support in beta on our platform</a>: now you can deploy Rust web applications in a few commands.</p>
<p>Go ahead and put Rust in production!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Let your logs help you</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2016/05/23/let-your-logs-help-you/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Mon, 23 May 2016 14:12:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[cloud]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2016/05/23/let-your-logs-help-you/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>We use logs for everything, to track errors, measure performance, keep a journal of how our software runs, or even debug code in production. Since we use it so much, we should be good at it by now, right?</p>
<span id="more-2805"></span>

<p>Surprisingly, well written, useful logs are not frequent. The norm is logs full of garbage, old debug statements (&quot;I was here&quot;), unhandled exceptions, and non actionable information.</p>
<p>You read the file, looking for that one word, that should be followed by another word, but two threads are performing the same task and each will output the two log messages. Maybe, if you look at the timing, you&#39;ll know which is which.</p>
<p>You try to make sense of multiple interleaving messages, but they come from two machines with desynchronized clocks, and one of them is sending batches of messages every second instead of sending them as they are generated. You wonder if the code is executing in the right order and write essays about causality and determinism.</p>
<p>I have a hundred stories like those, and there&#39;s a common theme, a root cause for the way we write logs. As a developer, we think of them first as a developer&#39;s tool, not as the main interface to check your app&#39;s health in production. They are meant to be read with <code>tail</code> while the application runs on small workloads, for a limited time.</p>
<h2 id="developer-logs-vs-ops-logs">Developer logs VS ops logs</h2>
<p>Managing software in production means detecting when something is wrong, but knowing every bit of the program&#39;s state is a counterproductive way of doing it.</p>
<p>You want to know the important metrics:</p>
<ul>
<li>someone consulted a web page: leave that to your web analytics software</li>
<li>someone consulted a web page, but the app failed to answer: log it</li>
<li>someone consulted a web page, and the page&#39;s size is larger than the buffer:
don&#39;t log it, it&#39;s useless most of the time</li>
<li>someone bought something: log it, even if you have a backend to see that</li>
<li>someone bought something and the server failed: log it and send an email to
the dev team to fix it right now</li>
</ul>
<p>More generally, here is a scale from ops log to developer log:</p>
<ul>
<li>a transaction has been performed, successfully or not =&gt; ops logs</li>
<li>individual steps of that transaction failed =&gt; ops logs</li>
<li>individual steps of that transaction succeeded =&gt; dev logs</li>
<li>value of variable X at point Y in code =&gt; definitely developer logs</li>
</ul>
<p>Here is an example (from code I wrote) of developer centric logs:</p>
<script src="https://gist.github.com/cnivolle/3bf213c8f22c88dbd23f2ae550d175d7.js"></script>

<p>I am not saying developer info should not appear in logs. Just that it is best hidden under &quot;debug&quot; or &quot;trace&quot; levels, if your logging system supports levels (most do). It is fine to have useless messages in there, as long as they are not used in production/ It is fine to use &quot;printf debugging&quot; in development, but it should never appear in production.</p>
<p>Your goal in writing logs is to spare time for the person that will read them. It may be a sysadmin in your company, a client using your software, or yourself, six months from now, trying to put the app back online at 2 AM. Please think of your future self.</p>
<h2 id="making-the-logs-more-ops-friendly">Making the logs more ops friendly</h2>
<p>To make the life of the journal&#39;s reader easier, you need to optimize for two reading engines:</p>
<ul>
<li>filtering software, like grep</li>
<li>the human eye</li>
</ul>
<p>Why the human eye?</p>
<p>Because we are good at detecting patterns, and filtering out the useless parts of an image. If a sequence of three lines appears regularly, we will see it easily. If we only care about the message part of the log, not the prefix (time, PID, etc), we will focus our attention on it and ignore the rest.</p>
<p>The consequence is that everything that will break the brain&#39;s flow will make your logs harder to read. if the user id appears at the beginning of one message, but at the end of another one, it will be much harder to see which messages are related.</p>
<p>Fortunately, what works well for the human eye also works for filtering tools. Standardized, common prefixes are easy to search for, and easy to recognize. Related information should have identifying information, always stored in the same place.</p>
<h2 id="practical-advice">Practical advice</h2>
<p>How can you apply those principles right now? You begin by making a small wrapper over your logging library to automatically insert useful information, in a fixed format:</p>
<ul>
<li><em>a timestamp, preferably in ISO8601</em> (easier to read) at UTC (no timezone conversion
when reading). By the way, make sure your servers are all set up to use the same
timezone, this will save headaches</li>
<li><em>a timestamp from a monotonic clock</em> if your application is time critical</li>
<li>identify the current instance: add a <em>server identifier</em> (name, IP, whatever)
and an <em>instance identifier</em> (process id, thread id)</li>
<li><em>the running code&#39;s version</em> (commit id or version number)</li>
<li>the file&#39;s name, line number, class and function names are useful for debugging,
so add them for the &quot;debug&quot; and &quot;trace&quot; levels (but don&#39;t activate those levels in
production unless you have a good reason)</li>
<li>add some correlation information: the <em>user id</em>, a <em>request id</em>, anything that
will let you track which action resulted in which messages</li>
<li><em>code status</em>: are we in the middle of an error? Is something pending?</li>
<li>then, at the end, you can put a written message. You can use structured logging
instead of raw text if you want to track data with more automated tools</li>
</ul>
<p>This is a lot of information to put on one line, but we have great tools at our disposal. We can filter on one of these fields and remove it from the output. We can use terminals larger than 80 characters. We can even color parts of those logs to let the eye separate them easily.</p>
<p>If I had to rewrite the previous example logs that way:</p>
<script src="https://gist.github.com/cnivolle/2486db9d0c73a9986146d85f4fcbf1bc.js"></script>

<p>Side note: beware exceptions. It is fine to display an exception&#39;s stack trace while debugging the code, but an exception in production means two things:</p>
<ul>
<li>you forgot to replace the stacktrace with a proper error message for an exception
you handled</li>
<li>there&#39;s an exception that you do not handle in your code</li>
</ul>
<p>In both cases, it is a signal that something wrong happened and that it should be fixed soon. Also, it usually messes up the log&#39;s format, and fills up the log with useless information. I once heard about an app that needed to run on machines with big disks and big CPUs, because there were so many exceptions logged that the machine could not keep up.</p>
<p>Anyway, The goal of that approach is to have a common format for every message, simple to parse and filter. Make sure that those common parts have the same length, and that you use the same separators everywhere. Tabs are usually better than spaces, since we rarely use them in log messages. This will make the logs easier to read, and much easier to filter for.</p>
<p>With a good logging discipline, you will soon see non conforming messages as bugs, and you will be much more efficient when debugging and operating your application.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/logs-help-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>We use logs for everything, to track errors, measure performance, keep a journal of how our software runs, or even debug code in production. Since we use it so much, we should be good at it by now, right?</p>
<span id="more-2805"></span>

<p>Surprisingly, well written, useful logs are not frequent. The norm is logs full of garbage, old debug statements (&quot;I was here&quot;), unhandled exceptions, and non actionable information.</p>
<p>You read the file, looking for that one word, that should be followed by another word, but two threads are performing the same task and each will output the two log messages. Maybe, if you look at the timing, you&#39;ll know which is which.</p>
<p>You try to make sense of multiple interleaving messages, but they come from two machines with desynchronized clocks, and one of them is sending batches of messages every second instead of sending them as they are generated. You wonder if the code is executing in the right order and write essays about causality and determinism.</p>
<p>I have a hundred stories like those, and there&#39;s a common theme, a root cause for the way we write logs. As a developer, we think of them first as a developer&#39;s tool, not as the main interface to check your app&#39;s health in production. They are meant to be read with <code>tail</code> while the application runs on small workloads, for a limited time.</p>
<h2 id="developer-logs-vs-ops-logs">Developer logs VS ops logs</h2>
<p>Managing software in production means detecting when something is wrong, but knowing every bit of the program&#39;s state is a counterproductive way of doing it.</p>
<p>You want to know the important metrics:</p>
<ul>
<li>someone consulted a web page: leave that to your web analytics software</li>
<li>someone consulted a web page, but the app failed to answer: log it</li>
<li>someone consulted a web page, and the page&#39;s size is larger than the buffer:
don&#39;t log it, it&#39;s useless most of the time</li>
<li>someone bought something: log it, even if you have a backend to see that</li>
<li>someone bought something and the server failed: log it and send an email to
the dev team to fix it right now</li>
</ul>
<p>More generally, here is a scale from ops log to developer log:</p>
<ul>
<li>a transaction has been performed, successfully or not =&gt; ops logs</li>
<li>individual steps of that transaction failed =&gt; ops logs</li>
<li>individual steps of that transaction succeeded =&gt; dev logs</li>
<li>value of variable X at point Y in code =&gt; definitely developer logs</li>
</ul>
<p>Here is an example (from code I wrote) of developer centric logs:</p>
<script src="https://gist.github.com/cnivolle/3bf213c8f22c88dbd23f2ae550d175d7.js"></script>

<p>I am not saying developer info should not appear in logs. Just that it is best hidden under &quot;debug&quot; or &quot;trace&quot; levels, if your logging system supports levels (most do). It is fine to have useless messages in there, as long as they are not used in production/ It is fine to use &quot;printf debugging&quot; in development, but it should never appear in production.</p>
<p>Your goal in writing logs is to spare time for the person that will read them. It may be a sysadmin in your company, a client using your software, or yourself, six months from now, trying to put the app back online at 2 AM. Please think of your future self.</p>
<h2 id="making-the-logs-more-ops-friendly">Making the logs more ops friendly</h2>
<p>To make the life of the journal&#39;s reader easier, you need to optimize for two reading engines:</p>
<ul>
<li>filtering software, like grep</li>
<li>the human eye</li>
</ul>
<p>Why the human eye?</p>
<p>Because we are good at detecting patterns, and filtering out the useless parts of an image. If a sequence of three lines appears regularly, we will see it easily. If we only care about the message part of the log, not the prefix (time, PID, etc), we will focus our attention on it and ignore the rest.</p>
<p>The consequence is that everything that will break the brain&#39;s flow will make your logs harder to read. if the user id appears at the beginning of one message, but at the end of another one, it will be much harder to see which messages are related.</p>
<p>Fortunately, what works well for the human eye also works for filtering tools. Standardized, common prefixes are easy to search for, and easy to recognize. Related information should have identifying information, always stored in the same place.</p>
<h2 id="practical-advice">Practical advice</h2>
<p>How can you apply those principles right now? You begin by making a small wrapper over your logging library to automatically insert useful information, in a fixed format:</p>
<ul>
<li><em>a timestamp, preferably in ISO8601</em> (easier to read) at UTC (no timezone conversion
when reading). By the way, make sure your servers are all set up to use the same
timezone, this will save headaches</li>
<li><em>a timestamp from a monotonic clock</em> if your application is time critical</li>
<li>identify the current instance: add a <em>server identifier</em> (name, IP, whatever)
and an <em>instance identifier</em> (process id, thread id)</li>
<li><em>the running code&#39;s version</em> (commit id or version number)</li>
<li>the file&#39;s name, line number, class and function names are useful for debugging,
so add them for the &quot;debug&quot; and &quot;trace&quot; levels (but don&#39;t activate those levels in
production unless you have a good reason)</li>
<li>add some correlation information: the <em>user id</em>, a <em>request id</em>, anything that
will let you track which action resulted in which messages</li>
<li><em>code status</em>: are we in the middle of an error? Is something pending?</li>
<li>then, at the end, you can put a written message. You can use structured logging
instead of raw text if you want to track data with more automated tools</li>
</ul>
<p>This is a lot of information to put on one line, but we have great tools at our disposal. We can filter on one of these fields and remove it from the output. We can use terminals larger than 80 characters. We can even color parts of those logs to let the eye separate them easily.</p>
<p>If I had to rewrite the previous example logs that way:</p>
<script src="https://gist.github.com/cnivolle/2486db9d0c73a9986146d85f4fcbf1bc.js"></script>

<p>Side note: beware exceptions. It is fine to display an exception&#39;s stack trace while debugging the code, but an exception in production means two things:</p>
<ul>
<li>you forgot to replace the stacktrace with a proper error message for an exception
you handled</li>
<li>there&#39;s an exception that you do not handle in your code</li>
</ul>
<p>In both cases, it is a signal that something wrong happened and that it should be fixed soon. Also, it usually messes up the log&#39;s format, and fills up the log with useless information. I once heard about an app that needed to run on machines with big disks and big CPUs, because there were so many exceptions logged that the machine could not keep up.</p>
<p>Anyway, The goal of that approach is to have a common format for every message, simple to parse and filter. Make sure that those common parts have the same length, and that you use the same separators everywhere. Tabs are usually better than spaces, since we rarely use them in log messages. This will make the logs easier to read, and much easier to filter for.</p>
<p>With a good logging discipline, you will soon see non conforming messages as bugs, and you will be much more efficient when debugging and operating your application.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Security is a process, not a reaction</title>
		<link>https://stagingv6.cleverapps.io/blog/company/2016/04/04/security-is-a-process/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Mon, 04 Apr 2016 15:32:00 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[analysis]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2016/04/04/security-is-a-process/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p>Wake up. Check the news. There is a new OpenSSL vulnerability, the world is on fire. That vulnerability was published a week ago. Panic. Patch everything in a hurry. Break production. Panic^2.

<span id="more-2746"></span>

If this sounds familiar, you are probably running a web application of some kind. Maybe your whole business depends on it. Maybe you didn't hear about the latest world-on-fire vulnerability. Panic.

How do you keep up with security issues when everything is happening so fast? Which parts of your technical stack are the most at risk? Is the customer data safe? Do you really need to care?

At Clever Cloud, we support many languages and databases, running on hundreds of machines. And our core business is to execute code we didn't write, on our infrastructure.

This has an interesting effect on security management: there is always an issue somewhere. Vulnerabilities appear every day. You are lucky if they are not "0 day vulnerabilities". Those are flaws published without notifying the developers. This means there is no solution available at publication time. How do we handle our security calmly when we should actually run around screaming?

Our approach to security comes from the way we run our systems. You cannot manage hundreds of machines without automation and well defined processes. Every action on our infrastructure must be cheap to perform, or have a great impact.

People see security as a huge cost because of the work it implies:
<ul>
 	<li>unclear risk and impact on the business</li>
 	<li>time spent tracking new vulnerabilities for various applications</li>
 	<li>unclear result of updating code (will it stop working? Will it break other applications on the same machine?)</li>
</ul>
You want to reduce that cost, make security management easier and easier, until it is just a part of a day's job.
<h2 id="defining-your-risk-budget">Defining your risk budget</h2>
Calculating the risk requires some time at first, to teach your team how a threat model works, and how to update it. The threat model is a description of your system used to evaluate the cost of an attack:
<ul>
 	<li>targets: user data, intellectual property, machines</li>
 	<li>entry points: web server, internal WiFi</li>
 	<li>weaknesses: unpatched application, SQL injection, key employees victims of phishing</li>
</ul>
With this model, you calculate the difficulty of exploiting one weakness, which access level you obtain, where you can go from there. At the end, you get a list of issues in your system, ordered by impact on your system and ease of exploitation. Typically, if an automated script can steal your whole database, fix it immediately.

That model is the baseline everybody will use to evaluate security issues. It makes the risk real, not something you can just handwave with saying "we can take that risk". It is something you can plan for and budget for.
<h2 id="staying-up-to-date-with-security-news">Staying up to date with security news</h2>
Once you have a model, you need to keep it up to date with current news. Maybe requiring Java applets in your client's browsers is not such a good idea anymore. Maybe your advertisement network is now serving malware (as a side note, to drastically reduce malware infection at your company, install ad blockers everywhere, trust me on this).

Following security news can look like a daunting task, but you can simplify it with good sources:
<ul>
 	<li>avoid news websites. They write long articles, they want you to panic and they rarely provide usable solutions</li>
 	<li>Follow security mailing lists. There are generalist ones, like <a href="mailto:oss-security@lists.openwall.com">oss-security@lists.openwall.com</a> and <a href="mailto:cve-assign@mitre.org">cve-assign@mitre.org</a>. There are more specific ones, like <a href="mailto:debian-security@lists.debian.org">debian-security@lists.debian.org</a> (translate to your specific distribution), or <a href="mailto:rubyonrails-security@googlegroups.com">rubyonrails-security@googlegroups.com</a> and <a href="mailto:ruby-security-ann@googlegroups.com">ruby-security-ann@googlegroups.com</a>. There is also <a href="mailto:fulldisclosure@seclists.org">fulldisclosure@seclists.org</a>, where 0-day vulnerabilities are sometimes published</li>
 	<li>Twitter is still a good source of information on vulnerabilities, since people easily share. If you see security people suddenly buzzing in your timeline, you should pay attention. There are good lists of people to follow to get you started <a href="http://www.securityinnovationeurope.com/blog/87-security-experts-you-need-to-be-following-on-twitter">here</a> and <a href="http://www.marblesecurity.com/2013/11/20/100-security-experts-follow-twitter/">there</a>. They each have their own focus, though, so you may not be interested in everything</li>
 	<li>keep up with new versions of your software and their dependencies. Use your package manager, project specific mailing lists, subscribe to their github feed</li>
</ul>
Tracking security news becomes a simple process:
<ul>
 	<li>check the mailing lists, see if you use any of the applications mentioned</li>
 	<li>check your dependencies: anything new? Any security issues mentioned?</li>
 	<li>check Twitter: is the world on fire?</li>
</ul>
Be careful, though. Twitter is often on fire, and security experts like to jump on the new vulnerability and dissect it at length. Even when there is no information available. Not every vulnerability needs attention right now, some of them may not even apply to your particular usage of the software. Don't panic (yet).

Taking the time to verify security issues regularly makes security part of your daily/weekly process. Applying a security patch is just another item to raise at your morning stand up meeting (or whatever other process).

Note that the person tracking the vulnerability might not be the one fixing it. When I first learned about the <a href="https://weakdh.org/">Logjam flaw</a>, I was about to enter a plane for 10 hours. Notify the team by SMS/Slack, get an acknowledgment from someone, then go to sleep.
<h2 id="reducing-the-risk-of-code-updates">Reducing the risk of code updates</h2>
Here lies the huge cost of security: any code change in production is a potential liability. It brings no value to the customer, can introduce bugs or even crash the whole system (please make backups and test them regularly).

But this cost is not limited to security. It applies to your whole business. If modifying the production environment is complex and error prone, bugfixes come rarely. New versions come in huge chunks of code that <em>will</em> break things. Huge list of changes may even require some service downtime.

The point of our job at Clever Cloud is to make new deployments fast and painless. It has influenced our whole approaches to security. If you can start and remove a new instance of your application in seconds, you get huge benefits:
<ul>
 	<li>staging environments to test updates</li>
 	<li>replacing huge, risky updates with small increments</li>
 	<li>applications can be completely independent. Updating the company's WordPress blog will not affect the SaaS application</li>
</ul>
This is how we do code updates now: when a project's dependency gets a new version to fix a security issue, just redeploy the application. When there's a security patch for the Linux kernel, apply the patch, redeploy all the virtual machines, move on.
<figure><img id="img" src="https://www2.cleverapps.io/app/uploads/2021/08/redeploy-vm.jpg" /></figure>
We do not run around with our hair on fire. It is just a basic loop of:
<ul>
 	<li>get notified of a vulnerability</li>
 	<li>see if it applies</li>
 	<li>see if there's a patch (or if you can develop one quickly)</li>
 	<li>apply the patch</li>
 	<li>redeploy the applications</li>
 	<li>go make yourself a nice tea</li>
</ul>
We have good examples of this:
<ul>
 	<li>The recent CVE-2016-0728 is a privilege escalation in Linux, something we need to take seriously. We took a look at <a href="http://perception-point.io/2016/01/14/analysis-and-exploitation-of-a-linux-kernel-vulnerability-cve-2016-0728/">the advisory</a>, wrote a patch, tested it and deployed it in a few hours. Most Linux distributions took days to publish updated packages.</li>
 	<li>In the same way, the infamous <a href="http://heartbleed.com/">Heartbleed bug</a> was fixed quickly. One of our clients came to us hours later asking if we knew about it: "oh, that's the reason my applications were redeployed in the middle of the night"</li>
</ul>
When deploying new versions of an application is easy, it suddenly reduces the cost of code changes. The operational risk gets tiny, compared to the security risk. And you can update everything fast. You have no more excuse to keep unpatched systems.

Following those tips to set up your security process will improve your operations as well. With a systematic approach, you know your application better, you can see the cost of managing issues and take action.

There is still a lot to talk about, like training for incidents, defining operations procedures, or how to set up your infrastructure for easy deployments. But that last item, we can handle it for you <a href="https://stagingv6.cleverapps.io/contact/">right now</a>.]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/security-link-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p>Wake up. Check the news. There is a new OpenSSL vulnerability, the world is on fire. That vulnerability was published a week ago. Panic. Patch everything in a hurry. Break production. Panic^2.

<span id="more-2746"></span>

If this sounds familiar, you are probably running a web application of some kind. Maybe your whole business depends on it. Maybe you didn't hear about the latest world-on-fire vulnerability. Panic.

How do you keep up with security issues when everything is happening so fast? Which parts of your technical stack are the most at risk? Is the customer data safe? Do you really need to care?

At Clever Cloud, we support many languages and databases, running on hundreds of machines. And our core business is to execute code we didn't write, on our infrastructure.

This has an interesting effect on security management: there is always an issue somewhere. Vulnerabilities appear every day. You are lucky if they are not "0 day vulnerabilities". Those are flaws published without notifying the developers. This means there is no solution available at publication time. How do we handle our security calmly when we should actually run around screaming?

Our approach to security comes from the way we run our systems. You cannot manage hundreds of machines without automation and well defined processes. Every action on our infrastructure must be cheap to perform, or have a great impact.

People see security as a huge cost because of the work it implies:
<ul>
 	<li>unclear risk and impact on the business</li>
 	<li>time spent tracking new vulnerabilities for various applications</li>
 	<li>unclear result of updating code (will it stop working? Will it break other applications on the same machine?)</li>
</ul>
You want to reduce that cost, make security management easier and easier, until it is just a part of a day's job.
<h2 id="defining-your-risk-budget">Defining your risk budget</h2>
Calculating the risk requires some time at first, to teach your team how a threat model works, and how to update it. The threat model is a description of your system used to evaluate the cost of an attack:
<ul>
 	<li>targets: user data, intellectual property, machines</li>
 	<li>entry points: web server, internal WiFi</li>
 	<li>weaknesses: unpatched application, SQL injection, key employees victims of phishing</li>
</ul>
With this model, you calculate the difficulty of exploiting one weakness, which access level you obtain, where you can go from there. At the end, you get a list of issues in your system, ordered by impact on your system and ease of exploitation. Typically, if an automated script can steal your whole database, fix it immediately.

That model is the baseline everybody will use to evaluate security issues. It makes the risk real, not something you can just handwave with saying "we can take that risk". It is something you can plan for and budget for.
<h2 id="staying-up-to-date-with-security-news">Staying up to date with security news</h2>
Once you have a model, you need to keep it up to date with current news. Maybe requiring Java applets in your client's browsers is not such a good idea anymore. Maybe your advertisement network is now serving malware (as a side note, to drastically reduce malware infection at your company, install ad blockers everywhere, trust me on this).

Following security news can look like a daunting task, but you can simplify it with good sources:
<ul>
 	<li>avoid news websites. They write long articles, they want you to panic and they rarely provide usable solutions</li>
 	<li>Follow security mailing lists. There are generalist ones, like <a href="mailto:oss-security@lists.openwall.com">oss-security@lists.openwall.com</a> and <a href="mailto:cve-assign@mitre.org">cve-assign@mitre.org</a>. There are more specific ones, like <a href="mailto:debian-security@lists.debian.org">debian-security@lists.debian.org</a> (translate to your specific distribution), or <a href="mailto:rubyonrails-security@googlegroups.com">rubyonrails-security@googlegroups.com</a> and <a href="mailto:ruby-security-ann@googlegroups.com">ruby-security-ann@googlegroups.com</a>. There is also <a href="mailto:fulldisclosure@seclists.org">fulldisclosure@seclists.org</a>, where 0-day vulnerabilities are sometimes published</li>
 	<li>Twitter is still a good source of information on vulnerabilities, since people easily share. If you see security people suddenly buzzing in your timeline, you should pay attention. There are good lists of people to follow to get you started <a href="http://www.securityinnovationeurope.com/blog/87-security-experts-you-need-to-be-following-on-twitter">here</a> and <a href="http://www.marblesecurity.com/2013/11/20/100-security-experts-follow-twitter/">there</a>. They each have their own focus, though, so you may not be interested in everything</li>
 	<li>keep up with new versions of your software and their dependencies. Use your package manager, project specific mailing lists, subscribe to their github feed</li>
</ul>
Tracking security news becomes a simple process:
<ul>
 	<li>check the mailing lists, see if you use any of the applications mentioned</li>
 	<li>check your dependencies: anything new? Any security issues mentioned?</li>
 	<li>check Twitter: is the world on fire?</li>
</ul>
Be careful, though. Twitter is often on fire, and security experts like to jump on the new vulnerability and dissect it at length. Even when there is no information available. Not every vulnerability needs attention right now, some of them may not even apply to your particular usage of the software. Don't panic (yet).

Taking the time to verify security issues regularly makes security part of your daily/weekly process. Applying a security patch is just another item to raise at your morning stand up meeting (or whatever other process).

Note that the person tracking the vulnerability might not be the one fixing it. When I first learned about the <a href="https://weakdh.org/">Logjam flaw</a>, I was about to enter a plane for 10 hours. Notify the team by SMS/Slack, get an acknowledgment from someone, then go to sleep.
<h2 id="reducing-the-risk-of-code-updates">Reducing the risk of code updates</h2>
Here lies the huge cost of security: any code change in production is a potential liability. It brings no value to the customer, can introduce bugs or even crash the whole system (please make backups and test them regularly).

But this cost is not limited to security. It applies to your whole business. If modifying the production environment is complex and error prone, bugfixes come rarely. New versions come in huge chunks of code that <em>will</em> break things. Huge list of changes may even require some service downtime.

The point of our job at Clever Cloud is to make new deployments fast and painless. It has influenced our whole approaches to security. If you can start and remove a new instance of your application in seconds, you get huge benefits:
<ul>
 	<li>staging environments to test updates</li>
 	<li>replacing huge, risky updates with small increments</li>
 	<li>applications can be completely independent. Updating the company's WordPress blog will not affect the SaaS application</li>
</ul>
This is how we do code updates now: when a project's dependency gets a new version to fix a security issue, just redeploy the application. When there's a security patch for the Linux kernel, apply the patch, redeploy all the virtual machines, move on.
<figure><img id="img" src="https://www2.cleverapps.io/app/uploads/2021/08/redeploy-vm.jpg" /></figure>
We do not run around with our hair on fire. It is just a basic loop of:
<ul>
 	<li>get notified of a vulnerability</li>
 	<li>see if it applies</li>
 	<li>see if there's a patch (or if you can develop one quickly)</li>
 	<li>apply the patch</li>
 	<li>redeploy the applications</li>
 	<li>go make yourself a nice tea</li>
</ul>
We have good examples of this:
<ul>
 	<li>The recent CVE-2016-0728 is a privilege escalation in Linux, something we need to take seriously. We took a look at <a href="http://perception-point.io/2016/01/14/analysis-and-exploitation-of-a-linux-kernel-vulnerability-cve-2016-0728/">the advisory</a>, wrote a patch, tested it and deployed it in a few hours. Most Linux distributions took days to publish updated packages.</li>
 	<li>In the same way, the infamous <a href="http://heartbleed.com/">Heartbleed bug</a> was fixed quickly. One of our clients came to us hours later asking if we knew about it: "oh, that's the reason my applications were redeployed in the middle of the night"</li>
</ul>
When deploying new versions of an application is easy, it suddenly reduces the cost of code changes. The operational risk gets tiny, compared to the security risk. And you can update everything fast. You have no more excuse to keep unpatched systems.

Following those tips to set up your security process will improve your operations as well. With a systematic approach, you know your application better, you can see the cost of managing issues and take action.

There is still a lot to talk about, like training for incidents, defining operations procedures, or how to set up your infrastructure for easy deployments. But that last item, we can handle it for you <a href="https://stagingv6.cleverapps.io/contact/">right now</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>nom 1.0 is here! REJOICE!</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2015/11/16/nom-1-0/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Mon, 16 Nov 2015 14:35:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2015/11/16/nom-1-0/</guid>

					<description><![CDATA[<p><img width="2560" height="987" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1.jpg 2560w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-1536x592.jpg 1536w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-2048x790.jpg 2048w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-1368x527.jpg 1368w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></p><p><a href="https://github.com/Geal/nom">nom</a> is a parser combinators library witten in Rust that I started about a year ago. Its goal is to let you write parsers that are safe by default, fast, and abstract all of the dangerous or annoying details of data consumption.</p>
<span id="more-2802"></span>

<p>During that year, more than 50 projects have started using it; from toy parsers to high performance production code. Their feedback has been invaluable to improve the library, include more and more parsing patterns, and test ideas on what makes a great parser library. The 1.0 version is the result of that feedback. More stable version, but also a few breaking changes to improve the architecture, make it more flexible and easier to use. We now feel it is reliable enough to be used in production at Clever Cloud. We have a lot of data to manage, coming from trusted and untrusted sources, and this is exactly the kind of tool we need to build a safe infrastructure.</p>
<p>The quantity of open source projects using nom has been really helpful in developing that stable release. If you maintain one of those projects, you may have received a pull request from me. That&#39;s right: I took care of testing the 1.0 branch on every project I could get my hands on, to see what would break, which features developers were using, and document the upgrade process. This has been a lot of work, but worth it. I&#39;ll probably tell more about that in a future blog post, for other library maintainers that want to try the approach.</p>
<p>That&#39;s all good, but why would you use nom right now? Let&#39;s see!</p>
<p>nom is fast. How fast? A few <a href="https://github.com/Geal/nom_benchmarks">benchmarks</a> have shown that it is consistently faster than Parsec and attoparsec (Haskell parser combinator libraries), faster than other Rust parser combinator libraries, and even <a href="https://github.com/hoodie/dateparser_benchmarks/blob/3d76de5edc11ddcb98446bcd2b66e64a87652705/README.md">faster than Rust&#39;s regular expression library</a>. There is even a benchmark where it beats Joyent&#39;s <a href="https://github.com/nodejs/http-parser">http-parser</a> on parsing HTTP request headers.</p>
<p>Why is it faster? I have a few ideas about this. First, unlike most parser combinators systems, nom does not copy data if it is not needed. It uses the slice heavily, a Rust data structure containing a pointer and a length. Since Rust&#39;s compiler manages memory correctly, you can afford to refer to the original input from the beginning to the end of the parser, without copying anything.</p>
<p>Second, nom does not chain parsers at runtime. The macros directly generate the parsing code at compile time. This creates very linear code, something that CPUs find very easy to handle. If you tried to decompile the final binary to C code, you would just see a long list of if-else branches.</p>
<p>It is also a safe alternative to handwritten C parsers. nom bases its memory safety on Rust&#39;s compiler: it knows, at any moment, which part of the code owns which part of the memory, prevents out of bound accesses, automatically manages memory allocation and deallocation. And since that is not enough, some nom parsers were fuzzed to hell with <a href="http://lcamtuf.coredump.cx/afl/">American Fuzzy Lop</a>, just to verify those claims.</p>
<p>The result? The only flaws that were found appeared, not in nom generated code, but in code written manually outside of nom: index calculations that could overflow if a specific value appeared in the input. And those could not result in memory corruption, just crashes.</p>
<blockquote>
<p>you can quickly write a parser that will be safe by default</p>
</blockquote>
<p>This has awesome implications: you can quickly write a parser that will be safe by default. This lets you test ideas, experiment with your design, without fear for your security.</p>
<p>You should now see where I&#39;m going: with parsers that are easy to write, as fast or faster than handwritten C, and safe by default; you can replace old and vulnerable C parsers. Rust can work without a runtime, and is easily embedded in C code. It has already been used to write extensions for Ruby, Python, NodeJS and others. It is only a matter of time until it replaces the vulnerable parts of current C projects.</p>
<p>This is one of my long term goals: making reliable, safe building blocks to build our systems. Not only new bricks, but also replacing the old ones. This will require a tremendous effort, and nom is just the first step, but a big one.</p>
<p>To get started using nom, you can include it in your Rust projects from <a href="https://crates.io/crates/nom">crates.io</a>. Here are a few links you will find useful:</p>
<ul>
<li><a href="https://github.com/Geal/nom">Github repository Geal/nom</a></li>
<li><a href="http://rust.unhandledexpression.com/nom/">Reference documentation</a></li>
<li><a href="https://github.com/Geal/nom/wiki/Upgrading-to-nom-1.0">Upgrading to nom 1.0</a></li>
<li><a href="https://gitter.im/Geal/nom">Gitter chat room</a>. You can also go to the #nom IRC
channel on irc.mozilla.org, or ping &#39;geal&#39; on Mozilla, Freenode, Geeknode or oftc IRC</li>
<li><a href="https://fnordig.de/2015/07/16/omnomnom-parsing-iso8601-dates-using-nom/">Tutorial about parsing ISO8601 dates</a></li>
<li><a href="https://github.com/Geal/nom/wiki/Making-a-new-parser-from-scratch">Making a new parser from scratch</a>
(general tips on writing a parser and code architecture)</li>
<li><a href="https://github.com/Geal/nom/wiki/Error-management">How to handle parser errors</a></li>
<li><a href="https://github.com/Geal/nom/wiki/How-nom-macros-work">How nom&#39;s macro combinators work</a></li>
</ul>
<p>Also, if you have existing code running older versions of nom, please take a look at the <a href="https://github.com/Geal/nom/wiki/Upgrading-to-nom-1.0">upgrade documentation</a></p>
]]></description>
										<content:encoded><![CDATA[<p><img width="2560" height="987" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1.jpg 2560w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-1536x592.jpg 1536w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-2048x790.jpg 2048w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/nom10-scaled-1-1368x527.jpg 1368w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></p><p><a href="https://github.com/Geal/nom">nom</a> is a parser combinators library witten in Rust that I started about a year ago. Its goal is to let you write parsers that are safe by default, fast, and abstract all of the dangerous or annoying details of data consumption.</p>
<span id="more-2802"></span>

<p>During that year, more than 50 projects have started using it; from toy parsers to high performance production code. Their feedback has been invaluable to improve the library, include more and more parsing patterns, and test ideas on what makes a great parser library. The 1.0 version is the result of that feedback. More stable version, but also a few breaking changes to improve the architecture, make it more flexible and easier to use. We now feel it is reliable enough to be used in production at Clever Cloud. We have a lot of data to manage, coming from trusted and untrusted sources, and this is exactly the kind of tool we need to build a safe infrastructure.</p>
<p>The quantity of open source projects using nom has been really helpful in developing that stable release. If you maintain one of those projects, you may have received a pull request from me. That&#39;s right: I took care of testing the 1.0 branch on every project I could get my hands on, to see what would break, which features developers were using, and document the upgrade process. This has been a lot of work, but worth it. I&#39;ll probably tell more about that in a future blog post, for other library maintainers that want to try the approach.</p>
<p>That&#39;s all good, but why would you use nom right now? Let&#39;s see!</p>
<p>nom is fast. How fast? A few <a href="https://github.com/Geal/nom_benchmarks">benchmarks</a> have shown that it is consistently faster than Parsec and attoparsec (Haskell parser combinator libraries), faster than other Rust parser combinator libraries, and even <a href="https://github.com/hoodie/dateparser_benchmarks/blob/3d76de5edc11ddcb98446bcd2b66e64a87652705/README.md">faster than Rust&#39;s regular expression library</a>. There is even a benchmark where it beats Joyent&#39;s <a href="https://github.com/nodejs/http-parser">http-parser</a> on parsing HTTP request headers.</p>
<p>Why is it faster? I have a few ideas about this. First, unlike most parser combinators systems, nom does not copy data if it is not needed. It uses the slice heavily, a Rust data structure containing a pointer and a length. Since Rust&#39;s compiler manages memory correctly, you can afford to refer to the original input from the beginning to the end of the parser, without copying anything.</p>
<p>Second, nom does not chain parsers at runtime. The macros directly generate the parsing code at compile time. This creates very linear code, something that CPUs find very easy to handle. If you tried to decompile the final binary to C code, you would just see a long list of if-else branches.</p>
<p>It is also a safe alternative to handwritten C parsers. nom bases its memory safety on Rust&#39;s compiler: it knows, at any moment, which part of the code owns which part of the memory, prevents out of bound accesses, automatically manages memory allocation and deallocation. And since that is not enough, some nom parsers were fuzzed to hell with <a href="http://lcamtuf.coredump.cx/afl/">American Fuzzy Lop</a>, just to verify those claims.</p>
<p>The result? The only flaws that were found appeared, not in nom generated code, but in code written manually outside of nom: index calculations that could overflow if a specific value appeared in the input. And those could not result in memory corruption, just crashes.</p>
<blockquote>
<p>you can quickly write a parser that will be safe by default</p>
</blockquote>
<p>This has awesome implications: you can quickly write a parser that will be safe by default. This lets you test ideas, experiment with your design, without fear for your security.</p>
<p>You should now see where I&#39;m going: with parsers that are easy to write, as fast or faster than handwritten C, and safe by default; you can replace old and vulnerable C parsers. Rust can work without a runtime, and is easily embedded in C code. It has already been used to write extensions for Ruby, Python, NodeJS and others. It is only a matter of time until it replaces the vulnerable parts of current C projects.</p>
<p>This is one of my long term goals: making reliable, safe building blocks to build our systems. Not only new bricks, but also replacing the old ones. This will require a tremendous effort, and nom is just the first step, but a big one.</p>
<p>To get started using nom, you can include it in your Rust projects from <a href="https://crates.io/crates/nom">crates.io</a>. Here are a few links you will find useful:</p>
<ul>
<li><a href="https://github.com/Geal/nom">Github repository Geal/nom</a></li>
<li><a href="http://rust.unhandledexpression.com/nom/">Reference documentation</a></li>
<li><a href="https://github.com/Geal/nom/wiki/Upgrading-to-nom-1.0">Upgrading to nom 1.0</a></li>
<li><a href="https://gitter.im/Geal/nom">Gitter chat room</a>. You can also go to the #nom IRC
channel on irc.mozilla.org, or ping &#39;geal&#39; on Mozilla, Freenode, Geeknode or oftc IRC</li>
<li><a href="https://fnordig.de/2015/07/16/omnomnom-parsing-iso8601-dates-using-nom/">Tutorial about parsing ISO8601 dates</a></li>
<li><a href="https://github.com/Geal/nom/wiki/Making-a-new-parser-from-scratch">Making a new parser from scratch</a>
(general tips on writing a parser and code architecture)</li>
<li><a href="https://github.com/Geal/nom/wiki/Error-management">How to handle parser errors</a></li>
<li><a href="https://github.com/Geal/nom/wiki/How-nom-macros-work">How nom&#39;s macro combinators work</a></li>
</ul>
<p>Also, if you have existing code running older versions of nom, please take a look at the <a href="https://github.com/Geal/nom/wiki/Upgrading-to-nom-1.0">upgrade documentation</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
