Subnetze und IP Adressen extrahieren aus SPF Records (z.B. Office365 oder Google Apps for Business)

Wenn man bei Office365 oder Google Apps for Business einen eigenen Mailserver (Postfix) vorschalten möchte beim versenden/empfangen muss man die Mailserver von Microsoft/Google Whitelisten in den mynetworks bei Postfix.

Das Script löst alle SPF Record includes auf und generiert CIDR Maps die sich in Postfix einbinden lassen.

Beispiel:

max@dev1:~$ python get_subnets_of_spf_record_mynetwoks.py
Working on job office365
Working on job google

Es werden 2 Files erzeugt:

max@dev1:~$ cat /etc/postfix/networks/google 
64.18.0.0/20 OK
64.233.160.0/19 OK
66.102.0.0/20 OK
66.249.80.0/20 OK
72.14.192.0/18 OK
74.125.0.0/16 OK
108.177.8.0/21 OK
173.194.0.0/16 OK
207.126.144.0/20 OK
209.85.128.0/17 OK
216.58.192.0/19 OK
216.239.32.0/19 OK
[2001:4860:4000::]/36 OK
[2404:6800:4000::]/36 OK
[2607:f8b0:4000::]/36 OK
[2800:3f0:4000::]/36 OK
[2a00:1450:4000::]/36 OK
[2c0f:fb50:4000::]/36 OK
172.217.0.0/19 OK
108.177.96.0/19 OK
max@dev1:~/test$ cat /etc/postfix/networks/office365
207.46.101.128/26 OK
207.46.100.0/24 OK
207.46.163.0/24 OK
65.55.169.0/24 OK
157.56.110.0/23 OK
157.55.234.0/24 OK
213.199.154.0/24 OK
213.199.180.0/24 OK
157.56.112.0/24 OK
207.46.51.64/26 OK
157.55.158.0/23 OK
64.4.22.64/26 OK
40.92.0.0/14 OK
40.107.0.0/17 OK
40.107.128.0/17 OK
134.170.140.0/24 OK
[2a01:111:f400::]/48 OK
23.103.128.0/19 OK
23.103.198.0/23 OK
65.55.88.0/24 OK
104.47.0.0/17 OK
23.103.200.0/21 OK
23.103.208.0/21 OK
23.103.191.0/24 OK
216.32.180.0/23 OK
94.245.120.64/26 OK
[2001:489a:2202::]/48 OK

In Posftix werden sie in der main.cf eingebunden:

# ----------------------------------------------------------------------
# My Networks
# ----------------------------------------------------------------------
mynetworks =
        cidr:/etc/postfix/networks/local
        cidr:/etc/postfix/networks/other
        cidr:/etc/postfix/networks/google
        cidr:/etc/postfix/networks/office365

Da sich zwischendurch die Records auch mal ändern können empfiehlt es sich einen Cronjob dafür einzurichten. Ich habe eine Variante mit diff die nur patcht wenn das Resultat nicht null ist.

Das Script lässt sich auch noch für andere Dienste / etc. anpassen:

lookup_spf = {
# Google Apps for Business
"google": {
          "domain": "google.com",
          "file"  : "/etc/postfix/networks/google",
          },

# Office365
"office365": {
          "domain": "spf.protection.outlook.com",
          "file"  : "/etc/postfix/networks/office365",
          },

# Example
"example": {
          "domain": "example.com",
          "file"  : "/etc/postfix/networks/example",
          },

}

Sourcecode:

#!/usr/bin/env python

#
# get_subnets_of_spf_record_mynetwoks.py
# Resolve all known ip addresses from spf record and generate cidr map for postfix
#
# Version 1.0
# Written by Maximilian Thoma (http://www.lanbugs.de)
#
# The generated files can be used in postfix config with for example mynetworks = cidr:/etc/postfix/<generated_file>
#
# This program is free software; you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation;
# either version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program;
# if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 
# MA 02110, USA
#

#
# Requirements:
# dnspython module  -> pip install dnspython
#

import dns.resolver
from dns.exception import DNSException
import re
import sys

# Look for DNS Record at:
#
# "jobname": {
#            "domain": "domainname",
#            "file": "output_file",
#            }
#

# 

lookup_spf = {
# Google Apps for Business
"google": {
          "domain": "google.com",
          "file"  : "/etc/postfix/networks/google",
          },

# Office365
"office365": {
          "domain": "spf.protection.outlook.com",
          "file"  : "/etc/postfix/networks/office365",
          },
}

############################################################################################

def getspf(record, filehandler):
    # Init Resolver
    myResolver = dns.resolver.Resolver()

    try:
        # Try to lookup TXT record
        myAnswer = myResolver.query(record,"TXT")

    except DNSException:
        sys.stderr.write("Failed to query record, SPF broken.")
        return

    results = []

    for rdata in myAnswer:
        # Get string out of records
        for txt_string in rdata.strings:
            # Append to SPF Records buffer if "spf" in string
            if "spf" in txt_string:
                results.append(txt_string)

    # If results >=1
    if len(results) >= 1:
        # Work on records
        for spf in results:
            # Split parts
            parts = spf.split(" ")
            # Check parts
            for part in parts:

                s_include = re.match(r"^include:(?P<domain>.*)$", part)
                s_ip4 = re.match(r"^ip4:(?P<ip4>.*)$", part)
                s_ip6 = re.match(r"^ip6:(?P<ip6>.*)$", part)

                # If in part "include" found, next round
                if s_include:
                    getspf(s_include.group('domain'), filehandler)
                # elif ip4 found
                elif s_ip4:
                    filehandler.write(s_ip4.group('ip4') + " OK\n")
                # elif ip6 found
                elif s_ip6:
                    filehandler.write("[" + s_ip6.group('ip6').replace("/","]/") + " OK\n")
                # else no valid record
                else:
                    pass
    # no results 
    else:
        sys.stderr.write("No results")
        pass

def main():
    # Working on jobs
    for jobname, config in lookup_spf.iteritems():

        print "Working on job %s" % jobname

        # open file
        filehandler = open(config['file'], 'w')
        # start query spf records
        getspf(config['domain'], filehandler)
        # close file
        filehandler.close()


#getspf(lookup_spf)

if __name__ == "__main__":
    main()

 

Postfix Mails aus der Queue von bestimmten Absendern löschen

Mit diesen Kommandos lassen sich aus der Postfix Queue Mails löschen die dort wegen Zustellungsproblemen liegengeblieben sind. Besonders wenn man einen Kunden drauf hat mit Malware Infektion und man die Reste aus der Queue beseitigen möchte.

Für die komplette Domain:

postqueue -p | tail -n +2 | awk 'BEGIN { RS = "" } /@example\.com/ { print $1 }' | tr -d '*!' | postsuper -d -

Für einen einzelnen Absender:

postqueue -p | tail -n +2 | awk 'BEGIN { RS = "" } /mail@example\.com/ { print $1 }' | tr -d '*!' | postsuper -d -

 

HP Server Tools für Debian/Ubuntu

HP stellt für verschiedene Linux Distributionen seine eigenen Tools bereit. Unteranderem System Health Application and Command line Utilities, iLO Online Configuration Utilities und die Insight Management Agents.

HP SDR (Software Delivery Repository): http://downloads.linux.hpe.com/SDR/index.html

Repository für Debian 8 (jessie) hinzufügen

/etc/apt/sources.list.d/HP-mcp.list anlegen

deb http://downloads.linux.hpe.com/SDR/repo/mcp jessie/current non-free

Alternativ Repository für Ubuntu 16.04 LTS hinzufügen

/etc/apt/sources.list.d/HP-mcp.list anlegen

deb http://downloads.linux.hpe.com/SDR/repo/mcp xenial/current non-free

Repository PGP Keys importieren (curl wird benötigt)

curl http://downloads.linux.hpe.com/SDR/hpPublicKey1024.pub | apt-key add -
curl http://downloads.linux.hpe.com/SDR/hpPublicKey2048.pub | apt-key add -
curl http://downloads.linux.hpe.com/SDR/hpPublicKey2048_key1.pub | apt-key add -
curl http://downloads.linux.hpe.com/SDR/hpePublicKey2048_key1.pub | apt-key add -

Paketquellen updaten

apt update

Pakete installieren (hp-health, hponcfg, hp-snmp-agents)

apt install hp-health hponcfg hp-snmp-agents

HP-Health (hpasmcli)

Das Kommando für die Health Tools ist hpasmcli.

root@rzm-srv01e13:~# hpasmcli
HPE management CLI for Linux (v2.0)
Copyright 2015 Hewlett Packard Enterprise Development LP.

--------------------------------------------------------------------------
NOTE: Some hpasmcli commands may not be supported on all Proliant servers.
      Type 'help' to get a list of all top level commands.
--------------------------------------------------------------------------
hpasmcli> 

Beispiele

show server

hpasmcli> show server
System        : ProLiant DL360 G7
Serial No.    : XXXXXXXXXX      
ROM version   : P68 08/16/2015
UEFI Support  : No
iLo present   : Yes
Embedded NICs : 4
  NIC1 MAC: d8:9d:67:aa:aa:aa
  NIC2 MAC: d8:9d:67:bb:bb:bb
  NIC3 MAC: d8:9d:67:cc:cc:cc
  NIC4 MAC: d8:9d:67:dd:dd:dd

Processor: 0
  Name         : Intel(R) Xeon(R) CPU E5640 @ 2.67GHz            
  Stepping     : 2
  Speed        : 2667 MHz
  Bus          : 133 MHz
  Core         : 4
  Thread       : 8
  Socket       : 1
  Level1 Cache : 128 KBytes
  Level2 Cache : 1024 KBytes
  Level3 Cache : 12288 KBytes
  Status       : Ok

Processor: 1
  Name         : Intel(R) Xeon(R) CPU E5640 @ 2.67GHz            
  Stepping     : 2
  Speed        : 2667 MHz
  Bus          : 133 MHz
  Core         : 4
  Thread       : 8
  Socket       : 2
  Level1 Cache : 128 KBytes
  Level2 Cache : 1024 KBytes
  Level3 Cache : 12288 KBytes
  Status       : Ok

Processor total  : 2

Memory installed : 49152 MBytes
ECC supported    : Yes

show temp

hpasmcli>  show temp         
Sensor   Location              Temp       Threshold
------   --------              ----       ---------
#1        AMBIENT              22C/71F    42C/107F 
#2        PROCESSOR_ZONE       40C/104F   82C/179F 
#3        PROCESSOR_ZONE       40C/104F   82C/179F 
#4        MEMORY_BD            35C/95F    87C/188F 
#5        MEMORY_BD            38C/100F   78C/172F 
#6        MEMORY_BD            35C/95F    87C/188F 
#7        MEMORY_BD            36C/96F    78C/172F 
#8        MEMORY_BD            38C/100F   87C/188F 
#9        MEMORY_BD            37C/98F    78C/172F 
#10       MEMORY_BD            37C/98F    87C/188F 
#11       MEMORY_BD            37C/98F    78C/172F 
#12       POWER_SUPPLY_BAY     39C/102F   59C/138F 
#13       POWER_SUPPLY_BAY     50C/122F   73C/163F 
#14       MEMORY_BD            32C/89F    72C/161F 
#15       PROCESSOR_ZONE       35C/95F    73C/163F 
#16       PROCESSOR_ZONE       34C/93F    64C/147F 
#17       MEMORY_BD            35C/95F    63C/145F 
#18       PROCESSOR_ZONE       43C/109F   69C/156F 
#19       SYSTEM_BD            39C/102F   69C/156F 
#20       SYSTEM_BD            43C/109F   71C/159F 
#21       SYSTEM_BD            50C/122F   65C/149F 
#22       SYSTEM_BD            52C/125F   71C/159F 
#23       SYSTEM_BD            45C/113F   69C/156F 
#24       SYSTEM_BD            50C/122F   69C/156F 
#25       SYSTEM_BD            39C/102F   63C/145F 
#26       SYSTEM_BD            49C/120F   66C/150F 
#27       SCSI_BACKPLANE_ZONE  50C/122F   60C/140F 
#28       SYSTEM_BD            72C/161F   110C/230F

show fan

hpasmcli>  show fan 
Fan  Location        Present Speed  of max  Redundant  Partner  Hot-pluggable
---  --------        ------- -----  ------  ---------  -------  -------------
#1   SYSTEM          Yes     NORMAL  29%     Yes        0        No            
#2   SYSTEM          Yes     NORMAL  29%     Yes        0        No            
#3   SYSTEM          Yes     NORMAL  29%     Yes        0        No            
#4   SYSTEM          Yes     NORMAL  29%     Yes        0        No            

show powersupply

hpasmcli> show powersupply
Power supply #1
  Present  : Yes
  Redundant: No
  Condition: Ok
  Hotplug  : Supported
  Power    : 110 Watts
Power supply #2
  Present  : Yes
  Redundant: No
  Condition: FAILED
  Hotplug  : Supported

Kommandos lassen sich auch ohne die interaktive hpasmcli ausführen.

root@rzm-srv01e13:~# hpasmcli -s "show fan; show powersupply"

Fan  Location        Present Speed  of max  Redundant  Partner  Hot-pluggable
---  --------        ------- -----  ------  ---------  -------  -------------
#1   SYSTEM          Yes     NORMAL  30%     Yes        0        No            
#2   SYSTEM          Yes     NORMAL  30%     Yes        0        No            
#3   SYSTEM          Yes     NORMAL  30%     Yes        0        No            
#4   SYSTEM          Yes     NORMAL  30%     Yes        0        No            


Power supply #1
  Present  : Yes
  Redundant: No
  Condition: Ok
  Hotplug  : Supported
  Power    : 115 Watts
Power supply #2
  Present  : Yes
  Redundant: No
  Condition: FAILED
  Hotplug  : Supported

hponcfg (Online iLO Configuration Utility)

Über hponcfg lässt sich das iLO ohne Systemneustart konfigurieren.

root@rzm-srv01e13:~# hponcfg 
HP Lights-Out Online Configuration utility
Version 4.6.0 Date 09/28/2015 (c) Hewlett-Packard Company, 2015
Firmware Revision = 1.87 Device type = iLO 3 Driver name = hpilo

USAGE:
  hponcfg  -?
  hponcfg  -h
  hponcfg  -m minFw
  hponcfg  -r [-m minFw ]
  hponcfg  [-a] -w filename [-m minFw]
  hponcfg  -g [-m minFw]
  hponcfg  -f filename [-l filename] [-s namevaluepair] [-v] [-m minFw]
  hponcfg  -i [-l filename] [-s namevaluepair] [-v] [-m minFw]

  -h,  --help           Display this message
  -?                    Display this message
  -r,  --reset          Reset the Management Processor to factory defaults
  -b,  --reboot         Reboot Management Processor without changing any setting
  -f,  --file           Get/Set Management Processor configuration from "filename" 
  -i,  --input          Get/Set Management Processor configuration from the XML input 
                        received through the standard input stream.
  -w,  --writeconfig    Write the Management Processor configuration to "filename"
  -a,  --all            Capture complete Management Processor configuration to the file.
                        This should be used along with '-w' option
  -l,  --log            Log replies to "filename"
  -v,  --xmlverbose     Display all the responses from Management Processor
  -s,  --substitute     Substitute variables present in input config file
                        with values specified in "namevaluepairs"
  -g,  --get_hostinfo   Get the Host information
  -m,  --minfwlevel     Minimum firmware level

hp-snmp-agents (SNMP Erweiterungen für HP Sensoren)

HP liefert ein Konfigurationstool mit das Menügeführt einen durch das Grundsetup durchführt.

/sbin/hpsnmpconfig

Ich habe nur die Read/Write und ReadOnly Community geändert und alles andere auf Default lassen.

Anschließend habe ich noch Korrekturen durchgeführt in der /etc/snmp/snmpd.conf

# Anpassung der Communitys
# Schreiben nur von Loopback aus
rwcommunity supergeheim 127.0.0.1
# Lesezugriff fuer Monitoring
rocommunity public 10.10.10.200

# Listener angepasst das er nur auf der Management NW Karte erreichbar ist
agentAddress  udp:10.10.10.1:161

Restart des SNMP Daemons nicht vergessen:

service snmpd restart

 

 

Check_MK: Agent Monitoring via SSH

Falls eine unverschlüsselte Abfrage des Check_MK Agemten nicht in Frage kommt ist es möglich den Agenten über SSH abzurufen.

SSH Key erzeugen in der OMD Umgebung

OMD[dev1]:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/omd/sites/dev1/.ssh/id_rsa): 
Created directory '/omd/sites/dev1/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /omd/sites/dev1/.ssh/id_rsa.
Your public key has been saved in /omd/sites/dev1/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:1Gxpgs9G9f4nK5uIvhe1iKU8xII1UzxFGZ7aApkYsNI dev1@cmkdev.m.local
The key's randomart image is:
+---[RSA 2048]----+
|  ...  o.o=o     |
| . . o++o=.+     |
|. E .o=++.O .    |
| .  . .*o*...    |
|       +S+.o..   |
|       .=.o ..   |
|         . .  o .|
|         ..... + |
|       .+o. oo.  |
+----[SHA256]-----+

Auf Zielsystem User anlegen, per sudo auf den Agenten berechtigen und SSH Publickey anlegen

User monitoring anlegen

root@target:~# adduser monitoring
Lege Benutzer »monitoring« an ...
Lege neue Gruppe »monitoring« (1003) an ...
Lege neuen Benutzer »monitoring« (1002) mit Gruppe »monitoring« an ...
Erstelle Home-Verzeichnis »/home/monitoring« ...
Kopiere Dateien aus »/etc/skel« ...
Geben Sie ein neues UNIX-Passwort ein: 
Geben Sie das neue UNIX-Passwort erneut ein: 
passwd: password updated successfully
Changing the user information for monitoring
Enter the new value, or press ENTER for the default
  Full Name []: Monitoring
  Room Number []: 
  Work Phone []: 
  Home Phone []: 
  Other []: 
Sind diese Informationen korrekt? [J/n] j

/etc/sudoers File anpassen

monitoring     ALL = NOPASSWD: /usr/bin/check_mk_agent

/home/monitoring/.ssh/authorized_keys anlegen

command="sudo /usr/bin/check_mk_agent" ssh-rsa AAAAB3NzaC..................GOXzCLX dev1@cmkdev.m.local

Rechte anpassen

chmod 640 /home/monitoring/.ssh/
chmod 600 /home/monitoring/.ssh/authorized_keys

xinetd Port 6556 abschalten

/etc/xinetd.d/check_mk anpassen

disable = yes

Anschließend „service xinetd restart“

Check_MK bekannt machen das Agent per SSH abgefragt werden muss

In WATO muss hierfür eine Regel angelegt werden.

Zu finden unter: Host & Service Parameters -> Datasource Programs -> Individual program call instead of agent access

Command line to execute:

ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no monitoring@$HOSTADDRESS$

Speichern und Regeln deployen, danach kann man mit WATO die Services suchen, etc.

Viel Spaß 😉

 

Weak SSH/SSL protocols and ciphers & hardening

Sammlung aller SSH/SSL relevanten und meist genutzten Dienste und deren optimale SSH/SSL Konfiguration.

Apache / Nginx

apache 2.4.18 | modern profile | OpenSSL 1.0.1e

Oldest compatible clients: Firefox 27, Chrome 30, IE 11 on Windows 7, Edge, Opera 17, Safari 9, Android 5.0, and Java 8

<VirtualHost *:443>
    ...
    SSLEngine on
    SSLCertificateFile      /path/to/signed_certificate_followed_by_intermediate_certs
    SSLCertificateKeyFile   /path/to/private/key

    # Uncomment the following directive when using client certificate authentication
    #SSLCACertificateFile    /path/to/ca_certs_for_client_authentication


    # HSTS (mod_headers is required) (15768000 seconds = 6 months)
    Header always set Strict-Transport-Security "max-age=15768000"
    ...
</VirtualHost>

# modern configuration, tweak to your needs
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder     on
SSLCompression          off
SSLSessionTickets       off

# OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling          on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache        shmcb:/var/run/ocsp(128000)

nginx 1.10.1 | modern profile | OpenSSL 1.0.1e

Oldest compatible clients: Firefox 27, Chrome 30, IE 11 on Windows 7, Edge, Opera 17, Safari 9, Android 5.0, and Java 8

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;


    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    resolver <IP DNS resolver>;

    ....
}

Quelle: https://mozilla.github.io/server-side-tls/ssl-config-generator/

SSL Webserver Test

Qualys hat eine tolle SSL Analyse Webseite, Link: https://www.ssllabs.com/ssltest/

Beispiel google.de:

Es zeigt einen schnellen Überblick plus sehr detailierte Informationen was nicht passt oder was man verbessern kann.

Alternative check with nmap

max@cmkdevel:~$ nmap --script ssl-cert,ssl-enum-ciphers -p 443 www.google.de            

Starting Nmap 7.01 ( https://nmap.org ) at 2017-08-01 09:08 CEST
Nmap scan report for www.google.de (172.217.17.35)
Host is up (0.031s latency).
Other addresses for www.google.de (not scanned): 2a00:1450:400e:804::2003
rDNS record for 172.217.17.35: ams16s29-in-f3.1e100.net
PORT    STATE SERVICE
443/tcp open  https
| ssl-cert: Subject: commonName=www.google.de/organizationName=Google Inc/stateOrProvinceName=California/countryName=US
| Issuer: commonName=Google Internet Authority G2/organizationName=Google Inc/countryName=US
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2017-07-19T11:48:30
| Not valid after:  2017-10-11T11:31:00
| MD5:   f21e dd1d 579f 5ea3 1b3d 2e79 873d 616c
|_SHA-1: f2af ac3f fb43 20be 9f6a b0fc 9356 808a f677 86fc
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 3.31 seconds

Postfix

/etc/postfix/main.cf

smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_mandatory_ciphers=high

tls_high_cipherlist=EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA

smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA, KRB5-DES, CBC3-SHA

smtpd_tls_dh1024_param_file=/etc/ssl/dh2048.pem

smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
smtp_tls_protocols = !SSLv2, !SSLv3

lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3
lmtp_tls_protocols = !SSLv2, !SSLv3

smtp_tls_security_level = may
smtp_tls_loglevel = 1

smtpd_tls_auth_only = yes

Generate new Diffie Hellman Keys

openssl dhparam -out /etc/ssl/dh2048.pem 2048

Restart Postfix

service postfix restart

Mehr: http://www.postfix.org/TLS_README.html

Check Postfix SSL Configuration

Test mit openssl s_client

openssl s_client -starttls smtp -connect mailserver.example.org:25

Alternative mit nmap

nmap --script ssl-cert,ssl-enum-ciphers -p 993,995,25,587 -Pn mailserver.example.org

Dovecot

/etc/dovecot/conf.d/10-ssl.conf

ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4
#only for dovecot >=2.2.6, enforce the server cipher preference
ssl_prefer_server_ciphers = yes
#disable SSLv2 and SSLv3
ssl_protocols = !SSLv2 !SSLv3

Restart dovecot

service dovecot restart

Überprüfen mit openssl s_connect

openssl s_client -connect mailserver.example.org:993
openssl s_client -connect mailserver.example.org:995

Alternative mit nmap

nmap --script ssl-cert,ssl-enum-ciphers -p 993,995 -Pn mailserver.example.org

SSH

/etc/ssh/sshd_config

# Remove dsa hostkeys
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key

KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
Macs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256

AuthenticationMethods publickey
LogLevel VERBOSE
Subsystem sftp  /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO
PermitRootLogin No
UsePrivilegeSeparation sandbox

Achtung ! DSA SSH Keys werden danach nicht mehr funktionieren.

Quelle: https://github.com/mozilla/wikimo_content/blob/master/Security/Guidelines/OpenSSH.mediawiki#Modern_OpenSSH_67

Restart SSH

service ssh restart

OpenVPN

/etc/openvpn/openvpn.conf

tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
cipher AES-256-CBC
auth SHA512
reneg-sec 60

Quelle: https://community.openvpn.net/openvpn/wiki/Hardening / https://gist.github.com/pwnsdx/8fc14ee1e9f561a0a5b8

Patch für automysqlbackup: mysqldump: [Warning] Using a password on the command line interface can be insecure.

In der aktuellen Version von automysqlbackup kommt es auf Ubuntu 16.04 LTS wieder zu der Fehlermeldung:

mysqldump: [Warning] Using a password on the command line interface can be insecure.

Es gab vor einiger Zeit bereits einen Patch für das Problem allerdings hat sich der Code geändert dementsprechend waren anpassungen nötig. Orginalpatch zu finden unter: http://wiki.nkosi.org/Automysqlbackup / https://www.redeo.nl/2013/11/automysqlbackup-warning-using-password-command-line-interface-can-insecure/

Hier die neue angepasste Version für automysqlbackup v.2.5:

# Einfügen ab Zeile 644 vor if [ "$MAILCONTENT" = "files" ]

# Patch error message since MySQL 5.6
if [ -s "$LOGERR" ]
then

XLOGERR=$BACKUPDIR/XERRORS_$DBHOST-`date +%N`.log
grep -v "Using a password on the command line interface can be insecure." "$LOGERR" > $XLOGERR
mv $XLOGERR $LOGERR
fi

Patchfile

Ich habe auch ein Patchfile bereitgestellt, einfacher als im Code zu suchen.

Achtung! Patchfile ist für eine Standardinstallation auf einem Ubuntu 16.04 LTS, evtl. passt der Patch nicht wenn das File von einer anderen Distribution erstellt wurde, dann lieber manuell obigen Patch einfügen.
max@cmkdevel:~$ cp /usr/sbin/automysqlbackup automysqlbackup.backup
max@cmkdevel:~$ sudo patch /usr/sbin/automysqlbackup automysqlbackup.patch

Python: Snippet – Python Code aus Textdateien ausführen/importieren

Check_MK speichert alle Daten in einfachen Dateien direkt als ausführbaren Python Code.

Um die abgelegten Dictionarys etc. in seinen eigenen Skripten weiterverwenden zu können kann man sich die mit eval() oder exec() laden.

eval() kann verwendet werden um z.B.  ein Dictionary in eine Variable zu laden, exec() kann auch ganze Funktionen etc. laden.

Beispiel eval():

dict.txt

{"foo":"bar","aaa":"bbb"}

import_dict.py

#!/usr/bin/env python

with open("dict1.txt","r") as f:
    x = eval(f.read().replace("\n",""))

print x

print x['foo']

Ergebnis:

max@cmkdevel:~/dev$ python import_dict.py
{'foo': 'bar', 'aaa': 'bbb'}
bar

Beispiel exec()

code.txt

max['foo'] = {
             "foo": "bar",
             "fxx": "boo",
             }


def hello(name):
    print "Hallo " + name

import_code.py

#!/usr/bin/env python

max = {}

with open("code.txt","r") as f:
    exec(f.read())


print max
print max['foo']
print max['foo']['foo']
hello("max")

Ergebnis:

max@cmkdevel:~/dev$ python import_code.py 
{'foo': {'foo': 'bar', 'fxx': 'boo'}}
{'foo': 'bar', 'fxx': 'boo'}
bar
Hallo max

 

 

Python: Snippet – Speichern und weiterverwenden von Objekten

Mit dem Modul pickle (deutsch pökeln, konservieren) bietet Funktionen für das Speichern von Objekten. Die gespeicherten Objekte können wiederhergestellt werden. Die Daten werden als Byte Stream gespeichert.

Folgende Datentypen werden unterstützt:

Hier ein kleines Beispiel:

dict_to_file.py

#!/usr/bin/env python

import pickle

t = {
"sname": "Foo",
"lname": "Bar",
"street": "Foo Street",
"city": "Bar City"
}

with open("test.pkl","wb") as f:
    pickle.dump(t, f, pickle.HIGHEST_PROTOCOL)

file_to_dict.py

#!/usr/bin/env python

import pickle
import pprint

with open("test.pkl","rb") as f:
    t = pickle.load(f)

pprint.pprint(t)

Ausgabe von file_to_dict.py

max@cmkdevel:~$ python file_to_dict.py 
{'city': 'Bar City', 'lname': 'Bar', 'sname': 'Foo', 'street': 'Foo Street'}

 

debian-sys-maint Zugangsdaten verwenden für MySQL Login in der Bash

Für Wartungszwecke gibt es einen User „debian-sys-maint“ der auf jedem Debian verwandten System automatisch angelegt wird. Die Zugangsdaten sind unter /etc/mysql/debain.cnf zu finden. Der User hat die gleichen Rechte wie der DB root User.

Da die Zugangsdaten eh schon auf dem System sind kann man sich ein kleines Helferlein bauen welches den User und das Passwort verwendet für einen MySQL Login auf der CLI.

Dazu folgendes Script anlegen z.B. /usr/local/sbin/my

#!/bin/bash

mysql -u`grep user /etc/mysql/debian.cnf | tail -n 1 | cut -d"=" -f2 | awk '{print $1}'` -p`grep password /etc/mysql/debian.cnf | tail -n 1 | cut -d"=" -f2 | awk '{print $1}'`

Danach noch einen „chmod 500 /usr/local/sbin/my“ und wir können es testen:

max@cmkdevel:~$ sudo my
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6264
Server version: 5.7.18-0ubuntu0.16.04.1-log (Ubuntu)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

Viel Spaß 😉

 

Python: Snippet – Suchen und ersetzen in Dateien

Der Titel des Posts sagt eigentlich schon alles 😉

Python 3:

#!/usr/bin/env python3

import fileinput
import re

file = fileinput.FileInput("/etc/ssh/sshd_config", inplace=True, backup=".bak")

for line in file:
    line = re.sub(r".*Banner.*","Banner /etc/issue.net", line)
    print(line, end='')

file.close()

Python 2:

#!/usr/bin/env python

import fileinput
import re
import sys

file = fileinput.FileInput("/etc/ssh/sshd_config", inplace=True, backup=".bak")

for line in file:
    line = re.sub(r".*Banner.*","Banner /etc/issue.net", line)
    sys.stdout.write(line)

file.close()

 

Python: Snippet – Threading mit Result

Code-Snippet:

#!/usr/bin/env python

import socket
from multiprocessing.pool import ThreadPool
import pprint


jobs = ("www.heise.de","www.google.com","www.golem.de","www.google.de","www.lanbugs.de","www.microsoft.com")

def worker(domain):
    print socket.gethostbyname(domain)
    return socket.gethostbyname(domain)

pool = ThreadPool(processes=3)

result_buffer = {}

for d in jobs:
    print "start " + d
    async_result = pool.apply_async(worker, args=(d,))
    result_buffer[d]=async_result.get()


pprint.pprint(result_buffer)


Ausgabe:

>python thread_with_result.py 
start www.heise.de
193.99.144.85
start www.google.com
172.217.20.68
start www.golem.de
109.68.230.138
start www.google.de
172.217.20.99
start www.lanbugs.de
81.169.181.94
start www.microsoft.com
104.108.168.41
{'www.golem.de': '109.68.230.138',
 'www.google.com': '216.58.207.68',
 'www.google.de': '172.217.20.99',
 'www.heise.de': '193.99.144.85',
 'www.lanbugs.de': '81.169.181.94',
 'www.microsoft.com': '104.108.168.41'}

 

Unattended Installation von APT Paketen (Debian/Ubuntu)

Um Pakete ohne manuelle Eingaben zu Installieren müssen die Antworten für die Assistenten bereits vorliegen.

Als Beispiel eine unattended Installation von Postfix auf einem Ubuntu 16.04 LTS System.

Um die möglichen Parameter zu erfahren verwendet man das „debconf-show“ Tool, Postfix muss auf dem Testsystem bereits installiert sein.

max@cmkdevel:/opt$ sudo debconf-show postfix
  postfix/procmail: false
  postfix/chattr: false
  postfix/recipient_delim: +
  postfix/sqlite_warning:
  postfix/dynamicmaps_conversion_warning:
  postfix/mydomain_warning:
  postfix/relayhost:
  postfix/compat_conversion_warning: true
  postfix/not_configured:
  postfix/rfc1035_violation: false
  postfix/root_address:
  postfix/protocols: all
  postfix/destinations: $myhostname, cmkdevel.m.local, localhost.m.local, , localhost
  postfix/kernel_version_warning:
  postfix/relay_restrictions_warning:
  postfix/mynetworks: 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
  postfix/mailbox_limit: 0
  postfix/tlsmgr_upgrade_warning:
* postfix/mailname: cmkdevel.m.local
* postfix/main_mailer_type: Internet Site
  postfix/bad_recipient_delimiter:
  postfix/main_cf_conversion_warning: true
  postfix/retry_upgrade_warning:

Um für ein neues System jetzt die Antworten dem Assistenten zu übergeben verwendet man das Tool „debconf-set-selections“. Der Kommandostapel setzt alle Optionen und Installiert automatisch Postfix.

debconf-set-selections <<< "postfix postfix/main_cf_conversion_warning string true"
debconf-set-selections <<< "postfix postfix/destinations string \$myhostname, $(hostname), localhost"
debconf-set-selections <<< "postfix postfix/root_address string max@m.local"
debconf-set-selections <<< "postfix postfix/bad_recipient_delimiter string ''"
debconf-set-selections <<< "postfix postfix/mynetworks string 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
debconf-set-selections <<< "postfix postfix/recipient_delim string +"
debconf-set-selections <<< "postfix postfix/protocols string all"
debconf-set-selections <<< "postfix postfix/relayhost string mail.example.org"
debconf-set-selections <<< "postfix postfix/mailname string $(hostname)"
debconf-set-selections <<< "postfix postfix/mailbox_limit string 0"
debconf-set-selections <<< "postfix postfix/chattr string false"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Satellite system'"
apt-get install -y postfix

Viel Spaß 😉

TMUX die Screen Alternative

TMUX ist eine nette Alternative zu Screen, es unterstützt per Default das Teilen eines Fensters horizontal oder/und vertikal.

Installation von TMUX

#Für Ubuntu / Debian:
apt install tmux

#Für Fedora / RedHat / CentOS:
yum install tmux

Tastenkürzel (Hotkeys)

HotkeyBedeutung
CTRL-B ?Anzeiger aller Hotkeys
CTRL-B D(detatch) Trennen der aktuellen Sitzung
CTRL-B S(switch) Wechseln zwischen verschiedenen Sitzungen
CTRL-B C(create) Neues Fenster
CTRL-B &Beenden des Fensters
CTRL-B ,Umbennennen des Fensters
CTRL-B "Fenster horizonal Teilen
CTRL-B %Fenster vertikal Teilen
CTRL-B PfeiltastenWechseln zwischen den Panes (Fensterscheiben)
CTRL-B WListe aller Fenster anzeigen
CTRL-B [SPACE]Pane Größe ändern
CTRL-B L(last) Wechseln zum letzen Fenster, ist mit einem Minus markiert
CTRL-B Pvorheriges Fenster
CTRL-B Nnächstes Fenster
CTRL-B 1...Wechsel zu Fenster Nr.
CTRL-B !Pane Lösen und neues Fenster

per SSH direkt in tmux Sitzung starten

Praktisches Feature wenn man seine Sitzung nicht verlieren möchte bei einem Verbindungsabriss. Dazu muss die .bashrc des Users angepasst werden.

Einfach am Ende folgendes einfügen:

if [[ -z "$TMUX" ]] && [ "$SSH_CONNECTION" != "" ]; then
    tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux
fi

tmux Scripting

Man kann auch ganz Easy sich eigene Umgebungen scripten.

Hier ein angepasstes Beispiel von ubuntuusers.de (https://wiki.ubuntuusers.de/tmux/):

#!/bin/bash
SESSION=main
tmux="tmux -2"

# if the session is already running, just attach to it.
$tmux has-session -t $SESSION
if [ $? -eq 0 ]; then
       echo "Session $SESSION already exists. Attaching."
       sleep 1
       $tmux attach -t $SESSION
       exit 0;
fi
                                 
# create a new session, named $SESSION, and detach from it
$tmux new-session -d -s $SESSION
$tmux new-window    -t $SESSION:0 
$tmux rename-window    -t $SESSION:0 "Default SHELL"
$tmux split-window  -h -t $SESSION:0
$tmux new-window    -t $SESSION:1 "tail -f /var/log/syslog"
$tmux rename-window    -t $SESSION:1 "SYSLOG"
$tmux new-window    -t $SESSION:2 "top"
$tmux rename-window    -t $SESSION:2 "TOP"
$tmux new-window    -t $SESSION:3 "tail -f /var/log/mail.log"
$tmux rename-window    -t $SESSION:3 "MAILLOG"
$tmux split-window  -h -t $SESSION:3
$tmux new-window    -t $SESSION:4 "tail -f /omd/sites/dev1/var/log/cmc.log"
$tmux rename-window    -t $SESSION:4 "CMCLOG"
$tmux select-window -t $SESSION:0
$tmux attach -t $SESSION

 

 

Check_MK: Inventory erweitern mit SNMP Daten

Check_MK hat seit Version 1.2.5i1 das Feature Inventory an Board. Per Default werden von Systemen CPU, Memory, Harddisks, Softwarepakete und vieles mehr eingesammelt. Die Anleitung dient dazu das Inventory zu erweitern und eigene Informationen per SNMP einzusammeln und per View durchsuchbar zu machen.

Ich habe mittlerweile mehrere eigene Ergänzungen gemacht, darunter CDP Neighbors, Dot1X Authentications, Wireless Accesspoints und Hardware Inventory von Cisco Geräten.

Als Beispiel zeige ich das Cisco Hardware Inventory mit Seriennummern.

Bestandteile für eine Inventory Erweiterung:

  1. Daten sammeln -> Erweiterung für den Inventory Collector unter  ~/local/share/check_mk/inventory/
  2. Daten darstellen -> Erweiterung für die Inventory Views unter ~/local/share/check_mk/web/plugins/views/

1. Daten sammeln

Die Inventory Daten werden innerhalb einer Baumstruktur abgelegt. Man kann für seine eigenen Daten neue Knoten erzeugen. z.B. unter networking das hw_inventory wird im Tree dargestellt als networking.hw_inventory: . Der Doppelpunkt zeigt an das Daten unterhalb des Knotens folgen.

Das Inventory Plugin besteht aus einer Funktion und dem inv_info Directory welches alle Inventory Plugins kennt. In inv_info  im Key snmp_scan_function ist genauso wie bei den Check_MK SNMP Checks angegeben ob Check_MK überhaupt Daten finden wird bei einem SNMP Bulkwalk. snmp_info beinhaltet die OID und alle Untertabellen mit Daten die von Check_MK eingesammelt werden sollen.

Beispiel: ~/local/share/check_mk/inventory/my_hw_inventory.py

#!/usr/bin/python

port = {
0: "-",
1: "other",
2: "unknown",
3: "chassis",
4: "backplane",
5: "container",
6: "powerSupply",
7: "fan",
8: "sensor",
9: "module",
10: "port",
11: "stack",
12: "cpu"

}

def inv_hw_inventory(info, params):
    
    node = inv_tree("networking.hw_inventory:")

    for x in info[0]:
        
        #print x
        
        # If Serial Number is longer than 1 char
        if len(x[10]) >= 1:
        
            fru = "true" if "1" in x[15] else "false"
            
            classx = port[int(x[4])] if len(x[4]) is 1 else port[0]
            
            node.append(
            {
            "index": x[0],
            "description": x[1],
            "vendor_type": x[2],
            "contained_in_id": x[3],
            "class": classx,
            "parent_rel_pos": x[5],
            "name": x[6],
            "hw_rev": x[7],
            "fw_rev": x[8],
            "sw_rev": x[9],
            "serial_number": x[10],
            "manufactor": x[11],
            "model": x[12],
            "alias": x[13],
            "asset_id": x[14],
            "is_fru": fru,
            }
            )
        

inv_info["inv_hw_inventory"] = {
"inv_function": inv_hw_inventory,
"snmp_info": [(".1.3.6.1.2.1.47.1.1.1.1",[OID_END, # entPhysicalIndex
                                        "2", # entPhysicalDescr
                                        "3", # entPhysicalVendorType
                                        "4", # entPhysicalContainedIn
                                        "5", # entPhysicalClass
                                        "6", # entPhysicalParentRelPos
                                        "7", # entPhysicalName
                                        "8", # entPhysicalHardwareRev
                                        "9", # entPhysicalFirmwareRev
                                        "10", # entPhysicalSoftwareRev
                                        "11", # entPhysicalSerialNum                                        
                                        "12", # entPhysicalMfgName
                                        "13", # entPhysicalModelName
                                        "14", # entPhysicalAlias
                                        "15", # entPhysicalAssetID
                                        "16", # entPhysicalIsFRU
                                             ]),
             ],
"snmp_scan_function": lambda oid: oid(".1.3.6.1.2.1.1.2.0").startswith(".1.3.6.1.4.1.9.1"),
}

Mit der inv_tree Funktion wird ein neuer Inventory Baum eröffnet (siehe Code). Alle eingesammelten Informationen werden dann an diesen neuen Baum mit append als Dictionary hinzugefügt.

Die eigene Inventory Funktion kann man testen mit:

OMD[dev1]:~/local/share/check_mk/web/plugins/views$ cmk -v -i testswitch
Doing HW/SW-Inventory for testswitch...inv_hw_inventory snmp_extended_info snmp_os snmp_info ..unchanged..1603 entries..OK

Wenn in der Inventory Funktion ein pprint.pprint(info) eingebaut wird können auch die Rohdaten betrachtet werden.

2. Daten darstellen

Hierfür muss ein View gebaut werden der die Informationen des neuen Inventory Baums darstellt.

Beispiel ~/local/share/check_mk/web/plugins/views/my_inv_hw_inventory.py

#!/usr/bin/python

inventory_displayhints.update({

        ".networking.hw_inventory:"                          : { "title" : _("HW Inventory"), "render" : render_inv_dicttable,  "view" : "invhwi_of_host", "keyorder": 
                                                               ["index","name","description","model","contained_in_id","serial_number","hw_rev","fw_rev","sw_rev","class","manufactor","asset_id","alias","is_fru"] },
        ".networking.hw_inventory:*.index"                   : { "title" : _("Index") },
        ".networking.hw_inventory:*.description"             : { "title" : _("Description") },
        ".networking.hw_inventory:*.contained_in_id"         : { "title" : _("Contained in Index") },
        ".networking.hw_inventory:*.class"                   : { "title" : _("Class") },
        ".networking.hw_inventory:*.name"                    : { "title" : _("Name") },
        ".networking.hw_inventory:*.hw_rev"                  : { "title" : _("HW REV") },
        ".networking.hw_inventory:*.fw_rev"                  : { "title" : _("FW REV") },
        ".networking.hw_inventory:*.sw_rev"                  : { "title" : _("SW REV") },
        ".networking.hw_inventory:*.serial_number"           : { "title" : _("Serial Number") },
        ".networking.hw_inventory:*.manufactor"              : { "title" : _("Manufactor") },
        ".networking.hw_inventory:*.model"                   : { "title" : _("Model") },
        ".networking.hw_inventory:*.alias"                   : { "title" : _("Alias") },
        ".networking.hw_inventory:*.asset_id"                : { "title" : _("Asset ID") },
        ".networking.hw_inventory:*.is_fru"                  : { "title" : _("Is FRU") },
})

declare_invtable_view("invhwi", ".networking.hw_inventory:", _("HW Inventory"), _("HW Inventory"))

Danach sollte man mit „omd restart apache && cmk -v -R“ Check_MK und den Apachen neu starten, damit die neuen Views sichtbar werden. Damit Daten angezeigt werden muss 1 mal das Inventory auf dem Gerät gelaufen sein.

Im Views Menü sollte dann unser neuer View unter Inventory auftauchen:

Man kann sich alle Daten anzeigen lassen oder gezielt nach einzelnen Informationen oder Geräten suchen.

Wenn man im Host View ist kann man über das obere Menü auch direkt zu den Inventory Daten kommen, wurde der Button noch nicht genutzt kann er sichtbar gemacht werden mit dem „…“ Button.

Die Daten werden für den Host als Baumstruktur dargestellt.

Viel Spaß beim Erweitern 😉

Python: Oracle DB Modul für Python für CentOS6

Quelle: https://gist.github.com/hangtwenty/5547377

#!/bin/bash

# INSTALL ORACLE INSTANT CLIENT #
#################################

# NOTE: Oracle requires at least 1176 MB of swap (or something around there).
# If you are using CentOS in a VMWare VM, there's a good chance that you don't have enough by default.
# If this describes you and you need to add more swap, see the
# "Adding a Swap File to a CentOS System" section, here:
# http://www.techotopia.com/index.php/Adding_and_Managing_CentOS_Swap_Space

# Install basic dependencies
sudo yum -y install libaio bc flex

echo "Now go get some the following two RPMs ..."
echo "- basic: oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm"
echo "- SDK/devel: oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm"
echo "... from this URL: http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html"
echo "WARNING: It's pretty annoying, they make you sign up for an Oracle account, etc."
echo 'I will assume you have put these two files are into ~/Downloads'
echo "Press any key once you're ready" && read -n 1 -s

sudo rpm -ivh ~/Downloads/oracle-instantclient11.2-basic-*
sudo rpm -ivh ~/Downloads/oracle-instantclient11.2-devel-*

# SET ENVIRONMENT VARIABLES #
#############################

# Source for this section: http://cx-oracle.sourceforge.net/BUILD.txt

# (SIDENOTE: I had to alter it by doing some digging around for where the Oracle RPMs really installed to;
# if you ever need to do this, do a command like this:
#     rpm -qlp <rpm_file_of_concern.rpm>)

echo '# Convoluted undocumented Oracle bullshit.' >> $HOME/.bashrc
echo 'export ORACLE_VERSION="11.2"' >> $HOME/.bashrc
echo 'export ORACLE_HOME="/usr/lib/oracle/$ORACLE_VERSION/client64/"' >> $HOME/.bashrc
echo 'export PATH=$PATH:"$ORACLE_HOME/bin"' >> $HOME/.bashrc
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"$ORACLE_HOME/lib"' >> $HOME/.bashrc
. $HOME/.bashrc

# INSTALL cx_Oracle #
#####################

pip install cx_Oracle

Gute Anleitung zur Verwendung von cs_Oracle: http://www.oracle.com/technetwork/articles/dsl/prez-python-queries-101587.html

Beispiel:

import cx_Oracle

# db helper named arrays
def rows_to_dict_list(cursor):
    columns = [i[0] for i in cursor.description]
    return [dict(zip(columns, row)) for row in cursor]

# Connect to DB
dsn_tns = cx_Oracle.makedsn("10.10.10.1",1521,"TESTDB")
db = cx_Oracle.connect("testuser","password",dsn_tns)
cursor = db.cursor()

# Get data from DB
cursor.execute("SELECT * FROM test_tab")
result = rows_to_dict_list(cursor)

# Insert to DB
cursor.execute('INSERT INTO test_tab (row1, row2, row2) VALUES ("xxx", "yyy", "zzz")')
db.commit()

# close db
db.close()

 

Check_MK: Werte simulieren in einem SNMPwalk

Wer in Check_MK mittels gespeicherter SNMP Walks Checks entwickelt möchte unter umständen auch gerne sich ändernde Werte haben und keine statischen aus dem Dump.

Check_MK hat 3 eingebaute Funktionen um steigende Counter etc. zu simulieren.

Ausschnitt aus dem Check_MK Code lib/python/cmk_base/agent_simulator.py (GPLv2):

def agentsim_uptime(rate = 1.0, period = None): # period = sinus wave
    if period == None:
        return int(our_uptime() * rate)
    else:
        a = (rate * period) / (2.0 * math.pi)
        u = our_uptime()
        return int(u * rate + int(a * math.sin(u * 2.0 * math.pi / period)))


def agentsim_enum(values, period = 1): # period is in seconds
    hit = int(our_uptime()) / period % len(values)
    return values[hit]


def agentsim_sinus(base = 50, amplitude = 50, period = 300):
    return int(math.sin(our_uptime() * 2.0 * math.pi / period) * amplitude + base)



Wie kann man die Simulatoren verwenden?

Im gespeicherten SNMP Walk müssen die Simulatoren eingefügt werden statt des statisch exportieren Werts. Die SNMP Walks liegen unter ~/var/check_mk/snmpwalks/<hostname>

Beispiel:

.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.1.3 0
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.2.1 0
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.2.2 %{uptime(rate=10)}
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.2.3 %{sinus()}
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.3.1 %{enum([10,20,30,40,50,60,70,80,90])}
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.3.2 0
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.3.3 31008
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.4.1 5353
.1.3.6.1.4.1.9.9.189.1.3.5.1.4.10101.4.2 0