def test_ssh_key_bits_and_fingerprint(self): with self.assertRaises(sshpubkeys.InvalidKeyException): sshpubkeys.SSHKey('an invalid key string') valid_ssh_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3uta/x/kAwbs2G7AOUQtRG7l1hjEws4mrvnTZmwICoGNi+TUwxerZgMbBBID7Kpza/ZSUqXpKX5gppRW9zECBsbJ+2D0ch/oVSZ408aUE6ePNzJilLA/2wtRct/bkHDZOVI+iwEEr1IunjceF+ZQxnylUv44C6SgZvrDj+38hz8z1Vf4BtW5jGOhHkddTadU7Nn4jQR3aFXMoheuu/vHYD2OyDJj/r6vh9x5ey8zFmwsGDtFCCzzLgcfPYfOdDxFIWhsopebnH3QHVcs/E0KqhocsEdFDRvcFgsDCKwmtHyZVAOKym2Pz9TfnEdGeb+eKrleZVsApFrGtSIfcf4pH user@host' ssh_key = sshpubkeys.SSHKey(valid_ssh_key) self.assertEqual(ssh_key.bits, 2048) self.assertEqual(ssh_key.hash(), '73:e7:0c:60:7b:d2:7b:df:81:2e:c2:57:54:53:81:91')
def test_stress_post_token_and_host(client): my_auth_id = random_uuid() test_post_authority(client, my_auth_id) # Generate a single RSA key pair and reuse it - it takes a few seconds. key = RSA.generate(2048) pub_key = key.publickey().exportKey('OpenSSH') fingerprint = sshpubkeys.SSHKey(pub_key).hash_md5() # Should do about 15 iterations/second, so only do 4 seconds worth. start = time.time() for i in range(60): hid = random_uuid() token = token_request(auth=my_auth_id, host=hid) response = client.simulate_post('/hosttokens', body=json.dumps(token)) assert response.status == falcon.HTTP_CREATED assert 'location' in response.headers location_path = response.headers['location'].split('/') assert location_path[1] == 'hosttokens' token_id = location_path[-1] # Verify that it's a valid UUID uuid.UUID(token_id, version=4) host = host_request(token_id, host=hid, pub_key=pub_key) response = client.simulate_post('/hostcerts', body=json.dumps(host)) assert response.status == falcon.HTTP_CREATED assert 'location' in response.headers location = response.headers['location'].split('/') assert location[1] == 'hostcerts' assert location[2] == hid assert location[3] == fingerprint assert time.time() - start < 5
def add_public_key(session, user, public_key_str): """Add a public key for a particular user. Args: session: db session user: User model of user in question public_key_str: public key to add Return created PublicKey model or raises DuplicateKey if key is already in use. """ pubkey = sshpubkeys.SSHKey(public_key_str, strict=True) pubkey.parse() db_pubkey = PublicKey( user=user, public_key=pubkey.keydata.strip(), fingerprint=pubkey.hash_md5().replace(b"MD5:", b""), key_size=pubkey.bits, key_type=pubkey.key_type, ) try: db_pubkey.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() raise DuplicateKey() session.commit() return db_pubkey
def save(self, *args, **kwargs): self.key = self.key.strip() if self.key else self.key k = sshpubkeys.SSHKey(self.key) self.bits = k.bits self.fingerprint = k.hash() self.full_clean() super(SSHKey, self).save(*args, **kwargs)
def min_bits(self): """ The minimum number of bits considered secure for the type of this key. """ k = sshpubkeys.SSHKey(self.key) return settings.SSH_KEY_MIN_BITS_FOR_TYPE.get( k.key_type, settings.SSH_KEY_MIN_BITS_DEFAULT)
def get_bitbucket_users(self): uname = self.conf['username'] appwd = self.conf['password'] email = self.conf['email'] auth = BasicAuthenticator(uname, appwd, email) bitbucket = Client(auth) teams = Team.find_teams_for_role(role="admin", client=bitbucket) for t in teams: for m in t.members(): pprint(m) login = m['nickname'] name = m['display_name'] email = '' self.init_user(login, name, email) r = requests.get("{}/users/{}/ssh-keys".format( BitbucketConn.v1url, login), auth=(uname, appwd)) if r.status_code == 200: key_response = r.json() for keyvalue in key_response['values']: key = sshpubkeys.SSHKey(keyvalue['key']) fingerprint = key.hash_md5() self.user_list[login][PUBKEYS][fingerprint] = keyvalue[ 'key'] else: print(r.status_code)
def is_ok(self, key: str): """ Args: key (str): the ssh key to check. Returns: bool: is the key ok or not. """ if key == '': return False ssh_key = sshpubkeys.SSHKey(key) try: ssh_key.parse() except sshpubkeys.InvalidKeyError as err: logging.error("Invalid key: {}".format(err)) return False except NotImplementedError as err: logging.error("Invalid key type: {}".format(err)) return False if ssh_key.key_type == b'ssh-rsa' and ssh_key.bits < self.rsa_key_size: logging.error( "Invalid key: minimum key size for RSA is {} bits".format( self.rsa_key_size)) return False elif ssh_key.key_type in (b'ssh-ed25519', b'ssh-rsa'): return True else: logging.error("Skipping unsupported key type {}".format( ssh_key.key_type)) return False
def public_key_obj(self): if self.public_key: try: return sshpubkeys.SSHKey(self.public_key) except TabError: pass return None
def ssh_keys_POST(): user = User.query.get(current_user.id) valid = Validation(request) ssh_key = valid.require("ssh-key") if valid.ok: try: parsed_key = ssh.SSHKey(ssh_key) valid.expect(parsed_key.bits, "This is not a valid SSH key", "ssh-key") except: valid.error("This is not a valid SSH key", "ssh-key") if valid.ok: fingerprint = parsed_key.hash_md5()[4:] valid.expect(SSHKey.query\ .filter(SSHKey.fingerprint == fingerprint) \ .count() == 0, "We already have this SSH key on file.", "ssh-key") if not valid.ok: return render_template("keys.html", current_user=user, ssh_key=ssh_key, valid=valid) key = SSHKey(user, ssh_key, fingerprint, parsed_key.comment) db.session.add(key) audit_log("ssh key added", 'Added SSH key {}'.format(fingerprint)) db.session.commit() return redirect("/keys")
def get_github_users(self): username = self.conf['username'] password = self.conf['password'] g = Github(username, password) for member in g.get_organization(self.organization).get_members(): login = member.login.lower() name = member.name email = member.email self.init_user(login, name, email) if member.get_keys().totalCount < 1: print( "Skipping {}. User doesn't have an SSH key associated with his github account.. " .format(login)) continue if not self.valid_login(login): print("Skipping {}, GitHub account is considered invalid.". format(login)) continue for userkey in member.get_keys(): key = sshpubkeys.SSHKey(userkey.key) fingerprint = key.hash_md5() self.user_list[login][PUBKEYS][fingerprint] = userkey.key
def post(self, request, **kwargs): #pylint:disable=all if hasattr(request.data, '_mutable'): request.data._mutable = True #pylint:disable=protected-access #1. Create the account serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() #2. Create it's SSH key account = Account.objects.get(username=serializer.data['username'], email=serializer.data['email']) key = RSA.generate(4096) model = SSHKey(name='default', owner=account.username, public=key.exportKey('OpenSSH'), fingerprint=sshpubkeys.SSHKey( key.exportKey('OpenSSH')).hash_md5()) model.user_creation = True model.organization_creation = True model.save() key = { 'name': model.name, 'private': key.exportKey('PEM'), 'public': model.public, 'fingerprint': model.fingerprint } return Response({ 'account': serializer.data, 'key': key }, status=status.HTTP_201_CREATED)
def createUserCert(session, user_id, user_name, auth_id, pub): # Retrieve the authority's private key and generate the certificate auth = getAuthority(session, auth_id) if auth is None: raise falcon.HTTPNotFound( description='No Authority found with that ID') fingerprint = sshpubkeys.SSHKey(pub).hash_md5() certRecord = getUserCert(session, user_id, fingerprint) if certRecord is not None: return certRecord principals = getProjectRoleNamesForUser(auth_id, user_id) user = UserCert( user_id=user_id, user_name=user_name, principals=','.join(principals), fingerprint=fingerprint, auth_id=auth_id, ) session.add(user) session.flush() user.cert = generateCert(get_secret(auth.user_key), pub, user=True, principal_list=principals, serial=user.serial, days_valid=365, identity=user_name) if user.cert is None: raise falcon.HTTPInternalServerError( "Failed to generate the certificate") session.commit() return user
def validate_ssh_public_key(text): ssh = sshpubkeys.SSHKey(text) try: ssh.parse() except (sshpubkeys.InvalidKeyException, UnicodeDecodeError): return False except NotImplementedError as e: return False return True
def test_post_user(client): body = user_request() response = client.simulate_post('/usercerts', body=json.dumps(body)) assert response.status == falcon.HTTP_CREATED assert 'location' in response.headers location = response.headers['location'].split('/') assert location[1] == 'usercerts' assert location[2] == body['user_id'] assert location[3] == sshpubkeys.SSHKey(body['pub_key']).hash_md5()
def ssh_public_key_validator(public_key): ''' validate public key string ''' try: key = sshpubkeys.SSHKey(public_key) key.parse() except (sshpubkeys.InvalidKeyError, sshpubkeys.exceptions.MalformedDataError, UnicodeEncodeError) as exc: LOGGER.exception(exc) raise ValidationError('Malformed SSH Public Key')
def test_post_second_cert_same_user(client): key = RSA.generate(2048) pub_key = key.publickey().exportKey('OpenSSH') body = user_request(pub_key=pub_key) response = client.simulate_post('/usercerts', body=json.dumps(body)) assert response.status == falcon.HTTP_CREATED assert 'location' in response.headers location = response.headers['location'].split('/') assert location[1] == 'usercerts' assert location[2] == user_id assert location[3] == sshpubkeys.SSHKey(pub_key).hash_md5()
def public_key_obj(self): class PubKey(object): def __getattr__(self, item): return '' if self.public_key: import sshpubkeys try: return sshpubkeys.SSHKey(self.public_key) except (TabError, TypeError): pass return PubKey()
def validate_pubkey(pubkey): # TODO see if I can get the type out key = ssh.SSHKey(pubkey, strict_mode=False, skip_option_parsing=True) try: key.parse() except ssh.InvalidKeyException as e: raise ValidationError('Could not validate key: {}'.format(e)) except NotImplementedError as e: raise ValidationError('Invalid key type') except Exception as e: raise ValidationError('unknown error: {}'.format(e))
def check_ssh_key(key_path: str) -> bool: if key_path and os.path.exists(key_path): with open(key_path) as key: contents = key.read() key = sshpubkeys.SSHKey(contents) try: key.parse() except (sshpubkeys.InvalidKeyError, NotImplementedError) as e: return False return True return False
def ssh_key_fingerprint(self): if self.public_key: public_key = self.public_key elif self.private_key: public_key = ssh_pubkey_gen(self.private_key, self.password) else: return '' public_key_obj = sshpubkeys.SSHKey(public_key) fingerprint = public_key_obj.hash_md5() return fingerprint
def _parse_public_key(self): """parse publickey and update fiels""" key = sshpubkeys.SSHKey(self.public_key) key.parse() self.type = key.key_type.decode('utf-8').replace('ssh-', '') self.bits = key.bits self.fingerprint = key.hash_sha256() self.comment = key.comment LOGGER.debug(self.__dict__)
def createHostCert(session, token_id, host_id, pub): token = session.query(Token).get(token_id) if token is None: raise falcon.HTTPNotFound(description='No Token found with that ID') if token.host_id != host_id: raise falcon.HTTPConflict( description='The token is not valid for this instance ID') fingerprint = sshpubkeys.SSHKey(pub).hash_md5() if token.used: if token.fingerprint_used != fingerprint: raise falcon.HTTPConflict( description='Token already signed a different public key') # The token was already used for same host and pub key. Return record. host = session.query(HostCert).get([host_id, fingerprint]) if host is None: raise falcon.HTTPInternalServerError( description='Token already used, but Host record not found.') if host.token_id == token_id: return host raise falcon.HTTPConflict( description='The presented token was previously used') auth = getAuthority(session, token.auth_id) if auth is None: raise falcon.HTTPNotFound( description='No Authority found with that ID') certRecord = session.query(HostCert).get([host_id, fingerprint]) if certRecord is not None: raise falcon.HTTPConflict('This public key is already signed.') cert = generateCert(get_secret(auth.host_key), pub, user=False, days_valid=365, identity=token.hostname) if cert == '': raise falcon.HTTPInternalServerError( "Failed to generate the certificate") host = HostCert(host_id=host_id, fingerprint=fingerprint, auth_id=token.auth_id, token_id=token_id, pubkey=pub, cert=cert, hostname=token.hostname) session.add(host) # Update the token token.used = True token.date_used = datetime.utcnow() token.fingerprint_used = host.fingerprint session.add(token) session.commit() return host
def add_user_ssh_key(username, key): username = pipes.quote(username) k = sshpubkeys.SSHKey(key) try: k.parse() run("mkdir -p /home/" + username + "/.ssh") run("echo '" + key + "' >> /home/" + username + "/.ssh/authorized_keys") except: return False return True
def get_user_ssh_keys(username): username = pipes.quote(username) keyFile = open("/home/" + username + "/.ssh/authorized_keys", "r") keys = [] for line in keyFile.read().split("\n"): if line: k = sshpubkeys.SSHKey(line) keys.append(SSHKey(k.comment, k.hash_md5())) keyFile.close() return keys
def ssh_key_fingerprint(self): if self.public_key: public_key = self.public_key elif self.private_key: try: public_key = ssh_pubkey_gen(private_key=self.private_key, password=self.password) except IOError as e: return str(e) else: return '' public_key_obj = sshpubkeys.SSHKey(public_key) fingerprint = public_key_obj.hash_md5() return fingerprint
def add_public_key(session, user, public_key_str): """Add a public key for a particular user. Args: session: db session user: User model of user in question public_key_str: public key to add Throws: DuplicateKey if key is already in use PublicKeyParseError if key can't be parsed BadPublicKey if a plugin rejects the key Returns: PublicKey model object representing the key """ pubkey = sshpubkeys.SSHKey(public_key_str, strict=True) try: pubkey.parse() except sshpubkeys.InvalidKeyException as e: raise PublicKeyParseError(e.message) try: get_plugin_proxy().will_add_public_key(pubkey) except PluginRejectedPublicKey as e: raise BadPublicKey(e.message) db_pubkey = PublicKey( user=user, public_key=pubkey.keydata.strip(), fingerprint=pubkey.hash_md5().replace(b"MD5:", b""), fingerprint_sha256=pubkey.hash_sha256().replace(b"SHA256:", b""), key_size=pubkey.bits, key_type=pubkey.key_type, comment=pubkey.comment, ) try: db_pubkey.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() raise DuplicateKey() session.commit() return db_pubkey
def run(self, session, dry_run=True): for key in session.query(PublicKey): pubkey = sshpubkeys.SSHKey(key.public_key, strict=True) logging.info("Processing Key (id={})".format(key.id)) try: pubkey.parse() except sshpubkeys.InvalidKeyException as e: logging.error("Invalid Key (id={}): {}".format(key.id, e.message)) continue try: get_plugin_proxy().will_add_public_key(pubkey) except PluginRejectedPublicKey as e: logging.error("Bad Key (id={}): {}".format(key.id, e.message)) continue
def get_ssh_host_key_infos(): ''' get fingerprints of ssh host keys ''' KEY_TYPES = ['rsa', 'ecdsa', 'ed25519'] data = {} for key_type in KEY_TYPES: file = os.path.join(settings.BORGHIVE['CONFIG_PATH'], 'ssh_host_{}_key.pub'.format(key_type)) if os.path.isfile(file): LOGGER.debug('found %s', file) with open(file) as f: key = sshpubkeys.SSHKey(f.read()) key.parse() data[key_type] = key.hash_sha256() LOGGER.debug(data) return data
def validate_key(line): if not line: return None key = sshpubkeys.SSHKey(line, skip_option_parsing=True) try: key.parse() # rebuild the key to make sure it's safe raw_key = base64.b64encode(key._decoded_key).decode('UTF-8') return "{type:s} {key:s} {bits:d} {comment:s}".format( type=key.key_type.decode('UTF-8'), key=raw_key, bits=key.bits, comment=key.comment) except sshpubkeys.InvalidKeyError as err: LOG.warning("Skipping invalid key %s: %s", line, str(err)) except NotImplementedError as err: LOG.warning("Skipping unknown key type: %s", str(err)) return None
def validate_public(self, data): """ Validate the public key, and generate the fingerprint. :param data: The public key to validate. :type data: str :returns: The validated public key :rtype: str :raises serializers.ValidationError: If the public key is invalid. """ try: ssh = sshpubkeys.SSHKey(data) ssh.parse() except (sshpubkeys.InvalidKeyException, NotImplementedError): self.initial_data['fingerprint'] = 'invalid' raise serializers.ValidationError("Invalid key") fingerprint = ssh.hash_md5() self.initial_data['fingerprint'] = fingerprint return data