Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
104
Merge Requests
104
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
slapos
Commits
00ac69e6
Commit
00ac69e6
authored
Mar 02, 2023
by
Łukasz Nowak
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
monitor: Implement re6stnet certificate check
parent
06f01fd6
Pipeline
#27251
passed with stage
in 0 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
169 additions
and
2 deletions
+169
-2
software/monitor/buildout.hash.cfg
software/monitor/buildout.hash.cfg
+2
-2
software/monitor/instance-default-input-schema.json
software/monitor/instance-default-input-schema.json
+15
-0
software/monitor/instance-node-monitoring.jinja2.cfg
software/monitor/instance-node-monitoring.jinja2.cfg
+13
-0
software/monitor/instance.cfg
software/monitor/instance.cfg
+1
-0
software/monitor/test/test.py
software/monitor/test/test.py
+138
-0
No files found.
software/monitor/buildout.hash.cfg
View file @
00ac69e6
...
...
@@ -14,7 +14,7 @@
# not need these here).
[template]
filename = instance.cfg
md5sum =
e1dd16a6f50468959b5c4572b8c82f23
md5sum =
cfb3bf67b11e5b1278d94f7e729d740c
[json-test-template]
_update_hash_filename_ = json-test-template.json.in.jinja2
...
...
@@ -26,7 +26,7 @@ md5sum = 6b933beb0744d97c7760e4601298e137
[template-node-monitoring]
_update_hash_filename_ = instance-node-monitoring.jinja2.cfg
md5sum =
2d8bd1224472983e54f36770d3e3f969
md5sum =
6dbc34d9052989225ada3b2a2d0b588c
[network-bench-cfg]
filename = network_bench.cfg.in
...
...
software/monitor/instance-default-input-schema.json
View file @
00ac69e6
...
...
@@ -146,6 +146,21 @@
"title"
:
"Boolean to display prediction (unit: N/A)"
,
"description"
:
"Enable prediction display by setting boolean to True (unit: N/A)"
,
"type"
:
"boolean"
},
"promise_re6stnet_config_directory"
:
{
"default"
:
"/etc/re6stnet/"
,
"title"
:
"Directory of re6stnet configuration on the node"
,
"type"
:
"string"
},
"promise_re6stnet_certificate_file"
:
{
"default"
:
"cert.crt"
,
"title"
:
"Filename of the re6stnet certificate in the re6stnet directory"
,
"type"
:
"string"
},
"re6stnet_certificate_expiration_delay"
:
{
"default"
:
15
,
"title"
:
"Days before expiration until certificate is considered valid"
,
"type"
:
"number"
}
}
}
software/monitor/instance-node-monitoring.jinja2.cfg
View file @
00ac69e6
...
...
@@ -8,6 +8,7 @@ parts =
check-network-errors.py
check-network-transit.py
check-cpu-load.py
check-re6stnet-certificate.py
publish-connection-information
extends = {{ monitor_template }}
...
...
@@ -105,3 +106,15 @@ config-last-transit-file = ${directory:var}/promise_network_last_transit_file
promise = check_server_cpu_load
config-frequency = {{ slapparameter_dict.get("promise_cpu_load_frequency", 3) }}
config-cpu-load-threshold = {{ slapparameter_dict.get("promise_cpu_load_threshold", 1.5) }}
[check-re6stnet-certificate.py]
<= macro.promise
{% set RE6STNET_CONFIG_DIR = slapparameter_dict.get('promise_re6stnet_config_directory', '/etc/re6stnet') %}
{% if os_module.path.exists(os_module.path.join(RE6STNET_CONFIG_DIR, 're6stnet.conf')) %}
promise = check_certificate
config-certificate = {{ os_module.path.join(RE6STNET_CONFIG_DIR, slapparameter_dict.get('promise_re6stnet_certificate_file', 'cert.crt')) }}
config-certificate-expiration-days = {{ slapparameter_dict.get('re6stnet_certificate_expiration_delay', '15') }}
{% else %}
promise = check_command_execute
config-command = echo "re6stnet disabled on the node"
{% endif %}
software/monitor/instance.cfg
View file @
00ac69e6
...
...
@@ -30,6 +30,7 @@ context =
<= instance-template
url = ${template-node-monitoring:target}
extra-context =
import os_module os
raw buildout_directory ${buildout:directory}
section slap_connection slap-connection
...
...
software/monitor/test/test.py
View file @
00ac69e6
...
...
@@ -25,16 +25,26 @@
#
##############################################################################
import
datetime
import
glob
import
hashlib
import
json
import
os
import
re
import
requests
import
shutil
import
subprocess
import
tempfile
import
xml.etree.ElementTree
as
ET
from
cryptography
import
x509
from
cryptography.hazmat.backends
import
default_backend
from
cryptography.hazmat.primitives
import
hashes
from
cryptography.hazmat.primitives
import
serialization
from
cryptography.hazmat.primitives.asymmetric
import
rsa
from
cryptography.x509.oid
import
NameOID
from
slapos.recipe.librecipe
import
generateHashFromFiles
from
slapos.testing.testcase
import
makeModuleSetUpAndTestCaseClass
from
slapos.util
import
bytes2str
setUpModule
,
SlapOSInstanceTestCase
=
makeModuleSetUpAndTestCaseClass
(
os
.
path
.
abspath
(
...
...
@@ -571,3 +581,131 @@ class TestNodeMonitoring(SlapOSInstanceTestCase):
def
test_node_monitoring_instance
(
self
):
pass
class
TestNodeMonitoringRe6stCertificate
(
SlapOSInstanceTestCase
):
@
classmethod
def
getInstanceSoftwareType
(
cls
):
return
'default'
def
reRequestInstance
(
self
,
partition_parameter_kw
=
None
,
state
=
'started'
):
if
partition_parameter_kw
is
None
:
partition_parameter_kw
=
{}
software_url
=
self
.
getSoftwareURL
()
software_type
=
self
.
getInstanceSoftwareType
()
return
self
.
slap
.
request
(
software_release
=
software_url
,
software_type
=
software_type
,
partition_reference
=
self
.
default_partition_reference
,
partition_parameter_kw
=
partition_parameter_kw
,
state
=
state
)
def
test_default
(
self
):
self
.
reRequestInstance
()
self
.
slap
.
waitForInstance
()
promise
=
os
.
path
.
join
(
self
.
computer_partition_root_path
,
'etc'
,
'plugin'
,
'check-re6stnet-certificate.py'
)
self
.
assertTrue
(
os
.
path
.
exists
(
promise
))
with
open
(
promise
)
as
fh
:
promise_content
=
fh
.
read
()
# this test depends on OS level configuration
if
os
.
path
.
exists
(
'/etc/re6stnet/cert.crt'
):
self
.
assertIn
(
"extra_config_dict = {'certificate': '/etc/re6stnet/cert.crt', "
"'certificate-expiration-days': '15'}"
,
promise_content
)
self
.
assertIn
(
"from slapos.promise.plugin.check_certificate import RunPromise"
,
promise_content
)
else
:
self
.
assertIn
(
"extra_config_dict = {'command': 'echo
\
"
re6stnet disabled on the "
"node
\
"
'}"
,
promise_content
)
self
.
assertIn
(
"from slapos.promise.plugin.check_command_execute import RunPromise"
,
promise_content
)
def
createKey
(
self
):
key
=
rsa
.
generate_private_key
(
public_exponent
=
65537
,
key_size
=
2048
,
backend
=
default_backend
())
key_pem
=
key
.
private_bytes
(
encoding
=
serialization
.
Encoding
.
PEM
,
format
=
serialization
.
PrivateFormat
.
TraditionalOpenSSL
,
encryption_algorithm
=
serialization
.
NoEncryption
()
)
return
key
,
key_pem
def
createCertificate
(
self
,
key
,
days
=
30
):
subject
=
issuer
=
x509
.
Name
([
x509
.
NameAttribute
(
NameOID
.
COUNTRY_NAME
,
u"FR"
),
x509
.
NameAttribute
(
NameOID
.
STATE_OR_PROVINCE_NAME
,
u"Nord"
),
x509
.
NameAttribute
(
NameOID
.
LOCALITY_NAME
,
u"Lille"
),
x509
.
NameAttribute
(
NameOID
.
ORGANIZATION_NAME
,
u"Nexedi"
),
x509
.
NameAttribute
(
NameOID
.
COMMON_NAME
,
u"Common"
),
])
certificate
=
x509
.
CertificateBuilder
().
subject_name
(
subject
).
issuer_name
(
issuer
).
public_key
(
key
.
public_key
()
).
serial_number
(
x509
.
random_serial_number
()
).
not_valid_before
(
datetime
.
datetime
.
utcnow
()
).
not_valid_after
(
datetime
.
datetime
.
utcnow
()
+
datetime
.
timedelta
(
days
)
).
sign
(
key
,
hashes
.
SHA256
(),
default_backend
())
certificate_pem
=
certificate
.
public_bytes
(
encoding
=
serialization
.
Encoding
.
PEM
)
return
certificate
,
certificate_pem
def
createKeyCertificate
(
self
,
certificate_path
):
key
,
key_pem
=
self
.
createKey
()
certificate
,
certificate_pem
=
self
.
createCertificate
(
key
,
30
)
with
open
(
certificate_path
,
'w'
)
as
fh
:
fh
.
write
(
bytes2str
(
key_pem
))
with
open
(
certificate_path
,
'a'
)
as
fh
:
fh
.
write
(
bytes2str
(
certificate_pem
))
def
setUp
(
self
):
super
().
setUp
()
self
.
re6st_dir
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
self
.
re6st_dir
)
def
test_re6st_dir
(
self
,
days
=
None
,
filename
=
'cert.crt'
):
self
.
createKeyCertificate
(
os
.
path
.
join
(
self
.
re6st_dir
,
filename
))
with
open
(
os
.
path
.
join
(
self
.
re6st_dir
,
're6stnet.conf'
),
'w'
)
as
fh
:
fh
.
write
(
""
)
partition_parameter_kw
=
{
'promise_re6stnet_config_directory'
:
self
.
re6st_dir
}
if
filename
!=
'cert.crt'
:
partition_parameter_kw
[
'promise_re6stnet_certificate_file'
]
=
filename
if
days
is
not
None
:
partition_parameter_kw
[
're6stnet_certificate_expiration_delay'
]
=
days
self
.
reRequestInstance
(
partition_parameter_kw
=
{
'_'
:
json
.
dumps
(
partition_parameter_kw
)})
self
.
slap
.
waitForInstance
()
promise
=
os
.
path
.
join
(
self
.
computer_partition_root_path
,
'etc'
,
'plugin'
,
'check-re6stnet-certificate.py'
)
self
.
assertTrue
(
os
.
path
.
exists
(
promise
))
with
open
(
promise
)
as
fh
:
promise_content
=
fh
.
read
()
self
.
assertIn
(
"""extra_config_dict = { 'certificate': '%(re6st_dir)s/%(filename)s',
'certificate-expiration-days': '%(days)s'}"""
%
{
're6st_dir'
:
self
.
re6st_dir
,
'days'
:
days
or
15
,
'filename'
:
filename
},
promise_content
)
self
.
assertIn
(
"from slapos.promise.plugin.check_certificate import RunPromise"
,
promise_content
)
def
test_re6st_dir_expiration
(
self
):
self
.
test_re6st_dir
(
days
=
10
)
def
test_re6st_dir_filename
(
self
):
self
.
test_re6st_dir
(
filename
=
"cert.pem"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment