Freitag, 22. November 2013

python jenkinsapi unsigned SSL certificate workaround/disable cert check

Einer meiner Kunden nutzt zur Unterstützung seiner Softwareentwicklung ein Jenkins basiertes Build Cluster. Um den darauf laufenden Buildprozess weitestgehend zu automatisieren bietet Jenkins selbst eine API Schnittstelle an. Zu dieser Schnittstelle gibt es diverse Libraries in mehreren Sprachen, u.a. Python (pip install jenkinsapi). Aufgrund einer Integration der Jenkins Server ins LDAP wollte dieser Kunde nun seine Jenkins Instanzes auf SSL umstellen. Dabei sollten selbst signierte SSL Zertifikate/Root-Zertifikate zum Einsatz kommen.

Versucht man sich nun via JenkinsAPI (siehe Codeausschnitt) mit den Server jenkins-master zu verbinden, so bekommt man folgende Fehlermeldung.

from jenkinsapi.jenkins import Jenkins
jenkins = Jenkins('https://jenkins-master:8080')
 
Meldung/Fehler:
SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Die Meldung wird durch den verwendeten SSL Layer erzeugt, welcher nicht in der  Lage war das verwendete Zertifikat zu verifizieren. Es gibt nun verschiedene Möglichkeiten um dem Problem zu begegnen:
  1. offizielle SSL Zertifikate erwerben
  2. selbst signierte Zertifikate als vertrauenswürdige Zertifikate im SSL Layer installieren
  3. Überprüfung des Zertifikates für diese Verbindung deaktivieren.
Option 1 kam aufgrund der hohen Kosten und der angestrebten internen verwendung nicht in betracht. Auf Option 2 werde ich in einem anderen Blogpost näher eingehen. Vorerst soll uns aber mit Option 3 geholfen werden - meist ist dies auch ausreichend.
Nach einer Analyse der JenkinsAPI und der darunterliegenden requests API bietet es sich an die SSL Zertifikat Überprüfung über eine eigene Requester Klasse zu deaktivieren. Dies kann man wie folgt erreichen.
from jenkinsapi.jenkins import Jenkins
from jenkinsapi.utils.requester import Requester

class SSLRequester(Requester):
    def __init__(self, username=None, password=None):
        super(SSLRequester, self).__init__(username, password)

    def get_request_dict(self, url, params, data, headers):
        requestKWargs = super(SSLRequester, self).get_request_dict(url, params, data, headers)
        requestKWargs['verify'] = False
        return requestKWargs

jenkins = Jenkins('https://jenkins-master:8080', requester=SSLRequester())

Die Klasse SSLRequester überschreibt hierbei die in der Klasse Requester definierte get_request_dict Methode in der Art und Weise das zusätzlich zu den url, params, data, headers Parametern noch die Option verify=false als die darunterliegende requests Klasse/Methode übergeben wird. Nun wird die Jenkins Instanz ohne Fehlermeldungen über eine "sichere" SSL Verbindung erzeugt. Über dieselbe Art und Weise, mit Hilfe der SSLRequester Klasse kann man auch einen Pfad zu einer sogenannten "trusted certificate base" (Vertrauenswürdige Basiszertifikate) übergeben um dann mit Hilfe dieser Zertifikate seine selbst signierten Zertifikate zu verfifizieren.

Keine Kommentare:

Kommentar veröffentlichen