def validate(self, request): """Validate uploaded test results.""" super(PubkeyValidator, self).validate(request) body = json.loads(request.body.decode('utf-8')) key_format = body['raw_key'].strip().split()[0] if key_format not in ('ssh-dss', 'ssh-rsa', 'pgp-sign-rsa', 'pgp-sign-dss'): raise api_exc.ValidationError('Public key has unsupported format') try: sign = binascii.a2b_hex(body['self_signature']) except (binascii.Error, TypeError) as e: raise api_exc.ValidationError('Malformed signature', e) try: key = load_ssh_public_key(body['raw_key'].encode('utf-8'), backend=backends.default_backend()) except (binascii.Error, ValueError) as e: raise api_exc.ValidationError('Malformed public key', e) verifier = key.verifier(sign, padding.PKCS1v15(), hashes.SHA256()) verifier.update('signature'.encode('utf-8')) try: verifier.verify() except InvalidSignature: raise api_exc.ValidationError('Signature verification failed')
def validate(self, request): """Validate uploaded test results.""" super(TestResultValidator, self).validate(request) if request.headers.get('X-Signature') or \ request.headers.get('X-Public-Key'): try: sign = binascii.a2b_hex(request.headers.get('X-Signature', '')) except (binascii.Error, TypeError) as e: raise api_exc.ValidationError('Malformed signature', e) try: key = load_ssh_public_key( request.headers.get('X-Public-Key', ''), backend=backends.default_backend() ) except (binascii.Error, ValueError) as e: raise api_exc.ValidationError('Malformed public key', e) verifier = key.verifier(sign, padding.PKCS1v15(), hashes.SHA256()) verifier.update(request.body) try: verifier.verify() except InvalidSignature: raise api_exc.ValidationError('Signature verification failed') if self._is_empty_result(request): raise api_exc.ValidationError('Uploaded results must contain at ' 'least one passing test.')
def check_emptyness(self, body, keys): """Check that all values are not empty.""" for key in keys: value = body[key] if isinstance(value, six.string_types): value = value.strip() if not value: raise api_exc.ValidationError(key + ' should not be empty') elif value is None: raise api_exc.ValidationError(key + ' must be present')
def test_str_validation_error(self): err = api_exc.ValidationError( 'Something went wrong!', AttributeError("'NoneType' object has no attribute 'a'")) self.assertEqual(err.title, 'Something went wrong!') self.assertEqual( "%s(%s: %s)" % ('Something went wrong!', 'AttributeError', "'NoneType' object has no attribute 'a'"), str(err)) err = api_exc.ValidationError('Something went wrong again!') self.assertEqual('Something went wrong again!', str(err))
def validate(self, request): """Validate request.""" try: body = json.loads(request.body) except (ValueError, TypeError) as e: raise api_exc.ValidationError('Malformed request', e) try: jsonschema.validate(body, self.schema) except jsonschema.ValidationError as e: raise api_exc.ValidationError( 'Request doesn''t correspond to schema', e)
def decode_token(request): """Validate request signature. ValidationError rises if request is not valid. """ if not request.headers.get(const.JWT_TOKEN_HEADER): return try: auth_schema, token = request.headers.get(const.JWT_TOKEN_HEADER).split( ' ', 1) except ValueError: raise api_exc.ValidationError("Token is not valid") if auth_schema != 'Bearer': raise api_exc.ValidationError( "Authorization schema 'Bearer' should be used") try: token_data = jwt.decode(token, algorithms='RS256', verify=False) except jwt.InvalidTokenError: raise api_exc.ValidationError("Token is not valid") openid = token_data.get(const.USER_OPENID) if not openid: raise api_exc.ValidationError("Token does not contain user's openid") pubkeys = db.get_user_pubkeys(openid) for pubkey in pubkeys: try: pubkey_string = '%s %s' % (pubkey['format'], pubkey['pubkey']) pubkey_obj = serialization.load_ssh_public_key( pubkey_string.encode('utf-8'), backend=backends.default_backend()) pem_pubkey = pubkey_obj.public_bytes( serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo) except (ValueError, IndexError, TypeError, binascii.Error): pass else: try: token_data = jwt.decode(token, key=pem_pubkey, options={ 'verify_signature': True, 'verify_exp': True, 'require_exp': True }, leeway=const.JWT_VALIDATION_LEEWAY) # NOTE(sslipushenko) If at least one key is valid, let # the validation pass return token_data except jwt.InvalidTokenError: pass # NOTE(sslipushenko) If all user's keys are not valid, the validation fails raise api_exc.ValidationError("Token is not valid")
def validate(self, request): """Validate uploaded test results.""" super(TestResultValidator, self).validate(request) if request.headers.get('X-Signature') or \ request.headers.get('X-Public-Key'): try: sign = binascii.a2b_hex(request.headers.get('X-Signature', '')) except (binascii.Error, TypeError) as e: raise api_exc.ValidationError('Malformed signature', e) try: key = RSA.importKey(request.headers.get('X-Public-Key', '')) except (binascii.Error, ValueError) as e: raise api_exc.ValidationError('Malformed public key', e) signer = PKCS1_v1_5.new(key) data_hash = SHA256.new() data_hash.update(request.body.encode('utf-8')) if not signer.verify(data_hash, sign): raise api_exc.ValidationError('Signature verification failed') if self._is_empty_result(request): raise api_exc.ValidationError('Uploaded results must contain at ' 'least one passing test.')
def register(self, vendor): """Handler for applying for registration with Foundation.""" if not api_utils.check_user_is_vendor_admin(vendor['id']): pecan.abort(403, 'Forbidden.') _check_is_not_foundation(vendor['id']) if vendor['type'] != const.PRIVATE_VENDOR: raise api_exc.ValidationError( 'Invalid organization state for this action.') # change vendor type to pending org_info = {'id': vendor['id'], 'type': const.PENDING_VENDOR} db.update_organization(org_info)
def deny(self, vendor, reason): """Handler for denying a vendor.""" if not api_utils.check_user_is_foundation_admin(): pecan.abort(403, 'Forbidden.') _check_is_not_foundation(vendor['id']) if not reason: raise api_exc.ValidationError('Param "reason" can not be empty') if vendor['type'] != const.PENDING_VENDOR: raise api_exc.ValidationError( 'Invalid organization state for this action.') props = vendor.get('properties') props = json.loads(props) if props else {} props['reason'] = reason # change vendor type back to private org_info = { 'id': vendor['id'], 'type': const.PRIVATE_VENDOR, 'properties': json.dumps(props) } db.update_organization(org_info)
def validate(self, request): """Validate uploaded test results.""" super(PubkeyValidator, self).validate(request) body = json.loads(request.body) key_format = body['raw_key'].strip().split()[0] if key_format not in ('ssh-dss', 'ssh-rsa', 'pgp-sign-rsa', 'pgp-sign-dss'): raise api_exc.ValidationError('Public key has unsupported format') try: sign = binascii.a2b_hex(body['self_signature']) except (binascii.Error, TypeError) as e: raise api_exc.ValidationError('Malformed signature', e) try: key = RSA.importKey(body['raw_key']) except (binascii.Error, ValueError) as e: raise api_exc.ValidationError('Malformed public key', e) signer = PKCS1_v1_5.new(key) data_hash = SHA256.new() data_hash.update('signature'.encode('utf-8')) if not signer.verify(data_hash, sign): raise api_exc.ValidationError('Signature verification failed')
def cancel(self, vendor): """Handler for canceling registration. This action available to user. It allows him to cancel registrationand move state of his vendor from pending to private. """ if not api_utils.check_user_is_vendor_admin(vendor['id']): pecan.abort(403, 'Forbidden.') _check_is_not_foundation(vendor['id']) if vendor['type'] != const.PENDING_VENDOR: raise api_exc.ValidationError( 'Invalid organization state for this action.') # change vendor type back to private org_info = {'id': vendor['id'], 'type': const.PRIVATE_VENDOR} db.update_organization(org_info)
def action(self, vendor_id, **kw): """Handler for action on Vendor object.""" params = list() for param in ('register', 'approve', 'deny', 'cancel'): if param in kw: params.append(param) if len(params) != 1: raise api_exc.ValidationError('Invalid actions in the body: ' + str(params)) vendor = db.get_organization(vendor_id) if 'register' in params: self.register(vendor) elif 'approve' in params: self.approve(vendor) elif 'cancel' in params: self.cancel(vendor) else: self.deny(vendor, kw.get('registration_decline_reason'))
def approve(self, vendor): """Handler for making vendor official.""" if not api_utils.check_user_is_foundation_admin(): pecan.abort(403, 'Forbidden.') _check_is_not_foundation(vendor['id']) if vendor['type'] != const.PENDING_VENDOR: raise api_exc.ValidationError( 'Invalid organization state for this action.') # change vendor type to public props = vendor.get('properties') props = json.loads(props) if props else {} props.pop('registration_decline_reason', None) org_info = { 'id': vendor['id'], 'type': const.OFFICIAL_VENDOR, 'properties': json.dumps(props) } db.update_organization(org_info)