Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
21
Merge Requests
21
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
slapos.core
Commits
5d1130cf
Commit
5d1130cf
authored
Jun 27, 2017
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update certificate client request
parent
2fc808b8
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
161 additions
and
48 deletions
+161
-48
setup.py
setup.py
+1
-1
slapos/certificate.py
slapos/certificate.py
+116
-0
slapos/cli/configure_client.py
slapos/cli/configure_client.py
+7
-4
slapos/cli/register.py
slapos/cli/register.py
+25
-26
slapos/grid/SlapObject.py
slapos/grid/SlapObject.py
+7
-2
slapos/slap/slap.py
slapos/slap/slap.py
+4
-3
slapos/util.py
slapos/util.py
+1
-12
No files found.
setup.py
View file @
5d1130cf
...
...
@@ -48,6 +48,7 @@ setup(name=name,
'netifaces'
,
# to fetch information about network devices
'setuptools'
,
# namespaces
'supervisor'
,
# slapgrid uses supervisor to manage processes
'pyOpenSSL'
,
# manage ssl certificates
'psutil>=2.0.0'
,
'xml_marshaller>=0.9.3'
,
# to unmarshall/marshall python objects to/from
# XML
...
...
@@ -56,7 +57,6 @@ setup(name=name,
'cliff'
,
'requests>=2.4.3'
,
'six'
,
'caucase'
,
# used to manage ca client request
'uritemplate'
,
# used by hateoas navigator
]
+
additional_install_requires
,
extras_require
=
{
...
...
slapos/certificate.py
0 → 100644
View file @
5d1130cf
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010-2014 Vifib SARL and Contributors.
# All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import
errno
import
os
import
subprocess
import
sqlite3
import
re
from
OpenSSL
import
crypto
from
datetime
import
datetime
,
timedelta
def
parse_certificate_from_html
(
html
):
"""
Extract certificate from an HTML page received by SlapOS Master.
"""
regex
=
r"(-{5}BEGIN\
sCERTIFICATE-{
5}.*-{5}END\
sCERTIFICATE-{
5})"
result
=
re
.
search
(
regex
,
html
,
re
.
DOTALL
)
if
result
:
return
result
.
groups
()[
0
]
return
certificate
def
generateCertificateRequest
(
self
,
key_string
,
cn
,
country
=
''
,
state
=
''
,
locality
=
''
,
email
=
''
,
organization
=
''
,
organization_unit
=
''
,
csr_file
=
None
,
digest
=
"sha256"
):
"""
Generate certificate Signature request.
Parameter `cn` is mandatory
"""
key
=
crypto
.
load_privatekey
(
crypto
.
FILETYPE_PEM
,
key_string
)
req
=
crypto
.
X509Req
()
subject
=
req
.
get_subject
()
subject
.
CN
=
cn
if
country
:
subject
.
C
=
country
if
state
:
subject
.
ST
=
state
if
locality
:
subject
.
L
=
locality
if
organization
:
subject
.
O
=
organization
if
organization_unit
:
subject
.
OU
=
organization_unit
if
email
:
subject
.
emailAddress
=
email
req
.
set_pubkey
(
key
)
req
.
add_extensions
([
crypto
.
X509Extension
(
"basicConstraints"
,
False
,
"CA:FALSE"
),
crypto
.
X509Extension
(
"keyUsage"
,
False
,
"nonRepudiation, digitalSignature, keyEncipherment"
)
])
req
.
sign
(
key
,
digest
)
csr
=
crypto
.
dump_certificate_request
(
crypto
.
FILETYPE_PEM
,
req
)
if
csr_file
is
not
None
:
with
open
(
csr_file
,
'w'
)
as
req_file
:
req_file
.
write
(
csr
)
os
.
chmod
(
csr_file
,
0640
)
return
csr
def
generatePkey
(
size
=
2048
):
key
=
crypto
.
PKey
()
key
.
generate_key
(
crypto
.
TYPE_RSA
,
size
)
return
crypto
.
dump_privatekey
(
crypto
.
FILETYPE_PEM
,
key
)
def
generatePrivatekey
(
self
,
output_file
,
size
=
2048
):
"""
Generate private key into `output_file` and return the pkey string
"""
try
:
key_fd
=
os
.
open
(
output_file
,
os
.
O_CREAT
|
os
.
O_WRONLY
|
os
.
O_EXCL
|
os
.
O_TRUNC
,
0600
)
except
OSError
,
e
:
if
e
.
errno
!=
errno
.
EEXIST
:
raise
else
:
pkey
=
generatePkey
(
size
)
os
.
write
(
key_fd
,
pkey
)
os
.
close
(
key_fd
)
return
pkey
slapos/cli/configure_client.py
View file @
5d1130cf
...
...
@@ -36,7 +36,10 @@ import requests
from
caucase.cli_flask
import
CertificateAuthorityRequest
from
slapos.cli.config
import
ClientConfigCommand
from
slapos.util
import
mkdir_p
,
parse_certificate_key_pair
from
slapos.util
import
mkdir_p
from
slapos.certificate
import
(
parse_certificate_from_html
,
generateCertificateRequest
,
generatePkey
)
class
ConfigureClientCommand
(
ClientConfigCommand
):
...
...
@@ -138,9 +141,9 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url):
ca_url
=
''
)
logger
.
debug
(
'Generating key to %s'
,
key_path
)
ca_client
.
generatePrivatekey
(
key_path
,
size
=
2048
)
csr_string
=
ca_client
.
generateCertificateRequest
(
key_
path
,
key_string
=
generatePrivatekey
(
key_path
,
size
=
2048
)
csr_string
=
generateCertificateRequest
(
key_
string
,
cn
=
str
(
uuid
.
uuid4
()))
# retrieve a template for the configuration file
...
...
slapos/cli/register.py
View file @
5d1130cf
...
...
@@ -37,9 +37,10 @@ import pkg_resources
import
requests
import
uuid
from
caucase.cli_flask
import
CertificateAuthorityRequest
from
slapos.cli.command
import
Command
,
must_be_root
from
slapos.util
import
parse_certificate_key_pair
from
slapos.certificate
import
(
parse_certificate_from_html
,
generateCertificateRequest
,
generatePkey
)
class
RegisterCommand
(
Command
):
...
...
@@ -183,8 +184,10 @@ def sign_certificate(logger, master_url_web, node_name, csr_string,
else
:
req
.
raise_for_status
()
return
(
get_computer_name
(
req
.
text
),
parse_certificate_from_html
(
req
.
text
))
certificate
=
parse_certificate_from_html
(
req
.
text
)
if
certificate
is
None
:
raise
Exception
(
"Computer Certificate was not returned by the Master"
)
return
(
get_computer_name
(
req
.
text
),
certificate
)
def
get_computer_name
(
text_string
):
...
...
@@ -247,12 +250,16 @@ def slapconfig(conf):
if
not
dry_run
:
os
.
mkdir
(
user_certificate_repository_path
,
0o711
)
conf
.
logger
.
info
(
'Copying to %r, and setting minimum privileges'
,
conf
.
certificate_path
)
key_file
=
os
.
path
.
join
(
user_certificate_repository_path
,
'key'
)
cert_file
=
os
.
path
.
join
(
user_certificate_repository_path
,
'certificate'
)
for
src
,
dst
in
[(
conf
.
key
,
key_file
),
(
conf
.
certificate
,
cert_file
)]:
conf
.
logger
.
info
(
'Copying to %r, and setting minimum privileges'
,
dst
)
if
not
dry_run
:
with
open
(
conf
.
certificate_path
,
'w'
)
as
destination
:
with
open
(
dst
,
'w'
)
as
destination
:
destination
.
write
(
''
.
join
(
src
))
os
.
chmod
(
conf
.
certificate_path
,
0o600
)
os
.
chown
(
conf
.
certificate_path
,
0
,
0
)
os
.
chmod
(
dst
,
0o600
)
os
.
chown
(
dst
,
0
,
0
)
certificate_repository_path
=
os
.
path
.
join
(
slap_conf_dir
,
'ssl'
,
'partition_pki'
)
if
not
os
.
path
.
exists
(
certificate_repository_path
):
...
...
@@ -299,6 +306,7 @@ class RegisterConfig(object):
self
.
logger
=
logger
self
.
computer_id
=
None
self
.
certificate
=
None
self
.
dry_run
=
False
def
setConfig
(
self
,
options
):
"""
...
...
@@ -308,11 +316,12 @@ class RegisterConfig(object):
for
option
,
value
in
options
.
__dict__
.
items
():
setattr
(
self
,
option
,
value
)
def
COMPConfig
(
self
,
slapos_configuration
):
def
COMPConfig
(
self
,
slapos_configuration
,
key
):
ssl_path
=
os
.
path
.
join
(
slapos_configuration
,
'ssl'
)
self
.
slapos_configuration
=
slapos_configuration
self
.
certificate_path
=
os
.
path
.
join
(
ssl_path
,
'certificate'
)
self
.
key_path
=
os
.
path
.
join
(
ssl_path
,
'key'
)
self
.
key
=
key
def
displayUserConfig
(
self
):
self
.
logger
.
debug
(
'Computer Name: %s'
,
self
.
node_name
)
...
...
@@ -339,20 +348,10 @@ def do_register(conf):
"""Register new computer on SlapOS Master and generate slapos.cfg"""
# Getting configuration parameters
conf
.
COMPConfig
(
slapos_configuration
=
'/etc/opt/slapos/'
)
# create certificate authority client
ca_client
=
CertificateAuthorityRequest
(
conf
.
key_path
,
conf
.
certificate_path
,
ca_cert_path
,
ca_url
=
''
)
conf
.
COMPConfig
(
slapos_configuration
=
'/etc/opt/slapos/'
,
key
=
generatePkey
(
size
=
2048
))
conf
.
logger
.
info
(
'Generating private key to %s'
,
conf
.
key_path
)
ca_client
.
generatePrivatekey
(
conf
.
key_path
,
size
=
2048
)
csr_string
=
ca_client
.
generateCertificateRequest
(
conf
.
key_path
,
cn
=
str
(
uuid
.
uuid4
()))
csr_string
=
generateCertificateRequest
(
conf
.
key
,
cn
=
str
(
uuid
.
uuid4
()))
if
conf
.
login
or
conf
.
login_auth
:
for
login
,
password
in
gen_auth
(
conf
):
...
...
@@ -388,6 +387,6 @@ def do_register(conf):
# Prepare Slapos Configuration
slapconfig
(
conf
)
conf
.
logger
.
info
(
'Node has successfully been configured as %s.'
,
COMP
)
conf
.
logger
.
info
(
'Node has successfully been configured as %s.'
,
computer_id
)
conf
.
logger
.
info
(
'Now please invoke slapos node boot on your site.'
)
return
0
slapos/grid/SlapObject.py
View file @
5d1130cf
...
...
@@ -38,6 +38,7 @@ import tarfile
import
tempfile
import
time
import
xmlrpclib
import
uuid
from
supervisor
import
xmlrpc
...
...
@@ -50,6 +51,7 @@ from slapos.grid.exception import (BuildoutFailedError, WrongPermissionError,
PathDoesNotExistError
,
DiskSpaceError
)
from
slapos.grid.networkcache
import
download_network_cached
,
upload_network_cached
from
slapos.human
import
bytes2human
from
slapos.certificate
import
generateCertificateRequest
,
generatePrivatekey
WATCHDOG_MARK
=
'-on-watch'
...
...
@@ -405,15 +407,18 @@ class Partition(object):
required
=
bytes2human
(
required
)))
def
_updateCertificate
(
self
):
key_string
=
generatePrivatekey
(
self
.
key_file
)
csr_string
=
generateCertificateRequest
(
key_string
,
cn
=
str
(
uuid
.
uuid4
()))
try
:
partition_certificate
=
self
.
computer_partition
.
getCertificate
()
partition_certificate
=
self
.
computer_partition
.
getCertificate
(
certificate_request
=
csr_string
)
except
NotFoundError
:
raise
NotFoundError
(
'Partition %s is not known by SlapOS Master.'
%
self
.
partition_id
)
uid
,
gid
=
self
.
getUserGroupId
()
for
name
,
path
in
[(
'certificate'
,
self
.
cert_file
)
,
(
'key'
,
self
.
key_file
)
]:
for
name
,
path
in
[(
'certificate'
,
self
.
cert_file
)]:
new_content
=
partition_certificate
[
name
]
old_content
=
None
if
os
.
path
.
exists
(
path
):
...
...
slapos/slap/slap.py
View file @
5d1130cf
...
...
@@ -372,9 +372,9 @@ class Computer(SlapDocument):
self
.
_connection_helper
.
POST
(
'revokeComputerCertificate'
,
data
=
{
'computer_id'
:
self
.
_computer_id
})
def
generateCertificate
(
self
):
def
generateCertificate
(
self
,
certificate_request
):
xml
=
self
.
_connection_helper
.
POST
(
'generateComputerCertificate'
,
data
=
{
'computer_id'
:
self
.
_computer_id
})
'computer_id'
:
self
.
_computer_id
,
certificate_request
=
certificate_request
})
return
xml_marshaller
.
loads
(
xml
)
...
...
@@ -641,11 +641,12 @@ class ComputerPartition(SlapRequester):
# XXX: this implementation has not been reviewed
self
.
usage
=
usage_log
def
getCertificate
(
self
):
def
getCertificate
(
self
,
certificate_request
=
None
):
xml
=
self
.
_connection_helper
.
GET
(
'getComputerPartitionCertificate'
,
params
=
{
'computer_id'
:
self
.
_computer_id
,
'computer_partition_id'
:
self
.
_partition_id
,
'certificate_request'
:
certificate_request
,
}
)
return
xml_marshaller
.
loads
(
xml
)
...
...
slapos/util.py
View file @
5d1130cf
...
...
@@ -31,6 +31,7 @@ import errno
import
os
import
subprocess
import
sqlite3
import
re
def
mkdir_p
(
path
,
mode
=
0o700
):
...
...
@@ -60,18 +61,6 @@ def chownDirectory(path, uid, gid):
])
def
parse_certificate_from_html
(
html
):
"""
Extract certificate from an HTML page received by SlapOS Master.
"""
c_start
=
html
.
find
(
"Certificate:"
)
c_end
=
html
.
find
(
"</textarea>"
,
c_start
)
certificate
=
html
[
c_start
:
c_end
]
return
certificate
def
string_to_boolean
(
string
):
"""
Return True if the value of the "string" parameter can be parsed as True.
...
...
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