python kubernetes module - egyszeru szkript hibaval: unable to get issuer certificate (_ssl.c:1091)

Fórumok

Sziasztok,

windows alatt Thonny IDE-ben: a kovetkezo szkript:

import kubernetes.client
from kubernetes import client, config
config.load_kube_config()   

v1 = kubernetes.client.CoreV1Api()
print("Listing pods with their IPs:")
ret = v1.list_pod_for_all_namespaces(watch=False)
for i in ret.items:
    print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))

ezt a hibat dobja ki:

 raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='xx.xx.xx.com', port=443): Max retries exceeded with url: /k8s/clusters/xxxx/api/v1/pods?watch=False (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1091)')))

Tudna valaki segiteni?

Koszonom elore.

Ardi

Hozzászólások

Nem szereti a géped az endpointon levő certet, vagy csináld meg normálisan (tegyél oda egy letsencryptet, vagy tedd be a géped trust storejába a CAt), vagy

 

    configuration = client.Configuration()
    configuration.verify_ssl=False
    configuration.debug = False
    client.Configuration.set_default(configuration)

    v1 = client.CoreV1Api()

(loptam, fingom incs pontosan hogy mi a különbség az általad használt load confighoz képest, a lényeg az a verify_ssl=False dolog belőle.)

Sajna, kell az SSL. Nem lenne eleg  kopirozni a CA-t akarhova es az utat beirni a szkriptbe?

Errol van szo: certificate-authority-data: "egyhosszu, tobbsoros sztring", amit a konfigbol [.kube/config] is kiolvashatok?

Ardi

Hát lehet, hogy ezt így nem tudom távoktatásban elmondani, de feltöltöttem ide pár scriptet (cert* néven), a cert-split.sh szétvagdos darabokra egy chain-t tartalmazó fájlt, a cert-addheader.sh meg kis fejrésszel látja el a paraméterként megadott fájlokat, abból lehet kitalálni, hogy melyik az, ahol a subject azonos az issuerrel.

$ ~/commoner/bin/cert-split.sh 2023.cert.pem
Totally 3 parts have been written ("part*.cert.pem")

$ ~/commoner/bin/cert-addheader.sh part*

$ grep '^[si]:' part*
part1.cert.pem:s: C=HU, L=Budapest, O=Initech, CN=*.company.hu, serialNumber=20230713
part1.cert.pem:i: C=HU, L=Budapest, O=Microsec Ltd., CN=e-Szigno SSL CA 2014, emailAddress=info@e-szigno.hu

part2.cert.pem:s: C=HU, L=Budapest, O=Microsec Ltd., CN=e-Szigno SSL CA 2014, emailAddress=info@e-szigno.hu
part2.cert.pem:i: C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA 2009, emailAddress=info@e-szigno.hu

part3.cert.pem:s: C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA 2009, emailAddress=info@e-szigno.hu
part3.cert.pem:i: C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA 2009, emailAddress=info@e-szigno.hu

Ebben a példában a part3.cert.pem az önaláírt root-ca-cert, ezt kellene telepíteni (a név mindegy, de azért érdemes valami frappánsat kitalálalni, hogy pl. MicroSec_RootCA_2009.cert)

nos, a bibi az, hogy van egy xxx-ca-bundle.pem fajlom.

Ha erre raengedem a cert-split.sh szkriptet, 143 part*.pem fajlt hoz letre.

Ezutan:

cert-addheader.sh part*

majd:

grep '^[si]:' part*sok sort dob ki, ahol a sorok igy neznek ki:

.

.

.

part98.cert.pem:s: C=US, O="Entrust, Inc.", OU=See www.entrust.net/legal-terms, OU="(c) 2015 Entrust, Inc. - for authorized use only", CN=Entrust Root Certification Authority - G4
part98.cert.pem:i: C=US, O="Entrust, Inc.", OU=See www.entrust.net/legal-terms, OU="(c) 2015 Entrust, Inc. - for authorized use only", CN=Entrust Root Certification Authority - G4
part99.cert.pem:s: C=US, O=Microsoft Corporation, CN=Microsoft ECC Root Certificate Authority 2017
part99.cert.pem:i: C=US, O=Microsoft Corporation, CN=Microsoft ECC Root Certificate Authority 2017

 

Akkor nem elegendo az xxx-ca-bundle.pem fajlt kopirozni ide rootkent: c:\cygwin64\etc\pki\tls\certs\ (megtortent)

utana root alatt: update-ca-trust

majd

$ update-ca-trust
$ openssl rehash -v

Doing /etc/pki/tls/certs
rehash: warning: skipping ca-bundle.crt,it does not contain exactly one certificate or CRL
rehash: warning: skipping ca-bundle.trust.crt,it does not contain exactly one certificate or CRL
link xxx-ca-bundle.pem -> f85c55d6.0
$

Sajna, nem segitett - a hiba maradt.

Ardi

Éreztem, hogy nem fog távoktatással menni :(
Nem általában valamilyen pem-fájlra kell ráküldeni, hanem arra, amivel a távoli partner igazolja magát.

Itt írta kallo kolléga, hogy hogyan lehet az `openssl s_client showcerts` paranccsal kinyerni ezt a cert-et chaint, még annyit tennék hozzá, hogy fájlba kell terelgetni az outputját, és abból editorral kiszedni az első -----BEGIN CERTIFICATE----- és az utolsó -----END CERTIFICATE----- közötti részt.

(Na mondjuk előfordulhat, hogy pont a RootCA nincs benne a chain-ben, de ezzel majd akkor foglalkozzunk, ha odaérünk.)

OK, kikuldtem a proba nevu file-be:

$ openssl s_client -showcerts -connect xx.xx.xx.com:443 > proba

$ cat proba

CONNECTED(00000004)
---
Certificate chain
 0 s:C = xx, ST = xx, L = xx, O = xx, OU = xxx, CN = xx, emailAddress = xx
   i:C = yy, O = yy, OU = yy, CN = xxx Server CA
-----BEGIN CERTIFICATE-----
MII
.
.
.
4yf7Q==
-----END CERTIFICATE-----
---
Server certificate
subject=C = xx, ST = xx, L = xx, O = xx, OU = xxx, CN = xx, emailAddress = xx
issuer=C = yy, O = yy, OU = yy, CN = xxx Server CA

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2067 bytes and written 416 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 21 (unable to verify the first certificate)
---

Most mi a teendo?

Ardi

Ha jól látom, akkor a standard kubeconfig -ot használod (ami a .kube/config -ban van).

Egy sima "kubectl get nodes" fut rendesen vagy ott is "--insecure-skip-tls-verify" opcióval sikerül futatnod?

Lényeg a lényeg, rakd rendbe a kubeconfig-odat és akkor jó lesz:

1. cluster/certificate-authority-data -ba berakod a cacert-edet (base64 encode-olva)

2. cluster/insecure-skip-tls-verify: true

Heloka,

cygwin alatt a "kubectl get nodes" nem fut - ez le van tiltva.

Viszont "kubectl get pods -n mynamespace" lefut.

1.

Van cacert a clusteren - cert-ca nev alatt:

harom bejegyzes

-----BEGIN CERTIFICATE-----

xx
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

aaa
-----END CERTIFICATE-----

dddd

-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

formaban.

 

Nem ertem, miert es hogy hasznaljam : cluster/insecure-skip-tls-verify: true

 

Ard

$ kubectl config get-contexts
CURRENT   NAME                        CLUSTER     AUTHINFO          NAMESPACE
          kube-dev-admin@kube-dev     kube-dev    kube-dev-admin    
          kube-int-admin@kube-int     kube-int    kube-int-admin    
*         kube-prod-admin@kube-prod   kube-prod   kube-prod-admin   

$ kubectl config  get-clusters
NAME
kube-dev
kube-int
kube-prod

$ kubectl config set-cluster kube-prod --insecure-skip-tls-verify=true
Cluster "kube-prod" set.

$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://10.1.1.1:6443
  name: kube-prod
...
​​​​​​​

Még soha nem használtam ezt a modult, de itt  https://github.com/kubernetes-client/python/issues/1131#issuecomment-74… úgy látom, hogy van ssl_ca_cert változód szal itt meg tudod adni a CA certedet.

amit le is tudsz szedni közvetlen az endpointról is akár:

openssl s_client -showcerts -connect xx.xx.xx.com:443

a címet az errorodból ki tudod szedni, innen:

urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='xx.xx.xx.com', port=443): Max retries exceeded with url: /k8s/clusters/xxxx/api/v1/pods?watch=False (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1091)')))

ezt dobja:

 

$ openssl s_client -showcerts -connect xx.xx.xx.xx.com:443
CONNECTED(00000004)
xxxxxxxxx
verify error:num=20:unable to get local issuer certificate
verify return:1
xxxxxxxxx
verify error:num=21:unable to verify the first certificate
verify return:1
xxxxxxxxx
verify return:1
---
.
.
.

Ahh, ahogy látom az openssl se bízik meg benne :( De láttam feljebb hogy van ca cert fileod, add meg neki akkor azt a fájlt, ez a formátum megfelelő kell legyen
 

Van cacert a clusteren - cert-ca nev alatt:

harom bejegyzes

-----BEGIN CERTIFICATE-----

xx
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

aaa
-----END CERTIFICATE-----

dddd

-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

formaban.

Ahh, ahogy látom az openssl se bízik meg benne

Hát általában az szokott lenni, hogy a k8s API endpointon a k8s saját CA-ja által aláírt cert lakik. Nyilván lehet ezt máshogy is csinálni, de inkább az a standard, hogy a kubeconfigban bent van ez az CA cert, ergó a k8s kliens emiatt meg fog bízni a szerver tanúsítványban. Mivel a kubectl-lel ez megy is, a python modullal meg nem, ezért ott valami nagy gyíkság lesz (mondjuk pl. olyan régi a python modul alatti SSL, hogy teszemazt nem támogatja a tanúsítványt).

Szerkesztve: 2023. 07. 14., p – 11:00

Sziasztok,

azt hiszem, az openssl resz talan mar mukodik. (koszi kallo - latom, ez visszajott :-))

Lehuztam a Kubernetes-rol a cert-ca bol a 3 blokkot:

-----BEGIN CERTIFICATE-----

xx
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

yy
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

zz
-----END CERTIFICATE-----

Ezzel mukodik:

openssl s_client -CAfile cert-ca.crt -connect xx.xx.xxcom:443

Most mar az a kerdes, hogy tudom ezt a python fajlba is valahogy beleoktrojalni?

Van a kubernetes module-nak olyan parametere, ami ezt megengedi?

UPDATE: nem valami hasonlo a bibi az alabbi link alatt??

https://github.com/kubernetes-client/python/issues/1017

UPDATE2:

Valahogy a) szerint kell a verify a c)-be is, mert anelkul b) ugyanolyan hibat dob mint c).

a)
import requests
#import json
#import certifi
#print(certifi.where())
s = requests.Session()

# execute the get
r = s.get(https://xx.xx.xx.com, verify="C:/Users/../cacert.crt")
print("ok-ok-ok")

OK

b)
import requests
#import json
#import certifi
#print(certifi.where())
s = requests.Session()

# execute the get
r = s.get(https://xx.xx.xx.com)
print("ok-ok-ok")

NOK
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='xx.xx.xx.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)')))

c)
import kubernetes.client
from kubernetes import client, config
config.load_kube_config()   

v1 = kubernetes.client.CoreV1Api()
#v1.list_namespaced_pod(namespace='mynamespace')

# v1.list_namespaced_service(<namespace>)
v1.list_namespaced_service(namespace='mynamespace')

NOK
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='xx.xx.xx.com', port=443): Max retries exceeded with url: /k8s/clusters/xxxx/api/v1/namespaces/mynamespace/services (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1091)')))

Ardi

Na de próbáld már ki az ssl_ca_cert változót amit már írtam fent

Így ni, ennek a kódnak mennie kell, kipróbáltam OpenShifttel és nekem megy:
 

import kubernetes.client
from kubernetes import client, config
config.load_kube_config()

cc = client.Configuration.get_default_copy()
cc.ssl_ca_cert = '"C:/Users/../cacert.crt"' # Itt az útvonalat lehet meg kell fixálnod, hogy a te CA certedre mutassom
client.Configuration.set_default(cc)

v1 = kubernetes.client.CoreV1Api()
#v1.list_namespaced_pod(namespace='mynamespace')
print(v1.list_namespaced_service(namespace='mynamespace'))

Sok energiát nem fektettem bele, de úgy fest a modulnak erre nicns semmi paramétere.

A ChatGPT szerint így kell megoldani:
 

import kubernetes.client
from kubernetes import client, config
import json
import yaml
from datetime import datetime

# Custom JSON Encoder class to handle datetime objects
class DateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

config.load_kube_config()

cc = client.Configuration.get_default_copy()
cc.ssl_ca_cert = '"C:/Users/../cacert.crt"' # Itt az útvonalat lehet meg kell fixálnod, hogy a te CA certedre mutassom
client.Configuration.set_default(cc)

v1 = kubernetes.client.CoreV1Api()
output = v1.list_namespaced_service(namespace='mynamespace')
print("YAML output: ", yaml.dump(output.to_dict(), default_flow_style=False))
print("JSON output: ", json.dumps(output.to_dict(), cls=DateTimeEncoder))

egyébként tudom ajánlani, akkor is ha nem akarsz megtanulni pythonozni.

Hohooo!! Koszi szepen a megoldast.

A ChatGPT-vel probalkoztam jo par honappal ezelott. Igaz, nem ebben a temaban.

Ezzel azert meeg csinjan kell banni... :-)

Igaz, a kerdes az, mennyire surgos a megoldas, mik a tapasztalatok, mennyi idot vagyunk hajlando a valasz keresesebe es

a problema megertesebe fektetni es/vagy mennyire vagyunk lustak. :-)

No persze zero tapasztalat mellett a ChatGPT a nyero...

Ardi