Feuerfest

Just the private blog of a Linux sysadmin

Go home GoDaddy, you're drunk!

Photo by Tim Gouw: https://www.pexels.com/photo/man-in-white-shirt-using-macbook-pro-52608/

I'm just so fucking happy right now I have never been a customer of GoDaddy. As I learned via Reddit yesterday GoDaddy closed the access to their DNS API for many customers.

No prior information.

No change of the documentation regarding API access.

Nothing.

For many customers this meant that their revenue stream was affected as, for example, the SSL-Certificates for web services couldn't be automatically renewed. Which is the case when you are using Let's Encrypt.

Therefore I can't say it in any other words: GoDaddy deliberately sabotaged it's customers in order to maximize it's income.

Yeah, fuck you GoDaddy. You are on my personal blacklist now. Never going to do business with you. Not that I planned, but sometimes decisions like this must be called out and sanctioned.

When customers asked why their API calls returned an HTTP 403 error (Forbidden) GoDaddy provided the following answer (accentuation done by myself):

Hi, We have recently updated the account requirements to access parts of our production Domains API. As part of this update, access to these APIs are now limited: If you have lost access to these APIs, but feel you meet these requirements, please reply back with your account number and we will review your account and whitelist you if we have denied you access in error. Please note that this does not affect your access to any of our OTE APIs. If you have any further questions or need assistance with other API questions, please reach out. Regards, API Support TeamAvailability API: Limited to accounts with 50 or more domains Management and DNS APIs: Limited to accounts with 10 or more domains and/or an active Discount Domain Club plan.

Wow. The mentioned OTE API meanwhile is no workaround. It's GoDaddy's test API. Used to verify that your API-Calls work, prior to sending them to the productive API. You can't do anything there which would help GoDaddy's customers to find a solution without having to pay.

Sources

Am I the only one who can't use the API? (Reddit)

Warning: Godaddy silently cut access to their DNS API unless you pay them more money. If you're using Godaddy domain with letsencrypt or acme, be aware because your autorenewal will fail. (Reddit)

Comments

Things to do when updating Bludit

Photo by Markus Spiske: https://www.pexels.com/photo/green-and-yellow-printed-textile-330771/

I finally got around to update to the recent version of Bludit. And as I made two changes to files which will be overwritten, I made myself a small documentation.

Changing the default link target

Post with code example, here: https://admin.brennt.net/changing-the-default-link-target-in-bludits-tinymce

  1. Open file bludit-folder/bl-plugins/tinymce/plugin.php file
  2. Search for tinymce.init
  3. Then we add the default_link_target: '_blank' parameter at the end of the list
  4. Don't forget to add a semicolon behind the formerly last parameter

Keep the syntax highlighting

Original post: https://admin.brennt.net/bludit-and-syntax-highlighting

  1. Open: bludit-folder/bl-plugins/tinymce/tinymce/plugins/codesample/plugin.min.js
  2. Search for <pre and in the class property add line-numbers. It should now look like this: t.insertContent('<pre id="__new" class="language-'+a+' line-numbers">'+r+"</pre>")
  3. A little after that pre you will also find t.dom.setAttrib(e,"class","language-"+a), add the line-numbers class in there too, it should look like this: t.dom.setAttrib(e,"class","line-numbers language-"+a)
  4. Edit a random blogpost with code in it to verify that newly rendered pages get the line-numbers and syntax highlighting.

Enhancing Cookie security

Mozillas Observatory states that the Bludit Session Cookie is missing the samesite attribute and the Cookie name isn't prefixed with __Secure- or __Host-. I opened an issue for this on GitHub (Bludit issue #1582 Enhance cookie security by setting samesite attribute and adding __Secure- prefix to sessionname) but until this is integrated we can fix it in the following way:

  1. Open bludit-folder/bl-kernel/helpers/session.class.php
  2. Comment out the line containing: private static $sessionName = 'BLUDIT-KEY';
  3. Copy & paste the following to change the Cookie name:
    • // Set the __Secure- prefix if site is called via HTTPS, preventing overwrites from insecure origins
      //   see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes
      //private static $sessionName = 'BLUDIT-KEY';
      private static $sessionName = '__Secure-BLUDIT-KEY';
  4. Search for the function session_set_cookie_params
  5. Add the following line to add the samesite attribute to the Cookie by adding the following line. Also add a comma at the end of the formerly last line.
    • 'samesite' => 'strict'
  6. it should looks like this:
    • session_set_cookie_params([
          'lifetime' => $cookieParams["lifetime"],
          'path' => $path,
          'domain' => $cookieParams["domain"],
          'secure' => $secure,
          'httponly' => true,
          'samesite' => 'strict'
      ]);

Check is the RSS-Feed works

  1. Access https://admin.brennt.net/rss.xml and verify there is content displayed.
    • If not: Check if the RSS-Plugin works and is activated

Apply / check CSS changes

I made some small changes to the Solen Theme CSS. These must be re-done when the theme is updated.

  1. Open bl-themes/solen-1.0/css/style.css
  2. Change link color:
    • Element: .plugin a, ul li a, .footer_entry a, .judul_artikel a, line 5
    • Change: color: #DE004A;
    • To: color: #F06525;
  3. Change link color when hovering:
    • Element: .plugin a:hover, ul li a:hover, .footer_entry a:hover, .judul_artikel a:hover, line 10
    • Change: color: #F06525;
    • To: color: #C68449;
  4. Fix position of the blockquote bar:
    • Element: blockquote::box-shadow, line 24
    • Change:  box-shadow: inset 5px 0 rgb(255, 165, 0);
    • To:  box-shadow: -5px 0px 0px 0px rgb(255, 165, 0);
  5. Format code in posts:
    • Add the following element after line 37:
    • /* My custom stuff */
      code {
          font-size: 87.5%;
          color: #e83e8c;
          word-wrap: break-word;
          font-family: 'Roboto Mono', monospace;
      }
  6. Same padding-bottom as padding-top for header:
    • Element .section_title, line 136
    • Change: padding-bottom: 0px;
    • To: padding-bottom: 0.6em;
  7. Disable the white blur for the introduction texts:
    • Element: .pratinjau_artikel p:after, line 277
    • Change background: linear-gradient(to right, transparent, #ffffff 80%);
    • To: background: 0% 0%;

Solen-Theme changes

  1. Make header smaller:
    • Open solen-1.2/php/mini-hero.php
    • Remove line 4: <h2 class="hero_welcome"><?php echo $L->get('welcome'); ?></h2>
Comments

The problem with social networks - and why I still miss Google+

Photo by Kaique Rocha: https://www.pexels.com/photo/people-walking-on-pedestrian-lane-during-daytime-109919/

Nowadays, it feels like everyone of us uses at least five different social networks. Mastodon, Twitter/X, Facebook, Instagram, TikTok, LinkedIn, etc. Even messaging apps like Whatsapp and Telegram try more and more to become social networks of their own. Allowing you to follow channels of your favorite brand, celebrity, topic, etc. And even technical sites like GitHub are slowly getting new social features. Following the age-old mantra, "User retention and engagement are key."

Unfortunately, I have a basic problem with all these social networks. See, a human being is not a single-interest individual. Each one of us has multiple interests. And those can vary widely. Additionally, they overlap in different parts of our lives. Sure, your kids are your most valued and precious interest, and you love sharing your experiences with them. What about professional or job-related experiences? Or your leisure time crafts like gardening or cooking? Do you fancy some videogaming to relax? Are you politically active? Help out in your community? All of these are good examples.

Unfortunately, I have a basic problem with all these social networks.

But.. What, and forgive me my ignorance, what if I'm only interested in your job-related experiences? Or your experiences as a developer of some open-source software I use, and I simply wish to be a little ahead on the information flow. And not rely on some IT news site but instead get it directly from the developer?

I don't know your kids. So why should I care? Surely some stories are nice and sweet. Alas I have the same limited time each day as everyone else. Therefore, for me, information reduction is key. I don't want to be constantly bombarded with bits of knowledge I don't want and don't need to know. Each single social network out there forces me to swallow every single drop that comes out of the "digital information water tap".

Each single social network out there forces me to swallow every single drop that comes out of the "digital information water tap".

Yes, you can unfollow. Or block people entirely. Maybe blacklist some channels. Click the "show me less of this" button. But again, these are partially incomplete features. What if I am interested in only some aspects of a person's life? Not their garden, not their kids, not their political views. How do I filter that? Or those "lovely contacts" that set up automatic content generation and spill 3-5 posts into your feed every single day. Do these features help in such a situation? No, they don't. And that is the problem I have with social networks in general.

Currently, I feel the only option offered to me is a rather ultimate one. Block, unfollow, unfriend, or mute. And while the unfollow feature is somewhat usable, it still doesn't solve my problem.

The solution, or: What Google+ did right

The main feature of Google+ was that the content creator was able to group his contacts into circles, for example, a circle called "family" for family members and a circle called "coworkers" for work-related postings. And then he or she could share content only with that circle (or both). Or decide to share publicly for everyone. The follower or friend, of course, was able to group his or her friend into different circles. But the key point was: It was possible to choose which content stream to display by clicking on the button for each circle on the left of Google+.

Yes, that leaves room for improvement. I can't control with which circle(s) the creator associated me. But for me, it was a step in the right direction. One, which sadly was shut down by Google.

One step further

How about a social network where each profile of a person has several feeds (or streams)? Several. Not just one. And of course, we are allowed to define, create, and delete as many feeds (or streams) as we like. And every follower can choose to just follow one stream (or none at all) or the whole profile with all feeds. Sounds a bit like (Hash-)Tags? Yes! Exactly! As hashtags in themselves are nothing different than key words. Each post can be linked to any number of feeds. Like a post about budgeting your new hobby can be shared in your streams labeled "Finance Tips" and "Gardening".

Then the burden of information sorting and reduction is shifted from the followers to the creators. Giving them the burden of choosing what to post where. But in return they should get users who are more engaged, as they are actually only consuming content they are interested in. Well, in theory. The whole psychology and market behavior regarding social networks is not my strong point. And I fear that most people just don't care. They just scroll past that content that is not interesting to them and never think about whether they should be forced to scroll that much, let alone how to fix that problem.

Google+ was social media for me. Forget every other network.

But I remember that Google+ was social media for me. Forget every other network. There, I engaged the most. I posted the most. I commented the most. And I actually learned more than in any other social network I've been or am still active in.

Yes, Twitter has lists, Mastodon too, and so on. But these networks weren't designed around that feature! It wasn't displayed prominently on the start page. Always hidden 2-3 layers deep in some sub-section of some rarely used menu.

I still miss Google+.
(Does this count as an "Old man yells at cloud"-post? 😅 )

Comments

Understanding the structure of Email addresses

Photo by Miguel Á. Padriñán: https://www.pexels.com/photo/email-blocks-on-gray-surface-1591062/

Some rather fun stories revolve around my usage of mail addresses. Like many IT people, I like to use identifiable email addresses. In my case, it means I always use companyname-DDMMYYYY@my-domain.tld or website-domain-DDMMYYYY@my-domain.tld when I need to specify a mail address.

This has the advantage that I can verify if the sender matches the recipient address. Obviously, Paypal won't send mail to some-webshop05072024@my-domain.tld. And it is a good pointer when some customer database was leaked or if sites are selling customer data. I experienced it like 10 times already: the mail associated with a certain website or shop got spam right after I deleted my account there. Truly unsuspicious...

And in the few cases where a company's customer database was leaked several times, I can easily change the mail address and still track if the new address is being spammed or not.

The unexpected benefit of unique mail addresses

The first real surprise came to me some years ago when I bought new furniture for my new flat. When the furniture was being delivered and built up one of the people setting them up said to me: "Ah, I see we work at the same company."

I was confused and replied: "Uh, no. I'm not working for (that furniture company's name). Why do you think I do?"
"Well, according to the receipt you got the employee discount.", the man replied. I was dumbfounded. I definitely didn't lie, and when I was in the store and purchased the furniture the employee also said nothing regarding this topic.

Then it dawned on me: My mailaddress! It was companyname@my-domain.tld! But.. I thought in disbelief, "It's only in the local-part!" Well.. Looks like the employee doesn't understand the structure of mail addresses and that everyone is free to choose the part before the @-sign (the so-called local-part or username). And thought I do work for the company, and gave me the discount without saying a single word. Wow.

Basic IT-Security in the banking industry?

And today? The same happened. With my bank. I needed an appointment and called them. As I didn't provide a mail address to them in all these years they asked for one to set up the online calendar entry. I told the customer rep to use bankname2024@my-domain.tld. The representative immediately asked in surprise: "Oh! You work for one of our branches?"

Well.. I was a bit shocked as, until that point, I thought that bank employees were at least minimally trained to properly read mail. In order to detect at least the most obvious phishing attempts. It seems I was wrong.

I gave the rep a quick run-down on the structure of mail addresses and said that basically everything in front of the @ is irrelevant (or at least should be treated as such). And that was it. On to the next adventure with mail addresses!

Comments

Puppet's optional parameters might not be what you think they are

Photo by Kevin Ku: https://www.pexels.com/photo/data-codes-through-eyeglasses-577585/

Recently I encountered a puppet-lint warning regarding one of the classes I maintain at a customer. And this warning lead me down a rabbit hole of things I knew, things I understood and things I didn't know and apparently haven't grasp fully before. Surprisingly I never encountered this warning before. Despite being, most likely, a pretty common one.

So, I learned a bit or two about "optional parameters" in Puppet and thought this will give a decent read for my blog.

The problem

Take the following class definition. The code/logic is omitted as it doesn't matter (likewise I removed the puppet-strings documentation at the start of the manifests). We can purely focus on the class definition.

class profile::services::test (
  String $blatest,
  String $password = "test",
  Pattern[/^\d+\.\d+\.\d+(?:-\d+)?$/] $version = '11.2.3-4',
  String $system = 'SOMEEXAMPELSTRING',
  Optional[Hash[Stdlib::Port, Stdlib::Host]] $backupservers,
) {
# intentionally left empty
}

puppet-lint printed out the following warning:

WARNING: optional parameter listed before required parameter on line 6 (check: parameter_order)

And I was stumped by it. "Line 6 IS an optional parameter!" I thought. "There is no parameter defined after this, so how can it be listed before a required parameter?" I was confused. I moved line 6 around and sometimes the warning would vanished, sometimes not. Always defying what I thought I knew was correct.

The documentation is always right?

When you pass a certain amount of time you should stop to fiddle around and start solving it in an iterative way. So I went on to read the documentation. Thinking that maybe I missed some change in the Puppet DSL.

That's when I came across the paragraph on "Display order of parameters" as it mentioned the term "optional parameter". However.. It defined it in a totally different way I was used to use this term.

Display order of parameters

In parameterized class and defined resource type definitions, you can list required parameters before optional parameters (that is, parameters with defaults). Required parameters are parameters that are not set to anything, including undef. For example, parameters such as passwords or IP addresses might not have reasonable default values.

You can also group related parameters, order them alphabetically, or in the order you encounter them in the code. How you order parameters is personal preference.

Note that treating a parameter like a namevar and defaulting it to $title or $name does not make it a required parameter. It should still be listed following the order recommended here.

Source: The Puppet language style guide: Display order of parameters

And here I learned that: Any parameter with an associated default-value is called an optional parameter. But what about the Optional-data type?

Puppet goes on to give us one good and one bad example regarding the ordering:

Good:

class dhcp (
  $dnsdomain,
  $nameservers,
  $default_lease_time = 3600,
  $max_lease_time     = 86400,
) {}

Bad:

class ntp (
  $options   = "iburst",
  $servers,
  $multicast = false,
) {}

This recommendation is the reason why the puppetlabs-puppet-lint Gem enforces the order of: Required parameters first, optional parameters last. Where "optional parameter" again means: Any parameter with an associated default-value.

I changed line 6 by setting an empty hash as the default-value and the puppet-lint warning was gone. I also could have moved line 6 above or below line 2 (String $blatest,). Which would have fixed the warning too.

But here it is more or less the coding-style to list Optional-data type parameters after all others. Regardless of being a required or optional parameter. And again, this is being done here this way as people watch them as "optional parameters" in the sense of "I don't have to use if I don't need them". And here the requirement for parameter ordering bites the official definition of "optional parameters"...

The solution:

class profile::services::test (
  String $blatest,
  String $password = "test",
  Pattern[/^\d+\.\d+\.\d+(?:-\d+)?$/] $version = '11.2.3-4',
  String $system = 'SOMEEXAMPELSTRING',
  Optional[Hash[Stdlib::Port, Stdlib::Host]] $backupservers = {},
) {
# intentionally left empty
}

A bit more explanation

Now that we have clarified what an optional parameter is: You are either already confused, or ask yourself where the confusion originates from. So, without further ado, let me introduce you to the Optional data type.

The Optional data type

The Optional data type wraps one other data type, and results in a data type that matches anything that type would match plus undef. This is useful for matching values that are allowed to be absent. It takes one required parameter.

Source: Puppert: Values, data types, and aliases: The Optional data type

Most likely you have seen that parameters in Puppet classes are defined with an identifier of the type of data they will store. Same as it's required in any programming language where you have to define type of the variable (Integer, Float, Boolean, String, etc.). The only difference to Puppet is that in Puppet this is not enforced (as to avoid the term "optional" here. 😅)

If we adopt the given "good example" from above, we can make it look like this:

class dhcp (
  String $dnsdomain,
  Hash[String] $nameservers,
  Optional[Integer] $default_lease_time = 3600,
  Integer $max_lease_time               = 86400,
) {}

Here $default_lease_time is an optional parameter, right? Yes, but not because it uses the Optional data type. It's only an optional parameter because it has a default-value of 3600 assigned. Likewise $max_lease_time is an optional parameter too.

And here the problem originates.

Most of people I encountered use the term "optional parameter" to refer to the $default_lease_time parameter and not $max_lease_time. Which is absolutely understandable given how your speech works, how we like to name things and how we combine those two.

Adding to this is the fact that parameters which are initialized with the additional Optional-data type are allowed to be undef additionally to the other types of data defined. Effectively making it optional to assign a value to them. And this is exactly how these type of parameters are often used. Hence the term "optional parameter" sounds logical when referring to these parameters.

Technically however, that's wrong. Alas in my case it was the reason why I spent more time than I liked fixing that one linter warning. But I learned something along that way. I think that's what matters, right?

A little bit more confusion?

When reading through all data language types definitions and data types I found a data type I knowingly never encountered before. The Undef and NotUndef data types.

The Undef data type

The data type of undef is Undef. It matches only the value undef, and takes no parameters.

Several abstract data types can match the undef value:

  • The Data type matches undef in addition to several other data types.
  • The Any type matches any value, including undef.
  • The Optional type wraps one other data type, and returns a type that matches undef in addition to that type.
  • The Variant type can accept the Undef type as a parameter, which makes the resulting data type match undef.
  • The NotUndef type matches any value except undef.

Source: Puppert: Values, data types, and aliases: The Undef data type

The NotUndef data type

The NotUndef type matches any value except undef. It can also wrap one other data type, resulting in a type that matches anything the original type would match except undef. It accepts one optional parameter.

Source: Puppert: Values, data types, and aliases: The NotUndef data type

And yes, they are useful for what they are designed. But I REALLY wished Puppet would rename that Optional data-type to something else. (Is: CanBeUndef still available? 😂)

Conclusion

All definition problems aside: This shows again why the usage of proper development/analyze tools like Linters is so important. It not only helps reducing errors, no. It forces you to understand what you are doing. 😉

Comments

Linkdump - Calendar Week 44

Photo by Element5 Digital: https://www.pexels.com/photo/person-holding-book-from-shelf-1370298/

From time to time I stumble across interesting links which I think are worth sharing. So I just make a "Link Dump"-Post when I have enough.

Enjoy!

Link Dump:

https://kagi.com/: Kagi is a Ad-free search engine with many customization features (see: https://blog.kagi.com/kagi-features). You can create a free account which is limited to 100 searches. 300search are 5$/month. Unlimited searches are 10$/month. Currently I'm trying the free tier and I'm loving the possibility to boost/block certain domains! (Bye bye SEO sites with no value that just copy-paste from StackOverflow and the like..)

https://sadservers.com/: You know online hacking challenges (Capture the flag)? Sadservers goes into another interesting direction. You get your own system and have a time limit to solve a certain problem. These are typical day-to-day problems at first, but with later challenges the problems get more complex. Definitely a good page for people that want to learn Linux.
Here is the article how it works: https://github.com/fduran/sadservers#replay-system

https://webvm.io/: This page is older, but I recommended it recently to a client for an internal training. Just open the webpage and you get a Debian VM to test your stuff.
They even offer a version called Mini.WebVM which you can host yourself! Details here: https://labs.leaningtech.com/blog/mini-webvm-your-linux-box-from-dockerfile-via-wasm

https://www.wired.com/story/tiktok-platforms-cory-doctorow/: Do you notice how platforms constantly get worse over time and even more so if they dominate or even have a monopoly? How they add features which add no real value for their users - but rather their advertisers... How settings are removed or stripped down? Useful features are cut just to release new ones which are no replacement and not really interesting? Or in the words of Cory Doctorow: Here is how platforms die: First, they are good to their users; then they abuse their users to make things better for their business customers; finally, they abuse those business customers to claw back all the value for themselves. Then, they die.
Cory Doctorow coined the term "Enshittyfication" in this article which I do read more and more on the web.

https://dmitry.khlebnikov.net/2015/07/18/should-we-use-sudo-for-day-to-day-activities/: A blog article from 2015 but still an interesting read which raises some interesting questions. It outlines how you can build and use systems that don't have sudo installed.

https://wejn.org/2023/09/running-ones-own-root-certificate-authority-in-2023/: How to run your own Root-CA for your personal certificates. Useful for my homelab which, of course, uses a domain which isn't publically reachable. So Let's Encrypt is not an option.

https://forum.proxmox.com/threads/shell-_-screen-text-are-broken-distortion-scramble.121947/: After switching to Firefox the WebUI-Shell in my Proxmox instances wasn't usable. Turns out: This is a side effect if you don't allow Browser Fingerprinting.

https://garrit.xyz/posts/2023-10-13-organizing-multiple-git-identities: Short read on how to organize multiple Git identities.

https://cockpit-project.org/: Web-based interface for the administration of your Linux server. Yes, there exist dozens of these like Webmin, Froxlor, Plesk.. But it looks like a nice alternative and it's also Open-Source.

https://austinsnerdythings.com/2021/04/19/microsecond-accurate-ntp-with-a-raspberry-pi-and-pps-gps/: Ever wanted to have our own NTP-Server? This article describes how to do it with a Raspberry Pi and a GPS module.

https://pboyd.io/posts/at-company-we-are-family/: This text tries to straighten the "We are a family!" claim by putting it in a somewhat bitchy way. ;-)

Comments