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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Roque
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,
...
@@ -48,6 +48,7 @@ setup(name=name,
'netifaces'
,
# to fetch information about network devices
'netifaces'
,
# to fetch information about network devices
'setuptools'
,
# namespaces
'setuptools'
,
# namespaces
'supervisor'
,
# slapgrid uses supervisor to manage processes
'supervisor'
,
# slapgrid uses supervisor to manage processes
'pyOpenSSL'
,
# manage ssl certificates
'psutil>=2.0.0'
,
'psutil>=2.0.0'
,
'xml_marshaller>=0.9.3'
,
# to unmarshall/marshall python objects to/from
'xml_marshaller>=0.9.3'
,
# to unmarshall/marshall python objects to/from
# XML
# XML
...
@@ -56,7 +57,6 @@ setup(name=name,
...
@@ -56,7 +57,6 @@ setup(name=name,
'cliff'
,
'cliff'
,
'requests>=2.4.3'
,
'requests>=2.4.3'
,
'six'
,
'six'
,
'caucase'
,
# used to manage ca client request
'uritemplate'
,
# used by hateoas navigator
'uritemplate'
,
# used by hateoas navigator
]
+
additional_install_requires
,
]
+
additional_install_requires
,
extras_require
=
{
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
...
@@ -36,7 +36,10 @@ import requests
from
caucase.cli_flask
import
CertificateAuthorityRequest
from
caucase.cli_flask
import
CertificateAuthorityRequest
from
slapos.cli.config
import
ClientConfigCommand
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
):
class
ConfigureClientCommand
(
ClientConfigCommand
):
...
@@ -138,9 +141,9 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url):
...
@@ -138,9 +141,9 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url):
ca_url
=
''
)
ca_url
=
''
)
logger
.
debug
(
'Generating key to %s'
,
key_path
)
logger
.
debug
(
'Generating key to %s'
,
key_path
)
ca_client
.
generatePrivatekey
(
key_path
,
size
=
2048
)
key_string
=
generatePrivatekey
(
key_path
,
size
=
2048
)
csr_string
=
ca_client
.
generateCertificateRequest
(
csr_string
=
generateCertificateRequest
(
key_
path
,
key_
string
,
cn
=
str
(
uuid
.
uuid4
()))
cn
=
str
(
uuid
.
uuid4
()))
# retrieve a template for the configuration file
# retrieve a template for the configuration file
...
...
slapos/cli/register.py
View file @
5d1130cf
...
@@ -37,9 +37,10 @@ import pkg_resources
...
@@ -37,9 +37,10 @@ import pkg_resources
import
requests
import
requests
import
uuid
import
uuid
from
caucase.cli_flask
import
CertificateAuthorityRequest
from
slapos.cli.command
import
Command
,
must_be_root
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
):
class
RegisterCommand
(
Command
):
...
@@ -183,8 +184,10 @@ def sign_certificate(logger, master_url_web, node_name, csr_string,
...
@@ -183,8 +184,10 @@ def sign_certificate(logger, master_url_web, node_name, csr_string,
else
:
else
:
req
.
raise_for_status
()
req
.
raise_for_status
()
certificate
=
parse_certificate_from_html
(
req
.
text
)
return
(
get_computer_name
(
req
.
text
),
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
):
def
get_computer_name
(
text_string
):
...
@@ -247,12 +250,16 @@ def slapconfig(conf):
...
@@ -247,12 +250,16 @@ def slapconfig(conf):
if
not
dry_run
:
if
not
dry_run
:
os
.
mkdir
(
user_certificate_repository_path
,
0o711
)
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
:
if
not
dry_run
:
with
open
(
conf
.
certificate_path
,
'w'
)
as
destination
:
with
open
(
dst
,
'w'
)
as
destination
:
destination
.
write
(
''
.
join
(
src
))
destination
.
write
(
''
.
join
(
src
))
os
.
chmod
(
conf
.
certificate_path
,
0o600
)
os
.
chmod
(
dst
,
0o600
)
os
.
chown
(
conf
.
certificate_path
,
0
,
0
)
os
.
chown
(
dst
,
0
,
0
)
certificate_repository_path
=
os
.
path
.
join
(
slap_conf_dir
,
'ssl'
,
'partition_pki'
)
certificate_repository_path
=
os
.
path
.
join
(
slap_conf_dir
,
'ssl'
,
'partition_pki'
)
if
not
os
.
path
.
exists
(
certificate_repository_path
):
if
not
os
.
path
.
exists
(
certificate_repository_path
):
...
@@ -299,6 +306,7 @@ class RegisterConfig(object):
...
@@ -299,6 +306,7 @@ class RegisterConfig(object):
self
.
logger
=
logger
self
.
logger
=
logger
self
.
computer_id
=
None
self
.
computer_id
=
None
self
.
certificate
=
None
self
.
certificate
=
None
self
.
dry_run
=
False
def
setConfig
(
self
,
options
):
def
setConfig
(
self
,
options
):
"""
"""
...
@@ -308,11 +316,12 @@ class RegisterConfig(object):
...
@@ -308,11 +316,12 @@ class RegisterConfig(object):
for
option
,
value
in
options
.
__dict__
.
items
():
for
option
,
value
in
options
.
__dict__
.
items
():
setattr
(
self
,
option
,
value
)
setattr
(
self
,
option
,
value
)
def
COMPConfig
(
self
,
slapos_configuration
):
def
COMPConfig
(
self
,
slapos_configuration
,
key
):
ssl_path
=
os
.
path
.
join
(
slapos_configuration
,
'ssl'
)
ssl_path
=
os
.
path
.
join
(
slapos_configuration
,
'ssl'
)
self
.
slapos_configuration
=
slapos_configuration
self
.
slapos_configuration
=
slapos_configuration
self
.
certificate_path
=
os
.
path
.
join
(
ssl_path
,
'certificate'
)
self
.
certificate_path
=
os
.
path
.
join
(
ssl_path
,
'certificate'
)
self
.
key_path
=
os
.
path
.
join
(
ssl_path
,
'key'
)
self
.
key_path
=
os
.
path
.
join
(
ssl_path
,
'key'
)
self
.
key
=
key
def
displayUserConfig
(
self
):
def
displayUserConfig
(
self
):
self
.
logger
.
debug
(
'Computer Name: %s'
,
self
.
node_name
)
self
.
logger
.
debug
(
'Computer Name: %s'
,
self
.
node_name
)
...
@@ -339,20 +348,10 @@ def do_register(conf):
...
@@ -339,20 +348,10 @@ def do_register(conf):
"""Register new computer on SlapOS Master and generate slapos.cfg"""
"""Register new computer on SlapOS Master and generate slapos.cfg"""
# Getting configuration parameters
# Getting configuration parameters
conf
.
COMPConfig
(
slapos_configuration
=
'/etc/opt/slapos/'
)
conf
.
COMPConfig
(
slapos_configuration
=
'/etc/opt/slapos/'
,
key
=
generatePkey
(
size
=
2048
))
# create certificate authority client
ca_client
=
CertificateAuthorityRequest
(
conf
.
key_path
,
conf
.
certificate_path
,
ca_cert_path
,
ca_url
=
''
)
conf
.
logger
.
info
(
'Generating private key to %s'
,
conf
.
key_path
)
csr_string
=
generateCertificateRequest
(
conf
.
key
,
cn
=
str
(
uuid
.
uuid4
()))
ca_client
.
generatePrivatekey
(
conf
.
key_path
,
size
=
2048
)
csr_string
=
ca_client
.
generateCertificateRequest
(
conf
.
key_path
,
cn
=
str
(
uuid
.
uuid4
()))
if
conf
.
login
or
conf
.
login_auth
:
if
conf
.
login
or
conf
.
login_auth
:
for
login
,
password
in
gen_auth
(
conf
):
for
login
,
password
in
gen_auth
(
conf
):
...
@@ -388,6 +387,6 @@ def do_register(conf):
...
@@ -388,6 +387,6 @@ def do_register(conf):
# Prepare Slapos Configuration
# Prepare Slapos Configuration
slapconfig
(
conf
)
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.'
)
conf
.
logger
.
info
(
'Now please invoke slapos node boot on your site.'
)
return
0
return
0
slapos/grid/SlapObject.py
View file @
5d1130cf
...
@@ -38,6 +38,7 @@ import tarfile
...
@@ -38,6 +38,7 @@ import tarfile
import
tempfile
import
tempfile
import
time
import
time
import
xmlrpclib
import
xmlrpclib
import
uuid
from
supervisor
import
xmlrpc
from
supervisor
import
xmlrpc
...
@@ -50,6 +51,7 @@ from slapos.grid.exception import (BuildoutFailedError, WrongPermissionError,
...
@@ -50,6 +51,7 @@ from slapos.grid.exception import (BuildoutFailedError, WrongPermissionError,
PathDoesNotExistError
,
DiskSpaceError
)
PathDoesNotExistError
,
DiskSpaceError
)
from
slapos.grid.networkcache
import
download_network_cached
,
upload_network_cached
from
slapos.grid.networkcache
import
download_network_cached
,
upload_network_cached
from
slapos.human
import
bytes2human
from
slapos.human
import
bytes2human
from
slapos.certificate
import
generateCertificateRequest
,
generatePrivatekey
WATCHDOG_MARK
=
'-on-watch'
WATCHDOG_MARK
=
'-on-watch'
...
@@ -405,15 +407,18 @@ class Partition(object):
...
@@ -405,15 +407,18 @@ class Partition(object):
required
=
bytes2human
(
required
)))
required
=
bytes2human
(
required
)))
def
_updateCertificate
(
self
):
def
_updateCertificate
(
self
):
key_string
=
generatePrivatekey
(
self
.
key_file
)
csr_string
=
generateCertificateRequest
(
key_string
,
cn
=
str
(
uuid
.
uuid4
()))
try
:
try
:
partition_certificate
=
self
.
computer_partition
.
getCertificate
()
partition_certificate
=
self
.
computer_partition
.
getCertificate
(
certificate_request
=
csr_string
)
except
NotFoundError
:
except
NotFoundError
:
raise
NotFoundError
(
'Partition %s is not known by SlapOS Master.'
%
raise
NotFoundError
(
'Partition %s is not known by SlapOS Master.'
%
self
.
partition_id
)
self
.
partition_id
)
uid
,
gid
=
self
.
getUserGroupId
()
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
]
new_content
=
partition_certificate
[
name
]
old_content
=
None
old_content
=
None
if
os
.
path
.
exists
(
path
):
if
os
.
path
.
exists
(
path
):
...
...
slapos/slap/slap.py
View file @
5d1130cf
...
@@ -372,9 +372,9 @@ class Computer(SlapDocument):
...
@@ -372,9 +372,9 @@ class Computer(SlapDocument):
self
.
_connection_helper
.
POST
(
'revokeComputerCertificate'
,
data
=
{
self
.
_connection_helper
.
POST
(
'revokeComputerCertificate'
,
data
=
{
'computer_id'
:
self
.
_computer_id
})
'computer_id'
:
self
.
_computer_id
})
def
generateCertificate
(
self
):
def
generateCertificate
(
self
,
certificate_request
):
xml
=
self
.
_connection_helper
.
POST
(
'generateComputerCertificate'
,
data
=
{
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
)
return
xml_marshaller
.
loads
(
xml
)
...
@@ -641,11 +641,12 @@ class ComputerPartition(SlapRequester):
...
@@ -641,11 +641,12 @@ class ComputerPartition(SlapRequester):
# XXX: this implementation has not been reviewed
# XXX: this implementation has not been reviewed
self
.
usage
=
usage_log
self
.
usage
=
usage_log
def
getCertificate
(
self
):
def
getCertificate
(
self
,
certificate_request
=
None
):
xml
=
self
.
_connection_helper
.
GET
(
'getComputerPartitionCertificate'
,
xml
=
self
.
_connection_helper
.
GET
(
'getComputerPartitionCertificate'
,
params
=
{
params
=
{
'computer_id'
:
self
.
_computer_id
,
'computer_id'
:
self
.
_computer_id
,
'computer_partition_id'
:
self
.
_partition_id
,
'computer_partition_id'
:
self
.
_partition_id
,
'certificate_request'
:
certificate_request
,
}
}
)
)
return
xml_marshaller
.
loads
(
xml
)
return
xml_marshaller
.
loads
(
xml
)
...
...
slapos/util.py
View file @
5d1130cf
...
@@ -31,6 +31,7 @@ import errno
...
@@ -31,6 +31,7 @@ import errno
import
os
import
os
import
subprocess
import
subprocess
import
sqlite3
import
sqlite3
import
re
def
mkdir_p
(
path
,
mode
=
0o700
):
def
mkdir_p
(
path
,
mode
=
0o700
):
...
@@ -60,18 +61,6 @@ def chownDirectory(path, uid, gid):
...
@@ -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
):
def
string_to_boolean
(
string
):
"""
"""
Return True if the value of the "string" parameter can be parsed as True.
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