Debugged/fixed revoked key file generation.

This commit is contained in:
Pino de Candia 2018-01-20 08:23:16 +00:00
parent 0b207f6123
commit 4450ba773f
5 changed files with 33 additions and 36 deletions

8
scripts/revoke-user-cert Normal file → Executable file
View File

@ -21,7 +21,7 @@ from Crypto.PublicKey import RSA
parser = argparse.ArgumentParser(description='Revoke a Tatu-generated user SSH certificate.')
parser.add_argument('--projid', '-P', required=True)
parser.add_argument('--serial', '-K', required=True)
parser.add_argument('--serial', '-S', required=True)
parser.add_argument('--tatu-url', default= 'http://127.0.0.1:18322',
help='URL of the Tatu API')
args = parser.parse_args()
@ -38,12 +38,6 @@ if not args.serial.isdigit():
server = args.tatu_url
body = {
'serial': args.serial,
'auth_id': auth_id,
'key.pub': pubkeytext
}
response = requests.post(
server + '/revokeduserkeys/' + auth_id,
data=json.dumps({'serial': args.serial})

View File

@ -12,7 +12,7 @@
import falcon
from oslo_log import log as logging
from tatu import models
from tatu.api import models
from tatu.db.persistence import SQLAlchemySessionManager
LOG = logging.getLogger(__name__)

View File

@ -311,7 +311,7 @@ class RevokedUserKeys(object):
self.session,
auth_id,
serial=req.body.get('serial', None),
key=req.body.get('key_id', None),
key_id=req.body.get('key_id', None),
cert=req.body.get('cert', None)
)
resp.status = falcon.HTTP_OK

View File

@ -67,16 +67,20 @@ def createAuthority(session, auth_id):
class UserCert(Base):
__tablename__ = 'user_certs'
user_id = sa.Column(sa.String(36), primary_key=True)
fingerprint = sa.Column(sa.String(60), primary_key=True)
serial = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
user_id = sa.Column(sa.String(36))
fingerprint = sa.Column(sa.String(60))
auth_id = sa.Column(sa.String(36), sa.ForeignKey('authorities.auth_id'))
cert = sa.Column(sa.Text)
serial = sa.Column(sa.Integer, index=True, autoincrement=True)
revoked = sa.Column(sa.Boolean, default=False)
sa.Index('idx_user_finger', UserCert.user_id, UserCert.fingerprint, unique=True)
def getUserCert(session, user_id, fingerprint):
return session.query(UserCert).get([user_id, fingerprint])
return session.query(UserCert).filter(
UserCert.user_id == user_id).filter(
UserCert.fingerprint == fingerprint).one_or_none()
def getUserCerts(session):
@ -90,21 +94,22 @@ def createUserCert(session, user_id, auth_id, pub):
raise falcon.HTTPNotFound(
description='No Authority found with that ID')
fingerprint = sshpubkeys.SSHKey(pub).hash_md5()
certRecord = session.query(UserCert).get([user_id, fingerprint])
certRecord = getUserCert(session, user_id, fingerprint)
if certRecord is not None:
return certRecord
cert = generateCert(getAuthUserKey(auth), pub,
principals='admin,root')
if cert is None:
raise falcon.HTTPInternalServerError(
"Failed to generate the certificate")
user = UserCert(
user_id=user_id,
fingerprint=fingerprint,
auth_id=auth_id,
cert=cert
)
session.add(user)
session.flush()
user.cert = generateCert(getAuthUserKey(auth), pub, user=True,
principals='admin,root', serial=user.serial)
if user.cert is None:
raise falcon.HTTPInternalServerError(
"Failed to generate the certificate")
session.commit()
return user
@ -124,7 +129,9 @@ def getRevokedKeysBase64(session, auth_id):
description='No Authority found with that ID')
serials = [k.serial for k in session.query(RevokedKey).filter(
RevokedKey.auth_id == auth_id)]
return revokedKeysBase64(getAuthUserKey(auth), serials)
user_key = RSA.importKey(getAuthUserKey(auth))
user_pub_key = user_key.publickey().exportKey('OpenSSH')
return revokedKeysBase64(user_pub_key, serials)
def revokeUserKey(session, auth_id, serial=None, key_id=None, cert=None):
@ -140,7 +147,7 @@ def revokeUserKey(session, auth_id, serial=None, key_id=None, cert=None):
raise falcon.HTTPBadRequest(
"Incorrect CA ID for serial # {}".format(serial))
ser = serial
elif key is not None:
elif key_id is not None:
# TODO(pino): look up the UserCert by key id and get the serial number
pass
elif cert is not None:
@ -242,8 +249,7 @@ def createHostCert(session, token_id, host_id, pub):
certRecord = session.query(HostCert).get([host_id, fingerprint])
if certRecord is not None:
raise falcon.HTTPConflict('This public key is already signed.')
cert = generateCert(getAuthHostKey(auth), pub,
hostname=token.hostname)
cert = generateCert(getAuthHostKey(auth), pub, user=False)
if cert == '':
raise falcon.HTTPInternalServerError(
"Failed to generate the certificate")

View File

@ -22,7 +22,7 @@ def random_uuid():
return str(uuid.uuid4())
def generateCert(auth_key, entity_key, hostname=None, principals='root'):
def generateCert(auth_key, entity_key, user=True, principals='root', serial=0):
# Temporarily write the authority private key, entity public key to files
temp_dir = mkdtemp()
ca_file = '/'.join([temp_dir, 'ca_key'])
@ -37,8 +37,8 @@ def generateCert(auth_key, entity_key, hostname=None, principals='root'):
with open(pub_file, "w", 0o644) as text_file:
text_file.write(entity_key)
args = ['ssh-keygen', '-s', ca_file, '-I', 'testID', '-V',
'-1d:+365d']
if hostname is None:
'-1d:+365d', '-z', str(serial)]
if user:
args.extend(['-n', principals, pub_file])
else:
args.extend(['-h', pub_file])
@ -51,22 +51,19 @@ def generateCert(auth_key, entity_key, hostname=None, principals='root'):
return cert
def revokedKeysBase64(auth_key, serial_list):
def revokedKeysBase64(ca_public, serial_list):
# Temporarily write the authority private key and list of serials
temp_dir = mkdtemp()
ca_file = '/'.join([temp_dir, 'ca_key'])
ca_file = '/'.join([temp_dir, 'ca_public'])
serials_file = '/'.join([temp_dir, 'serials'])
revoked_file = '/'.join([temp_dir, 'revoked'])
try:
fd = os.open(ca_file, os.O_WRONLY | os.O_CREAT, 0o600)
os.close(fd)
with open(ca_file, "w") as text_file:
text_file.write(auth_key)
with open(ca_file, "w", 0o644) as text_file:
text_file.write(ca_public)
with open(serials_file, "w", 0o644) as text_file:
for s in serial_list:
text_file.write("serial: " + s + "\n")
args = ['ssh-keygen', '-s', ca_file, '-k', '-f', revoked_file,
serials_file]
text_file.write("serial: {}\n".format(s))
args = ['ssh-keygen', '-k', '-f', revoked_file, '-s', ca_file, serials_file]
subprocess.check_output(args, stderr=subprocess.STDOUT)
# Return the base64 encoded contents of the revoked keys file
with open(revoked_file, 'r') as text_file: