Skip to content
Snippets Groups Projects
Commit f48c5e89 authored by Ben Morrice's avatar Ben Morrice
Browse files

rhncheck: change logic to download/merge entitlements instead of content checking

ref: LOS-806
parent 8ae1894e
No related branches found
No related tags found
1 merge request!178rhncheck: change logic to download/merge entitlements instead of content checking
Pipeline #3051371 passed
MOUNTPOINT="/mnt/data2/test/repos"
RHNCERTDIR="/mnt/data2/test/rhn_entitlements"
REPOS="dev.repos.d"
REPOSCONF="dev.repos.yaml"
RHNCHECK_RHN_USER="cernlinux"
......
MOUNTPOINT="/mnt/data1/dist"
RHNCERTDIR="/mnt/data2/rhn_entitlements"
REPOS="prod.repos.d"
REPOSCONF="prod.repos.yaml"
RHNCHECK_RHN_USER="cernlinux"
......
......@@ -42,7 +42,7 @@ job "${PREFIX}_reposync_${REPOID}" {
}
volumes = [
"${MOUNTPOINT}:/repo",
"/etc/cdn.redhat.com:/certs",
"${RHNCERTDIR}:/certs",
]
}
......
......@@ -3,13 +3,12 @@
import sys
import json
import requests
from time import sleep
import base64
import glob
import os
import configparser
import tempfile
import smtplib
import shutil
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
......@@ -25,13 +24,13 @@ if email_to is None or login is None or password is None:
print('Cannot determine email_to, login or password variables. Exiting')
sys.exit(1)
# taken from access.redhat.com for the 'linuxsoft-mirror' host
linuxsoft_uuid="b4ec8c2d-3eae-4ae0-b8fa-ec6d8a08ce9f"
email_from='linux.support@cern.ch'
problems = set()
tmpdir = tempfile.mkdtemp(dir = '/tmp')
existingcerts = set()
latestcerts = set()
def call_https_rhsm(url):
base64string = base64.encodestring(f"{login}:{password}".encode())
......@@ -39,25 +38,7 @@ def call_https_rhsm(url):
result = requests.get(url, headers=headers, verify=False)
return json.loads(result.content)
def call_https_cdn(url, cert):
url += '/repodata/repomd.xml'
retries = 0
try:
while retries <= 2:
request = requests.get(url, cert=(cert), verify=False)
if request.status_code == requests.codes.ok:
return True
print('Failed ({}) to get {} with {}'.format(request.status_code, url, cert))
retries+=1
sleep(1)
except:
pass
return False
def get_entitlements(directory):
if glob.glob(directory + '/*pem'):
print('rhn certs have already been downloaded this run, not doing that again')
return True
key = call_https_rhsm(f"https://subscription.rhsm.redhat.com/subscription/consumers/{linuxsoft_uuid}")['idCert']['key']
certificates = call_https_rhsm('https://subscription.rhsm.redhat.com/subscription/consumers/' + linuxsoft_uuid + "/certificates")
for cert in certificates:
......@@ -68,69 +49,38 @@ def get_entitlements(directory):
f.write(key)
f.close()
email_certs = []
for repofile in glob.glob("prod.repos.d/*repo"):
f = open(repofile, 'r')
config = configparser.RawConfigParser()
config.read(repofile)
for repo in config.sections():
if 'cdn.redhat.com' in config.get(repo, 'baseurl'):
baseurl = config.get(repo, 'baseurl')
sslclientcert = config.get(repo, 'sslclientcert')
print('Checking repo: %s' % repo)
if not os.path.exists(sslclientcert):
problems.add('%s: %s does not exist, however is defined' % (repo, sslclientcert))
else:
if not call_https_cdn(baseurl, sslclientcert):
print('Installed cert does not auth, trying with new certs from rhn')
get_entitlements(tmpdir)
valid_certs = []
for cert in glob.glob(tmpdir + '/*pem'):
if call_https_cdn(baseurl, cert):
valid_certs.append(os.path.split(cert)[1])
email_certs.append(cert)
if len(valid_certs) is 0:
problems.add('%s: %s failed to auth to %s. A replacement cert was not found.' % (repo, sslclientcert, baseurl))
else:
new_certs = ','.join(sorted(valid_certs))
problems.add('%s: %s failed to auth to %s. One of the following certs would be a valid replacement: %s (attached)' % (repo, sslclientcert, baseurl, new_certs))
email_max_problems = 60
if len(problems) > 0:
if len(problems) == 1:
problem_verb = 'is'
problem_noun = 'problem'
problem_quantity = 'a sync error'
else:
problem_verb = 'are'
problem_noun = 'problems'
problem_quantity = 'a few sync errors'
for existingcert in glob.glob('/certs/*pem'):
if 'rhn_entitlements.pem' not in existingcert and 'redhat-uep.pem' not in existingcert:
existingcerts.add(os.path.basename(existingcert))
get_entitlements(tmpdir)
for cert in glob.glob(f"{tmpdir}/*pem"):
latestcerts.add(os.path.basename(cert))
if latestcerts.difference(existingcerts):
print('New certificates detected from RHN, copying them in place and merging to /certs/rhn_entitlements.pem')
new_cert_filenames = set()
for cert in latestcerts.difference(existingcerts):
new_cert_filenames.add(os.path.basename(cert))
for cert in glob.glob('/certs/*pem'):
if 'redhat-uep.pem' not in cert:
os.remove(cert)
with open('/certs/rhn_entitlements.pem','wb') as wfd:
for f in latestcerts:
shutil.copy(f"{tmpdir}/{f}", f"/certs/{f}")
with open(f"{tmpdir}/{f}",'rb') as fd:
shutil.copyfileobj(fd, wfd)
msg = MIMEMultipart()
msg['Subject'] = "reposync: cdn.redhat.com sync {} detected".format(problem_noun)
msg['Subject'] = "[INFO] reposync: cdn.redhat.com certificate changes detected"
msg['From'] = email_from
msg['To'] = email_to
if len(problems) > email_max_problems:
problems_string = 'Too many problems to list via email!\n\nPlease check elastic search logs to see what is going on...'
else:
problems_string = '\n'.join(list(map(str,problems)))
newline = '\n'
body=MIMEText(f"Dear admins,{newline}{newline}I thought you might be interested to know that we encountered {problem_quantity} against cdn.redhat.com content.{newline}{newline}There {problem_verb} currently {str(len(problems))} {problem_noun} that need addressing.{newline}{newline} {problems_string} {newline}{newline}{newline}Best regards,{newline}CERN Linux Droid{newline}(on behalf of the friendly humans of Linux Support)",_subtype='plain')
email_certs = newline.join(new_cert_filenames)
body=MIMEText(f"Dear admins,{newline}{newline}This is an informational message to inform you that there were changes detected with the RedHat entitlement certificates.{newline}{newline}The new certificate(s):{newline}{newline}{email_certs}{newline}{newline}have been merged into /certs/rhn_entitlements.pem{newline}{newline}No action is required by real humans :){newline}{newline}Best regards,{newline}CERN Linux Droid{newline}(on behalf of the friendly humans of Linux Support)",_subtype='plain')
msg.attach(body)
if len(email_certs) > 0 and len(problems) < email_max_problems:
for cert in sorted(set(email_certs)):
part = MIMEBase('application', "octet-stream")
part.set_payload(open(cert, "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="' + os.path.split(cert)[1] + '"')
msg.attach(part)
server = smtplib.SMTP('cernmx.cern.ch')
server.sendmail(email_from, email_to, msg.as_string())
else:
print("No problems today! :)")
print('No cert changes today :)')
sys.exit(0)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment