<?xml version="1.0"?>
<!-- name="generator" content="pyblosxom/0.8.1" -->
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">

<rss version="0.91">
  <channel>
    <title>Tollef Fog Heen</title>
    <link>http://err.no/personal/blog/</link>
    <description>tfheen's blog</description>
    <webMaster>tfheen@err.no</webMaster>
    <managingEditor>tfheen@err.no</managingEditor>
    <language>en</language>
    <image>
        <url>http://err.no/tfheen.jpg</url>
        <title>Tollef Fog Heen</title>
        <description>Image of Tollef Fog Heen</description>
        <link>http://err.no/personal/blog</link>
        <width>66</width>
        <height>100</height>
    </image>
  <item>
    <title>Sharing an SSH key, securely</title>
    <link>http://err.no/personal/blog/tech/2013-03-22-09-45_sharing_an_ssh_key_securely.html</link>
    <pubDate>Fri, 22 Mar 2013 09:45 +0100</pubDate>
    <description>&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; This isn&apos;t actually that much better than letting them
access the private key, since nothing is stopping the user from
running their own SSH agent, which can be run under strace.  A better
solution is in the works.  Thanks Timo Juhani Lindfors and Bob Proulx
for both pointing this out.&lt;/p&gt;

&lt;p&gt;At &lt;a href=&quot;https://www.varnish-software.com&quot;&gt;work&lt;/a&gt;, we have a shared SSH key between the different people
manning the support queue.  So far, this has just been a file in a
directory where everybody could read it and people would &lt;code&gt;sudo&lt;/code&gt; to the
support user and then run SSH.&lt;/p&gt;

&lt;p&gt;This has bugged me a fair bit, since there was nothing stopping a
person from making a copy of the key onto their laptop, except policy.&lt;/p&gt;

&lt;p&gt;Thanks to a tip, I got around to implementing this and figured writing
up how to do it would be useful.&lt;/p&gt;

&lt;p&gt;First, you need a directory readable by root only, I use
&lt;code&gt;/var/local/support-ssh&lt;/code&gt; here.  The other bits you need are a small
&lt;code&gt;sudo&lt;/code&gt; snippet and a &lt;code&gt;profile.d&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;My sudo snippet looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Defaults!/usr/bin/ssh-add env_keep += &quot;SSH_AUTH_SOCK&quot;
%support ALL=(root)  NOPASSWD: /usr/bin/ssh-add /var/local/support-ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Everybody in group support can run ssh-add as root.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;profile.d&lt;/code&gt; goes in &lt;code&gt;/etc/profile.d/support.sh&lt;/code&gt; and looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if [ -n &quot;$(groups | grep -E &quot;(^| )support( |$)&quot;)&quot; ]; then
    export SSH_AUTH_ENV=&quot;$HOME/.ssh/agent-env&quot;
    if [ -f &quot;$SSH_AUTH_ENV&quot; ]; then
        . &quot;$SSH_AUTH_ENV&quot;
    fi
    ssh-add -l &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
    if [ $? = 2 ]; then
        mkdir -p &quot;$HOME/.ssh&quot;
        rm -f &quot;$SSH_AUTH_ENV&quot;
        ssh-agent &amp;gt; &quot;$SSH_AUTH_ENV&quot;
        . &quot;$SSH_AUTH_ENV&quot;
    fi
    sudo ssh-add /var/local/support-ssh/id_rsa
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The key is unavailable for the user in question because &lt;code&gt;ssh-add&lt;/code&gt; is
sgid and so runs with group ssh and the process is only debuggable for
root.  The only thing missing is there&apos;s no way to have the agent
prompt to use a key and I would like it to die or at least unload keys
when the last session for a user is closed, but that doesn&apos;t seem
trivial to do.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Abusing sbuild for fun and profit</title>
    <link>http://err.no/personal/blog/tech/2013-01-29-15-32_abusing_sbuild_for_fun_and_profit.html</link>
    <pubDate>Tue, 29 Jan 2013 15:32 +0100</pubDate>
    <description>&lt;p&gt;Over the last couple of weeks, I have been working on getting
binary packages for [Varnish] modules built.  In the current version,
you need to have a built, unpacked source tree to build a module
against.  This is being fixed in the next version, but until then, I
needed to provide this in the build environment somehow.&lt;/p&gt;

&lt;p&gt;RPMs were surprisingly easy, since our RPM build setup is much simpler
and doesn&apos;t use mock/mach or other chroot-based tools.  Just make a
source RPM available and unpack + compile that.&lt;/p&gt;

&lt;p&gt;Debian packages on the other hand, they were not easy to get going.
My first problem was to just get the Varnish source package into the
chroot.  I ended up making a directory in &lt;code&gt;/var/lib/sbuild/build&lt;/code&gt;
which is exposed as &lt;code&gt;/build&lt;/code&gt; once &lt;code&gt;sbuild&lt;/code&gt; runs.  The other hard part
was getting Varnish itself built.  &lt;code&gt;sbuild&lt;/code&gt; exposes two hooks that
could work: a &lt;code&gt;pre-build&lt;/code&gt; hook and a &lt;code&gt;chroot-setup&lt;/code&gt; hook.  Neither
worked:  Pre-build is called before the chroot is set up, so we can&apos;t
build Varnish.  Chroot-setup is run before the build-dependencies are
installed and it runs as the user invoking &lt;code&gt;sbuild&lt;/code&gt;, so it can&apos;t
install packages.&lt;/p&gt;

&lt;p&gt;Sparc32 and similar architectures use the &lt;code&gt;linux32&lt;/code&gt; tool to set the
personality before building packages.  I ended up abusing this, so I
set HOME to a temporary directory where I create a &lt;code&gt;.sbuildrc&lt;/code&gt; which sets
&lt;code&gt;$build_env_cmnd&lt;/code&gt; to a script which in turns unpacks the Varnish
source, builds it and then chains to &lt;code&gt;dpkg-buildpackage&lt;/code&gt;.  Of course,
the build-dependencies for modules don&apos;t include all the
build-dependencies for Varnish itself, so I have to extract those from
the Varnish source package too.&lt;/p&gt;

&lt;p&gt;No source available at this point, mostly because it&apos;s beyond ugly.
I&apos;ll see if I can get it cleaned up.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>FOSDEM talk: systemd in Debian</title>
    <link>http://err.no/personal/blog/tech/Debian/2013-01-28-16-20_FOSDEM_systemd_in_Debian.html</link>
    <pubDate>Mon, 28 Jan 2013 16:20 +0100</pubDate>
    <description>&lt;p&gt;Michael Biebl and I are giving a talk on &lt;a href=&quot;https://fosdem.org/2013/schedule/event/debian_systemd/&quot;&gt;systemd in Debian&lt;/a&gt; at
FOSDEM on Sunday morning at 10.  We&apos;ll be talking a bit about the
current state in Wheezy, what our plans for Jessie are and what Debian
packagers should be aware of.  We would love to get input from people
about what systemd in Jessie should look like, so if you have any
ideas, opinions or insights, please come along.  If you&apos;re just
curious, you are also of course welcome to join.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Gitano – git hosting with ACLs and other shininess</title>
    <link>http://err.no/personal/blog/tech/2013-01-17-07-34_gitano.html</link>
    <pubDate>Thu, 17 Jan 2013 07:34 +0100</pubDate>
    <description>&lt;p&gt;&lt;a href=&quot;http://www.gitano.org.uk&quot;&gt;gitano&lt;/a&gt; is not entirely unlike the
non-web, server side of github.  It allows you to create and manage
users and their SSH keys, groups and repositories from the command
line.  Repositories have ACLs associated with them.  Those can be
complex (&quot;allow user X to push to &lt;code&gt;master&lt;/code&gt; in the &lt;code&gt;doc/&lt;/code&gt; subtree) or
trivial (&quot;admin can do anything&quot;).  Gitano is written by Daniel
Silverstone, and I&apos;d like to thank him both for writing it and for
holding my hand as I went stumbling through my initial gitano setup.&lt;/p&gt;

&lt;p&gt;Getting started with Gitano can be a bit tricky, as it&apos;s not yet
packaged and fairly undocumented.  Until it is packaged, it&apos;s install
from source time.  You need &lt;a href=&quot;http://www.gitano.org.uk/luxio/&quot;&gt;luxio&lt;/a&gt;, &lt;a href=&quot;http://www.gitano.org.uk/lace/&quot;&gt;lace&lt;/a&gt;,
&lt;a href=&quot;http://www.gitano.org.uk/supple/&quot;&gt;supple&lt;/a&gt;, &lt;a href=&quot;http://git.gitano.org.uk/?p=clod.git;a=summary&quot;&gt;clod&lt;/a&gt;, &lt;a href=&quot;http://git.gitano.org.uk/?p=gall.git;a=summary&quot;&gt;gall&lt;/a&gt; and &lt;a href=&quot;http://www.gitano.org.uk&quot;&gt;gitano&lt;/a&gt;
itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;luxio&lt;/code&gt; needs a &lt;code&gt;make install LOCAL=1&lt;/code&gt;, the others will be installed
to &lt;code&gt;/usr/local&lt;/code&gt; with just &lt;code&gt;make install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once that is installed, create a user to hold the instance.  I&apos;ve
named mine &lt;code&gt;git&lt;/code&gt;, but you&apos;re free to name it whatever you would like.
As that user, run gitano-setup and answer the prompts.  I&apos;ll use
&lt;code&gt;git.example.com&lt;/code&gt; as the host name and &lt;code&gt;john&lt;/code&gt; as the user I&apos;m setting this
up for.&lt;/p&gt;

&lt;p&gt;To create users, run &lt;code&gt;ssh git@git.example.com user add john john@example.com
John Doe&lt;/code&gt;, then add their SSH key with &lt;code&gt;ssh git@git.example.com as john
sshkey add workstation &amp;lt; /tmp/john_id_rsa.pub&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To create a repository, run &lt;code&gt;ssh git@git.example.com repo create
myrepo&lt;/code&gt;.  Out of the box, this only allows the owner (typically
&quot;admin&quot;, unless overridden) to do anything with it.  To change ACLs,
you&apos;ll want to grab the &lt;code&gt;refs/gitano/admin&lt;/code&gt; branch.  This lives
outside of the space git usually use for branches, so you can&apos;t just
check it out. The easiest way to check it out is to use
&lt;a href=&quot;http://cgit.gitano.org.uk/gitano.git/tree/scripts/git-admin-clone&quot;&gt;git-admin-clone&lt;/a&gt;.  Run it as &lt;code&gt;git-admin-clone
git@git.example.com:myrepo ~/myrepo-admin&lt;/code&gt; and then edit in
&lt;code&gt;~/myrepo-admin&lt;/code&gt;.  Use git to add, commit and push as normal from
there.&lt;/p&gt;

&lt;p&gt;To change ACLs for a given repo, you&apos;ll want to edit the
&lt;code&gt;rules/main.lace&lt;/code&gt; file.  A real-world example can be found &lt;a href=&quot;http://git.netsurf-browser.org/netsurf.git/tree/rules/main.lace?h=refs/gitano/admin&quot;&gt;in the
NetSurf repository&lt;/a&gt; and the &lt;a href=&quot;http://www.gitano.org.uk/lace/v1.0/docs/syntax-define/&quot;&gt;lace syntax&lt;/a&gt;
might be useful. A lace file consists of four types of lines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comments, start with -- or #&lt;/li&gt;
&lt;li&gt;defines, look like &lt;code&gt;define name conditions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;allows, look like &lt;code&gt;allow &quot;reason&quot; definition [definition…]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;denials, look like &lt;code&gt;deny &quot;reason&quot; definition [definition…]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rules are processed one by one, from the top and terminate whenever a
matching allow or deny is found.&lt;/p&gt;

&lt;p&gt;Conditions can either be matches to an update, such as &lt;code&gt;ref
refs/heads/master&lt;/code&gt; to match updates to the master branch.  To create
groupings, you can use the &lt;code&gt;anyof&lt;/code&gt; or &lt;code&gt;allof&lt;/code&gt; verbs in a definition.
Allows and denials are checked against all the definitions listed and
if all of them match, the appropriate action is taken.&lt;/p&gt;

&lt;p&gt;Pay some attention to what conditions you group together, since a
basic operation (&lt;code&gt;is_basic_op&lt;/code&gt;, aka &lt;code&gt;op_read&lt;/code&gt; and &lt;code&gt;op_write&lt;/code&gt;) happens
before git is even involved and you don&apos;t have a tree at that point,
so rules like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;define is_master ref refs/heads/master
allow &quot;Devs can push&quot; op_is_basic is_master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;simply won&apos;t work.  You&apos;ll want to use a group and check on that for
basic operations and then have a separate rule to restrict refs.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Driving Jenkins using YAML and a bit of python</title>
    <link>http://err.no/personal/blog/tech/varnish/2012-09-04-13-03_jenkins_yaml_and_automation.html</link>
    <pubDate>Tue, 04 Sep 2012 13:03 +0100</pubDate>
    <description>&lt;p&gt;We recently switched from &lt;a href=&quot;http://buildbot.net/&quot;&gt;Buildbot&lt;/a&gt; to Jenkins at &lt;a href=&quot;https://www.varnish-software.com/&quot;&gt;work&lt;/a&gt;, for
building Varnish on various platforms.  Buildbot worked-ish, but
was a bit fiddly to get going on some platforms such as Mac OS and
Solaris.  Where buildbot has a daemon on each node that is responsible
for contacting the central host, Jenkins uses SSH as the transport and
centrally manages retries if a host goes down or is rebooted.&lt;/p&gt;

&lt;p&gt;All in all, we are pretty happy with Jenkins, except for one thing:
The job configurations are a bunch of XML files and the way you are
supposed to configure this is through a web interface.  That doesn&apos;t
scale particularly well when you want to build many very similar
jobs.  We want to build multiple branches, some which are not public
and we want to build on many slaves.  The latter we could partially
solve with matrix builds, except that will fail the entire build if a
single slave fails with an error that works on retry.  As the number
of slaves increases, such failures become more common.&lt;/p&gt;

&lt;p&gt;To solve this, I hacked together a crude tool that takes a &lt;a href=&quot;http://yaml.org/&quot;&gt;yaml&lt;/a&gt;
file and writes the XML files.  It&apos;s not anywhere near as well
structured and pretty as &lt;a href=&quot;http://git.gitano.org.uk/?p=personal/liw/jenkinstool.git;a=summary&quot;&gt;liw&apos;s jenkinstool&lt;/a&gt;, but it is quite good
at translating the YAML into a bunch of XML files.  I don&apos;t know if
it&apos;s useful for anybody else, there is no documentation and so on, but
if you want to take a look, it&apos;s &lt;a href=&quot;https://github.com/varnish/jenkins-yaml&quot;&gt;on github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feedback is most welcome, as usual.  Patches even more so.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Automating managing your on-call support rotation using google docs</title>
    <link>http://err.no/personal/blog/tech/2012-07-23-13-10_gdocs_automation_gammu_and_support.html</link>
    <pubDate>Mon, 23 Jul 2012 13:10 +0100</pubDate>
    <description>&lt;p&gt;At work, we have a rotation of who is on call at a given time.  We
have few calls, but they do happen and so it&apos;s important to ensure
both that a person is available, but also that they&apos;re aware they are
on call (so they don&apos;t stray too far from their phone or a computer).&lt;/p&gt;

&lt;p&gt;In the grand tradition of abusing spreadsheets, we are using google
docs for the roster.  It&apos;s basically just two columns, one with date
and one with user name.  Since the volume is so low, people tend to be
on call for about a week at a time, 24 hours a day.&lt;/p&gt;

&lt;p&gt;Up until now, we&apos;ve just had a pretty old and dumb phone that people
have carried around, but that&apos;s not really swish, so I have
implemented a small system which grabs the current data, looks up the
support person in LDAP and sends SMSes when people go on and off duty
as well as reminding the person who&apos;s on duty once a day.&lt;/p&gt;

&lt;p&gt;If you&apos;re interested, you can look at the (slightly redacted)
&lt;a href=&quot;http://err.no/src/vs-support-phone&quot;&gt;script&lt;/a&gt;.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Today's rant about RPM</title>
    <link>http://err.no/personal/blog/tech/2011-10-21-16-04_todays_rant_about_rpm.html</link>
    <pubDate>Fri, 21 Oct 2011 16:04 +0100</pubDate>
    <description>&lt;p&gt;Before I start, I&apos;ll admit that I&apos;m not a real RPM packager.  Maype
I&apos;m approaching this from completely the wrong direction, what do I
know?&lt;/p&gt;

&lt;p&gt;I&apos;m in the process of packaging Varnish 3.0.2 which includes mangling
the spec file.  The top of the spec file reads:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;%define v_rc
%define vd_rc %{?v_rc:-%{?v_rc}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Apparently, this is not legal, since we&apos;re trying to define v_rc as a
macro with no body.  It&apos;s however not possible to directly define it
as an empty string which can later be tested on, you have to do
something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;%define v_rc %{nil}
%define vd_rc %{?v_rc:-%{?v_rc}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, this doesn&apos;t work correctly either.  &lt;code&gt;%{?macro}&lt;/code&gt; tests if macro
is defined, not whether it&apos;s an empty string so instead of two lines,
we have to write:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;%define v_rc %{nil}
%if 0%{?v_rc} != 0
%define vd_rc %{?v_rc:-%{?v_rc}}
%endif
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;0{?v_rc} != 0&lt;/code&gt; workaround is there so that we don&apos;t accidentially
end up with &lt;code&gt;== 0&lt;/code&gt; which would be a syntax error.&lt;/p&gt;

&lt;p&gt;I think having four lines like that is pretty ugly, so I looked for a
workaround and figured that, ok, I&apos;ll just rewrite every use of
&lt;code&gt;%{vd_rc}&lt;/code&gt; to &lt;code&gt;%{?v_rc:-%{?v_rc}}&lt;/code&gt;.  There are only a couple, so the
damage is limited.  Also, I&apos;d then just comment out the &lt;code&gt;v_rc&lt;/code&gt;
definition, since that makes it clear what you should uncomment to
have a release candidate version.&lt;/p&gt;

&lt;p&gt;In my naivety, I tried:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# %define v_rc &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#&lt;/code&gt; is used as a comment character in spec files, but apparently not
for defines.  The define was still processed and the build process
stopped pretty quickly.&lt;/p&gt;

&lt;p&gt;Luckily, doing &lt;code&gt;# % define &quot;&quot;&lt;/code&gt; seems to work fine and is not
processed.  I have no idea how people put up with this or if I&apos;m doing
something very wrong.  Feel free to point me at a better way of doing
this, of course.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>The SugarCRM rest interface</title>
    <link>http://err.no/personal/blog/tech/2011-10-05-09-40_sugarcrm_rest_interface.html</link>
    <pubDate>Wed, 05 Oct 2011 09:40 +0100</pubDate>
    <description>&lt;p&gt;We use SugarCRM at work and I&apos;ve complained about its not-very-RESTy
REST interface.  John Mertic a (the?) SugarCRM Community Manager asked
me about what problems I&apos;d had (apart from its lack of RESTfulness)
and I said I&apos;d write a blog post about it.&lt;/p&gt;

&lt;p&gt;In our case, the REST interface is used to integrate Sugar and RT so
we get a link in both interfaces to jump from opportunities to the
corresponding RT ticket (and back again).  This should be a fairly
trivial exercise or so you would think.&lt;/p&gt;

&lt;p&gt;The problems, as I see it are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not REST-y.&lt;/li&gt;
&lt;li&gt;Exposes the database tables all the way through the REST interface&lt;/li&gt;
&lt;li&gt;Lack of useful documentation forcing the developer to cargo cult and
guess&lt;/li&gt;
&lt;li&gt;Annoying data structures&lt;/li&gt;
&lt;li&gt;Forced pagination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My first gripe is the complete lack of REST in the URLs.  Everything
is just sent to &lt;code&gt;https://sugar/service/v2/rest.php&lt;/code&gt;.  Usually a POST,
but sometimes a GET.  It&apos;s not documented what to use where.&lt;/p&gt;

&lt;p&gt;The POST parameters we send when logging in are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;method=&amp;gt;&quot;login&quot;
input_type=&amp;gt;&quot;JSON&quot;
response_type=&amp;gt;&quot;JSON&quot;
rest_data=&amp;gt;json($params)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;$params is a hash as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;user_auth =&amp;gt; {
            user_name =&amp;gt; $USERNAME,
            password =&amp;gt; $PW,
            version =&amp;gt; &quot;1.2&quot;,
},
application =&amp;gt; &quot;foo&quot;,
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nothing seems to actually care about the value of &lt;code&gt;application&lt;/code&gt;, nor
about the &lt;code&gt;user_auth.version&lt;/code&gt; value.  The password is the md5 of the
actual password, hex encoded.  I&apos;m not sure why it is, as this adds
absolutely no security, but it is.  This is also not properly
documented.&lt;/p&gt;

&lt;p&gt;This gives us a JSON object back with a somewhat haphazard selection
of attributes (reformatted here for readability):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
     &quot;id&quot;:&quot;&amp;lt;hex session id&amp;gt;,
     &quot;module_name&quot;:&quot;Users&quot;,
     &quot;name_value_list&quot;: {
             &quot;user_id&quot;: {
                     &quot;name&quot;:&quot;user_id&quot;,
                     &quot;value&quot;:&quot;1&quot;
             },
             &quot;user_name&quot;: {
                     &quot;name&quot;:&quot;user_name&quot;,
                     &quot;value&quot;:&quot;&amp;lt;username&amp;gt;&quot;
             },
             &quot;user_language&quot;: {
                     &quot;name&quot;:&quot;user_language&quot;,
                     &quot;value&quot;:&quot;en_us&quot;
             },
             &quot;user_currency_id&quot;: {
                     &quot;name&quot;:&quot;user_currency_id&quot;,
                 &quot;value&quot;:&quot;-99&quot;
             },
             &quot;user_currency_name&quot;: {
                     &quot;name&quot;:&quot;user_currency_name&quot;,
                     &quot;value&quot;:&quot;Euro&quot;
             }
     }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What is the &lt;code&gt;module_name&lt;/code&gt;?  No real idea.  In general, when you get
back an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;module_name&lt;/code&gt; field, it tells you that the id
exists is an object that exists in the context of the given module.
Not here, since the session id is not a user.&lt;/p&gt;

&lt;p&gt;The worst here is the &lt;code&gt;name_value_list&lt;/code&gt; concept which is used all over
the REST interface. First, it&apos;s not a list, it&apos;s a hash.  Secondly, I
have no idea what would be wrong by just using keys directly in the
top level object, so the object would have looked somewhat like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
     &quot;id&quot;:&quot;&amp;lt;hex session id&amp;gt;,
     &quot;user_id&quot;: 1,
     &quot;user_name&quot;: &quot;&amp;lt;username&amp;gt;,
     &quot;user_language&quot;:&quot;en_us&quot;,
     &quot;user_currency_id&quot;: &quot;-99&quot;,
     &quot;user_currency_name&quot;: &quot;Euro&quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some people might argue that since you can have custom field names
this can cause clashes.  Except, it can&apos;t, since they&apos;re all suffixed
with &lt;code&gt;_c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we&apos;re now logged in and can fetch all opportunities.  This we do by
posting:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;method=&amp;gt;&quot;get_entry_list&quot;,
input_type=&amp;gt;&quot;JSON&quot;,
response_type=&amp;gt;&quot;JSON&quot;,
rest_data=&amp;gt;to_json([
            $sid,
            $module,
            $where,
            &quot;&quot;,
            $next,
            $fields,
            $links,
            1000
])
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$sid&lt;/code&gt; is our session id from the login&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$module&lt;/code&gt; is &quot;Opportunities&quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$where&lt;/code&gt; is &lt;code&gt;opportunities_cstm.rt_id_c IS NOT NULL&lt;/code&gt;.  Yes, that&apos;s
right.  An SQL fragment right there and you have to know that you&apos;ll
join the &lt;code&gt;opportunities_cstm&lt;/code&gt; and &lt;code&gt;opportunities&lt;/code&gt; tables because we
are using a custom field.  I find this completely crazy.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$next&lt;/code&gt; starts out at 0 and we&apos;re limited to 1000 entries at a time.
There is, apparently, no way to say &quot;just give me all you have&quot;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$fields&lt;/code&gt; is an array, in our case consisting of &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;,
&lt;code&gt;description&lt;/code&gt;, &lt;code&gt;rt_id_c&lt;/code&gt; and &lt;code&gt;rt_status_c&lt;/code&gt;.  To find out the field
names, look at the database schema or poke around in the SugarCRM
studio.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$links&lt;/code&gt; is to link records together.  I still haven&apos;t been able to
make this work properly and just do multiple queries.&lt;/li&gt;
&lt;li&gt;1000 is the maximum number of records.  No, you can&apos;t say -1 and get
everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why this is a list rather than a hash?  Again, I don&apos;t know.  A hash
would make more sense to me.&lt;/p&gt;

&lt;p&gt;The resulting JSON looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
    &quot;result_count&quot; : 16,
    &quot;relationship_list&quot; : [],
    &quot;entry_list&quot; : [
       {
          &quot;name_value_list&quot; : {
             &quot;rt_status_c&quot; : {
                &quot;value&quot; : &quot;resolved&quot;,
                &quot;name&quot; : &quot;rt_status_c&quot;
             },
             […]
          },
          &quot;module_name&quot; : &quot;Opportunities&quot;,
          &quot;id&quot; : &quot;&amp;lt;entry_uuid&amp;gt;&quot;
       },
       […]
    ],
    &quot;next_offset&quot; : 16
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, &lt;code&gt;entry_list&lt;/code&gt; actually is a list here, which is good and all, but
there&apos;s still the annoying &lt;code&gt;name_value_list&lt;/code&gt; concept.&lt;/p&gt;

&lt;p&gt;Last, we want to update the record in Sugar, to do this we do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;method=&amp;gt;&quot;set_entry&quot;,
input_type=&amp;gt;&quot;JSON&quot;,
response_type=&amp;gt;&quot;JSON&quot;,
rest_data=&amp;gt;to_json([
    $sid,
    &quot;Opportunities&quot;,
    $fields
])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$fields&lt;/code&gt; is not a &lt;code&gt;name_value_list&lt;/code&gt;, but instead is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
    &quot;rt_status_c&quot; : &quot;resolved&quot;,
    &quot;id&quot; : &quot;&amp;lt;status text&amp;gt;&quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why this works and my attempts at using a proper &lt;code&gt;name_value_list&lt;/code&gt;
didn&apos;t work?  I have no idea.&lt;/p&gt;

&lt;p&gt;I think that pretty much sums it up.  I&apos;m sure there are other
problems in there (such as the over 100 lines of support code for the
about 20 lines of actual code that does useful work), though.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Bizarre slapd (and gnutls) failures</title>
    <link>http://err.no/personal/blog/tech/2011-08-31-10-30_bizarre_slapd_failures.html</link>
    <pubDate>Wed, 31 Aug 2011 10:30 +0100</pubDate>
    <description>&lt;p&gt;Just this morning, I was setting up TLS on a LDAP host, but &lt;code&gt;slapd&lt;/code&gt;
refused to start afterwards with a bizarre error message:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TLS init def ctx failed: -207
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The key and certificate was freshly generated using &lt;code&gt;openssl&lt;/code&gt; on my
laptop (running wheezy, so OpenSSL 1.0.0d-3).  After a bit of
googling, I discovered that -207 is gnutls-esque for &quot;Base64 error&quot;.
Of course, the key looks just fine and decodes fine using &lt;code&gt;base64&lt;/code&gt;,
&lt;code&gt;openssl base64&lt;/code&gt; and even gnutls&apos;s own &lt;code&gt;certtool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;certtool&lt;/code&gt; also spits out what it considers the right base64
version of the key and I noticed it differed.  Using the one
&lt;code&gt;certtool&lt;/code&gt; output seems to work, though, so if you ever run into this
problem try running the key through &lt;code&gt;certtool --infile foo.pem -k&lt;/code&gt; and
use the base64 representation it outputs.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>libvmod_curl – using cURL from inside Varnish Cache</title>
    <link>http://err.no/personal/blog/tech/2011-08-03-11-44_libvmod_curl.html</link>
    <pubDate>Wed, 03 Aug 2011 11:44 +0100</pubDate>
    <description>&lt;p&gt;It&apos;s sometimes necessary to be able to access HTTP resources from
inside VCL.  Some use cases include authentication or authorization
where a service validates a token and then tell Varnish whether to
proceed or not.&lt;/p&gt;

&lt;p&gt;To do this, we recently implemented &lt;a href=&quot;https://github.com/varnish/libvmod-curl&quot;&gt;&lt;code&gt;libvmod_curl&lt;/code&gt;&lt;/a&gt; which is a set of
cURL bindings for VCL so you can fetch remote resource easily.  HTTP
would be the usual method, but cURL also supports other protocols such
as LDAP or POP3.&lt;/p&gt;

&lt;p&gt;The API is very simple, to use it you would do something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require curl;

sub vcl_recv {
    curl.fetch(&quot;http://authserver/validate?key=&quot; + regsub(req.url, &quot;.*key=([a-z0-9]+), &quot;\1&quot;));
    if (curl.status() != 200) {
        error 403 &quot;Go away&quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Other methods you can use are &lt;code&gt;curl.header(headername)&lt;/code&gt; to get the
contents of a given header and &lt;code&gt;curl.body()&lt;/code&gt; to get the body of the
response.  See the README file in the source for more information.&lt;/p&gt;
</description>
  </item>
  </channel>
</rss>
