forked from scionproto/scion
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtrust_store.py
More file actions
148 lines (134 loc) · 5.55 KB
/
trust_store.py
File metadata and controls
148 lines (134 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Copyright 2015 ETH Zurich
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
:mod:`trust_store` --- Storage and management of trust objects (TRCs and certs).
================================================================================
"""
# Stdlib
from collections import defaultdict
import glob
import logging
import os
import threading
# External packages
from prometheus_client import Gauge
# SCION
from lib.crypto.certificate_chain import CertificateChain
from lib.crypto.trc import TRC
from lib.crypto.util import CERT_DIR
from lib.util import read_file, write_file
TRCS_TOTAL = Gauge("ts_trcs_total", "# of TRCs in TrustStore", ["server_id", "isd_as"])
CERTS_TOTAL = Gauge("ts_certs_total", "# of Certs in TrustStore", ["server_id", "isd_as"])
class TrustStore(object):
"""Trust Store class."""
def __init__(self, conf_dir, cache_dir, ename, labels=None): # pragma: no cover
"""
:param str conf_dir: configuration directory.
:param str cache_dir: directory to cache TRCs and certs in.
:param str ename: element name, used to generate cache file names.
:param dict labels:
Labels added to the exported metrics. The following labels are supported:
- server_id: A unique identifier of the server that is exporting
- isd_as: The ISD_AS of where the server is running
"""
self._dir = os.path.join(conf_dir, CERT_DIR)
self._cachedir = cache_dir
self._ename = ename
self._labels = labels
self._certs = defaultdict(list)
self._trcs = defaultdict(list)
self._trcs_lock = threading.Lock()
self._certs_lock = threading.Lock()
self._init_trcs()
self._init_certs()
if self._labels:
self._init_metrics()
def _init_metrics(self): # pragma: no cover
TRCS_TOTAL.labels(**self._labels).set(0)
CERTS_TOTAL.labels(**self._labels).set(0)
def _init_trcs(self): # pragma: no cover
trcfiles = list(glob.glob("%s/*.trc" % self._dir))
trcfiles.extend(glob.glob("%s/%s-*.trc" % (self._cachedir, self._ename)))
for path in trcfiles:
trc_raw = read_file(path)
self.add_trc(TRC.from_raw(trc_raw), write=False)
logging.debug("Loaded: %s" % path)
def _init_certs(self): # pragma: no cover
certfiles = list(glob.glob("%s/*.crt" % self._dir))
certfiles.extend(glob.glob("%s/%s-*.crt" % (self._cachedir, self._ename)))
for path in certfiles:
cert_raw = read_file(path)
self.add_cert(CertificateChain.from_raw(cert_raw), write=False)
logging.debug("Loaded: %s" % path)
def get_trc(self, isd, version=None):
with self._trcs_lock:
if not self._trcs[isd]:
return None
if version is None or version == 0:
# Return the most recent TRC.
_, trc = max(self._trcs[isd])
return trc
# Otherwise, try to find a TRC with given version.
for ver, trc in self._trcs[isd]:
if version == ver:
return trc
return None
def get_trcs(self): # pragma: no cover
# Return list of the most recent TRCs.
res = []
for isd in self._trcs:
res.append(self.get_trc(isd))
return res
def get_cert(self, isd_as, version=None):
with self._certs_lock:
if not self._certs[isd_as]:
return None
if version is None or version == 0:
# Return the most recent cert.
_, cert = max(self._certs[isd_as])
return cert
# Otherwise, try to find a cert with given version.
for ver, cert in self._certs[isd_as]:
if version == ver:
return cert
return None
def add_trc(self, trc, write=True):
isd, version = trc.get_isd_ver()
with self._trcs_lock:
for ver, _ in self._trcs[isd]:
if version == ver:
return
self._trcs[isd].append((version, trc))
if self._labels:
TRCS_TOTAL.labels(**self._labels).inc()
if write:
os.makedirs(self._cachedir, exist_ok=True)
write_file(os.path.join(self._cachedir,
"%s-ISD%s-V%s.trc" % (self._ename, isd, version)),
str(trc))
def add_cert(self, cert, write=True):
isd_as, version = cert.get_leaf_isd_as_ver()
with self._certs_lock:
for ver, _ in self._certs[isd_as]:
if version == ver:
return
self._certs[isd_as].append((version, cert))
if self._labels:
CERTS_TOTAL.labels(**self._labels).inc()
if write:
os.makedirs(self._cachedir, exist_ok=True)
write_file(
os.path.join(self._cachedir, "%s-ISD%s-AS%s-V%s.crt" %
(self._ename, isd_as.isd_str(), isd_as.as_file_fmt(), version)),
str(cert))