<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Field encryption on back(d)</title><link>https://fernandezvara.github.io/backd/docs/build/encryption/</link><description>Recent content in Field encryption on back(d)</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://fernandezvara.github.io/backd/docs/build/encryption/index.xml" rel="self" type="application/rss+xml"/><item><title>Recipes</title><link>https://fernandezvara.github.io/backd/docs/build/encryption/recipes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/encryption/recipes/</guid><description>&lt;p&gt;Each recipe is complete: the commands and the configuration in order. The rules of the game are in &lt;a href="../../configuration/field-keys/"&gt;Field keys and encrypted fields&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="a-tax-id-you-can-look-up"&gt;A tax id you can look up&lt;a class="hd-anchor" href="#a-tax-id-you-can-look-up" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You need the tax id unreadable in a dump, and still need &lt;code&gt;GET …?where={&amp;quot;tax_id&amp;quot;: &amp;quot;B1234&amp;quot;}&lt;/code&gt; and one patient per tax id.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;backd secret create --realm clinic --type key --generate --name TAX &amp;gt; tax.key &lt;span class="c1"&gt;# save tax.key; the fingerprint is printed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# main/patients/collection.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tax_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;TAX&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;equality &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# = and in, through a blind index&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;trim, upper] &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# &amp;#34; b1234 &amp;#34; finds &amp;#34;B1234&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# a second patient with the same tax id is a 409&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Restart &lt;code&gt;backd&lt;/code&gt; (it refuses to start if the key is missing). Then:&lt;/p&gt;</description></item><item><title>Errors and what to do</title><link>https://fernandezvara.github.io/backd/docs/build/encryption/errors/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/encryption/errors/</guid><description>&lt;p&gt;Startup refusals name the file, the field and what to do; all problems of a config are reported at once.&lt;/p&gt;
&lt;h2 id="at-startup"&gt;At startup&lt;a class="hd-anchor" href="#at-startup" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;You see&lt;/th&gt;
 &lt;th&gt;It means&lt;/th&gt;
 &lt;th&gt;Do&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…: names the key HEALTH, which does not exist&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A field names a key that was never created&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;backd-server secret create --realm r --type key --generate --name HEALTH&lt;/code&gt;, and &lt;strong&gt;save the key&lt;/strong&gt;; or &lt;code&gt;--value&lt;/code&gt; to restore a key you hold&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…names HEALTH, which is a plain secret, not a key&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The name belongs to an ordinary secret&lt;/td&gt;
 &lt;td&gt;Use another name, or delete the secret if nothing uses it&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;fields are declared encrypted … but the realm has no auth&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Encrypted fields need somewhere to keep keys&lt;/td&gt;
 &lt;td&gt;Enable &lt;code&gt;auth&lt;/code&gt; in &lt;code&gt;realm.yaml&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;fields.x: field &amp;quot;x&amp;quot; is not declared in schema.json&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The path isn&amp;rsquo;t a field of the collection&lt;/td&gt;
 &lt;td&gt;Declare it, or fix the path&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…encrypt.key: name the key secret …&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;key&lt;/code&gt; is missing or malformed&lt;/td&gt;
 &lt;td&gt;Upper-case letters, digits and &lt;code&gt;_&lt;/code&gt;, starting with a letter&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…encrypt.search: &amp;quot;…&amp;quot; is not a kind of search&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Only &lt;code&gt;equality&lt;/code&gt; exists&lt;/td&gt;
 &lt;td&gt;Use &lt;code&gt;search: equality&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…encrypt.normalize: normalization applies to the blind index&lt;/code&gt; / &lt;code&gt;…&amp;quot;x&amp;quot; is not a normalization&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;normalize&lt;/code&gt; without &lt;code&gt;search&lt;/code&gt;, or an unknown step&lt;/td&gt;
 &lt;td&gt;Add &lt;code&gt;search: equality&lt;/code&gt;; steps are &lt;code&gt;trim&lt;/code&gt;, &lt;code&gt;lower&lt;/code&gt;, &lt;code&gt;upper&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…encrypt.unique: a unique encrypted field needs search: equality&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The blind index is what is unique&lt;/td&gt;
 &lt;td&gt;Add &lt;code&gt;search: equality&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;system fields (id, _meta) can't be encrypted&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Those are backd&amp;rsquo;s&lt;/td&gt;
 &lt;td&gt;Encrypt a field of your own&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;a field inside an array can't be encrypted&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An element has no stable path&lt;/td&gt;
 &lt;td&gt;Encrypt the array as a whole&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;a date field (x-backd-store: date) can't be encrypted&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A date is stored as a date, not text&lt;/td&gt;
 &lt;td&gt;Store it as a string, or leave it plain&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;x is already encrypted as a whole&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An object and its parts&lt;/td&gt;
 &lt;td&gt;Encrypt one of them&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;x is the source of the reference …&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Expanding a reference needs the plain value&lt;/td&gt;
 &lt;td&gt;Reference a plain field&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;x is a file field&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;File contents rely on bucket encryption&lt;/td&gt;
 &lt;td&gt;Leave file fields out&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;x is in an index of indexes.json&lt;/code&gt; / &lt;code&gt;…in the text index&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An index can&amp;rsquo;t see inside an encrypted value&lt;/td&gt;
 &lt;td&gt;Use &lt;code&gt;search: equality&lt;/code&gt; (and &lt;code&gt;unique&lt;/code&gt;) instead of an index&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;x is a replace / pull / unset target of on_owner_delete&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Those edit values inside the database&lt;/td&gt;
 &lt;td&gt;Use &lt;code&gt;remove&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;x is grouped or measured by aggregate&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The database can&amp;rsquo;t compute over encrypted values&lt;/td&gt;
 &lt;td&gt;Aggregate a plain field&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;read rules: document.x is encrypted without search: equality&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A read rule is applied inside the database query&lt;/td&gt;
 &lt;td&gt;Add &lt;code&gt;search: equality&lt;/code&gt; and compare with &lt;code&gt;==&lt;/code&gt; or &lt;code&gt;in&lt;/code&gt;, or move the condition to &lt;code&gt;reveal&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;read rules: document.x is encrypted with a blind index, which only answers == and in&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;, ranges and the rest can&amp;rsquo;t use an index of hashes&lt;/td&gt;
 &lt;td&gt;Use &lt;code&gt;==&lt;/code&gt; or &lt;code&gt;in&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;…reveal: unknown field document.y&lt;/code&gt; / &lt;code&gt;`data` is only available on create and update&lt;/code&gt; / &lt;code&gt;role &amp;quot;z&amp;quot; is not declared&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A &lt;code&gt;reveal&lt;/code&gt; rule is checked like any rule&lt;/td&gt;
 &lt;td&gt;Fix the expression; it sees &lt;code&gt;document&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;now&lt;/code&gt;, the helpers and &lt;code&gt;appConfig&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="in-a-request"&gt;In a request&lt;a class="hd-anchor" href="#in-a-request" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;You see&lt;/th&gt;
 &lt;th&gt;It means&lt;/th&gt;
 &lt;th&gt;Do&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;400 field_encrypted&lt;/code&gt; on a &lt;code&gt;where&lt;/code&gt; or &lt;code&gt;order_by&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The field is encrypted: only &lt;code&gt;=&lt;/code&gt;/&lt;code&gt;$in&lt;/code&gt; on a field with &lt;code&gt;search: equality&lt;/code&gt; work, and never &lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Filter on another field, or enable search&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;500&lt;/code&gt; &amp;ldquo;an encrypted field can&amp;rsquo;t be read or written: its key is not available&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;The key is missing or the instance has no secrets master key&lt;/td&gt;
 &lt;td&gt;Look at the server log (it names the field, never the value); restore the key with &lt;code&gt;backd-server secret create --value …&lt;/code&gt; and check &lt;code&gt;BACKD_SECRETS_KEY&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;A value comes back &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;_meta.redacted&lt;/code&gt; lists it&lt;/td&gt;
 &lt;td&gt;Its &lt;code&gt;reveal&lt;/code&gt; rule said no for this caller&lt;/td&gt;
 &lt;td&gt;Intended; change the rule or the caller&amp;rsquo;s roles&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;409&lt;/code&gt; on a write naming the field&lt;/td&gt;
 &lt;td&gt;A &lt;code&gt;unique: true&lt;/code&gt; field already holds that value&lt;/td&gt;
 &lt;td&gt;Choose another value&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="in-a-command"&gt;In a command&lt;a class="hd-anchor" href="#in-a-command" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;You see&lt;/th&gt;
 &lt;th&gt;It means&lt;/th&gt;
 &lt;th&gt;Do&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;409&lt;/code&gt; creating a key&lt;/td&gt;
 &lt;td&gt;A secret with that name exists&lt;/td&gt;
 &lt;td&gt;Another name; &lt;code&gt;--skip-existing&lt;/code&gt; in scripts&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;409&lt;/code&gt; deleting a key: &amp;ldquo;still used by …&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;A field names it, or data keys that encrypted values depend on are wrapped by it&lt;/td&gt;
 &lt;td&gt;Change the configuration and &lt;code&gt;backd encrypt migrate&lt;/code&gt; until &lt;code&gt;status&lt;/code&gt; is complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;409 a rotation of this key is unfinished&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A rotation stopped half way&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;backd secret rotate --resume&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;409 a migration of this collection is already running&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;One job per collection&lt;/td&gt;
 &lt;td&gt;Wait, or cancel it&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;the key given for … has the fingerprint …, but … is encrypted with the key …&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Wrong key for an export or import &lt;code&gt;--field&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Use the key whose fingerprint the manifest records&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;422 import_refused&lt;/code&gt; naming encrypted fields&lt;/td&gt;
 &lt;td&gt;Nobody here can open them&lt;/td&gt;
 &lt;td&gt;Give the source keys with &lt;code&gt;--field&lt;/code&gt;; the dry run lists them&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item></channel></rss>