Category Archives: Script

Zabbix Monitor CRL for renewal

Operating an offline Certificate Authority (CA) requires meticulous management of the Certificate Revocation List (CRL), which must be periodically updated to maintain security integrity. Relying on calendar reminders to track CRL expiration is prone to human error, potentially resulting in an expired CRL that disrupts validation processes. While not critical, an expired CRL can cause operational issues and should be proactively avoided. A more robust solution is to leverage Zabbix for automated monitoring and alerting of CRL expiration dates.

To implement this, deploy the accompanying script into the externalscripts directory on your Zabbix Server or Proxy—typically located at:

/usr/lib/zabbix/externalscripts

This enables Zabbix to regularly check CRL status and send timely notifications, ensuring uninterrupted certificate validation.

#!/usr/bin/env bash

url=$1

if [ -z $url ];
then

echo "Parameter1 for URL missing!"
exit 1
fi


if [[ $(curl -s -o /dev/null -w "%{http_code}" http://pki.forensik.justiz.gv.at/ForensikRootCA.crl) -ne 200 ]];
then
echo "URL does not return a valid return-code"
exit 1
fi


timestamp=$(openssl crl -in $url -noout -nextupdate | cut -d= -f2 | xargs -I{} date -d "{}" +%s)

echo $timestamp

Template example:

<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>7.0</version>
    <template_groups>
        <template_group>
            <uuid>d425d61f4e974282812817affe7836b2</uuid>
            <name>FAWCS Templates</name>
        </template_group>
    </template_groups>
    <templates>
        <template>
            <uuid>4d00efa818484e048020a73a2331c9b9</uuid>
            <template>Monitor_CRL_for_next_Update</template>
            <name>Monitor_CRL_for_next_Update</name>
            <groups>
                <group>
                    <name>FAWCS Templates</name>
                </group>
            </groups>
            <items>
                <item>
                    <uuid>b09fc8a561934a768bc100290f4832f1</uuid>
                    <name>Root-CA - CRL ExpirationDate</name>
                    <type>EXTERNAL</type>
                    <key>checkCRL.sh[http://address.to/your/RootCA.crl]</key>
                    <delay>1d</delay>
                    <units>unixtime</units>
                    <description>Uses a shell script to get the timestamp of a CRLs nextupdatedate (CRL should be a http-address</description>
                    <tags>
                        <tag>
                            <tag>CRL</tag>
                        </tag>
                    </tags>
                    <triggers>
                        <trigger>
                            <uuid>1ba5a78e5eaf4ed9b3a14d1b88321d5a</uuid>
                            <expression>last(/Monitor_CRL_for_next_Update/checkCRL.sh[http://address.to/your/RootCA.crl],#1)&lt;(now()+3600*24*7)</expression>
                            <name>CRL Update Required in 7d</name>
                            <priority>DISASTER</priority>
                            <description>CRL needs to be updated in the next 7d!</description>
                        </trigger>
                        <trigger>
                            <uuid>8985748a1b9542f2879915941e36a009</uuid>
                            <expression>last(/Monitor_CRL_for_next_Update/checkCRL.sh[http://address.to/your/RootCA.crl],#1)&lt;(now()+3600*24*15)</expression>
                            <name>CRL Update Required in 15d</name>
                            <priority>HIGH</priority>
                            <description>CRL needs to be updated in the next 15d!</description>
                        </trigger>
                        <trigger>
                            <uuid>85ece5ff79654f6e82b757d5e72cd143</uuid>
                            <expression>last(/Monitor_CRL_for_next_Update/checkCRL.sh[http://address.to/your/RootCA.crl],#1)&lt;(now()+3600*24*30)</expression>
                            <name>CRL Update Required in 30d</name>
                            <priority>AVERAGE</priority>
                            <description>CRL needs to be updated in the next 30d!</description>
                        </trigger>
                    </triggers>
                </item>
            </items>
        </template>
    </templates>
</zabbix_export>

example

Automated Fortigate Config Backup on Config-Change

With Forti-Manager it’s possible to automatically save a config-copy on every config change. However – If you don’t want to buy/operate/whatever a dedicated manager but still want the advantage off having a copy on every config-change that could also be accomplished with foritgates “automation stitches”.

The following config shows how this could be archived:

FORTIGATE-SHELL # show system automation-stitch Automated_Config_Backup
config system automation-stitch
    edit "Automated_Config_Backup"
        set description "Creates Backup of the Config on a detected change"
        set trigger "Config_change_detected"
        config actions
            edit 1
                set action "Execute_Config_Backup"
                set required enable
            next
        end
    next
end

FORTIGATE-SHELL # show system automation-trigger Config_change_detected
config system automation-trigger
    edit "Config_change_detected"
        set event-type event-log
        set logid 44546 44547
    next
end

FORTIGATE-SHELL # show system automation-action Execute_Config_Backup
config system automation-action
    edit "Execute_Config_Backup"
        set description "Creates a Backup of the current Config"
        set action-type cli-script
        set script "execute backup config sftp /path/on/sftp-server/backup_%%log.eventtime%%.conf <SFTP-SERVER> <USERNAME> <PASSWORD>
        set accprofile "super_admin"
    next
end

This stich will run the backup action every time an object attribute or attribute was configured and push the new config to the SFTP-server.,

On the server it will be named “backup_<TS_in_ns>.config”

Zabbix Error “an array is expected” with Powershell

When trying to interact with the Zabbix-API via Powershell one might run into the problem, that an API request will not be executed successfully, but an error similar to the following one, will be displayed:

  code message         data                                                           
  ---- -------         ----                                                           
-32602 Invalid params. Invalid parameter "/1/filter/conditions": an array is expected.

Especially when using some code like in the below snippet which uses @(…) and @{…} to define data via arrays and hashtables:

function ZbxUpdateTestAction
{

    $params = @{
        body =  @{
            "jsonrpc"= "2.0"
            "method"= "action.update"
            "params"= @{
                "actionid" = "117"
                "status" = 0
                "filter" = @{
                    "evaltype" = 0
                    "conditions" = @(
                        @{
                            "conditiontype" = 4
                            "operator" = 5
                            "value"= 3
                        }
                        @{
                            "conditiontype" = 0
                            "operator" = 0
                            "value"= 435
                        }
                    )
                }
            }
            "id"= 1
            "auth" = "$api_token"
        } | ConvertTo-Json
        uri = $zbx_api_uri
        headers = @{
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $api_token"
            }
        method = "Post"
    }
    $result = Invoke-WebRequest @params
    return $result.Content | ConvertFrom-Json
}

The above snippet just shows a test function to manually update an action and set conditions to send out alerts for severities of warning or higher for a specific host group.

However – when executed it will fail with the error from snippet 1.

This is because Powershell does the JSON-conversion only to a certain depth. If your structure reaches a deeper level, it will simply stop converting the dict or array which results in the above error.

Troubleshooting it, could be quite a pain in the ass as it’s not that simple to spot and when gradually extending the object it just works fine till you exceed a depth of 2.

To fix this – simple specify the depth for ConvertTo-Json

e.g.

function ZbxUpdateTestAction
{

    $params = @{
        body =  @{
            "jsonrpc"= "2.0"
            "method"= "action.update"
            "params"= @{
                "actionid" = "117"
                "status" = 0
                "filter" = @{
                    "evaltype" = 0
                    "conditions" = @(
                        @{
                            "conditiontype" = 4
                            "operator" = 5
                            "value"= 3
                        }
                        @{
                            "conditiontype" = 0
                            "operator" = 0
                            "value"= 435
                        }
                    )
                }
            }
            "id"= 1
            "auth" = "$api_token"
        } | ConvertTo-Json -Depth 5
        uri = $zbx_api_uri
        headers = @{
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $api_token"
            }
        method = "Post"
    }
    $result = Invoke-WebRequest @params
    return $result.Content | ConvertFrom-Json
}

Compare line 29 between the two snippets

Refs:

Nerdfonts in zsh for exa

After switching to exa as an ls-replacement i also wanted to make use of the nerd-font support ho have icons displayed for files.

alias etree='exa --color --tree --icons=always'

However, in reality the fonts never looked the same in my terminal as in the web preview

So, to easy things up (getting the zip, unzipping it in ~/.local/share/fonts and updateing the fonts-cache) there is a little function which can be placed in the .zshrc/.bashrc to automate things.

#Function to install NerdFonts
function install_nerdfont()
{
	if [ -not $1 ];
	then	
		echo -e "\e[91mParameter missing!\e[0m"
	fi

	cd ~/.local/share/fonts
	wget $1
	unzip -u *.zip
	rm *.zip
	fc-cache -fv	
	cd -

}

Once executed with the download-URL as a paremeter, the font will be installed to your home directory.

If the fonts should be installed system-wide, this can be archived by placing them in /usr/local/share/fonts (folder might needs to be created if it does not exist).

Once the fonts are installed – the terminal-profile must be configured to use the newly installed fonts and that’s it.