Esempio n. 1
0
    def test_query(self, drvmock):
        cmduuid = 'someuuid'

        dnd = BetterDummyNodeDriver(1)
        drvmock.return_value = dnd

        # Get the existing instance id
        node = dnd.list_nodes()[0]
        instid = node.name

        cmd = Command(action='query', target=NewContextAWS(instance=instid))

        # That a request to query a command
        response = self.test_client.get('/ec2',
                                        data=_seropenc2(cmd),
                                        headers={'X-Request-ID': cmduuid})

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and matches the node state
        self.assertEqual(dcmd.status_text, node.state)

        # and has the same command id
        self.assertEqual(response.headers['X-Request-ID'], cmduuid)

        # that when the instance does not exist
        dnd.list_nodes()[0].destroy()

        # That a request to query a command the returns nothing
        response = self.test_client.get('/ec2',
                                        data=_seropenc2(cmd),
                                        headers={'X-Request-ID': cmduuid})

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and that the status is 404 (instance not found)
        self.assertEqual(dcmd.status, 404)

        # and has the instance id
        self.assertEqual(dcmd.status_text, 'instance not found')

        # That when we post the same command as a get request
        response = self.test_client.post('/ec2', data=_seropenc2(cmd))

        # that it fails
        self.assertEqual(response.status_code, 400)
Esempio n. 2
0
    def test_genresp(self):
        res = 'soijef'
        cmdid = 'weoiudf'
        resp = OpenC2Response(source=ec2target,
                              status='OK',
                              results=res,
                              cmdref=cmdid)

        # that a generated response
        r = genresp(resp, 400)

        # has the passed in status code
        self.assertEqual(r.status_code, 400)

        # has the correct mime-type
        self.assertEqual(r.mimetype, 'application/json')

        # has the correct body
        self.assertEqual(r.data, _seropenc2(resp))

        # that a generated response
        r = genresp(resp)

        # has the default status code
        self.assertEqual(r.status_code, 200)
Esempio n. 3
0
    def test_genresp(self):
        res = 'soijef'
        cmdid = 'weoiudf'

        resp = OpenC2Response(status=400)

        # that a generated response
        r = genresp(resp, command_id=cmdid)

        # has the passed in status code
        self.assertEqual(r.status_code, 400)

        # has the correct mime-type
        self.assertEqual(r.content_type,
                         'application/openc2-rsp+json;version=1.0')

        # has the correct body
        self.assertEqual(r.data, _seropenc2(resp).encode('utf-8'))

        # and the command id in the header
        self.assertEqual(r.headers['X-Request-ID'], cmdid)

        # that a generated response
        resp = OpenC2Response(status=200)
        r = genresp(resp, cmdid)

        # has the passed status code
        self.assertEqual(r.status_code, 200)
Esempio n. 4
0
    def test_create(self, bec2):
        cmduuid = 'someuuid'
        instid = 'sdkj'
        ami = 'bogusimage'

        cmd = OpenC2Command(action=CREATE,
                            target=ec2target,
                            modifiers={
                                'image': ami,
                                'command_id': cmduuid
                            })

        bec2().run_instances.return_value = {
            'Instances': [{
                'InstanceId': instid,
            }]
        }

        # That a request to create a command
        response = self.test_client.post('/ec2', data=_seropenc2(cmd))

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # that the status is correct
        self.assertEqual(dcmd.status, 'OK')

        # and has the instance id
        self.assertEqual(dcmd.results, instid)

        # and has the same command id
        self.assertEqual(dcmd.cmdref, cmduuid)

        # and that the image was run
        bec2().run_instances.assert_called_once_with(ImageId=ami,
                                                     MinCount=1,
                                                     MaxCount=1)

        # That when we get the same command as a get request
        response = self.test_client.get('/ec2', data=_seropenc2(cmd))

        # that it fails
        self.assertEqual(response.status_code, 400)
Esempio n. 5
0
def genresp(oc2resp, status_code=200):
    '''Generate a response from a OpenC2Response.'''

    body = _seropenc2(oc2resp)
    r = Response(response=body,
                 status=status_code,
                 mimetype='application/json')

    return r
Esempio n. 6
0
def genresp(oc2resp, command_id):
    '''Generate a response from a Response.'''

    # be explicit about encoding, the automatic encoding is undocumented
    body = _seropenc2(oc2resp).encode('utf-8')
    r = Response(response=body,
                 status=oc2resp.status,
                 headers={'X-Request-ID': command_id},
                 mimetype='application/openc2-rsp+json;version=1.0')

    return r
Esempio n. 7
0
def ec2route():
    app.logger.debug('received msg: %s' % ` request.data `)
    req = _deseropenc2(request.data)
    try:
        if request.method == 'POST' and req.action == CREATE:
            ami = req.modifiers['image']
            r = get_bec2().run_instances(ImageId=ami, MinCount=1, MaxCount=1)

            inst = r['Instances'][0]['InstanceId']
            app.logger.debug('started ami %s, instance id: %s' % (ami, inst))

            res = inst
        elif request.method == 'POST' and req.action == START:
            r = get_bec2().start_instances(
                InstanceIds=[req.modifiers['instance']])

            res = ''
        elif request.method == 'POST' and req.action == STOP:
            r = get_bec2().stop_instances(
                InstanceIds=[req.modifiers['instance']])

            res = ''
        elif request.method == 'POST' and req.action == DELETE:
            r = get_bec2().terminate_instances(
                InstanceIds=[req.modifiers['instance']])

            res = ''
        elif request.method == 'GET' and req.action == 'query':
            r = get_bec2().describe_instances(
                InstanceIds=[req.modifiers['instance']])

            insts = r['Reservations']
            if insts:
                res = insts[0]['Instances'][0]['State']['Name']
            else:
                res = 'instance not found'
        else:
            raise Exception('unhandled request')
    except botocore.exceptions.ClientError as e:
        app.logger.debug('operation failed: %s' % ` e `)
        raise CommandFailure(req, ` e `)
    except Exception as e:
        app.logger.debug('generic failure: %s' % ` e `)
        app.logger.debug(traceback.format_exc())
        raise CommandFailure(req, ` e `)

    resp = OpenC2Response(source=ec2target,
                          status='OK',
                          results=res,
                          cmdref=req.modifiers['command_id'])

    return _seropenc2(resp)
Esempio n. 8
0
    def test_delete(self, bec2):
        #terminate_instances
        cmduuid = 'someuuid'
        instid = 'sdkj'

        cmd = OpenC2Command(action=DELETE,
                            target=ec2target,
                            modifiers={
                                'instance': instid,
                                'command_id': cmduuid
                            })

        bec2().terminate_instances.return_value = {
            'TerminatingInstances': [{
                'InstanceId': instid,
            }]
        }

        # That a request to create a command
        response = self.test_client.post('/ec2', data=_seropenc2(cmd))

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and has the same command id
        self.assertEqual(dcmd.cmdref, cmduuid)

        # and that the image was terminated
        bec2().terminate_instances.assert_called_once_with(
            InstanceIds=[instid])

        # That when we get the same command as a get request
        response = self.test_client.get('/ec2', data=_seropenc2(cmd))

        # that it fails
        self.assertEqual(response.status_code, 400)
Esempio n. 9
0
    def test_start(self, drvmock):
        cmduuid = 'someuuid'

        dnd = BetterDummyNodeDriver(1)
        drvmock.return_value = dnd

        # Get the existing instance id
        instid = dnd.list_nodes()[0].name
        node = dnd.list_nodes()[0]
        node.stop_node()
        self.assertEqual(node.state, NodeState.STOPPED)

        cmd = Command(action=START, target=NewContextAWS(instance=instid))

        # That a request to start an instance
        response = self.test_client.post('/ec2',
                                         data=_seropenc2(cmd),
                                         headers={'X-Request-ID': cmduuid})

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and has the same command id
        self.assertEqual(response.headers['X-Request-ID'], cmduuid)

        # and that the image was started
        self.assertEqual(node.state, NodeState.RUNNING)

        # That when we get the same command as a get request
        response = self.test_client.get('/ec2',
                                        data=_seropenc2(cmd),
                                        headers={'X-Request-ID': cmduuid})

        # that it fails
        self.assertEqual(response.status_code, 400)
Esempio n. 10
0
    def test_cmdfailure(self):
        cmduuid = 'weoiud'
        ami = 'owiejp'
        failmsg = 'this is a failure message'

        cmd = OpenC2Command(action=CREATE,
                            target=ec2target,
                            modifiers={
                                'image': ami,
                                'command_id': cmduuid
                            })

        oc2resp = OpenC2Response(source=ec2target,
                                 status='ERR',
                                 results=failmsg,
                                 cmdref=cmd.modifiers['command_id'])

        # that a constructed CommandFailure
        failure = CommandFailure(cmd, failmsg)

        # when handled
        r = handle_commandfailure(failure)

        # has the correct status code
        self.assertEqual(r.status_code, 400)

        # has the correct mime-type
        self.assertEqual(r.mimetype, 'application/json')

        # has the correct body
        self.assertEqual(r.data, _seropenc2(oc2resp))

        # that a constructed CommandFailure
        failure = CommandFailure(cmd, failmsg, 500)

        # when handled
        r = handle_commandfailure(failure)

        # has the correct status code
        self.assertEqual(r.status_code, 500)
Esempio n. 11
0
    def test_cmdfailure(self):
        cmduuid = 'weoiud'
        ami = 'owiejp'
        failmsg = 'this is a failure message'

        cmd = Command(action=CREATE, target=NewContextAWS(image=ami))

        oc2resp = OpenC2Response(status=500, status_text=failmsg)

        # that a constructed CommandFailure
        failure = CommandFailure(cmd, failmsg, cmduuid, 500)

        # when handled
        r = handle_commandfailure(failure)

        # has the correct status code
        self.assertEqual(r.status_code, 500)

        # has the correct mime-type
        self.assertEqual(r.content_type,
                         'application/openc2-rsp+json;version=1.0')

        # has the correct body
        self.assertEqual(r.data, _seropenc2(oc2resp).encode('utf-8'))

        # and the command id in the header
        self.assertEqual(r.headers['X-Request-ID'], cmduuid)

        # that a constructed CommandFailure
        failure = CommandFailure(cmd, failmsg, cmduuid, 500)

        # when handled
        r = handle_commandfailure(failure)

        # has the correct status code
        self.assertEqual(r.status_code, 500)
Esempio n. 12
0
def ec2route():
    app.logger.debug('received msg: %s' % repr(request.data))
    try:
        cmdid = request.headers['X-Request-ID']
    except KeyError:
        resp = make_response('missing X-Request-ID header'.encode('us-ascii'),
                             400)
        resp.charset = 'us-ascii'
        resp.mimetype = 'text/plain'
        return resp

    req = _deseropenc2(request.data)
    ncawsargs = {}
    status = 200
    clddrv = get_clouddriver()
    try:
        if hasattr(req.target, 'instance'):
            inst = req.target.instance
        if request.method == 'POST' and req.action == CREATE:
            ami = req.target['image']
            img = MagicMock()
            img.id = ami
            try:
                inst = req.target.instance
            except AttributeError:
                inst = next(nameiter)
            r = clddrv.create_node(image=img, name=inst, **createnodekwargs)
            inst = r.name
            app.logger.debug('started ami %s, instance id: %s' % (ami, inst))

            res = inst
            ncawsargs['instance'] = inst
        elif request.method == 'POST' and req.action == START:
            get_node(inst).start()

            res = ''
        elif request.method == 'POST' and req.action == STOP:
            if not get_node(inst).stop_node():
                raise RuntimeError('unable to stop instance: %s' % repr(inst))

            res = ''
        elif request.method == 'POST' and req.action == DELETE:
            get_node(inst).destroy()

            res = ''
        elif request.method in ('GET', 'POST') and req.action == 'query':
            insts = [x for x in clddrv.list_nodes() if x.name == inst]

            if insts:
                res = str(insts[0].state)
            else:
                res = 'instance not found'
                status = 404
        else:
            raise Exception('unhandled request')
    except Exception as e:
        app.logger.debug('generic failure: %s' % repr(e))
        app.logger.debug(traceback.format_exc())
        raise CommandFailure(req, repr(e), cmdid)

    if ncawsargs:
        kwargs = dict(results=NewContextAWS(**ncawsargs))
    else:
        kwargs = {}
    resp = OpenC2Response(status=status, status_text=res, **kwargs)

    app.logger.debug('replied msg: %s' % repr(_seropenc2(resp)))

    resp = make_response(_seropenc2(resp))

    # Copy over the command id from the request
    resp.headers['X-Request-ID'] = request.headers['X-Request-ID']

    return resp
Esempio n. 13
0
    def test_stop(self, drvmock):
        cmduuid = 'someuuid'

        dnd = BetterDummyNodeDriver(1)
        drvmock.return_value = dnd

        # Get the existing instance id
        instid = dnd.list_nodes()[0].name
        node = dnd.list_nodes()[0]
        self.assertEqual(node.state, NodeState.RUNNING)

        cmd = Command(allow_custom=True,
                      action=STOP,
                      target=NewContextAWS(instance=instid))

        # That a request to stop an instance
        response = self.test_client.post('/ec2',
                                         data=_seropenc2(cmd),
                                         headers={'X-Request-ID': cmduuid})

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and has the same command id
        self.assertEqual(response.headers['X-Request-ID'], cmduuid)

        # and that the image was stopped
        self.assertEqual(node.state, NodeState.STOPPED)

        # That when we get the same command as a get request
        response = self.test_client.get('/ec2',
                                        data=_seropenc2(cmd),
                                        headers={'X-Request-ID': cmduuid})

        # that it fails
        self.assertEqual(response.status_code, 400)

        with patch.object(dnd, 'stop_node') as sn:
            # that when a stop command
            cmd = Command(action=STOP, target=NewContextAWS(instance=instid))

            # and it returns an error
            sn.return_value = False

            # That a request to stop an instance
            response = self.test_client.post('/ec2',
                                             data=_seropenc2(cmd),
                                             headers={'X-Request-ID': cmduuid})

            # fails
            self.assertEqual(response.status_code, 400)

            # that it has a Response body
            resp = _deseropenc2(response.data)

            # that it is an ERR
            self.assertEqual(resp.status, 400)

            # that it references the correct command
            self.assertEqual(response.headers['X-Request-ID'], cmduuid)
Esempio n. 14
0
    def test_create(self, drvmock, nameiter):
        cmduuid = 'someuuid'
        ami = 'Ubuntu 9.10'
        instname = 'somename'

        # that the name is return by nameiter
        nameiter.__next__.return_value = instname

        cmd = Command(action=CREATE, target=NewContextAWS(image=ami))

        # Note that 0, creates two nodes, not zero, so create one instead
        dnd = BetterDummyNodeDriver(1)
        dnd.list_nodes()[0].destroy()
        self.assertEqual(len(dnd.list_nodes()), 0)
        drvmock.return_value = dnd

        # That a request to create a command
        response = self.test_client.post('/ec2',
                                         data=_seropenc2(cmd),
                                         headers={'X-Request-ID': cmduuid})

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # that the status is correct
        self.assertEqual(dcmd.status, 200)

        # and that the image was run
        self.assertEqual(len(dnd.list_nodes()), 1)

        # and has the correct instance id
        node = dnd.list_nodes()[0]
        runinstid = node.name
        self.assertEqual(runinstid, instname)
        self.assertEqual(dcmd.results['instance'], runinstid)

        # and was launched w/ the correct size
        self.assertEqual(node.size.name, createnodekwargs['size'])

        # and has the same command id
        self.assertEqual(response.headers['X-Request-ID'], cmduuid)

        # clean up previously launched instance
        dnd.list_nodes()[0].destroy()

        # That a request to create a command w/ instance name
        instname = 'anotherinstancename'
        cmd = Command(action=CREATE,
                      target=NewContextAWS(image=ami, instance=instname))

        response = self.test_client.post('/ec2',
                                         data=_seropenc2(cmd),
                                         headers={'X-Request-ID': cmduuid})

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # that the status is correct
        self.assertEqual(dcmd.status, 200)

        # and that the image was run
        self.assertEqual(len(dnd.list_nodes()), 1)

        # and has the correct instance id
        node = dnd.list_nodes()[0]
        runinstid = node.name
        self.assertEqual(runinstid, instname)
        self.assertEqual(dcmd.results['instance'], runinstid)

        # That when we get the same command as a get request
        response = self.test_client.get('/ec2',
                                        data=_seropenc2(cmd),
                                        headers={'X-Request-ID': cmduuid})

        # that it fails
        self.assertEqual(response.status_code, 400)
Esempio n. 15
0
    def test_stop(self, bec2):
        cmduuid = 'someuuid'
        instid = 'sdkj'

        cmd = OpenC2Command(action=STOP,
                            target=ec2target,
                            modifiers={
                                'instance': instid,
                                'command_id': cmduuid
                            })

        bec2().stop_instances.return_value = {
            'StoppingInstances': [{
                'InstanceId': instid,
            }]
        }

        # That a request to stop an instance
        response = self.test_client.post('/ec2', data=_seropenc2(cmd))

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and has the same command id
        self.assertEqual(dcmd.cmdref, cmduuid)

        # and that the image was stopped
        bec2().stop_instances.assert_called_once_with(InstanceIds=[instid])

        # That when we get the same command as a get request
        response = self.test_client.get('/ec2', data=_seropenc2(cmd))

        # that it fails
        self.assertEqual(response.status_code, 400)

        # that when a stop command
        cmd = OpenC2Command(action=STOP,
                            target=ec2target,
                            modifiers={
                                'instance': instid,
                                'command_id': cmduuid
                            })

        # and AWS returns an error
        bec2().stop_instances.side_effect = \
            botocore.exceptions.ClientError({}, 'stop_instances')

        # That a request to stop an instance
        response = self.test_client.post('/ec2', data=_seropenc2(cmd))

        # fails
        self.assertEqual(response.status_code, 400)

        # that it has a OpenC2Response body
        resp = _deseropenc2(response.data)

        # that it is an ERR
        self.assertEqual(resp.status, 'ERR')

        # that it references the correct command
        self.assertEqual(resp.cmdref, cmduuid)
Esempio n. 16
0
    def test_query(self, bec2):
        cmduuid = 'someuuid'
        instid = 'sdkj'

        cmd = OpenC2Command(action='query',
                            target=ec2target,
                            modifiers={
                                'instance': instid,
                                'command_id': cmduuid
                            })

        inststate = 'pending'
        instdesc = {
            'InstanceId': instid,
            'some': 'other',
            'data': 'included',
            'State': {
                'Code': 38732,
                'Name': 'pending',
            }
        }
        bec2().describe_instances.return_value = {
            'Reservations': [{
                'Instances': [instdesc],
            }]
        }

        # That a request to query a command
        response = self.test_client.get('/ec2', data=_seropenc2(cmd))

        # Is successful
        self.assertEqual(response.status_code, 200)

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and has the instance id
        self.assertEqual(dcmd.results, inststate)

        # and has the same command id
        self.assertEqual(dcmd.cmdref, cmduuid)

        # and that the image was run
        bec2().describe_instances.assert_called_once_with(InstanceIds=[instid])

        bec2().describe_instances.return_value = {
            'Reservations': [],
        }

        # That a request to query a command the returns nothing
        response = self.test_client.get('/ec2', data=_seropenc2(cmd))

        # and returns a valid OpenC2 response
        dcmd = _deseropenc2(response.data)

        # and has the instance id
        self.assertEqual(dcmd.results, 'instance not found')

        # That when we post the same command as a get request
        response = self.test_client.post('/ec2', data=_seropenc2(cmd))

        # that it fails
        self.assertEqual(response.status_code, 400)