<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Passing Curiosity: Posts tagged howto</title>
    <link href="https://passingcuriosity.com/tags/howto/howto.xml" rel="self" />
    <link href="https://passingcuriosity.com" />
    <id>https://passingcuriosity.com/tags/howto/howto.xml</id>
    <author>
        <name>Thomas Sutton</name>
        
        <email>me@thomas-sutton.id.au</email>
        
    </author>
    <updated>2024-01-26T00:00:00Z</updated>
    <entry>
    <title>Splitting predefined GCP roles</title>
    <link href="https://passingcuriosity.com/2024/splitting-gcp-predefined-roles/" />
    <id>https://passingcuriosity.com/2024/splitting-gcp-predefined-roles/</id>
    <published>2024-01-26T00:00:00Z</published>
    <updated>2024-01-26T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Recently I’ve worked with a client who wanted to restrict access to any <em>Set IAM
Policy</em> permissions in their Google Cloud Platform environment. Currently this
is implemented by defining a small number of custom roles which fall into one of
two groups:</p>
<ul>
<li><p>Roles which include all the <em>Set IAM Policy</em> permissions for the necessary
services;</p></li>
<li><p>Role/s which include all the non-<em>Set IAM Policy</em> permissions for the
necessary services.</p></li>
</ul>
<p>Currently these are defined by explicitly listing all the permissions that
should be granted (as far as they are known at the time we edit the definition).
I’ve recently been thinking about an approach that might help move toward a more
manageable approach.</p>
<ol type="1">
<li><p>Use the Google pre-defined roles where possible. This will help make sure
that documentation, error message, examples, etc. is more directly applicable
to the client’s environment.</p></li>
<li><p>Some pre-defined roles can’t be used because they mix <em>Set IAM Policy</em> with
other permissions that the client wants to manage separately. In this case,
use Terraform to define custom roles, but do so based on the definition of
the pre-defined role.</p></li>
</ol>
<p>Here’s a sketch of what this might look like.</p>
<pre class="terraform"><code>variable &quot;target_role&quot; {
  type        = string
  description = &quot;ID of the target role.&quot;
}

# Fetch the existing role.
data &quot;google_iam_role&quot; &quot;role&quot; {
  name = var.target_role
}

locals {
  role_components = split(&quot;/&quot;, var.target_role)
  role_name       = element(local.role_components, length(local.role_components) - 1)

  # Every permission in the target role that **IS** a setIamPolicy permission.
  setiam_permissions = [
    for permission in data.google_iam_role.role.included_permissions:
    permission if length(regexall(&quot;^.*[.]setIamPolicy$&quot;, permission)) == 1
  ]

  # Every permission in the target role that **IS NOT** a setIamPolicy permission.
  normal_permissions = [
    for permission in data.google_iam_role.role.included_permissions:
    permission if length(regexall(&quot;^.*[.]setIamPolicy$&quot;, permission)) == 0
  ]
}

resource &quot;google_project_iam_custom_role&quot; &quot;nonpriv_role&quot; {
  role_id     = &quot;custom.${role_name}.nonpriv&quot;
  title       = &quot;${data.google_iam_role.role.title} - (Non-priv)&quot;
  description = &quot;(Custom non-privileged version) ${data.google_iam_role.role.description}.&quot;
  permissions = local.normal_permissions
}

resource &quot;google_project_iam_custom_role&quot; &quot;priv_role&quot; {
  role_id     = &quot;custom.${role_name}.priv&quot;
  title       = &quot;${data.google_iam_role.role.title} - (Priv)&quot;
  description = &quot;(Custom privileged version) ${data.google_iam_role.role.description}.&quot;
  permissions = local.setiam_permissions
}

output &quot;permissions_role&quot; {
    value  = resource.google_project_iam_custom_role.nonpriv_role
}

output &quot;set_iam_policy_role&quot; {
    value  = resource.google_project_iam_custom_role.priv_role
}</code></pre>]]></summary>
</entry>
<entry>
    <title>Extract a CA certificate bundle from macOS Keychain</title>
    <link href="https://passingcuriosity.com/2024/export-keychain-certificates-to-pem/" />
    <id>https://passingcuriosity.com/2024/export-keychain-certificates-to-pem/</id>
    <published>2024-01-20T00:00:00Z</published>
    <updated>2024-01-20T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>How to generate a PEM file containing the trusted CA certificates in your macOS
Keychain. As described in <a href="https://stackoverflow.com/a/41853880">this answer on Stack Exchange</a> you can use the
<a href="https://ss64.com/mac/security.html"><code>security</code></a> tool added in Mac OS X 10.3:</p>
<pre><code>security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain &gt; cacerts.pem

security find-certificate -a -p /Library/Keychains/System.keychain &gt;&gt; cacerts.pem</code></pre>
<p>If there are missing CA certificates you need to trust, just append them to the
end of the file:</p>
<pre><code>cat MyTlsStrippingCorporateProxyCA.pem &gt;&gt; cacerts.pem</code></pre>
<p>You can store the <code>cacerts.pem</code> file somewhere convenient – maybe somewhere
under <code>~/Library/</code> would be sensible on macOS – and then export the many and
varied environment variables that will configure various tools to use the file:</p>
<pre><code>export AWS_CA_BUNDLE=&quot;$HOME/Library/cacerts.pem&quot;
export CURL_CA_BUNDLE=&quot;$HOME/Library/cacerts.pem&quot;
export HTTPLIB2_CA_CERTS=&quot;$HOME/Library/cacerts.pem&quot;
export REQUESTS_CA_BUNDLE=&quot;$HOME/Library/cacerts.pem&quot;
export SSL_CERT_FILE=&quot;$HOME/Library/cacerts.pem&quot;
export NODE_EXTRA_CA_CERTS=&quot;$HOME/Library/cacerts.pem&quot;</code></pre>]]></summary>
</entry>
<entry>
    <title>Ledger accounting with GnuPG</title>
    <link href="https://passingcuriosity.com/2024/ledger-with-gnupg/" />
    <id>https://passingcuriosity.com/2024/ledger-with-gnupg/</id>
    <published>2024-01-04T00:00:00Z</published>
    <updated>2024-01-04T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p><a href="https://ledger-cli.org/">Ledger</a> has <a href="https://github.com/ledger/ledger/pull/1949">support for GnuPG-encrypted journal files</a> but it’s not
really documented anywhere that I’ve been able to find. To check that it’s
enabled in your build, consult the version message:</p>
<pre><code>$ ledger --version
Ledger 3.3.2-20230330, the command-line accounting tool
with support for gpg encrypted journals and without Python support

Copyright (c) 2003-2023, John Wiegley.  All rights reserved.

This program is made available under the terms of the BSD Public License.
See LICENSE file included with the distribution for details and disclaimer.</code></pre>
<p>and check for “with support for gpg encrypted journals”.</p>
<p>If it’s present, then all you have to do is encrypt your journal files and
<code>ledger</code> will transparently decrypt the data as it reads. Doing this is a
simple matter of encrypting the files with yourself as the recipient. If you
only use <code>gpg --encrypt</code> to encrypt files for yourself (and not to send to
other people) then the easiest way might be to configure GnuPG to encrypt with
your own key by default:</p>
<pre><code>$ echo default-recipient-self &gt;&gt; ~/.gnupg/gpg.conf</code></pre>
<p>Alternatively, you can remember to pass the <code>--recipient</code> argument specifying
the key ID or email address for your own key when you run <code>gpg --encrypt</code>.</p>
<p>Now you can just create some encrypted journal files:</p>
<pre><code>$ cat 2024.journal | gpg --encrypt --armor &gt; 2024.journal.gpg
$ ledger -f 2024.journal.gpg bal
        AUD 2,187.50  Assets
        AUD 2,150.00    Bank
           AUD 37.50    Cash
           AUD 12.50  Expenses:Food:Dining
       AUD -2,200.00  Income:Gifts
--------------------
                   0</code></pre>
<p>For the sake of convenience, I give the encrypted files an extension like <code>.asc</code>
or <code>.gpg</code> so that tools like <a href="https://github.com/jamessan/vim-gnupg">vim-gnupg</a> can transparently decrypt them for
editing.</p>
<p>Ledger handles encryption transparently at the file-access level, so you
can split up your configuration and journal postings into different
files and make each encrypted or unencrypted as you like. Personally, I
like to have a single plain-text file that defines my chart of accounts
and then includes encrypted journal files containing the actual posting.</p>]]></summary>
</entry>
<entry>
    <title>Setup Yubikey with OpenPGP for git</title>
    <link href="https://passingcuriosity.com/2024/yubikey-opengpg-setup/" />
    <id>https://passingcuriosity.com/2024/yubikey-opengpg-setup/</id>
    <published>2024-01-03T00:00:00Z</published>
    <updated>2024-01-03T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>This is a pretty sparse log of things to do to set up a new Yubikey with
OpenPGP for use with <code>git</code>. If anything below doesn’t make sense consult the
sources linked at the end of the post.</p>
<h2 id="install-things">Install things</h2>
<p>We’ll install a bunch of stuff with Homebrew:</p>
<ul>
<li><p><code>git</code> to get a newer version than what Apple ships</p></li>
<li><p><code>ykman</code> to view and tweak Yubikey configuration</p></li>
<li><p><code>pinentry</code> (to pop up a window to enter your Yubikey PIN when required)</p></li>
<li><p>GnuPG 2 to take care of doing all the cryptography</p></li>
</ul>
<pre><code>brew install \
    git \
    ykman \
    gnupg \
    pinentry \
    pinentry-mac </code></pre>
<h2 id="setup-yubikey">Setup Yubikey</h2>
<p>A modern Yubikey probably supports a <em>lot</em> of different interfaces: OTP, PIV,
OpenPGP, FIDO U2F, FIDO2, OATH. Many have one or more PIN that help to prevent
unauthorised usage. If you haven’t already, you should configure the various
codes for all interfaces configured on your Yubikey.</p>
<p>We’re focussed on setting up OpenPGP so let’s just take care of that.</p>
<p>You can use <code>ykman</code> to check the current policy for OpenPGP on your Yubikey:</p>
<pre><code>$ ykman openpgp info
OpenPGP version:            3.4
Application version:        5.4.3
PIN tries remaining:        3
Reset code tries remaining: 0
Admin PIN tries remaining:  3
Require PIN for signature:  Once
Touch policies:
  Signature key:      Off
  Encryption key:     Off
  Authentication key: Off
  Attestation key:    Off</code></pre>
<p>You can use <code>gpg --edit-card</code> to modify the various passwords. When started,
it’ll output the current card configuration and prompt for commands. Use <code>admin</code>
to enter administration mode, then <code>passwd</code> to control the card passwords.</p>
<p>If you have a brand new card will have the following details:</p>
<ul>
<li>PIN: 123456</li>
<li>Admin PIN: 12345678</li>
<li>Reset Code: NONE</li>
<li>Retries: 3</li>
</ul>
<pre><code>$ gpg --edit-card

...

gpg/card&gt; admin
Admin commands are allowed

gpg/card&gt; passwd
gpg: OpenPGP card no. D2760001240100000006196516380000 detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit</code></pre>
<p>You can change the number of attempts allowed for the PIN, reset code, and admin
PIN:</p>
<pre><code>$ ykman openpgp access set-retries 10 10 10</code></pre>
<h2 id="create-new-keys">Create new keys</h2>
<p>The general process looks something like:</p>
<pre><code>$ gpg --gen-key
$ gpg --expert --edit-key KEY_ID
gpg&gt; addkey
# Select whichever &quot;set your own capabilities&quot; option you like; it's probably a
# good idea to use the same key type as your main key.
#
# Enable Authenticate, disable the other actions (Sign and Encrypt)
#
# Set the key expiry to the same as the first key. In my case it was 3y</code></pre>
<p>Export your key so that you can keep a backup off-line somewhere. Make sure that
it is safe, secure, and <em>offline</em>. Print it out or write it on a CD or something
and keep it with your important papers.</p>
<p>Then you can move the new keys to your Yubikey:</p>
<pre><code>$ gpg --edit-key KEY_ID
# Switch to viewing private keys:
gpg&gt; toggle
# First, move the primary key to the Yubikey. The key list will show usage of SC
# denoting a signing key, so move it to the &quot;Signature key&quot; slot.
gpg&gt; keytocard
# Then select the first sub-key.
gpg&gt; key 1
# The key list will show usage of E denoting encryption, so move it to the
# &quot;Encryption key&quot; slot in the Yubikey.
gpg&gt; keytocard
# Finally, deselect the first sub-key and select the second sub-key:
gpg&gt; key 1
gpg&gt; key 2
# This sub-key will have usage &quot;A&quot;, so move it to the &quot;Authentication key&quot; slot.
gpg&gt; keytocard</code></pre>
<p>At various points in this process, GnuPG will ask for the private key passphrase
(if you set one when generating the key) and the Yubikey Admin PIN.</p>
<h2 id="setup-gnupg">Setup GnuPG</h2>
<pre><code>echo &quot;pinentry-program $(which pinentry-mac)&quot; &gt;&gt; ~/.gnupg/gpg-agent.conf
killall gpg-agent</code></pre>
<h2 id="test-signing">Test signing</h2>
<p>You can verify that GnuPG is configured and working correctly by signing a
sample message:</p>
<pre><code>$ echo &quot;Hello world&quot; | gpg --clearsign
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hello world
-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----</code></pre>
<p>Depending on the settings for your key, you may need to enter your Yubikey PIN
(usually only the first time you’ve used it this session) and/or touch the key
(see the <code>ykman</code> settings above to control this).</p>
<h2 id="configure-git">Configure <code>git</code></h2>
<p>You need to tell <code>git</code> which key to use when signing things and might like to
set a few other options which control when things are signed and when signatures
are displayed:</p>
<pre><code>$ git config --global user.signingkey KEY_ID</code></pre>
<p>Some settings which may help <code>git</code> to run GnuPG correctly:</p>
<pre><code>$ git config --global gpg.program gpg</code></pre>
<p>Some settings that control when <code>git</code> will sign things and display signatures:</p>
<pre><code>$ git config --global log.showSignature true
$ git config --global commit.gpgSign true
$ git config --global tag.gpgSign true</code></pre>
<h2 id="github-configuration">GitHub configuration</h2>
<p>Export your <em>public</em> key (note the <code>PUBLIC KEY</code> in the output below) and copy
the output.</p>
<pre><code>$ gpg --export --armor KEY_ID

-----BEGIN PGP PUBLIC KEY BLOCK-----
....
-----END PGP PUBLIC KEY BLOCK-----</code></pre>
<p>Go to the “SSH and GPG keys” page of your GitHub settings and click add <a href="https://github.com/settings/gpg/new">New GPG
key</a>. Paste the key into the text area, add
a useful comment to help identify the key, and click the save button.</p>
<p>When you use the GitHub.com web-site to commit changes to your code, GitHub
signs your commits with an internal key. To validate these commits, you’ll need
to import and sign the key:</p>
<pre><code>$ curl https://github.com/web-flow.gpg | gpg --import
$ gpg --lsign-key noreply@github.com</code></pre>
<h2 id="references">References</h2>
<ul>
<li><p>Yubikey PGP <a href="https://developers.yubico.com/PGP/Card_edit.html">Card edit</a></p></li>
<li><p>Yubikey PGP <a href="https://developers.yubico.com/PGP/Importing_keys.html">Importing keys</a></p></li>
<li><p>Yubikey PGP <a href="https://developers.yubico.com/PGP/Git_signing.html">Git signing</a></p></li>
<li><p><a href="https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html">ykman openpgp manual</a></p></li>
<li><p><a href="https://stackoverflow.com/a/60482908">Trusting GitHub’s key</a></p></li>
<li><p><a href="https://github.com/drduh/YubiKey-Guide">YubiKey Guide</a></p></li>
<li><p><code>git-commit(1)</code> man page</p></li>
<li><p><code>git-tag(1)</code> man page</p></li>
<li><p><code>git-log(1)</code> man page</p></li>
</ul>]]></summary>
</entry>
<entry>
    <title>Notes on AWK scripting</title>
    <link href="https://passingcuriosity.com/2023/awk-scripts/" />
    <id>https://passingcuriosity.com/2023/awk-scripts/</id>
    <published>2023-11-01T00:00:00Z</published>
    <updated>2023-11-01T00:00:00Z</updated>
    <summary type="html"><![CDATA[<h2 id="writing-awk-scripts">Writing AWK <em>scripts</em></h2>
<p>Many large AWK scripts are wrapped in a useless
shell script. If all of your logic is in AWK
then there’s no need for the shell to get
involves in things; just use the correct
shebang!</p>
<pre><code>#!/usr/bin/awk -f

BEGIN { print(&quot;start&quot;) }
END { print(&quot;end&quot;) }</code></pre>
<p>Just make it executable and now you have a
script written directly in AWK with no
shells involved. Just make it executable
(with <code>chmod +x</code> as usual) and you are
good to go.</p>
<p>Why bother? It makes the script simpler
(e.g. no multiple levels of quoting and
escaping), makes it slightly less resource
intensive to start (only a single fork and
exec) and run (no shell waiting around for
the <code>awk</code> interpreter to finish), and makes
the script sightly easier to handle with
tools like syntax highlighting, code
formatting, etc.</p>
<h2 id="code-formatting">Code formatting</h2>
<p>Like any body of code, the formatting of a
longer AWK script can be an important help
or hindrance to anyone trying to understand
it. GNU AWK has a helpful option to format
AWK scripts.</p>
<pre><code>#!/usr/bin/awk -f
BEGIN { print(&quot;start&quot;); }
END   { print(&quot;end&quot;) }</code></pre>
<p>We can format this AWK script like so:</p>
<pre><code>$ gawk -f example.awk -o-
#!/usr/bin/awk -f
BEGIN {
        print(&quot;start&quot;)
}

END {
        print(&quot;end&quot;)
}</code></pre>
<p>We use <code>-f</code> to read the AWK script from a
file and <code>-o</code> to format and output the
script.</p>
<p>In this case, we’re writing it to the
standard output (<code>-o-</code>) but we could also
write it to another (different!) file with
<code>-oformatted.awk</code>) or use <code>-o</code> and let
<code>awk</code> write it to the default output file
(<code>awkprof.out</code>).</p>]]></summary>
</entry>
<entry>
    <title>Use Colima to build and run containers on macOS</title>
    <link href="https://passingcuriosity.com/2023/colima-docker-on-mac/" />
    <id>https://passingcuriosity.com/2023/colima-docker-on-mac/</id>
    <published>2023-10-20T00:00:00Z</published>
    <updated>2023-10-20T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>If you use Homebrew to install third-party packages on macOS, it’s
pretty straightforward to install and configure <a href="https://github.com/abiosoft/colima">Colima</a> along
with the various Docker and Kubernetes command-line tools.</p>
<p>First, make sure your Homebrew formulas are all up to date:</p>
<pre><code>brew update</code></pre>
<p>Install Colima along with the Docker and Kubernetes command-line tools:</p>
<pre><code>brew install colima docker kubectl</code></pre>
<p>If you work on a network controlled by an organisation that uses TLS stripping
security appliances you’ll probably need to install additional CA root
certificates before you can pull container images from the Internet, etc. You
can put them in the usual place in your home directory and Colima will
automatically install them in the VMs it starts:</p>
<pre><code>mkdir -p ~/.docker/certs.d
cd ~/.docker/certs.d
curl -o proxy-cert.crt https://insecurity.my.corp/proxy-cert.crt</code></pre>
<p>(Do make sure you put each certificate in a separate file; if they are
concatenated you’ll need to split them.)</p>
<p>With Colima installed, you should be able to start a Colima instance. There are
a handful of options to control the CPU, disk, and memory allocation for the VM,
the runtimes to configure on it, etc.</p>
<pre><code>colima start --memory 8 --kubernetes</code></pre>
<p>Check that the Docker and Kubernetes command-line tools have been configured to
talk to the new Colima instance:</p>
<pre><code>kubectl get pods -A
docker ps</code></pre>
<p>If you installed custom certs, you’d better check that it’s all working
correctly by pulling an image:</p>
<pre><code>docker pull python:3.12-slim</code></pre>
<p>Easy.</p>]]></summary>
</entry>
<entry>
    <title>Installing OpenBSD on a Microsoft Surface Go 3</title>
    <link href="https://passingcuriosity.com/2023/openbsd-surface-go-3/" />
    <id>https://passingcuriosity.com/2023/openbsd-surface-go-3/</id>
    <published>2023-01-08T00:00:00Z</published>
    <updated>2023-01-08T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I have a new Microsoft Surface Go 3 and installed OpenBSD 7.2 to see how it
does as a machine to carry while travelling. The box contained the Surface Go
itself, a 24 W charger with the silly proprietary connector, and a few bits of
paper. I already had a Type Cover keyboard (from the Go I bought when it came
out) so I was pretty much ready to go.</p>
<h2 id="installing-openbsd">Installing OpenBSD</h2>
<ol start="0" type="1">
<li><p>Boot the Surface and let Microsoft Update install a bunch of stuff. Most of
this isn’t important as I blew away the Windows installation completely, but
I guess the firmware updates will probably be useful (and there’s no chance
of getting them installed except through Windows). This takes absolutely
ages. Something on the order of an hour, much of it with a static
“installing updates” screen.</p></li>
<li><p>Download an OpenBSD installer image and write it to a USB storage device. I
used <code>install72.img</code> and the <code>dd</code> command but it doesn’t matter much. Don’t
forget to validate the signature of the image!</p></li>
<li><p>Boot the Surface into firmware mode (hold volume-up, press the power button,
and wait until it enters the firmware before you release volume-up). Disable
Secure Boot and set the boot order to include USB devices.</p></li>
<li><p>Insert the USB device and reboot. I needed a USB-C to USB-A converted for my
USB storage device.</p></li>
<li><p>Go through the OpenBSD installer process. While OpenBSD includes a driver
for the Intel wireless device, the installer doesn’t include the firmware. I
yanked out the USB storage device and inserted a USB Ethernet adaptor I had
handy at the network configuration point. This allowed me to use an HTTP
mirror as the source for the installation and, importantly, let installer
download the appropriate firmware.</p></li>
</ol>
<p>https://jcs.org/2020/05/15/surface_go2</p>
<h2 id="networking">Networking</h2>
<p>The installer identified the firmware packages needed for built-in Intel
wireless adaptor. But running <code>fw_update</code> is probably a good idea.</p>
<p>Configure the WiFi interface by creating <code>/etc/hostname.iwx0</code> with content like
the following:</p>
<pre><code>join HOME_NETWORK wpakey PASSWORD
join WORK_NETWORK wpakey OTHERPASS
dhcp</code></pre>
<p>There are more parameters that can be added; see <code>hostname.if(5)</code> and
<code>ifconfig(8)</code> for details.</p>
<p>I also have a new Google Pixel 7 Pro phone and want to get USB tethering up and
running. Recent Pixel models have stopped using RNDIS protocol for USB
tethering (though OpenBSD does have a driver for RNDIS). This is a good move by
Google! <em>And</em> they’ve moved to using an actual standard: CDC UNM. Unfortunately
OpenBSD does <em>not</em>, as far as I can tell, have a driver that supports CDC UNM
devices.</p>
<p>If your USB tethering device is supported, you can configure <code>hotplugd</code> to
bring up a network connection when you plug it in.</p>
<p>http://www.omarpolo.com/post/openbsd-tethering.html</p>
<h2 id="x-xenodm-and-a-window-manager">X, XenoDM, and a window manager</h2>
<p><code>xtsscale</code> to calibrate the touch screen but you need to find the right XInput
device. <code>xinput --list</code> will show a number of mouse devices (all alike except
for the device and XInput IDs).</p>
<p>I consulted <code>dmesg</code> for the <code>ims</code> devices:</p>
<pre><code>dmesg | grep -E 'ims[0-9]'</code></pre>
<p>On my machine <code>ims0</code> has “button, tip” while <code>ims1</code> also has “barrel, eraser”
listed: clearly <code>ims0</code> is the touch screen and <code>ims1</code> is the stylus support.
The other matched lines in <code>dmesg</code> should mention the <code>wsmouse</code> the corresponds
to each <code>ims</code> device: my machine had <code>wsmouse0</code> and <code>wsmouse1</code> respectively.
Use <code>xinput --list</code> and find the entry for <code>wsmouse0</code>. Then find the XInput ID
(e.g. <code>id=7</code>) and calibrate it:</p>
<pre><code>xtsscale -d 7</code></pre>
<p>If your fingers are as fat as mine the calibration process might take a few
attempts but eventually it will update the calibration parameters for the
running X server and print those same parameters so you can update your
configuration. The details are in <code>xtsscale(1)</code>.</p>
<p>https://www.birkey.co/2022-01-29-openbsd-7-xfce-desktop.html</p>
<p>https://www.tumfatig.net/2019/customizing-openbsd-xenodm/</p>
<p>https://dataswamp.org/~solene/2021-07-30-openbsd-xidle-xlock.html</p>
<p>https://www.tumfatig.net/2021/calibrate-your-touch-screen-on-openbsd/</p>]]></summary>
</entry>
<entry>
    <title>Aborting supersede Jenkins builds</title>
    <link href="https://passingcuriosity.com/2021/aborting-superseded-jenkins-builds/" />
    <id>https://passingcuriosity.com/2021/aborting-superseded-jenkins-builds/</id>
    <published>2021-06-30T00:00:00Z</published>
    <updated>2021-06-30T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Even small teams can find that their continuous integration servers get bogged
down with redundant builds. Some developers like to “commit early, commit often”
and if they also “open a PR early and leave it sitting there in draft mode” then
you can quite easily have multiple builds linting and building and testing code
that has already been supersede.</p>
<p>Happily, you can use the <a href="https://plugins.jenkins.io/pipeline-milestone-step/">Pipeline: Milestone Step</a> plugin to have Jenkins
terminate already running builds of the same job. The goal here is
straighforward:</p>
<blockquote>
<p>My multibranch pipeline build is notified of PR-123. It creates a new job
called PR-123 and starts build 1.</p>
<p>I push another commit to the branch. GitHub notifies Jenkins and Jenkins
starts PR-123 build 2. I now have two running builds – build 1 and build 2
– but the outcome of build 1 is no longer useful.</p>
<p>Suppose I notice a type and immediately push a fix. This would result in
<em>three</em> running builds, <em>two</em> of them useless.</p>
</blockquote>
<p>Milestones can be useful in a range of circumstances but I mostly want to take
advantage of one feature:</p>
<blockquote>
<p>When a build passes a milestone, any older build that passed the previous
milestone but not this one is aborted.</p>
</blockquote>
<p>If we use the <code>BUILD_ID</code> as the milestone, then we can use this to abort old
jobs when a new one starts.</p>
<pre><code>node {
    stage(&quot;Prepare&quot;) {
        milestone label: '', ordinal: Integer.parseInt(env.BUILD_ID) - 1
        milestone label: '', ordinal: Integer.parseInt(env.BUILD_ID)
        checkout scm
    }
    stage(&quot;One&quot;) {
        sh &quot;&quot;&quot;sleep 60&quot;&quot;&quot;
    }
    stage(&quot;Two&quot;) {
        sh &quot;&quot;&quot;sleep 120&quot;&quot;&quot;
    }
    stage(&quot;Three&quot;){
        sh &quot;&quot;&quot;sleep 180&quot;&quot;&quot;
    }
}</code></pre>
<p>Like everything involving Jenkins, there are bound to be heaps of interactions
with other features and scenarios where it doesn’t work reliably. Good luck.</p>]]></summary>
</entry>
<entry>
    <title>Making GitHub pull request comments in a Jenkins pipeline</title>
    <link href="https://passingcuriosity.com/2021/jenkins-pipeline-update-pull-request-comments/" />
    <id>https://passingcuriosity.com/2021/jenkins-pipeline-update-pull-request-comments/</id>
    <published>2021-05-04T00:00:00Z</published>
    <updated>2021-05-04T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Sometimes all you want from your continuous integration setup is one bit: red vs
green. In other circumstances, you might like more detailed feedback. For
configuration management scenarios I like to see a [summary of] the planned
changes as a comment on my pull request.</p>
<p>If you use the <a href="https://plugins.jenkins.io/pipeline-github/">Pipeline: GitHub</a>
Jenkins plugin you can use code like this to:</p>
<ol type="1">
<li>Delete any previous comments made by your CI/CD pipeline on that PR.</li>
<li>Post a comment to the PR.</li>
</ol>
<pre><code>node {
    stage(&quot;Prepare&quot;) {
        checkout scm
    }

    stage(&quot;Build&quot;) {
        echo &quot;...&quot;
    }

    stage(&quot;Comment&quot;) {
        if (env.CHANGE_ID) {
            for (comment in pullRequest.comments) {
                /* Where &quot;automation-user&quot; is the scm account. */
                if (comment.user == &quot;automation-user&quot;) {
                    pullRequest.deleteComment(comment.id)
                }
            }
            def date = sh(returnStdout: true, script: &quot;date -u&quot;).trim()
            pullRequest.comment(&quot;Build ${env.BUILD_ID} ran at ${date}&quot;)
        }
    }
}</code></pre>]]></summary>
</entry>
<entry>
    <title>Reducing TLS client security requirements on OpenSSL and GnuTLS</title>
    <link href="https://passingcuriosity.com/2021/diffie-hellman-short-primes-disable/" />
    <id>https://passingcuriosity.com/2021/diffie-hellman-short-primes-disable/</id>
    <published>2021-03-30T00:00:00Z</published>
    <updated>2021-03-30T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Most operating systems do a pretty OK job of shipping libraries that have
relatively secure configurations. Unfortunately, lots of organisations –
especially large organisations – do a terrible job of building secure
networks for them to run in. After “security” “appliances”, TLS is one thing
that sticks out as regularly screwed up.</p>
<p>In my current organisation we must interact with a number of servers with,
by modern standards, insecure TLS configuration. In particular, Diffie-Hellman
parameters that are too short to be considered secure. OpenSSL and GnuTLS as
shipped in Ubuntu 20.04 both refuse to handshake with these services. Well
done!</p>
<p>Unfortunately, it’s a large organisation so there is absolutely no chance of
getting these server configurations updated. So we need to reconfigure our
TLS client libraries to accept the low-security servers.</p>
<p>First, a disclaimer: I am not a cryptographer, security engineer, encryption
library developer, informed amateur, or even a particularly observant
bystander. You should be accepting security advice from me.</p>
<h2 id="gnutls">GnuTLS</h2>
<p>A great deal of GnuTLS operation is configured using a priority string. In
the version I’m looking at, the default priority string is</p>
<pre><code>NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-DTLS1.2:%PROFILE_MEDIUM</code></pre>
<p>It’s the <code>%PROFILE_MEDIUM</code> that does things like set the minimum lengths
for keys, DH primes, etc. You can find the various security profile options
in the GnuTLS manual at <a href="https://www.gnutls.org/manual/html_node/Selecting-cryptographic-key-sizes.html">Section 6.11 Selecting cryptographic key sizes</a>.
My current project needs to support servers using Diffie-Hellman primes of
1024 bits, so I need to use <code>PROFILE_LOW</code>.</p>
<p>You can override the default priority string by editing (or creating)
<code>/etc/gnutls/config</code> like so:</p>
<pre><code>[overrides]
default-priority-string = NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-DTLS1.2:%PROFILE_LOW</code></pre>
<p>This should then apply to any application that doesn’t specify it’s own
priority string.</p>
<h2 id="openssl">OpenSSL</h2>
<p>Updating the OpenSSL configuration is a <em>much</em> more complicated proposition.
The configuration used by applications is stored in a section named by the
<code>openssl_conf</code> variable. This is <em>not</em> in a section, so it’ll be at the top
of the file if it’s set. In my experience, it often isn’t set.</p>
<p>If it is set, go find the section it names, then follow <code>ssl_conf</code> to the
section containing the SSL configuration, then follow <code>system_default</code> to
the section <em>it</em> names.</p>
<p>Here, you can specify something like:</p>
<pre><code>CipherString = DEFAULT:@SECLEVEL=1</code></pre>
<p>If all that isn’t already in your <code>openssl.cnf</code>, you need to create a new
section, which points to a section, which points to a section. This can all
go at the end of the file. Then you need to add a variable <em>not</em> in a section
that points to the first of those sections.</p>
<p>Here’s a shell script that does just that:</p>
<pre><code>#!/bin/sh
# Update the OpenSSL configuration to use lower default security level. This
# allows us to connect to TLS servers using insecure certificates issued by the
# internal CA.

set -eux

mv /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.orig

{
cat &lt;&lt;EOF
# Override the default OpenSSL configuration with less secure settings that
# allow communication with the many services that use insecure certificates
# issued by the internal CA.
openssl_conf = default_conf
EOF

cat /etc/ssl/openssl.cnf.orig;

cat &lt;&lt;EOF
# Default configuration for applications which use OpenSSL.
[ default_conf ]
ssl_conf = ssl_sect

[ ssl_sect ]
system_default = system_default_sect

[ system_default_sect ]
MinProtocol = TLSv1.2
# Be less secure when negotiating ciphers, verifying certificates, etc.
CipherString = DEFAULT:@SECLEVEL=1
EOF
} &gt; /etc/ssl/openssl.cnf</code></pre>
<p>It’s probably a bit too lax but I use it in Docker images based on
<code>ubuntu:20.04</code> and it seems to do the trick.</p>]]></summary>
</entry>

</feed>
