Logbook + Scratchpad

tricks

In the previous post I mentioned the usage of ssh-keyscan to get and store a server's public SSH key. My doubt was that it may not be a secure-enough solution.

From what I understand, ssh-keyscan is just another instance of TOFU, or trust on first use. Basically, it only automates what you do when you're prompted to verify a key fingerprint upon first connection to a server. If the known_hosts file does not continuously change, it is ok to use this.

Anyway, I have still decided to update the GitHub Action and make use of a GitHub secret to hold the public key of the server I am connecting to.

#SSH #tricks

I decided to try and use a GitHub Action to copy some content onto an FTP server. At first I tried to use an existing action, but it didn't work and debugging was proving to be cumbersome. Then, I changed strategy and used an action with CLI commands instead.

Note: I would prefer using rsync but it is not an option in this case. Also, I do not have SSH access to the server – it's SFTP only.

The action looks roughly like this:

name: Copy files
on:
  push:
    branches:
      - main

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: scp
        run: |
          mkdir -p ~/.ssh/
          chmod 700 ~/.ssh/
          touch ~/.ssh/known_hosts
          ssh-keyscan ${{ secrets.HOST }} >> ~/.ssh/known_hosts
          echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          scp -i ~/.ssh/deploy_key -s -r some_file some_dir "${{ secrets.USERNAME }}@${{ secrets.HOST }}:"
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

Getting to this has been a bit difficult, so here are a few notes on the details:

  • scp needs to use a private SSH key, which cannot be added to GitHub as a file. I've added the key material as a GitHub secret and imported it as an environment variable. The key file is then (re)written by the action itself.
  • The .ssh directory has to be created manually, first of all because the host key has to be added to known_hosts (here with ssh-keyscan). If this is not done, scp fails with Host key verification failed. (Seen on StackOverflow)
  • The scp command needs to include the -s switch to force the SFTP protocol. This will likely change in the future, but with the current ubuntu-latest the installed OpenSSH version does not use SFTP as a default.

I am not yet 100% sure this is completely secure, so I'll keep checking. For example: is ssh-keyscan good enough, or do I need to get the key beforehand and then inject it manually into known_hosts?

#SSH #tricks

Yesterday I explored a potential solution to replace text with CSS. One of the drawbacks is that it only works if the text to be replaced is at the end of the line. I set out to remove this limitation, and the fix is relatively obvious: use another pair of classes, with the first class to be used with the ::after pseudoelement.

HTML content:

<h2 class="text-replace">
    <span class="before-text-data">Some </span>
    <span class="text-data">data</span> and more</span>
</h2>

CSS content:

.text-replace span.text-data {
    display: none;
}

.text-replace span.before-text-data::after {
    content: "d|2a|1t|3a|2";
}

#CSS #tricks

Since I discovered the Datalegreya font, I've started doing experiments to include it on a webpage. The main issue I have been thinking about is: if for any reason the font cannot be loaded (network issues, webfonts blocked, and so on, leading to a FOUT), is there a way to show the original, unstyled text instead of an unreadable version with ligatures? Can I show data instead of d|2a|1t|3a|2?

Although a Javascript solution wouldn't be difficult to write, I wanted a CSS-only solution – if at all possible. I've settled on something similar to this, where in a nutshell I enclose in a <span> element the original text I want to replace, then I use a pseudoelement to replace the <span> with the styled text.

With this solution, the HTML looks like this:

<h2 class="data-replace">Some <span>data</span></h2>

The CSS instead looks like this:

.data-replace span {
    display: none;
}

.data-replace::after {
    content: "d|2a|1t|3a|2";
}

There are two minor drawbacks to this:

  • It only works if the text to be replaced is at the end of the line.
  • The replaced text cannot be selected.

This approach does not prevent a FOUT, because the replacement will still happen as soon as the CSS is loaded. It is still useful anyway for “text mode” (for example with screen readers, or via the browser option) as it will show the original HTML content.

#CSS #tricks