<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><span class="">...<br></span></div></div></blockquote><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><span class="">
</span><p style="margin:0px 0px 1.2em!important">Sure, an example:</p>
<p style="margin:0px 0px 1.2em!important">A web application needs creds (secrets) in order to access a 3rd party api. These creds need to exist in a config file on the webserver/instance. As a user, you/I know what the secrets are, but now we need to share them with the web application, and only the web application in order for the webapp to connect to the 3rd party api. </p><span class="">
<p style="margin:0px 0px 1.2em!important">Who are we hiding the information from?</p>
</span><p style="margin:0px 0px 1.2em!important">Considering the above example, restricting access to the “secrets” from any entity outside of the one that would need access to them to provision them seems like a reasonable approach. That being said, I feel like access restrictions should be at the charm/layer level.</p></div></div></blockquote><div>So how does a charm/layer prove who it is, such that nobody else can do that proof? Juju tracks what charms are deployed to what machine, and each unit agent ends up having its own login back to the Controller. However, all charms hooks are run as 'root' on the machine (they sort of have to, because they need to do stuff like install software). Which means they can read any files that exist on the machine.</div><div><br></div><div>So there is very little we could do at the 'layer' level, aside from pretend that the information couldn't be read. (We could have a secret key for a layer, but where could that layer store its secret that any other software running as root on that machine couldn't get access to.)</div><div><br></div><div>You also have to be a little careful if you ever install 2 charms on the same machine (juju deploy foo --to 1), because then both bits of software could read the secrets that were for the other software. (Worst case, they just read the configuration of the actual service, which must have some way to get the unencrypted form, or it couldn't do its job.)</div><div><br></div><div>As is, we don't allow agents to read the data for other agents. (The agent for machine-1 could ask for the details of machine-2, but will get told EPERM).</div><div><br></div><div>If we aren't hiding the values from the <b>user</b> then simple application config is already secret. There may be bugs, but by design the only thing that can read the config for an application is the agents for the units of that application, the controller itself, and the user.</div><div><br></div><div>Now, there is a case for maybe storing the secrets encrypted on the controller, but again, all of the information for how to get the secrets out have to be in the system, so that *someone* could make use of them.</div><div><br></div><div>One thought, we could improve things slightly over the status quo if we had each agent create a public/private key pair and register it, and then anything flagged 'secret' gets encrypted with the agents public key, and the agent stores its private key somewhere on the machine-local disk. Then when a user enters secrets, we encrypt the values with that public key, and not even the controller has access anymore. Still can't do per-layer secrets (cause where can a layer store a secret that another layer in the same charm can't get to it)? But we could cut out the ability for anything but software running on that machine to read it. I'm not sure if the cost/benefit is really there, as if you want to deploy 2 units of the software, you have to re-encrypt the original settings for the second unit, and if the Controller doesn't have access to the original text, then it can't encrypt it for the second unit. The User has to re-enter the software. Likely we also need a public/private key that the User tracks, if they ever want to 'get' the value back. And I guess we could make it so 'add-unit' interacts with the User, who can decrypt the content with the User's key, and then encrypt it back with the agents public key.</div><div><br></div><div>Its a lot of hassle, with the one advantage that getting access to the Controller doesn't give you access to the secrets of all software that has been configured.</div><div><br></div><div>But I have the feeling that for your actual use case, just the fact that the Controller doesn't let anyone but the agent-in-charge-of-that-application read the values for that application is actually enough.</div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>
<p style="margin:0px 0px 1.2em!important">Two possibilities I’ve thought of:</p>
<p style="margin:0px 0px 1.2em!important">A) Layer Sensitive Secrets - I’m thinking a secret might only be readable to the layer in which it is configured to be used. A secret could be context sensitive to the :, such that when you set a secret in a model, you are setting it such that it can only be accessed by a named layer in named charm.</p>
<p style="margin:0px 0px 1.2em!important">B) Shared Model Secrets - Less restrictive “secrets”, accessible globally, at the model level.</p><span class="">
<p style="margin:0px 0px 1.2em!important">Are we hiding information from the Juju users?</p>
</span><p style="margin:0px 0px 1.2em!important">When a secret is set, it could be hashed before being stored in the database, then other users who are members of the same model wouldn’t be able to see what the secret was, but they could see that it exists by listing secrets.</p><span class="">
<p style="margin:0px 0px 1.2em!important">Are we trying to hide information from other processes on the same machines as the agents?</p>
</span><p style="margin:0px 0px 1.2em!important">I think the process isolation would come along for the ride inherently as long as processes and directories have their permissions locked down appropriately upon setup/configuration. </p><span class="">
<p style="margin:0px 0px 1.2em!important">Also, who generates and holds the keys?</p>
</span><p style="margin:0px 0px 1.2em!important">Here’s what I’m thinking, consider the following hypothetical situation:</p>
<p style="margin:0px 0px 1.2em!important">You basically want an action to do the following:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span style="color:rgb(0,134,179)">sudo</span> htpasswd -c /etc/nginx/htpasswd.users kibanaadmin
</code></pre>
<p style="margin:0px 0px 1.2em!important">Cloud admin of company X runs a Kibana instance that he desires to enhance access control on. Kibana is deployed via Juju. Seeing as Juju “secrets” exist, the cloud admin of company X can use the Juju CLI to set the users and passwords (secrets) of those he desires to grant access to the Kibana dashboard. The cloud admin wants to define the “secrets” in a .yaml file, and feed it to his Juju environment using the <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">juju add-secrets</code> command, after which he will trigger an “action” to write out the htpasswd file with the latest secrets associated with the environment. After running <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">juju add-secrets</code>, Juju hashes the secret values and stores them in the model context of the controller, only to be unencrypted (or read) upon a call to their getter function, called by the layer or charm whom they are configured to in <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">secrets.yaml</code>. e.g.</p>
<ol style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px"><p style="margin:0px 0px 1.2em!important;margin:0.5em 0px!important"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">secrets.yaml</code></p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)">secrets:
kibana:
 htpasswd-user: someuser
 htpasswd-pass: somepassword
</code></pre>
</li>
<li style="margin:0.5em 0px"><p style="margin:0px 0px 1.2em!important;margin:0.5em 0px!important"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">juju add-secret lxd-dev-controller:my-lxd-<wbr>model -f secrets.yaml</code> </p>
</li>
<li style="margin:0.5em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">rm secrets.yaml</code></li>
<li style="margin:0.5em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">juju run-action kibana/0 htpasswd access='allow'</code></li>
</ol>
<p style="margin:0px 0px 1.2em!important">On #1 the user defines the secrets for the controller:model:charm in the secrets.yaml.<br>On #2 the user updates the controller with the secrets to the controller:model:charm, juju hashes the secrets and stores them in the model context of the controller.<br>On #3 the user deletes the secrets.yaml file as he want to ensure no one will be able to view the secrets if access is breached on his local machine.<br>On #4 the user runs an action that decrypts the secrets stored in the state server, and puts them in the .htaccess file on the server. </p>
<p style="margin:0px 0px 1.2em!important">Starting to feel like I am rambling. Hopefully this will help clarify what I am thinking a "secret" might be!</p><p style="margin:0px 0px 1.2em!important">Thoughts?</p></div></div></blockquote><div>Hiding secrets from the user who uploaded them is possible, but poses some fairly significant usability costs. If we want to make the controller not a fault point, then you can see my above thoughts around creating per-unit and user public/private keys.</div><div><br></div><div>A cheaper thing could be 'write only' values, which lets you set a config value, but doesn't let the user see it. We already have this idea floating around for read-only vs admin users. (So I can give you read-only access to my Model, but that doesn't let you read the private ssl keyfile.) This would take it one step further where you can't read it either. This generally suffers from 'do I have the right ssl cert there?' and not being able to read the value that you put there.</div><div><br></div><div>Any sort of 'encrypting in the database' starts to suffer from 'where is the key that lets you read it', And how do you make sure that only the right places have access to that key. If you encrypt the whole database, but the keys for that database live next to it, you haven't really made anything more secure.</div><div><br></div><div>John</div><div>=:-></div><div><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><span class=""><p style="margin:0px 0px 1.2em!important"><br></p><p style="margin:0px 0px 1.2em!important">On Sun, Jul 24, 2016 at 1:53 PM, Tim Penhey <<a href="mailto:tim.penhey@canonical.com" target="_blank">tim.penhey@canonical.com</a>> wrote:</p>
<p style="margin:0px 0px 1.2em!important"></p><div><p></p><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span>On 25/07/16 06:32, James Beedy wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  Proposed Solution: Juju Secrets<br>
<br>
To give Juju a combative edge on the privacy pinwheel of secrets<br>
distribution in the realm of bleeding edge devops tooling, behold my<br>
hypothetical proposed solution: |juju secrets|.<br>
Juju secrets could be used like so:<br>
|juju add-secret mycloud:mymodel -f secrets.yaml|<br>
<br>
I know you guys are pressing hard to get 2.0 out the door, so please<br>
don’t mind my nonsense here. I just wanted to throw the idea out there<br>
and possibly get some feedback, and have others weigh in on this topic.<br>
<br>
Thoughts?<br>
</blockquote>
<br></span>
Interesting idea. How would this really work in practice?<br>
<br>
For the secrets to be any use, the units need to be able to get access to the information right?<br>
<br>
Who are we hiding the information from? This is always a key question that needs to be answered in order to choose a good solution.<br>
<br>
Are we hiding information from the Juju users?<br>
<br>
Are we trying to hide information from other processes on the same machines as the agents?<br>
<br>
Also, who generates and holds the keys?<br>
<br>
Just some more questions.<span><font color="#888888"><br>
<br>
<br>
Tim<br>
</font></span></blockquote><p></p></div><p style="margin:0px 0px 1.2em!important"></p>
<div title="MDH:VGltLDxkaXY+PGJyPjwvZGl2PjxkaXY+R3JlYXQgcXVlc3Rpb25zLiBJIGZlZWwgbGlrZSBJIHNo
b3VsZCBvZiBleHBhbmRlZCBhIGJpdCBtb3JlIG9uIHdoYXQgYSAic2VjcmV0IiBtaWdodCBiZSBh
ZnRlciBJIHNlbnQgdGhhdCBvZmYuLi4uJm5ic3A7PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5U
byBtZSwgYSBzZWNyZXQgaXMgc29tZXRoaW5nIHlvdSBkb24ndCB3YW50IGFueW9uZSB0byBrbm93
IC0gdGhhdCBiZWluZyBzYWlkLCB0aGUgYmVzdCBhcHByb2FjaCBmb3IgbG9va2luZyBhdCAic2Vj
cmV0cyIgbWlnaHQgYmUgdG8gdGhpbmsgYXMgcmVzdHJpY3RpdmVseSBhcyBwb3NzaWJsZS48L2Rp
dj48ZGl2Pjxicj48L2Rpdj48ZGl2Pjxmb250IGNvbG9yPSIjZmYwMDAwIj48c3BhbiBzdHlsZT0i
Zm9udC1zaXplOiAxMi44cHg7Ij5Gb3IgdGhlIHNlY3JldHMgdG8gYmUgYW55IHVzZSwgdGhlIHVu
aXRzIG5lZWQgdG8gYmUgYWJsZSB0byBnZXQgYWNjZXNzIHRvIHRoZSBpbmZvcm1hdGlvbiByaWdo
dD88L3NwYW4+PGJyPjwvZm9udD48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PlN1cmUsIGFuIGV4
YW1wbGU6PGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+QSB3ZWIgYXBwbGljYXRpb24gbmVl
ZHMgY3JlZHMmbmJzcDsoc2VjcmV0cykgaW4gb3JkZXIgdG8gYWNjZXNzIGEgM3JkIHBhcnR5IGFw
aS4gVGhlc2UgY3JlZHMgbmVlZCB0byBleGlzdCBpbiBhIGNvbmZpZyBmaWxlIG9uIHRoZSB3ZWJz
ZXJ2ZXIvaW5zdGFuY2UuIEFzIGEgdXNlciwgeW91L0kga25vdyB3aGF0IHRoZSBzZWNyZXRzIGFy
ZSwgYnV0IG5vdyB3ZSBuZWVkIHRvIHNoYXJlIHRoZW0gd2l0aCB0aGUgd2ViIGFwcGxpY2F0aW9u
LCBhbmQgb25seSB0aGUgd2ViIGFwcGxpY2F0aW9uIGluIG9yZGVyIGZvciB0aGUgd2ViYXBwIHRv
IGNvbm5lY3QgdG8gdGhlIDNyZCBwYXJ0eSBhcGkuJm5ic3A7PC9kaXY+PGRpdj48Zm9udCBjb2xv
cj0iI2ZmMDAwMCI+PGJyPjwvZm9udD48L2Rpdj48ZGl2PjxzcGFuIHN0eWxlPSJmb250LXNpemU6
IDEyLjhweDsiPjxmb250IGNvbG9yPSIjZmYwMDAwIj5XaG8gYXJlIHdlIGhpZGluZyB0aGUgaW5m
b3JtYXRpb24gZnJvbT88L2ZvbnQ+PC9zcGFuPjxicj48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2
PkNvbnNpZGVyaW5nIHRoZSBhYm92ZSBleGFtcGxlLCByZXN0cmljdGluZyBhY2Nlc3MgdG8gdGhl
ICJzZWNyZXRzIiBmcm9tIGFueSBlbnRpdHkgb3V0c2lkZSBvZiB0aGUgb25lIHRoYXQgd291bGQg
bmVlZCBhY2Nlc3MgdG8gdGhlbSB0byBwcm92aXNpb24gdGhlbSBzZWVtcyBsaWtlIGEgcmVhc29u
YWJsZSBhcHByb2FjaC4gVGhhdCBiZWluZyBzYWlkLCBJIGZlZWwgbGlrZSBhY2Nlc3MgcmVzdHJp
Y3Rpb25zIHNob3VsZCBiZSBhdCB0aGUgY2hhcm0vbGF5ZXIgbGV2ZWwuPC9kaXY+PGRpdj48YnI+
PC9kaXY+PGRpdj5Ud28gcG9zc2liaWxpdGllcyBJJ3ZlIHRob3VnaHQgb2Y6PC9kaXY+PGRpdj48
YnI+PC9kaXY+PGRpdj5BKSBMYXllciBTZW5zaXRpdmUgU2VjcmV0cyAtIEknbSB0aGlua2luZyBh
IHNlY3JldCBtaWdodCBvbmx5IGJlIHJlYWRhYmxlIHRvIHRoZSBsYXllciBpbiB3aGljaCBpdCBp
cyBjb25maWd1cmVkIHRvIGJlIHVzZWQuIEEgc2VjcmV0IGNvdWxkIGJlIGNvbnRleHQgc2Vuc2l0
aXZlIHRvIHRoZSAmbHQ7YXBwbGljYXRpb24tbmFtZSZndDs6Jmx0O2xheWVyLW5hbWUmZ3Q7LCBz
dWNoIHRoYXQgd2hlbiB5b3Ugc2V0IGEgc2VjcmV0IGluIGEgbW9kZWwsIHlvdSBhcmUgc2V0dGlu
ZyBpdCBzdWNoIHRoYXQgaXQgY2FuIG9ubHkgYmUgYWNjZXNzZWQgYnkgYSBuYW1lZCBsYXllciBp
biBuYW1lZCBjaGFybS48YnI+PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5CKSBTaGFyZWQgTW9k
ZWwgU2VjcmV0cyAtIExlc3MgcmVzdHJpY3RpdmUgInNlY3JldHMiLCBhY2Nlc3NpYmxlIGdsb2Jh
bGx5LCBhdCB0aGUgbW9kZWwgbGV2ZWwuPC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxi
cj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+PGZvbnQgY29sb3I9IiNmZjAwMDAiPjxi
cj48L2ZvbnQ+PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxmb250IGNvbG9yPSIjZmYw
MDAwIj5BcmUgd2UgaGlkaW5nIGluZm9ybWF0aW9uIGZyb20gdGhlIEp1anUgdXNlcnM/PGJyPjwv
Zm9udD48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+PGJyPjwvZGl2PjxkaXYgY2xhc3M9
ImdtYWlsX2V4dHJhIj5XaGVuIGEgc2VjcmV0IGlzIHNldCwgaXQgY291bGQgYmUgaGFzaGVkIGJl
Zm9yZSBiZWluZyBzdG9yZWQgaW4gdGhlIGRhdGFiYXNlLCB0aGVuIG90aGVyIHVzZXJzIHdobyBh
cmUgbWVtYmVycyBvZiB0aGUgc2FtZSBtb2RlbCB3b3VsZG4ndCBiZSBhYmxlIHRvIHNlZSB3aGF0
IHRoZSBzZWNyZXQgd2FzLCBidXQgdGhleSBjb3VsZCBzZWUgdGhhdCBpdCBleGlzdHMgYnkgbGlz
dGluZyBzZWNyZXRzLjwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48YnI+PC9kaXY+PGRp
diBjbGFzcz0iZ21haWxfZXh0cmEiPjxmb250IGNvbG9yPSIjZmYwMDAwIj5BcmUgd2UgdHJ5aW5n
IHRvIGhpZGUgaW5mb3JtYXRpb24gZnJvbSBvdGhlciBwcm9jZXNzZXMgb24gdGhlIHNhbWUgbWFj
aGluZXMgYXMgdGhlIGFnZW50cz88L2ZvbnQ+PGJyPjwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4
dHJhIj48YnI+PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPkkgdGhpbmsgdGhlIHByb2Nl
c3MgaXNvbGF0aW9uIHdvdWxkIGNvbWUgYWxvbmcgZm9yIHRoZSByaWRlIGluaGVyZW50bHkgYXMg
bG9uZyBhcyBwcm9jZXNzZXMgYW5kIGRpcmVjdG9yaWVzIGhhdmUgdGhlaXIgcGVybWlzc2lvbnMg
bG9ja2VkIGRvd24gYXBwcm9wcmlhdGVseSB1cG9uIHNldHVwL2NvbmZpZ3VyYXRpb24uJm5ic3A7
PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFp
bF9leHRyYSI+PHNwYW4gc3R5bGU9ImNvbG9yOiByZ2IoMjU1LCAwLCAwKTsiPkFsc28sIHdobyBn
ZW5lcmF0ZXMgYW5kIGhvbGRzIHRoZSBrZXlzPzwvc3Bhbj48YnI+PC9kaXY+PGRpdiBjbGFzcz0i
Z21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+SGVyZSdzIHdo
YXQgSSdtIHRoaW5raW5nLCBjb25zaWRlciB0aGUgZm9sbG93aW5nIGh5cG90aGV0aWNhbCBzaXR1
YXRpb246PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNz
PSJnbWFpbF9leHRyYSI+WW91IGJhc2ljYWxseSB3YW50IGFuIGFjdGlvbiB0byBkbyB0aGUgZm9s
bG93aW5nOjwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj5gYGBiYXNoPC9kaXY+PGRpdiBj
bGFzcz0iZ21haWxfZXh0cmEiPnN1ZG8gaHRwYXNzd2QgLWMgL2V0Yy9uZ2lueC9odHBhc3N3ZC51
c2VycyBraWJhbmFhZG1pbjxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+YGBgPC9k
aXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9l
eHRyYSI+Q2xvdWQgYWRtaW4gb2YgY29tcGFueSBYIHJ1bnMgYSBLaWJhbmEgaW5zdGFuY2UgdGhh
dCBoZSBkZXNpcmVzIHRvIGVuaGFuY2UgYWNjZXNzIGNvbnRyb2wgb24uIEtpYmFuYSBpcyBkZXBs
b3llZCB2aWEgSnVqdS4gU2VlaW5nIGFzIEp1anUgInNlY3JldHMiIGV4aXN0LCB0aGUgY2xvdWQg
YWRtaW4gb2YgY29tcGFueSBYIGNhbiB1c2UgdGhlIEp1anUgQ0xJIHRvIHNldCB0aGUgdXNlcnMg
YW5kIHBhc3N3b3JkcyAoc2VjcmV0cykgb2YgdGhvc2UgaGUgZGVzaXJlcyB0byBncmFudCBhY2Nl
c3MgdG8gdGhlIEtpYmFuYSBkYXNoYm9hcmQuIFRoZSBjbG91ZCBhZG1pbiB3YW50cyB0byBkZWZp
bmUgdGhlICJzZWNyZXRzIiBpbiBhIC55YW1sIGZpbGUsIGFuZCBmZWVkIGl0IHRvIGhpcyBKdWp1
IGVudmlyb25tZW50IHVzaW5nIHRoZSBganVqdSBhZGQtc2VjcmV0c2AgY29tbWFuZCwgYWZ0ZXIg
d2hpY2ggaGUgd2lsbCB0cmlnZ2VyIGFuICJhY3Rpb24iIHRvIHdyaXRlIG91dCB0aGUgaHRwYXNz
d2QgZmlsZSB3aXRoIHRoZSBsYXRlc3Qgc2VjcmV0cyBhc3NvY2lhdGVkIHdpdGggdGhlIGVudmly
b25tZW50LiBBZnRlciBydW5uaW5nIGBqdWp1IGFkZC1zZWNyZXRzYCwgSnVqdSBoYXNoZXMgdGhl
IHNlY3JldCB2YWx1ZXMgYW5kIHN0b3JlcyB0aGVtIGluIHRoZSBtb2RlbCBjb250ZXh0IG9mIHRo
ZSBjb250cm9sbGVyLCBvbmx5IHRvIGJlIHVuZW5jcnlwdGVkIChvciByZWFkKSB1cG9uIGEgY2Fs
bCB0byB0aGVpciBnZXR0ZXIgZnVuY3Rpb24sIGNhbGxlZCBieSB0aGUgbGF5ZXIgb3IgY2hhcm0g
d2hvbSB0aGV5IGFyZSBjb25maWd1cmVkIHRvIGluIGBzZWNyZXRzLnlhbWxgLiBlLmcuPC9kaXY+
PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRy
YSI+MS4gYHNlY3JldHMueWFtbGA8L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+YGBgeWFt
bDxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+c2VjcmV0czo8L2Rpdj48ZGl2IGNs
YXNzPSJnbWFpbF9leHRyYSI+Jm5ic3A7IGtpYmFuYTo8L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9l
eHRyYSI+Jm5ic3A7ICZuYnNwOyBodHBhc3N3ZC11c2VyOiBzb21ldXNlcjwvZGl2PjxkaXYgY2xh
c3M9ImdtYWlsX2V4dHJhIj4mbmJzcDsgJm5ic3A7IGh0cGFzc3dkLXBhc3M6IHNvbWVwYXNzd29y
ZDwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj5gYGA8L2Rpdj48ZGl2IGNsYXNzPSJnbWFp
bF9leHRyYSI+PGJyPjwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj4yLiBganVqdSBhZGQt
c2VjcmV0IGx4ZC1kZXYtY29udHJvbGxlcjpteS1seGQtbW9kZWwgLWYgc2VjcmV0cy55YW1sYCZu
YnNwOzwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj4zLiBgcm0gc2VjcmV0cy55YW1sYDwv
ZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj40LiBganVqdSBydW4tYWN0aW9uIGtpYmFuYS8w
IGh0cGFzc3dkIGFjY2Vzcz0nYWxsb3cnYDwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48
YnI+PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNzPSJn
bWFpbF9leHRyYSI+T24gIzEgdGhlIHVzZXIgZGVmaW5lcyB0aGUgc2VjcmV0cyBmb3IgdGhlIGNv
bnRyb2xsZXI6bW9kZWw6Y2hhcm0gaW4gdGhlIHNlY3JldHMueWFtbC4mbmJzcDs8L2Rpdj48ZGl2
IGNsYXNzPSJnbWFpbF9leHRyYSI+T24gIzIgdGhlIHVzZXIgdXBkYXRlcyB0aGUgY29udHJvbGxl
ciB3aXRoIHRoZSBzZWNyZXRzIHRvIHRoZSBjb250cm9sbGVyOm1vZGVsOmNoYXJtLCBqdWp1IGhh
c2hlcyB0aGUgc2VjcmV0cyBhbmQgc3RvcmVzIHRoZW0gaW4gdGhlIG1vZGVsIGNvbnRleHQgb2Yg
dGhlIGNvbnRyb2xsZXIuPC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPk9uICMzIHRoZSB1
c2VyIGRlbGV0ZXMgdGhlIHNlY3JldHMueWFtbCBmaWxlIGFzIGhlIHdhbnQgdG8gZW5zdXJlIG5v
IG9uZSB3aWxsIGJlIGFibGUgdG8gdmlldyB0aGUgc2VjcmV0cyBpZiBhY2Nlc3MgaXMgYnJlYWNo
ZWQgb24gaGlzIGxvY2FsIG1hY2hpbmUuPC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPk9u
ICM0IHRoZSB1c2VyIHJ1bnMgYW4gYWN0aW9uIHRoYXQgZGVjcnlwdHMgdGhlIHNlY3JldHMgc3Rv
cmVkIGluIHRoZSBzdGF0ZSBzZXJ2ZXIsIGFuZCBwdXRzIHRoZW0gaW4gdGhlIC5odGFjY2VzcyBm
aWxlIG9uIHRoZSBzZXJ2ZXIuJm5ic3A7PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxi
cj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+PGJyPjwvZGl2PjxkaXYgY2xhc3M9Imdt
YWlsX2V4dHJhIj5TdGFydGluZyB0byBmZWVsIGxpa2UgSSBhbSByYW1ibGluZy4gSG9wZWZ1bGx5
IHRoaXMgZ290IHRoZSBpZGVhIGFjcm9zcyBzbGlnaHRseSBiZXR0ZXIhPC9kaXY+PGRpdiBjbGFz
cz0iZ21haWxfZXh0cmEiPjxicj48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9leHRyYSI+VGhhbmtz
LDwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48YnI+PC9kaXY+PGRpdiBjbGFzcz0iZ21h
aWxfZXh0cmEiPn5KYW1lczwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48YnI+PGRpdiBj
bGFzcz0iZ21haWxfcXVvdGUiPk9uIFN1biwgSnVsIDI0LCAyMDE2IGF0IDE6NTMgUE0sIFRpbSBQ
ZW5oZXkgPHNwYW4gZGlyPSJsdHIiPiZsdDs8YSBocmVmPSJtYWlsdG86dGltLnBlbmhleUBjYW5v
bmljYWwuY29tIiB0YXJnZXQ9Il9ibGFuayI+dGltLnBlbmhleUBjYW5vbmljYWwuY29tPC9hPiZn
dDs8L3NwYW4+IHdyb3RlOjxicj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVvdGUiIHN0eWxl
PSJtYXJnaW46IDBweCAwcHggMHB4IDAuOGV4OyBib3JkZXItbGVmdDogMXB4IHNvbGlkIHJnYigy
MDQsIDIwNCwgMjA0KTsgcGFkZGluZy1sZWZ0OiAxZXg7Ij48c3BhbiBjbGFzcz0iIj5PbiAyNS8w
Ny8xNiAwNjozMiwgSmFtZXMgQmVlZHkgd3JvdGU6PGJyPgo8YmxvY2txdW90ZSBjbGFzcz0iZ21h
aWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46IDBweCAwcHggMHB4IDAuOGV4OyBib3JkZXItbGVmdDog
MXB4IHNvbGlkIHJnYigyMDQsIDIwNCwgMjA0KTsgcGFkZGluZy1sZWZ0OiAxZXg7Ij4KJm5ic3A7
IFByb3Bvc2VkIFNvbHV0aW9uOiBKdWp1IFNlY3JldHM8YnI+Cjxicj4KVG8gZ2l2ZSBKdWp1IGEg
Y29tYmF0aXZlIGVkZ2Ugb24gdGhlIHByaXZhY3kgcGlud2hlZWwgb2Ygc2VjcmV0czxicj4KZGlz
dHJpYnV0aW9uIGluIHRoZSByZWFsbSBvZiBibGVlZGluZyBlZGdlIGRldm9wcyB0b29saW5nLCBi
ZWhvbGQgbXk8YnI+Cmh5cG90aGV0aWNhbCBwcm9wb3NlZCBzb2x1dGlvbjogfGp1anUgc2VjcmV0
c3wuPGJyPgpKdWp1IHNlY3JldHMgY291bGQgYmUgdXNlZCBsaWtlIHNvOjxicj4KfGp1anUgYWRk
LXNlY3JldCBteWNsb3VkOm15bW9kZWwgLWYgc2VjcmV0cy55YW1sfDxicj4KPGJyPgpJIGtub3cg
eW91IGd1eXMgYXJlIHByZXNzaW5nIGhhcmQgdG8gZ2V0IDIuMCBvdXQgdGhlIGRvb3IsIHNvIHBs
ZWFzZTxicj4KZG9u4oCZdCBtaW5kIG15IG5vbnNlbnNlIGhlcmUuIEkganVzdCB3YW50ZWQgdG8g
dGhyb3cgdGhlIGlkZWEgb3V0IHRoZXJlPGJyPgphbmQgcG9zc2libHkgZ2V0IHNvbWUgZmVlZGJh
Y2ssIGFuZCBoYXZlIG90aGVycyB3ZWlnaCBpbiBvbiB0aGlzIHRvcGljLjxicj4KPGJyPgpUaG91
Z2h0cz88YnI+CjwvYmxvY2txdW90ZT4KPGJyPjwvc3Bhbj4KSW50ZXJlc3RpbmcgaWRlYS4gSG93
IHdvdWxkIHRoaXMgcmVhbGx5IHdvcmsgaW4gcHJhY3RpY2U/PGJyPgo8YnI+CkZvciB0aGUgc2Vj
cmV0cyB0byBiZSBhbnkgdXNlLCB0aGUgdW5pdHMgbmVlZCB0byBiZSBhYmxlIHRvIGdldCBhY2Nl
c3MgdG8gdGhlIGluZm9ybWF0aW9uIHJpZ2h0Pzxicj4KPGJyPgpXaG8gYXJlIHdlIGhpZGluZyB0
aGUgaW5mb3JtYXRpb24gZnJvbT8gVGhpcyBpcyBhbHdheXMgYSBrZXkgcXVlc3Rpb24gdGhhdCBu
ZWVkcyB0byBiZSBhbnN3ZXJlZCBpbiBvcmRlciB0byBjaG9vc2UgYSBnb29kIHNvbHV0aW9uLjxi
cj4KPGJyPgpBcmUgd2UgaGlkaW5nIGluZm9ybWF0aW9uIGZyb20gdGhlIEp1anUgdXNlcnM/PGJy
Pgo8YnI+CkFyZSB3ZSB0cnlpbmcgdG8gaGlkZSBpbmZvcm1hdGlvbiBmcm9tIG90aGVyIHByb2Nl
c3NlcyBvbiB0aGUgc2FtZSBtYWNoaW5lcyBhcyB0aGUgYWdlbnRzPzxicj4KPGJyPgpBbHNvLCB3
aG8gZ2VuZXJhdGVzIGFuZCBob2xkcyB0aGUga2V5cz88YnI+Cjxicj4KSnVzdCBzb21lIG1vcmUg
cXVlc3Rpb25zLjxzcGFuIGNsYXNzPSIiPjxmb250IGNvbG9yPSIjODg4ODg4Ij48YnI+Cjxicj4K
PGJyPgpUaW08YnI+CjwvZm9udD48L3NwYW4+PC9ibG9ja3F1b3RlPjwvZGl2Pjxicj48L2Rpdj4=" style="min-height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></span></div></div>
<br>--<br>
Juju-dev mailing list<br>
<a href="mailto:Juju-dev@lists.ubuntu.com">Juju-dev@lists.ubuntu.com</a><br>
Modify settings or unsubscribe at: <a href="https://lists.ubuntu.com/mailman/listinfo/juju-dev" rel="noreferrer" target="_blank">https://lists.ubuntu.com/<wbr>mailman/listinfo/juju-dev</a><br>
<br></blockquote></div><br></div></div>