Skip to content

Commit bd7c814

Browse files
Merge pull request #28 from matyasselmeci/wip/sw3305-fixprobes
Fix & simplify CA & CRL verification probes (SOFTWARE-3305)
2 parents a13d3c5 + b7f1bee commit bd7c814

File tree

3 files changed

+41
-223
lines changed

3 files changed

+41
-223
lines changed

rsv-metrics/libexec/probes/cacert-verify-probe

Lines changed: 14 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ Additionally it makes sure that all IGTF CAs are installed.
182182
self.return_ok(out_msg)
183183

184184
def Check_Local_CA(self, certdir, errorHrs):
185-
"Function to compare CA certificates against the list at GOC"
185+
"Function to compare CA certificates against the list at OSG"
186186
source = {}
187187
found_cas = []
188188
sha256 = {}
@@ -195,34 +195,8 @@ Additionally it makes sure that all IGTF CAs are installed.
195195
if not os.path.isdir(certdir):
196196
self.return_unknown("ERROR: CA Certs Directory %s does not exist.. Setting metric to unknown." % certdir)
197197

198-
#Check if the file CA cers are installed from ITB or OSG, new or old format
199-
local_urls = ["http://repo.opensciencegrid.org/pacman/cadist/cacerts_sha256sum-new.txt"]
200-
ca_format_type = 0
201-
ca_index = os.path.join(certdir, "INDEX.txt")
202-
if os.path.isfile(ca_index):
203-
try:
204-
lines = open(ca_index).readlines()
205-
for i in lines:
206-
if i.find("IndexTypeVersion") >= 0:
207-
try:
208-
ca_format_type = int(i.split()[2])
209-
except IndexError:
210-
# When the line with IndexTypeVersion is missing, the type is 0 (default value)
211-
pass
212-
except (OSError, ValueError):
213-
pass
214-
grid_type = rsvprobe.get_grid_type()
215-
if not grid_type in [0, 1]:
216-
self.return_unknown("ERROR: Unknown grid type %s. Setting metric to unknown." % grid_type)
217-
#ca_format_type can be only 0,1:
218-
cert_ext = ".0"
219-
local_url = local_urls[0]
220-
if ca_format_type == 1:
221-
cert_ext = ".pem"
222-
local_url = local_urls[1]
223-
elif ca_format_type != 0:
224-
self.return_unknown("ERROR: CA Certs Directory %s has unknown certificate type %s. Setting metric to unknown." % (certdir, ca_format_type))
225-
self.add_message("Grid type is %s. CA format type is %s. URL with CA distribution: %s" % (rsvprobe.get_grid_type_string(grid_type), ca_format_type, local_url))
198+
# Step 1: Download the sha256sums for CAs in the OSG
199+
cert_ext = ".pem"
226200
cert_files = rsvprobe.list_directory(certdir, [cert_ext])
227201
if not cert_files:
228202
self.return_unknown("ERROR: CA Certs Directory %s contains no certificate files (*.%s).. Setting metric to unknown." % (certdir, cert_ext))
@@ -234,28 +208,23 @@ Additionally it makes sure that all IGTF CAs are installed.
234208
self.add_message("Could not calculate sha256sums of your CA file %s. This may result in a probe error. Please verify the file." % f)
235209
# eliminate error? file may have been deleted in the mean time, just skip?
236210
pass
237-
# Download the checksum file from OSG/ITB cache
238-
lines = rsvprobe.get_http_doc(local_url)
211+
# Download the checksum file from OSG repo
212+
self.add_message("URL with CA distribution: %s" % rsvprobe.CA_CERT_HASH_URL)
213+
lines = rsvprobe.get_http_doc(rsvprobe.CA_CERT_HASH_URL)
239214
if not lines:
240-
self.return_unknown("Could not download the sha256sum for CA list from OSG (%s) or the file is empty. Unable to verify CAs." % local_url)
215+
self.return_unknown("Could not download the sha256sum for CA list from OSG (%s) or the file is empty."
216+
" Unable to verify CAs." % rsvprobe.CA_CERT_HASH_URL)
241217
for line in lines:
242218
line.strip()
243219
values = line.split()
244220
local_hash = values[1].split('.')[0].strip()
245221
sha256[local_hash] = values[0]
246222

247-
# Step 2: Get the list of Certs included in OSG from GOC website.
248-
#chdir($working_dir);
249-
local_urls = ["http://repo.opensciencegrid.org/pacman/cadist/INDEX.txt",
250-
"http://repo.opensciencegrid.org/pacman/cadist/INDEX-new.txt"]
251-
local_url = local_urls[ca_format_type]
252-
lines = rsvprobe.get_http_doc(local_url)
223+
# Step 2: Get the list of Certs included in OSG from OSG repo
224+
lines = rsvprobe.get_http_doc(rsvprobe.CA_CERT_INDEX_URL)
253225
if not lines:
254-
self.return_unknown("Could not download the CA list from OSG (%s) or the list is empty. Unable to verify CAs." % local_url)
255-
## Old format (remove 1 #):
256-
## Hash Source URL Accreditation
257-
##--------------------------------------------------------------------------------------------------------
258-
#09ff08b7 CNRS2-Projets http://igc.services.cnrs.fr/GRID-FR/ I
226+
self.return_unknown("Could not download the CA list from OSG (%s) or the list is empty. Unable to verify CAs." %
227+
rsvprobe.CA_CERT_INDEX_URL)
259228
## New format (remove 1 #):
260229
## OldHash NewHash CAfile CAURL Version Accreditation
261230
##--------------------------------------------------------------------------------------------------------
@@ -265,10 +234,8 @@ Additionally it makes sure that all IGTF CAs are installed.
265234
if not line or line.startswith('#'):
266235
continue
267236
line_content = line.split()
268-
chash = line_content[0]
269-
if ca_format_type == 1:
270-
# New CA format type we use file names
271-
chash = line_content[2].split('.')[0]
237+
# New CA format type we use file names
238+
chash = line_content[2].split('.')[0]
272239
source[chash] = line_content[-1]
273240

274241
# Step 3: Check the CAs to ensure that sha256sums match-up

rsv-metrics/libexec/probes/crl-freshness-probe

Lines changed: 24 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -113,75 +113,34 @@ Additionally it makes sure that all IGTF CAs are installed.
113113
certdir = rsvprobe.get_ca_dir()
114114
self.verify_CRL(certdir, self.warningHrs, self.errorHrs)
115115

116-
def get_osg_CAs(self, ca_format_type, grid_type):
117-
"Download and parce the CA list from OSG GOC"
118-
if not grid_type in [0, 1]:
119-
self.return_unknown("ERROR: Unknown grid type %s. Setting metric to unknown." % grid_type)
120-
if not ca_format_type in [0, 1]:
121-
self.return_unknown("ERROR: CA Certs Directory has unknown certificate type %s. Setting metric to unknown." %
122-
ca_format_type)
116+
def get_osg_CAs(self):
117+
"Download and parse the CA list from OSG repo"
123118
source_name = {} # list of crl files name -> data (hash0, hash1, accreditation)
124119
source_hash0 = {} # Old hash -> accreditation
125120
source_hash1 = {} # New hash -> accreditation
126-
local_urls = [["http://repo.opensciencegrid.org/pacman/cadist/INDEX.txt"]
127-
["http://repo.opensciencegrid.org/pacman/cadist/INDEX-new.txt"]
128-
]
129-
local_url = local_urls[ca_format_type][grid_type]
130-
# Download the CA list file from OSG/ITB cache
131-
lines = rsvprobe.get_http_doc(local_url)
121+
# Download the CA list file
122+
lines = rsvprobe.get_http_doc(rsvprobe.CA_CERT_INDEX_URL)
132123
if not lines:
133-
self.return_unknown("Could not download the CA list from OSG (%s) or the file is empty. Unable to verify CRLs." % local_url)
124+
self.return_unknown("Could not download the CA list from OSG (%s) or the file is empty."
125+
" Unable to verify CRLs." % rsvprobe.CA_CERT_INDEX_URL)
134126
## Parsing of the CA list
135-
## type 1 format:
136-
## OldHash NewHash CAfile CAURL Version Accreditation
127+
## OldHash NewHash CAfile CAURL Version Accreditation
137128
##--------------------------------------------------------------------------------------------------------
138129
#75680d2e ee64a828 AAACertificateServices.pem https://www.terena.org/activities/tcs/ 1.41 I
139130
#3c58f906 157753a5 AddTrust-External-CA-Root.pem http://www.comodo.com/ 1.41 I
140-
## type 0 format:
141-
## Hash Source URL Accreditation
142-
##--------------------------------------------------------------------------------------------------------
143-
#09ff08b7 CNRS2-Projets http://igc.services.cnrs.fr/GRID-FR/ I
144-
#0a12b607 UGRID https://ca.ugrid.org/ I
145131
for line in lines:
146132
if not line or line.startswith('#'):
147133
continue
148134
line_content = line.split()
149-
if ca_format_type == 1:
150-
# New CA format type, both old hash (hash0) and new hash (hash1), source name has extension (filename)
151-
source_hash0[line_content[0]] = line_content[-1]
152-
source_hash1[line_content[1]] = line_content[-1]
153-
source_name[line_content[2].split('.')[0]] = { 'hash': line_content[0],
154-
'newhash': line_content[1],
155-
'accreditation': line_content[-1]
156-
}
157-
else: # assuming type 0
158-
# Assuming CA format type (type 0), only old hash (hash0), source name has no extension
159-
source_hash0[line_content[0]] = line_content[-1]
160-
source_name[line_content[1]] = { 'hash': line_content[0],
161-
'newhash': None,
162-
'accreditation': line_content[-1]
163-
}
164-
return source_name, source_hash0, source_hash1
135+
# New CA format type, both old hash (hash0) and new hash (hash1), source name has extension (filename)
136+
source_hash0[line_content[0]] = line_content[-1]
137+
source_hash1[line_content[1]] = line_content[-1]
138+
source_name[line_content[2].split('.')[0]] = { 'hash': line_content[0],
139+
'newhash': line_content[1],
140+
'accreditation': line_content[-1]
141+
}
142+
return source_name, source_hash0, source_hash1
165143

166-
def parse_ca_index(self, certdir):
167-
"Parse INDEX.txt in CA certs directory and retrieve IndexTypeVersion, default to 0"
168-
ca_format_type = 0
169-
ca_index = os.path.join(certdir, "INDEX.txt")
170-
if os.path.isfile(ca_index):
171-
try:
172-
lines = open(ca_index).readlines()
173-
for i in lines:
174-
if i.find("IndexTypeVersion") >= 0:
175-
try:
176-
ca_format_type = int(i.split()[2])
177-
except IndexError:
178-
# When missing it is 0 (default value)
179-
pass
180-
except (OSError, ValueError):
181-
# If I don't find the index file or don't find the keyword IndexTypeVersion assume type 0
182-
pass
183-
return ca_format_type
184-
185144
def verify_CRL(self, certdir, warnHrs, errHrs):
186145
"""Check_Freshness_Local_CRL: Checks the last time when the CRLs were successfully downloaded
187146
parameters :
@@ -192,15 +151,9 @@ errHrs: Number hours since the failing downloads before an error is issued
192151
"""
193152
#status_code = 0 # Return status code as expected by RSV for summaryData
194153
found_crls = []
195-
ca_format_type = 0
196154

197155
# Step 1: Get the list of Certs included in OSG from GOC website.
198-
ca_format_type = self.parse_ca_index(certdir)
199-
200-
#Check if the file CA certs are installed from ITB
201-
# grid_type: 0 - osg; 1 - itb
202-
grid_type = rsvprobe.get_grid_type()
203-
source_name, source_hash0, source_hash1 = self.get_osg_CAs(ca_format_type, grid_type)
156+
source_name, source_hash0, source_hash1 = self.get_osg_CAs()
204157

205158
# Step 2: Get and Check time stamps on the CRL files to ensure that it has been recently downloaded
206159
error_count = 0
@@ -211,8 +164,7 @@ errHrs: Number hours since the failing downloads before an error is issued
211164
self.return_unknown("ERROR: CA Certs Directory %s contains no CRL files (*.r0). Aborting the probe (UNKOWN status)." %
212165
certdir)
213166
source_hash_list = source_hash0.keys()
214-
if ca_format_type == 1:
215-
source_hash_list += source_hash1.keys()
167+
source_hash_list += source_hash1.keys()
216168
for i in crl_files:
217169
local_hash = os.path.basename(i).split('.')[0] #remove the extension
218170
# List of CRLs found.
@@ -232,13 +184,12 @@ errHrs: Number hours since the failing downloads before an error is issued
232184
pass # not in hash0
233185
# keep the following outside form the except to cover the case when the hash h1 is the old hash of CA cert c1
234186
# and new hash of CA cert c2. Is this possible?
235-
if not is_igtf_cert and ca_format_type == 1:
187+
if not is_igtf_cert:
236188
try:
237189
if source_hash1[local_hash].find('I') >= 0:
238190
is_igtf_cert = True
239191
except KeyError:
240192
pass # not in hash1
241-
if not is_igtf_cert:
242193
if self.verbose:
243194
self.add_ok("EGEE test and CRL file for CA with hash %s that is not in IGTF, ignored." % local_hash)
244195
continue
@@ -265,25 +216,23 @@ errHrs: Number hours since the failing downloads before an error is issued
265216
# Ignore non IGTF CAs for wlcg probe
266217
continue
267218
# continue if found CRL
268-
if ca_format_type == 1 and ca_info['newhash'] in found_crls:
219+
if ca_info['newhash'] in found_crls:
269220
continue
270221
if ca_info['hash'] in found_crls:
271222
continue
272-
# continue if the CA file has been removed
273-
# if ca_format_type == 1 then both CA files must have been removed to continue
223+
# continue if the both CA files have been removed
274224
if not os.path.isfile(os.path.join(certdir, "%s.0" % ca_info['hash'])):
275-
if ca_format_type != 1 or not os.path.isfile(os.path.join(certdir, "%s.0" % ca_info['newhash'])):
225+
if not os.path.isfile(os.path.join(certdir, "%s.0" % ca_info['newhash'])):
276226
continue
277-
warning = ("MISSING: CRL file for %s (%s/%s, type %s) is missing. OSG policy requires CRL for every CA distributed by OSG." %
278-
(name, ca_info['newhash'], ca_info['hash'], ca_format_type))
227+
warning = ("MISSING: CRL file for %s (%s/%s) is missing. OSG policy requires CRL for every CA distributed by OSG." %
228+
(name, ca_info['newhash'], ca_info['hash']))
279229
if missing_count == 0:
280230
warning += (
281231
"\n- Has fetch-crl run recently? (See /etc/cron.d/fetch-crl*)\n"
282232
"- See fetch-crl output (mailed to root by cron or sent to syslog), "
283233
"or try running fetch-crl by hand to inspect its output.\n"
284234
"- More info on troubleshooting this probe can be found at: "
285-
"https://www.opensciencegrid.org/bin/view/Documentation/Release3/RsvProbeCrlFreshnessProbe\n"
286-
"- For more help, submit a ticket to the GOC at: https://ticket.opensciencegrid.org/")
235+
"- For more help, send email to help@opensciencegrid.org")
287236
self.add_warning(warning)
288237
missing_count += 1
289238

rsv-metrics/libexec/probes/rsvprobe.py

Lines changed: 3 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -111,107 +111,6 @@ def get_http_doc(url, quote=True):
111111
ret = f.readlines()
112112
return ret
113113

114-
def get_config_val(req_key, req_section=None):
115-
"""Get the value of an option from a section of OSG configuration in both Pacman and RPM installations. Return None if option is not found."""
116-
confini_fname = None
117-
confini_fname_list = []
118-
if os.getenv("OSG_LOCATION"):
119-
confini_fname_list.append(os.path.join(os.getenv("OSG_LOCATION"), "osg/etc/config.ini"))
120-
if os.getenv("VDT_LOCATION"):
121-
confini_fname_list.append(os.path.join(os.getenv("VDT_LOCATION"), "osg/etc/config.ini"))
122-
for i in confini_fname_list:
123-
if os.path.isfile(i):
124-
confini_fname = i
125-
if not confini_fname:
126-
# Assume new OSG 3
127-
# Using NEW osg-configure code/API
128-
try:
129-
from osg_configure.modules import configfile
130-
except:
131-
return None
132-
# necassary for exception raised by osg_configure
133-
import ConfigParser
134-
try:
135-
config = configfile.read_config_files()
136-
except IOError:
137-
return None
138-
if req_section:
139-
try:
140-
ret = config.get(req_section, req_key)
141-
except ConfigParser.NoSectionError:
142-
return None
143-
else:
144-
for section in config.sections():
145-
if config.has_option(section, req_key):
146-
return config.get(req_section, req_key)
147-
try:
148-
ret = config.defaults()[req_key]
149-
except KeyError:
150-
return None
151-
return ret
152-
# Continue old Pacman installation
153-
# Behaves like the old probe: no variable substitution in config.ini
154-
try:
155-
f = open(confini_fname)
156-
except (OSError, IOError):
157-
# unable to find config.ini
158-
return None
159-
# comments at end of section line are OK
160-
# comment at end of key = val line are not OK
161-
SECTION = re.compile('^\s*\[\s*([^\]]*)\s*\]\s*(?:#.*)$')
162-
PARAM = re.compile('^\s*(\w+)\s*=\s*(.*)\s*$')
163-
COMMENT = re.compile('^\s*#.*$')
164-
if not req_section:
165-
in_section = True
166-
else:
167-
in_section = False
168-
for line in f:
169-
if COMMENT.match(line): continue
170-
if req_section:
171-
m = SECTION.match(line)
172-
if m:
173-
section = m.groups()
174-
if section == req_section:
175-
in_section = True
176-
else:
177-
if in_section:
178-
# assume sections are all differents (same section not coming back later in file)
179-
break
180-
in_section = False
181-
continue
182-
if in_section:
183-
m = PARAM.match(line)
184-
if m:
185-
key, val = m.groups()
186-
return val
187-
continue
188-
# malformed line (not matching comment, section header or key=val)
189-
# key not found (in section)
190-
return None
191-
192-
# Returns the grid type:
193-
# 1 for itb (OSG-ITB)
194-
# 0 for production (OSG) or anything else
195-
def get_grid_type():
196-
"Return 1 for OSG-ITB sites, 0 otherwise (production sites)"
197-
# Equivalent of config.ini parsing in perl probe:
198-
# cat $1/osg/etc/config.ini | sed -e's/ //g'| grep '^group=OSG-ITB' &>/dev/null
199-
grid_type = get_config_val("group", "Site Information")
200-
if grid_type:
201-
if grid_type.strip() == "OSG-ITB":
202-
return 1
203-
return 0
204-
205-
def get_grid_type_string(gtype=-1):
206-
"Return the translation of the gtype provided 1:OSG-ITB, 0:OSG, or the value from Site_Information"
207-
if gtype == 0:
208-
grid_type = "OSG"
209-
elif gtype == 1:
210-
grid_type = "OSG-ITB"
211-
else:
212-
grid_type = get_config_val("group", "Site Information")
213-
return grid_type
214-
215114
def get_temp_dir():
216115
"Return the a temporary directory to store data across executions."
217116
# Should I create a directory per user?
@@ -718,3 +617,6 @@ def describe(self):
718617
return ret
719618

720619
EMPTY_METRIC = RSVMetric('UNKNOWN', 'UNKNOWN')
620+
621+
CA_CERT_HASH_URL = "http://repo.opensciencegrid.org/cadist/cacerts_sha256sum-new.txt"
622+
CA_CERT_INDEX_URL = "http://repo.opensciencegrid.org/cadist/INDEX.txt"

0 commit comments

Comments
 (0)