Ejemplo n.º 1
0
    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')
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
 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)
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
 def public_key_obj(self):
     if self.public_key:
         try:
             return sshpubkeys.SSHKey(self.public_key)
         except TabError:
             pass
     return None
Ejemplo n.º 9
0
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")
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
 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)
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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()
Ejemplo n.º 15
0
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')
Ejemplo n.º 16
0
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()
Ejemplo n.º 17
0
 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()
Ejemplo n.º 18
0
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))
Ejemplo n.º 19
0
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
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
    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__)
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
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
Ejemplo n.º 25
0
    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
Ejemplo n.º 26
0
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
Ejemplo n.º 27
0
    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
Ejemplo n.º 28
0
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
Ejemplo n.º 29
0
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
Ejemplo n.º 30
0
 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