Exemplo n.º 1
0
def manage_runtime_remove(args):
    if not args.domain:
        raise Exception("No domain supplied")
    domaindir = os.path.join(args.dir, args.domain) if args.dir else None
    runtime = runtime_credentials.RuntimeCredentials(args.node_name,
                                                     security_dir=args.dir)
    runtime.remove_runtime(args.node_name, domaindir)
Exemplo n.º 2
0
 def start(self):
     callbacks = {'connected': [CalvinCB(self._connected)]}
     tcp_f = TCPServerFactory(callbacks)
     runtime_to_runtime_security = _conf.get("security","runtime_to_runtime_security")
     trusted_ca_certs = []
     if runtime_to_runtime_security=="tls":
         _log.debug("TwistedCalvinServer with TLS chosen")
         try:
             self._runtime_credentials = runtime_credentials.RuntimeCredentials(self._node_name)
             ca_cert_list_str, ca_cert_list_x509, truststore =certificate.get_truststore(certificate.TRUSTSTORE_TRANSPORT)
             for ca_cert in ca_cert_list_str:
                 trusted_ca_certs.append(ssl.Certificate.loadPEM(ca_cert))
             server_credentials_data = self._runtime_credentials.get_runtime_credentials()
             server_credentials = ssl.PrivateCertificate.loadPEM(server_credentials_data)
         except Exception as err:
             _log.exception("Server failed to load credentials, err={}".format(err))
         try:
             self._tcp_server = reactor.listenSSL(self._port, tcp_f, server_credentials.options(*trusted_ca_certs), interface=self._iface)
         except Exception as err:
             _log.exception("Server failed listenSSL, err={}".format(err))
     else:
         _log.debug("TwistedCalvinServer without TLS chosen")
         try:
             self._tcp_server = reactor.listenTCP(self._port, tcp_f, interface=self._iface)
         except error.CannotListenError:
             _log.exception("Could not listen on port %s:%s", self._iface, self._port)
             raise
         except Exception as exc:
             _log.exception("Failed when trying listening on port %s:%s", self._iface, self._port)
             raise
     self._port = self._tcp_server.getHost().port
     self._callback_execute('server_started', self._port)
     return self._port
Exemplo n.º 3
0
def reactor_listen(node_name, factory, host, port):
    listener = None

    control_interface_security = _conf.get("security", "control_interface_security")
    if control_interface_security == "tls":
        _log.debug("ServerProtocolFactory with TLS enabled chosen")
        try:
            # TODO: figure out how to set more than one root cert in twisted truststore
            runtime_cred = runtime_credentials.RuntimeCredentials(node_name)
            server_credentials_data = runtime_cred.get_runtime_credentials()
            server_credentials = ssl.PrivateCertificate.loadPEM(server_credentials_data)
        except Exception as err:
            _log.error("Failed to fetch server credentials, err={}".format(err))
            raise
        try:
            listener = reactor.listenSSL(port, factory, server_credentials.options(), interface=host)
        except Exception as err:
            _log.error("Server failed listenSSL, err={}".format(err))
    else:
        listener = reactor.listenTCP(port, factory, interface=host)
        # @tif, check with Harald how to verify that workaround is still ok.
        # WORKAROUND This is here due to an obscure error in twisted trying to write to a listening port
        # on some architectures/OSes. The default is to raise a RuntimeError.
        listener.doWrite = lambda: None

    return listener
Exemplo n.º 4
0
def manage_runtime_import(args):
    if not args.node_name:
        raise Exception("No node name supplied")
    if not args.certificate:
        raise Exception("No certificate supplied")
    runtime = runtime_credentials.RuntimeCredentials(args.node_name,
                                                     security_dir=args.dir)
    cert_path = runtime.store_own_cert(certpath=args.certificate)
    print "cert_path_start<{}>cert_path_stop".format(cert_path)
Exemplo n.º 5
0
    def join(self):
        from twisted.internet._sslverify import OpenSSLCertificateAuthorities
        from OpenSSL import crypto
        if self._proto:
            raise Exception("Already connected")

        # Own callbacks
        callbacks = {'connected': [CalvinCB(self._connected)],
                     'disconnected': [CalvinCB(self._disconnected)],
                     'connection_failed': [CalvinCB(self._connection_failed)],
                     'data': [CalvinCB(self._data)],
                     'set_proto': [CalvinCB(self._set_proto)]}

        self._factory = TCPClientFactory(callbacks) # addr="%s:%s" % (self._host_ip, self._host_port))
        runtime_to_runtime_security = _conf.get("security","runtime_to_runtime_security")
        if runtime_to_runtime_security=="tls":
            _log.debug("TwistedCalvinTransport with TLS chosen")
            trusted_ca_certs = []
            try:
                self._runtime_credentials = runtime_credentials.RuntimeCredentials(self._node_name)
                ca_cert_list_str, ca_cert_list_x509, truststore = certificate.get_truststore(certificate.TRUSTSTORE_TRANSPORT)
                for ca_cert in ca_cert_list_str:
                    trusted_ca_certs.append(crypto.load_certificate(crypto.FILETYPE_PEM, ca_cert))
                ca_certs = OpenSSLCertificateAuthorities(trusted_ca_certs)
                client_credentials_data =self._runtime_credentials.get_runtime_credentials()
                client_credentials = ssl.PrivateCertificate.loadPEM(client_credentials_data)
            except Exception as err:
                _log.error("TwistedCalvinTransport: Failed to load client credentials, err={}".format(err))
                raise
            try:
                options = ssl.optionsForClientTLS(self._server_node_name,
                                                   trustRoot=ca_certs,
                                                   clientCertificate=client_credentials)
            except Exception as err:
                _log.error("TwistedCalvinTransport: Failed to create optionsForClientTLS "
                                "\n\terr={}"
                                "\n\tself._server_node_name={}".format(err,
                                                                      self._server_node_name))
                raise
            try:
                endpoint = endpoints.SSL4ClientEndpoint(reactor,
                                                        self._host_ip,
                                                        int(self._host_port),
                                                        options)
            except:
                _log.error("TwistedCalvinTransport: Client failed connectSSL")
                raise
            try:
                endpoint.connect(self._factory)
            except Exception as e:
                _log.error("TwistedCalvinTransport: Failed endpoint.connect, e={}".format(e))
                raise
        else:
            reactor.connectTCP(self._host_ip, int(self._host_port), self._factory)
Exemplo n.º 6
0
def manage_runtime_encrypt_csr_with_enrollment_password(args):
    if not args.node_name:
        raise Exception("No node name supplied")
    if not args.enrollment_password:
        raise Exception("No enrollment password supplied")
    rt_cred = runtime_credentials.RuntimeCredentials(
        args.node_name,
        security_dir=args.dir,
        enrollment_password=args.enrollment_password)
    try:
        encr_csr = rt_cred.cert_enrollment_encrypt_csr()
    except Exception as err:
        print "Failed to encrypt CSR, err={}".format(err)
        raise
    encr_csr_path = rt_cred.get_encrypted_csr_path()
    print "encr_csr_path_start<{}>encr_csr_path_stop".format(encr_csr_path)
Exemplo n.º 7
0
def _generate_certiticates(ca, runtimes, domain_name, credentials_testdir):
    from calvin.utilities import runtime_credentials
    from calvin.utilities import calvinuuid
    for i in range(len(runtimes)):
        runtimes[i]["id"] = calvinuuid.uuid("")
        node_name = runtimes[i]["node_name"]
        runtime = runtime_credentials.RuntimeCredentials(
            node_name,
            domain=domain_name,
            #                                                           hostnames=["elxahyc5lz1","elxahyc5lz1.localdomain"],
            security_dir=credentials_testdir,
            nodeid=runtimes[i]["id"],
            enrollment_password=runtimes[i]["enrollment_password"])
        runtimes[i]["credentials"] = runtime
        csr_path = runtime.get_csr_path()
        #CAs generated certificate for runtime
        cert_path = ca.sign_csr(csr_path)
        runtime.store_own_cert(certpath=cert_path)
Exemplo n.º 8
0
def manage_runtime_create(args):
    if not args.attr:
        raise Exception("No runtime attributes supplied")
    if not args.domain:
        raise Exception("No domain name supplied")
    if args.hostnames and len(args.hostnames) > 4:
        raise Exception("At most 3 hostnames can be supplied")
    attr = json.loads(args.attr)
    if not all(k in attr['indexed_public']['node_name']
               for k in ("organization", "name")):
        raise Exception("please supply name and organization of runtime")
    attributes = AttributeResolver(attr)
    node_name = attributes.get_node_name_as_str()
    nodeid = calvinuuid.uuid("NODE")
    rt_cred = runtime_credentials.RuntimeCredentials(node_name,
                                                     domain=args.domain,
                                                     security_dir=args.dir,
                                                     nodeid=nodeid,
                                                     hostnames=args.hostnames)
    print "node_name_start<{}>node_name_stop".format(rt_cred.get_node_name())
Exemplo n.º 9
0
def _generate_certiticates(ca, runtimes, domain_name, credentials_testdir):
    from calvin.utilities import runtime_credentials
    for i in range(len(runtimes)):
        node_name = runtimes[i]["node_name"]
        runtime = runtime_credentials.RuntimeCredentials(
            node_name,
            domain=domain_name,
            #                                                           hostnames=["elxahyc5lz1","elxahyc5lz1.localdomain"],
            security_dir=credentials_testdir,
            nodeid=runtimes[i]["id"],
            enrollment_password=runtimes[i]["enrollment_password"])
        runtimes[i]["credentials"] = runtime
        csr_path = os.path.join(runtime.runtime_dir, node_name + ".csr")
        #Decrypt encrypted CSR with CAs private key
        rsa_encrypted_csr = runtime.get_encrypted_csr()
        csr = ca.decrypt_encrypted_csr(
            encrypted_enrollment_request=rsa_encrypted_csr)
        csr_path = ca.store_csr_with_enrollment_password(csr)
        cert_path = ca.sign_csr(csr_path)
        runtime.store_own_cert(certpath=cert_path,
                               security_dir=credentials_testdir)
Exemplo n.º 10
0
 def start(self, host, port):
     control_interface_security = _conf.get("security","control_interface_security")
     if control_interface_security=="tls":
         _log.debug("ServerProtocolFactory with TLS enabled chosen")
         try:
             #TODO: figure out how to set more than one root cert in twisted truststore
             runtime_cred = runtime_credentials.RuntimeCredentials(self._node_name)
             server_credentials_data = runtime_cred.get_runtime_credentials()
             server_credentials = ssl.PrivateCertificate.loadPEM(server_credentials_data)
         except Exception as err:
             _log.error("Failed to fetch server credentials, err={}".format(err))
             raise
         try:
             self._tls_server = reactor.listenSSL(port, self, server_credentials.options(), interface=host)
         except Exception as err:
             _log.error("Server failed listenSSL, err={}".format(err))
         self._port = self._tls_server.getHost().port
     else:
         self._port = reactor.listenTCP(port, self, interface=host)
         # WORKAROUND This is here due to an obscure error in twisted trying to write to a listening port
         # on some architectures/OSes. The default is to raise a RuntimeError.
         self._port.doWrite = lambda : None
Exemplo n.º 11
0
def manage_runtime_do_it_all(args):
    if not args.attr:
        raise Exception("No runtime attributes supplied")
    if not args.domain:
        raise Exception("No domain name supplied")
    attr = json.loads(args.attr)
    if not all(k in attr['indexed_public']['node_name']
               for k in ("organization", "name")):
        raise Exception("please supply name and organization of runtime")

    ca = certificate_authority.CA(domain=args.domain,
                                  commonName=args.domain + " CA",
                                  security_dir=args.dir)
    ca_cert_path = ca.export_ca_cert("/tmp")
    certificate.store_trusted_root_cert(ca_cert_path,
                                        certificate.TRUSTSTORE_TRANSPORT,
                                        security_dir=args.dir)
    os.remove(ca_cert_path)
    attributes = AttributeResolver(attr)
    node_name = attributes.get_node_name_as_str()
    nodeid = calvinuuid.uuid("NODE")
    enrollment_password = ca.cert_enrollment_add_new_runtime(node_name)
    rt_cred = runtime_credentials.RuntimeCredentials(
        node_name,
        domain=args.domain,
        security_dir=args.dir,
        nodeid=nodeid,
        enrollment_password=enrollment_password)
    ca_cert = rt_cred.get_truststore(
        type=certificate.TRUSTSTORE_TRANSPORT)[0][0]
    #Encrypt CSR with CAs public key (to protect enrollment password)
    rsa_encrypted_csr_path = rt_cred.get_encrypted_csr_path()
    #Decrypt encrypted CSR with CAs private key
    csr = ca.decrypt_encrypted_csr(
        encrypted_enrollment_request_path=rsa_encrypted_csr_path)
    csr_path = ca.store_csr_with_enrollment_password(csr)
    cert_path = ca.sign_csr(csr_path)
    print "\ncertificate stored at: {}\n".format(
        rt_cred.store_own_cert(certpath=cert_path, security_dir=args.dir))
Exemplo n.º 12
0
    def test_dht_multi(self, monkeypatch):
        iface = "0.0.0.0"
        a = None
        b = None
        q = Queue.Queue()
        rt_credentials = []

        def server_started(aa, *args):
            for b in args:
                if isinstance(b, twisted.python.failure.Failure):
                    b.printTraceback()
                else:
                    _log.debug("** %s" % b)
            q.put([aa, args])

        try:
            amount_of_servers = 5
            # Twisted is using 20 threads so having > 20 server
            # causes threadlocks really easily.

            servers = []
            callbacks = []
            for servno in range(0, amount_of_servers):
                uri = "http://{}:500{}".format(ip_addr, servno)
                control_uri = "http://{}:502{}".format(ip_addr, servno)
                rt_cred = runtime_credentials.RuntimeCredentials(
                    name=name + str(servno),
                    domain=domain,
                    security_dir=testdir)
                rt_credentials.append(rt_cred)
                node_id = rt_cred.node_id
                a = AutoDHTServer(node_id, control_uri, rt_cred)
                servers.append(a)
                callback = CalvinCB(server_started, str(servno))
                servers[servno].start(iface,
                                      network="Niklas",
                                      cb=callback,
                                      name=name + "{}".format(servno))
                callbacks.append(callback)

            # Wait for start
            started = []
            while len(started) < amount_of_servers:
                try:
                    server = yield threads.defer_to_thread(q.get)
                except Queue.Empty:
                    _log.debug("Queue empty!")
                    #raise
                if server not in started:
                    started.append(server)
                    #print("DHT Servers added: {}".format(started))
                    callbacks[int(
                        server[0][0])].func = lambda *args, **kvargs: None
                else:
                    print("Server: {} already started." \
                               " {} out of {}".format(started,
                                                     len(started),
                                                     amount_of_servers))

            print("All {} out of {} started".format(started, len(started),
                                                    amount_of_servers))
            for servno in range(0, amount_of_servers):
                assert [str(servno), self._sucess_start] in started

            yield threads.defer_to_thread(q.queue.clear)
            yield threads.defer_to_thread(time.sleep, 8)

            key = "HARE"
            value = json.dumps(["morot"])
            set_def = servers[0].append(key=key, value=value)
            set_value = yield threads.defer_to_thread(set_def.wait, 10)
            assert set_value
            print("Node with port {} posted append key={}, value={}".format(
                servers[0].dht_server.port.getHost().port, key, value))
            value = json.dumps(["selleri"])
            set_def = servers[0].append(key=key, value=value)
            set_value = yield threads.defer_to_thread(set_def.wait, 10)
            assert set_value
            print("Node with port {} posted append key={}, value={}".format(
                servers[0].dht_server.port.getHost().port, key, value))
            get_def = servers[0].get_concat(key=key)
            get_value = yield threads.defer_to_thread(get_def.wait, 10)
            assert set(json.loads(get_value)) == set(["morot", "selleri"])
            print("Node with port {} confirmed key={}, value={} was reachable".
                  format(servers[0].dht_server.port.getHost().port, key,
                         get_value))

            drawNetworkState("1nice_graph.png", servers, amount_of_servers)
            yield threads.defer_to_thread(time.sleep, 7)
            drawNetworkState("1middle_graph.png", servers, amount_of_servers)
            yield threads.defer_to_thread(time.sleep, 7)
            drawNetworkState("1end_graph.png", servers, amount_of_servers)

            get_def = servers[0].get_concat(key=key)
            get_value = yield threads.defer_to_thread(get_def.wait, 10)
            assert set(json.loads(get_value)) == set(["morot", "selleri"])
            print("Node with port {} got right value: {}".format(
                servers[0].dht_server.port.getHost().port, get_value))
            value = json.dumps(["morot"])
            set_def = servers[0].remove(key=key, value=value)
            set_value = yield threads.defer_to_thread(set_def.wait, 10)
            assert set_value
            print("Node with port {} posted remove key={}, value={}".format(
                servers[0].dht_server.port.getHost().port, key, value))
            get_def = servers[1].get_concat(key=key)
            get_value = yield threads.defer_to_thread(get_def.wait, 10)
            assert set(json.loads(get_value)) == set(["selleri"])
            print("Node with port {} got right value: {}".format(
                servers[0].dht_server.port.getHost().port, get_value))
            for i in range(0, amount_of_servers):
                name_dir = rt_credentials[i].get_credentials_path()
                filenames = os.listdir(os.path.join(name_dir, "others"))
                print("Node with port {} has {} certificates in store".format(
                    servers[i].dht_server.port.getHost().port, len(filenames)))

        except AssertionError as e:
            print(
                "Node with port {} got wrong value: {}, should have been {}, e={}"
                .format(servers[0].dht_server.port.getHost().port, get_value,
                        value, e))
            pytest.fail(traceback.format_exc())
        except Exception as e:
            traceback.print_exc()
            pytest.fail(traceback.format_exc())
        finally:
            yield threads.defer_to_thread(time.sleep, 10)
            for server in servers:
                server.stop()
Exemplo n.º 13
0
    def test_dht_multi(self, monkeypatch):
        iface = "0.0.0.0"
        a = None
        b = None
        q = Queue.Queue()

        def server_started(aa, *args):
            for b in args:
                if isinstance(b, twisted.python.failure.Failure):
                    b.printTraceback()
                else:
                    _log.debug("** %s" % b)
            q.put([aa, args])

        try:
            amount_of_servers = 1
            # Twisted is using 20 threads so having > 20 server
            # causes threadlocks really easily.

            servers = []
            callbacks = []
            for servno in range(0, amount_of_servers):
                uri = "http://{}:500{}".format(ip_addr, servno)
                control_uri = "http://{}:502{}".format(ip_addr, servno)
                rt_cred = runtime_credentials.RuntimeCredentials(
                    name=name, domain=domain, security_dir=testdir)
                node_id = rt_cred.node_id
                a = evilAutoDHTServer(node_id, control_uri, rt_cred)
                servers.append(a)
                callback = CalvinCB(server_started, str(servno))
                servers[servno].start(iface,
                                      network="Niklas",
                                      cb=callback,
                                      type="poison",
                                      name=name)
                # servers[servno].start(iface, network="Hej", cb=callback, type="eclipse", name=name)
                # servers[servno].start(iface, network="Hej", cb=callback, type="sybil")
                # servers[servno].start(iface, network="Hej", cb=callback, type="insert")
                callbacks.append(callback)
            print("Starting {}".format(
                servers[servno].dht_server.port.getHost().port))

            # Wait for start
            started = []
            while len(started) < amount_of_servers:
                try:
                    server = yield threads.defer_to_thread(q.get)
                except Queue.Empty:
                    _log.debug("Queue empty!")
                    #raise
                if server not in started:
                    started.append(server)
                    _log.debug("DHT Servers added: {}".format(started))
                    callbacks[int(
                        server[0][0])].func = lambda *args, **kvargs: None
                else:
                    _log.debug("Server: {} already started." \
                               " {} out of {}".format(started,
                                                     len(started),
                                                     amount_of_servers))

            _log.debug("All {} out of {} started".format(
                started, len(started), amount_of_servers))

            for servno in range(0, amount_of_servers):
                assert [str(servno), self._sucess_start] in started

            yield threads.defer_to_thread(q.queue.clear)
            yield threads.defer_to_thread(time.sleep, 15)

            evilPort = servers[0].dht_server.port.getHost().port
            drawNetworkState("start_graph.png", servers, amount_of_servers)
            servers[0].dht_server.kserver.protocol.turn_evil(evilPort)
            print("Node with port {} turned evil".format(
                servers[servno].dht_server.port.getHost().port))

            yield threads.defer_to_thread(time.sleep, 12)
            # assert get_value[0] == "banan"
            # assert get_value[1] == "bambu"
            # assert get_value[2] == "morot"
            yield threads.defer_to_thread(time.sleep, 5)
            print("Attacking node exiting")

        except AssertionError as e:
            print("Server {} with port {} got wrong value".format(
                servno, servers[servno].dht_server.port.getHost().port))
            pytest.fail(traceback.format_exc())

        except Exception as e:
            traceback.print_exc()
            pytest.fail(traceback.format_exc())
        finally:
            for server in servers:
                server.stop()
                yield threads.defer_to_thread(time.sleep, 5)
Exemplo n.º 14
0
                                  commonName="sec-dht-test-security-CA",
                                  security_dir=testdir)
print "Created new domain."

print "Import CA cert into truststore."
testca.export_ca_cert(runtimes_truststore)

print "Generate runtime credentials and sign their certificates"
for i in range(1, 5):
    for j in range(0, 6):
        name = "node{}:{}".format(i, j)
        enrollment_password = testca.cert_enrollment_add_new_runtime(name)
        nodeid = calvinuuid.uuid("NODE")
        rt_cred = runtime_credentials.RuntimeCredentials(
            name,
            domain="test",
            security_dir=testdir,
            nodeid=nodeid,
            enrollment_password=enrollment_password)
        csr_path = os.path.join(rt_cred.runtime_dir, name + ".csr")
        try:
            with open(csr_path + ".challenge_password", 'w') as csr_fd:
                csr_fd.write(enrollment_password)
        except Exception as err:
            _log.exception(
                "Failed to write challenge password to file, err={}".format(
                    err))
            raise
        certpath = testca.sign_csr(csr_path)
        rt_cred.store_own_cert(certpath=certpath)

print "Generate evil node runtime credentials and sign certificate"
Exemplo n.º 15
0
    def setup(self, request):
        from calvin.Tools.csruntime import csruntime
        from conftest import _config_pytest
        import fileinput
        global rt
        global request_handler
        try:
            shutil.rmtree(credentials_testdir)
        except Exception as err:
            print "Failed to remove old tesdir, err={}".format(err)
            pass
        try:
            os.makedirs(credentials_testdir)
            os.makedirs(runtimesdir)
            os.makedirs(runtimes_truststore)
            os.makedirs(runtimes_truststore_signing_path)
            os.makedirs(actor_store_path)
            os.makedirs(os.path.join(actor_store_path, "test"))
            shutil.copy(
                os.path.join(orig_actor_store_path, "test", "__init__.py"),
                os.path.join(actor_store_path, "test", "__init__.py"))
            os.makedirs(os.path.join(actor_store_path, "std"))
            shutil.copy(
                os.path.join(orig_actor_store_path, "std", "__init__.py"),
                os.path.join(actor_store_path, "std", "__init__.py"))
            shutil.copytree(orig_application_store_path,
                            application_store_path)
            filelist = [
                f for f in os.listdir(application_store_path)
                if f.endswith(".sign.93d58fef")
            ]
            for f in filelist:
                os.remove(os.path.join(application_store_path, f))
            shutil.copytree(
                os.path.join(security_testdir, "identity_provider"),
                identity_provider_path)
        except Exception as err:
            _log.error(
                "Failed to create test folder structure, err={}".format(err))
            print "Failed to create test folder structure, err={}".format(err)
            raise

        print "Trying to create a new test application/actor signer."
        cs = code_signer.CS(organization="testsigner",
                            commonName="signer",
                            security_dir=credentials_testdir)

        #Create signed version of CountTimer actor
        orig_actor_CountTimer_path = os.path.join(orig_actor_store_path, "std",
                                                  "CountTimer.py")
        actor_CountTimer_path = os.path.join(actor_store_path, "std",
                                             "CountTimer.py")
        shutil.copy(orig_actor_CountTimer_path, actor_CountTimer_path)
        #        cs.sign_file(actor_CountTimer_path)

        #Create unsigned version of CountTimer actor
        actor_CountTimerUnsigned_path = actor_CountTimer_path.replace(
            ".py", "Unsigned.py")
        shutil.copy(actor_CountTimer_path, actor_CountTimerUnsigned_path)
        replace_text_in_file(actor_CountTimerUnsigned_path, "CountTimer",
                             "CountTimerUnsigned")

        #Create signed version of Sum actor
        orig_actor_Sum_path = os.path.join(orig_actor_store_path, "std",
                                           "Sum.py")
        actor_Sum_path = os.path.join(actor_store_path, "std", "Sum.py")
        shutil.copy(orig_actor_Sum_path, actor_Sum_path)
        #        cs.sign_file(actor_Sum_path)

        #Create unsigned version of Sum actor
        actor_SumUnsigned_path = actor_Sum_path.replace(".py", "Unsigned.py")
        shutil.copy(actor_Sum_path, actor_SumUnsigned_path)
        replace_text_in_file(actor_SumUnsigned_path, "Sum", "SumUnsigned")

        #Create incorrectly signed version of Sum actor
        #        actor_SumFake_path = actor_Sum_path.replace(".py", "Fake.py")
        #        shutil.copy(actor_Sum_path, actor_SumFake_path)
        #        #Change the class name to SumFake
        #        replace_text_in_file(actor_SumFake_path, "Sum", "SumFake")
        #        cs.sign_file(actor_SumFake_path)
        #        #Now append to the signed file so the signature verification fails
        #        with open(actor_SumFake_path, "a") as fd:
        #                fd.write(" ")

        #Create signed version of Sink actor
        orig_actor_Sink_path = os.path.join(orig_actor_store_path, "test",
                                            "Sink.py")
        actor_Sink_path = os.path.join(actor_store_path, "test", "Sink.py")
        shutil.copy(orig_actor_Sink_path, actor_Sink_path)
        #        cs.sign_file(actor_Sink_path)

        #Create unsigned version of Sink actor
        actor_SinkUnsigned_path = actor_Sink_path.replace(".py", "Unsigned.py")
        shutil.copy(actor_Sink_path, actor_SinkUnsigned_path)
        replace_text_in_file(actor_SinkUnsigned_path, "Sink", "SinkUnsigned")

        #Sign applications
        #        cs.sign_file(os.path.join(application_store_path, "test_security1_correctly_signed.calvin"))
        #        cs.sign_file(os.path.join(application_store_path, "test_security1_correctlySignedApp_incorrectlySignedActor.calvin"))
        #        cs.sign_file(os.path.join(application_store_path, "test_security1_incorrectly_signed.calvin"))
        #        #Now append to the signed file so the signature verification fails
        #        with open(os.path.join(application_store_path, "test_security1_incorrectly_signed.calvin"), "a") as fd:
        #                fd.write(" ")

        #        print "Export Code Signers certificate to the truststore for code signing"
        #        out_file = cs.export_cs_cert(runtimes_truststore_signing_path)

        print "Trying to create a new test domain configuration."
        ca = certificate_authority.CA(domain=domain_name,
                                      commonName="testdomain CA",
                                      security_dir=credentials_testdir)
        #
        print "Copy CA cert into truststore of runtimes folder"
        ca.export_ca_cert(runtimes_truststore)
        #Define the runtime attributes
        rt0_attributes = {
            'indexed_public': {
                'owner': {
                    'organization': domain_name,
                    'personOrGroup': 'testOwner1'
                },
                'node_name': {
                    'organization': 'org.testexample',
                    'name': 'CA'
                },
                'address': {
                    'country': 'SE',
                    'locality': 'testCity',
                    'street': 'testStreet',
                    'streetNumber': 1
                }
            }
        }
        rt1_attributes = {
            'indexed_public': {
                'owner': {
                    'organization': domain_name,
                    'personOrGroup': 'testOwner1'
                },
                'node_name': {
                    'organization': 'org.testexample',
                    'name': 'testNode1'
                },
                'address': {
                    'country': 'SE',
                    'locality': 'testCity',
                    'street': 'testStreet',
                    'streetNumber': 1
                }
            }
        }
        rt2_attributes = {
            'indexed_public': {
                'owner': {
                    'organization': domain_name,
                    'personOrGroup': 'testOwner1'
                },
                'node_name': {
                    'organization': 'org.testexample',
                    'name': 'testNode2'
                },
                'address': {
                    'country': 'SE',
                    'locality': 'testCity',
                    'street': 'otherStreet',
                    'streetNumber': 1
                }
            }
        }
        rt3_attributes = {
            'indexed_public': {
                'owner': {
                    'organization': domain_name,
                    'personOrGroup': 'testOwner1'
                },
                'node_name': {
                    'organization': 'org.testexample',
                    'name': 'testNode3'
                },
                'address': {
                    'country': 'SE',
                    'locality': 'testCity',
                    'street': 'testStreet',
                    'streetNumber': 1
                }
            }
        }
        rt4_attributes = {
            'indexed_public': {
                'owner': {
                    'organization': domain_name,
                    'personOrGroup': 'testOwner1'
                },
                'node_name': {
                    'organization': 'org.testexample',
                    'name': 'testNode4'
                },
                'address': {
                    'country': 'SE',
                    'locality': 'testCity',
                    'street': 'testStreet',
                    'streetNumber': 1
                }
            }
        }
        rt5_attributes = {
            'indexed_public': {
                'owner': {
                    'organization': domain_name,
                    'personOrGroup': 'testOwner1'
                },
                'node_name': {
                    'organization': 'org.testexample',
                    'name': 'testNode5'
                },
                'address': {
                    'country': 'SE',
                    'locality': 'testCity',
                    'street': 'testStreet',
                    'streetNumber': 1
                }
            }
        }
        rt_attributes = []
        rt_attributes.append(deepcopy(rt0_attributes))
        rt_attributes.append(deepcopy(rt1_attributes))
        rt_attributes.append(deepcopy(rt2_attributes))
        rt_attributes.append(deepcopy(rt3_attributes))
        rt_attributes.append(deepcopy(rt4_attributes))
        rt_attributes.append(deepcopy(rt5_attributes))
        rt_attributes_cpy = deepcopy(rt_attributes)
        runtimes = []
        #Initiate Requesthandler with trusted CA cert
        truststore_dir = certificate.get_truststore_path(
            type=certificate.TRUSTSTORE_TRANSPORT,
            security_dir=credentials_testdir)
        #   The following is less than optimal if multiple CA certs exist
        ca_cert_path = os.path.join(truststore_dir,
                                    os.listdir(truststore_dir)[0])
        request_handler = RequestHandler(verify=ca_cert_path)
        #Generate credentials, create CSR, sign with CA and import cert for all runtimes
        enrollment_passwords = []
        for rt_attribute in rt_attributes:
            attributes = AttributeResolver(rt_attribute)
            node_name = attributes.get_node_name_as_str()
            nodeid = calvinuuid.uuid("")
            enrollment_password = ca.cert_enrollment_add_new_runtime(node_name)
            enrollment_passwords.append(enrollment_password)
            runtime = runtime_credentials.RuntimeCredentials(
                node_name,
                domain=domain_name,
                security_dir=credentials_testdir,
                nodeid=nodeid,
                enrollment_password=enrollment_password)
            runtimes.append(runtime)
            ca_cert = runtime.get_truststore(
                type=certificate.TRUSTSTORE_TRANSPORT)[0][0]
            csr_path = os.path.join(runtime.runtime_dir, node_name + ".csr")
            #Encrypt CSR with CAs public key (to protect enrollment password)
            rsa_encrypted_csr = runtime.cert_enrollment_encrypt_csr(
                csr_path, ca_cert)
            #Decrypt encrypted CSR with CAs private key
            csr = ca.decrypt_encrypted_csr(
                encrypted_enrollment_request=rsa_encrypted_csr)
            csr_path = ca.store_csr_with_enrollment_password(csr)
            cert_path = ca.sign_csr(csr_path)
            runtime.store_own_cert(certpath=cert_path,
                                   security_dir=credentials_testdir)
        #Let's hash passwords in users.json file (the runtimes will try to do this
        # but they will all try to do it at the same time, so it will be overwritten
        # multiple times and the first test will always fail)
#        self.arp = FileAuthenticationRetrievalPoint(identity_provider_path)
#        self.arp.check_stored_users_db_for_unhashed_passwords()

#The policy allows access to control interface for everyone, for more advanced rules
# it might be appropriate to run set_credentials for request_handler, e.g.,
#  request_handler.set_credentials({domain_name:{"user": "******", "password": "******"}})

        rt_conf = copy.deepcopy(_conf)
        #        rt_conf.set('security', 'runtime_to_runtime_security', "tls")
        #        rt_conf.set('security', 'control_interface_security', "tls")
        rt_conf.set('security', 'domain_name', domain_name)
        #        rt_conf.set('security', 'certificate_authority_control_uri',"https://%s:5020" % hostname )
        rt_conf.set('security', 'security_dir', credentials_testdir)
        rt_conf.set('global', 'actor_paths', [actor_store_path])
        rt_conf.set('global', 'storage_type', "securedht")

        # Runtime 0: local authentication, signature verification, local authorization.
        # Primarily acts as Certificate Authority for the domain
        rt0_conf = copy.deepcopy(rt_conf)
        #        rt0_conf.set('security','enrollment_password',enrollment_passwords[0])
        #The csruntime certificate requests assumes TLS for the control interface
        #        rt0_conf.set('security', 'control_interface_security', "tls")
        #        rt0_conf.set('security','certificate_authority','True')
        #        rt0_conf.set("security", "security_conf", {
        #                        "comment": "Certificate Authority",
        #                        "authentication": {
        #                            "procedure": "local",
        #                            "identity_provider_path": identity_provider_path
        #                        },
        #                        "authorization": {
        #                            "procedure": "local",
        #                            "policy_storage_path": policy_storage_path
        #                        }
        #                    })
        rt0_conf.save("/tmp/calvin5000.conf")

        # Runtime 1: local authentication, signature verification, local authorization.
        rt1_conf = copy.deepcopy(rt_conf)
        #        rt1_conf.set('security','enrollment_password',enrollment_passwords[1])
        #        rt1_conf.set("security", "security_conf", {
        #                        "comment": "Local authentication, local authorization",
        #                        "authentication": {
        #                            "procedure": "local",
        #                            "identity_provider_path": identity_provider_path
        #                        },
        #                        "authorization": {
        #                            "procedure": "local",
        #                            "policy_storage_path": policy_storage_path
        #                        }
        #                    })
        rt1_conf.save("/tmp/calvin5001.conf")

        # Runtime 2: local authentication, signature verification, local authorization.
        # Can also act as authorization server for other runtimes.
        # Other street compared to the other runtimes
        rt2_conf = copy.deepcopy(rt_conf)
        #        rt2_conf.set('security','enrollment_password',enrollment_passwords[2])
        #        rt2_conf.set("security", "security_conf", {
        #                        "comment": "Local authentication, local authorization",
        #                        "authentication": {
        #                            "procedure": "local",
        #                            "identity_provider_path": identity_provider_path
        #                        },
        #                        "authorization": {
        #                            "procedure": "local",
        #                            "policy_storage_path": policy_storage_path,
        #                            "accept_external_requests": True
        #                        }
        #                    })
        rt2_conf.save("/tmp/calvin5002.conf")

        # Runtime 3: external authentication (RADIUS), signature verification, local authorization.
        rt3_conf = copy.deepcopy(rt_conf)
        #        rt3_conf.set('security','enrollment_password',enrollment_passwords[3])
        #        rt3_conf.set("security", "security_conf", {
        #                        "comment": "RADIUS authentication, local authorization",
        #                        "authentication": {
        #                            "procedure": "radius",
        #                            "server_ip": "localhost",
        #                            "secret": "elxghyc5lz1_passwd"
        #                        },
        #                        "authorization": {
        #                            "procedure": "local",
        #                            "policy_storage_path": policy_storage_path
        #                        }
        #                    })
        rt3_conf.save("/tmp/calvin5003.conf")

        # Runtime 4: local authentication, signature verification, external authorization (runtime 2).
        rt4_conf = copy.deepcopy(rt_conf)
        #        rt4_conf.set('security','enrollment_password',enrollment_passwords[4])
        #        rt4_conf.set("security", "security_conf", {
        #                        "comment": "Local authentication, external authorization",
        #                        "authentication": {
        #                            "procedure": "local",
        #                            "identity_provider_path": identity_provider_path
        #                        },
        #                        "authorization": {
        #                            "procedure": "external"
        #                        }
        #                    })
        rt4_conf.save("/tmp/calvin5004.conf")

        # Runtime 5: external authentication (runtime 1), signature verification, local authorization.
        rt5_conf = copy.deepcopy(rt_conf)
        #        rt5_conf.set('global','storage_type','proxy')
        #        rt5_conf.set('global','storage_proxy',"calvinip://%s:5000" % ip_addr )
        #        rt5_conf.set('security','enrollment_password',enrollment_passwords[5])
        #        rt5_conf.set("security", "security_conf", {
        #                        "comment": "Local authentication, external authorization",
        #                        "authentication": {
        #                            "procedure": "external",
        #                            "server_uuid": runtimes[1].node_id
        #                        },
        #                        "authorization": {
        #                            "procedure": "local",
        #                            "policy_storage_path": policy_storage_path
        #                        }
        #                    })
        rt5_conf.save("/tmp/calvin5005.conf")

        #Start all runtimes
        for i in range(len(rt_attributes_cpy)):
            _log.info("Starting runtime {}".format(i))
            try:
                logfile = _config_pytest.getoption("logfile") + "500{}".format(
                    i)
                outfile = os.path.join(
                    os.path.dirname(logfile),
                    os.path.basename(logfile).replace("log", "out"))
                if outfile == logfile:
                    outfile = None
            except:
                logfile = None
                outfile = None
            csruntime(hostname,
                      port=5000 + i,
                      controlport=5020 + i,
                      attr=rt_attributes_cpy[i],
                      loglevel=_config_pytest.getoption("loglevel"),
                      logfile=logfile,
                      outfile=outfile,
                      configfile="/tmp/calvin500{}.conf".format(i))
            #            rt.append(RT("https://{}:502{}".format(hostname, i)))
            rt.append(RT("http://{}:502{}".format(hostname, i)))
            # Wait to be sure that all runtimes has started
            time.sleep(1)
        time.sleep(10)

        request.addfinalizer(self.teardown)
Exemplo n.º 16
0
    def join(self):
        if self._proto:
            raise Exception("Already connected")

        # Own callbacks
        callbacks = {
            'connected': [CalvinCB(self._connected)],
            'disconnected': [CalvinCB(self._disconnected)],
            'connection_failed': [CalvinCB(self._connection_failed)],
            'data': [CalvinCB(self._data)],
            'set_proto': [CalvinCB(self._set_proto)]
        }

        self._factory = TCPClientFactory(
            callbacks)  # addr="%s:%s" % (self._host_ip, self._host_port))
        runtime_to_runtime_security = _conf.get("security",
                                                "runtime_to_runtime_security")
        if runtime_to_runtime_security == "tls":
            _log.debug("TwistedCalvinTransport with TLS chosen")
            try:
                self._runtime_credentials = runtime_credentials.RuntimeCredentials(
                    self._node_name)
                ca_cert_list_str, ca_cert_list_x509, truststore = certificate.get_truststore(
                    certificate.TRUSTSTORE_TRANSPORT)
                #TODO: figure out how to set more than one root cert in twisted truststore
                twisted_trusted_ca_cert = ssl.Certificate.loadPEM(
                    ca_cert_list_str[0])
                client_credentials_data = self._runtime_credentials.get_runtime_credentials(
                )
                client_credentials = ssl.PrivateCertificate.loadPEM(
                    client_credentials_data)
            except Exception as err:
                _log.error(
                    "TwistedCalvinTransport: Failed to load client credentials, err={}"
                    .format(err))
                raise
            try:
                options = ssl.optionsForClientTLS(self._server_node_name,
                                                  twisted_trusted_ca_cert,
                                                  client_credentials)
            except Exception as err:
                _log.error(
                    "TwistedCalvinTransport: Failed to create optionsForClientTLS "
                    "\n\terr={}"
                    "\n\tself._server_node_name={}".format(
                        err, self._server_node_name))
                raise
            try:
                endpoint = endpoints.SSL4ClientEndpoint(
                    reactor, self._host_ip, int(self._host_port), options)
            except:
                _log.error("TwistedCalvinTransport: Client failed connectSSL")
                raise
            try:
                endpoint.connect(self._factory)
            except Exception as e:
                _log.error(
                    "TwistedCalvinTransport: Failed endpoint.connect, e={}".
                    format(e))
                raise
        else:
            reactor.connectTCP(self._host_ip, int(self._host_port),
                               self._factory)
Exemplo n.º 17
0
    def setup(self, request):
        from calvin.Tools.csruntime import csruntime
        from conftest import _config_pytest
        import fileinput
        global hostname
        global rt
        global rt_attributes
        global request_handler
        try:
            ipv6_hostname = socket.gethostbyaddr('::1')
        except Exception as err:
            print(
                "Failed to resolve the IPv6 localhost hostname, please update the corresponding entry in the /etc/hosts file, e.g.,:\n"
                "\t::1              <hostname>.localdomain <hostname>.local <hostname> localhost"
            )
            raise
        try:
            ipv6_hostname = socket.gethostbyaddr('::ffff:127.0.0.1')
        except Exception as err:
            print(
                "Failed to resolve ::ffff:127.0.0.1, please add the following line (with your hostname) to  /etc/hosts :\n"
                "::ffff:127.0.0.1:           <hostname>.localdomain <hostname>.local <hostname>"
            )
            raise
        try:
            hostname = socket.gethostname()
            ip_addr = socket.gethostbyname(hostname)
            fqdn = socket.getfqdn(hostname)
            print("\n\tip_addr={}"
                  "\n\thostname={}"
                  "\n\tfqdn={}".format(ip_addr, hostname, fqdn))
        except Exception as err:
            print(
                "Failed to resolve the hostname, ip_addr or the FQDN of the runtime, err={}"
                .format(err))
            raise

        try:
            shutil.rmtree(credentials_testdir)
        except Exception as err:
            print "Failed to remove old tesdir, err={}".format(err)
            pass
        try:
            os.mkdir(credentials_testdir)
            os.mkdir(runtimesdir)
            os.mkdir(runtimes_truststore)
        except Exception as err:
            _log.error(
                "Failed to create test folder structure, err={}".format(err))
            print "Failed to create test folder structure, err={}".format(err)
            raise

        _log.info("Trying to create a new test domain configuration.")
        try:
            ca = certificate_authority.CA(domain=domain_name,
                                          commonName="testdomain CA",
                                          security_dir=credentials_testdir)
        except Exception as err:
            _log.error("Failed to create CA, err={}".format(err))

        _log.info("Copy CA cert into truststore of runtimes folder")
        ca.export_ca_cert(runtimes_truststore)
        node_names = []
        rt_attributes = []
        for i in range(6):
            node_name = {
                'organization': 'org.testexample',
                'name': 'testNode{}'.format(i)
            }
            owner = {'organization': domain_name, 'personOrGroup': 'testOwner'}
            address = {
                'country': 'SE',
                'locality': 'testCity',
                'street': 'testStreet',
                'streetNumber': 1
            }
            rt_attribute = {
                'indexed_public': {
                    'owner': owner,
                    'node_name': node_name,
                    'address': address
                }
            }
            rt_attributes.append(rt_attribute)
        rt_attributes_cpy = deepcopy(rt_attributes)
        runtimes = []
        #Initiate Requesthandler with trusted CA cert
        truststore_dir = certificate.get_truststore_path(
            type=certificate.TRUSTSTORE_TRANSPORT,
            security_dir=credentials_testdir)
        #   The following is less than optimal if multiple CA certs exist
        ca_cert_path = os.path.join(truststore_dir,
                                    os.listdir(truststore_dir)[0])
        request_handler = RequestHandler(verify=ca_cert_path)

        #Generate credentials, create CSR, sign with CA and import cert for all runtimes
        enrollment_passwords = []
        for rt_attribute in rt_attributes_cpy:
            _log.info("rt_attribute={}".format(rt_attribute))
            attributes = AttributeResolver(rt_attribute)
            node_name = attributes.get_node_name_as_str()
            nodeid = calvinuuid.uuid("")
            enrollment_password = ca.cert_enrollment_add_new_runtime(node_name)
            enrollment_passwords.append(enrollment_password)
            runtime = runtime_credentials.RuntimeCredentials(
                node_name,
                domain=domain_name,
                security_dir=credentials_testdir,
                nodeid=nodeid,
                enrollment_password=enrollment_password)
            runtimes.append(runtime)
            ca_cert = runtime.get_truststore(
                type=certificate.TRUSTSTORE_TRANSPORT)[0][0]
            csr_path = os.path.join(runtime.runtime_dir, node_name + ".csr")
            #Encrypt CSR with CAs public key (to protect enrollment password)
            rsa_encrypted_csr = runtime.cert_enrollment_encrypt_csr(
                csr_path, ca_cert)
            #Decrypt encrypted CSR with CAs private key
            csr = ca.decrypt_encrypted_csr(
                encrypted_enrollment_request=rsa_encrypted_csr)
            csr_path = ca.store_csr_with_enrollment_password(csr)
            cert_path = ca.sign_csr(csr_path)
            runtime.store_own_cert(certpath=cert_path,
                                   security_dir=credentials_testdir)

        rt_conf = copy.deepcopy(_conf)
        rt_conf.set('security', 'runtime_to_runtime_security', "tls")
        rt_conf.set('security', 'control_interface_security', "tls")
        rt_conf.set('security', 'domain_name', domain_name)
        rt_conf.set('security', 'security_dir', credentials_testdir)
        rt0_conf = copy.deepcopy(rt_conf)
        rt_conf.set('global', 'storage_type', 'proxy')
        rt_conf.set('global', 'storage_proxy', "calvinip://%s:5000" % hostname)

        # Runtime 0: local authentication, signature verification, local authorization.
        # Primarily acts as Certificate Authority for the domain
        rt0_conf.set('global', 'storage_type', 'local')
        rt0_conf.save("/tmp/calvin5000.conf")

        # Runtime 1: local authentication, signature verification, local authorization.
        rt1_conf = copy.deepcopy(rt_conf)
        rt1_conf.save("/tmp/calvin5001.conf")

        # Runtime 2: local authentication, signature verification, local authorization.
        # Can also act as authorization server for other runtimes.
        # Other street compared to the other runtimes
        rt2_conf = copy.deepcopy(rt_conf)
        rt2_conf.save("/tmp/calvin5002.conf")

        # Runtime 3: external authentication (RADIUS), signature verification, local authorization.
        rt3_conf = copy.deepcopy(rt_conf)
        rt3_conf.save("/tmp/calvin5003.conf")

        # Runtime 4: local authentication, signature verification, external authorization (runtime 2).
        rt4_conf = copy.deepcopy(rt_conf)
        rt4_conf.save("/tmp/calvin5004.conf")

        # Runtime 5: external authentication (runtime 1), signature verification, local authorization.
        rt5_conf = copy.deepcopy(rt_conf)
        rt5_conf.save("/tmp/calvin5005.conf")

        #Start all runtimes
        for i in range(len(rt_attributes)):
            _log.info("Starting runtime {}".format(i))
            try:
                logfile = _config_pytest.getoption("logfile") + "500{}".format(
                    i)
                outfile = os.path.join(
                    os.path.dirname(logfile),
                    os.path.basename(logfile).replace("log", "out"))
                if outfile == logfile:
                    outfile = None
            except:
                logfile = None
                outfile = None
            csruntime(hostname,
                      port=5000 + i,
                      controlport=5020 + i,
                      attr=rt_attributes[i],
                      loglevel=_config_pytest.getoption("loglevel"),
                      logfile=logfile,
                      outfile=outfile,
                      configfile="/tmp/calvin500{}.conf".format(i))
            rt.append(RT("https://{}:502{}".format(hostname, i)))
            # Wait to be sure that all runtimes has started
            time.sleep(1)
        time.sleep(2)

        request.addfinalizer(self.teardown)
Exemplo n.º 18
0
def runtime_certificate(rt_attributes):
    import copy
    import requests
    import sys
    from calvin.requests.request_handler import RequestHandler
    from calvin.utilities.attribute_resolver import AttributeResolver
    from calvin.utilities import calvinconfig
    from calvin.utilities import calvinuuid
    from calvin.utilities import runtime_credentials
    from calvin.utilities import certificate
    from calvin.utilities import certificate_authority
    from calvin.runtime.south.plugins.storage.twistedimpl.dht.service_discovery_ssdp import parse_http_response
    global _conf
    global _log
    _conf = calvinconfig.get()
    if not _conf.get_section("security"):
        #If the security section is empty, no securty features are enabled and certificates aren't needed
        _log.debug("No runtime security enabled")
    else:
        _log.debug(
            "Some security features are enabled, let's make sure certificates are in place"
        )
        _ca_conf = _conf.get("security", "certificate_authority")
        security_dir = _conf.get("security", "security_dir")
        storage_type = _conf.get("global", "storage_type")
        if _ca_conf:
            try:
                ca_ctrl_uri = _ca_conf[
                    "ca_control_uri"] if "ca_control_uri" in _ca_conf else None
                domain_name = _ca_conf[
                    "domain_name"] if "domain_name" in _ca_conf else None
                is_ca = _ca_conf["is_ca"] if "is_ca" in _ca_conf else None
                enrollment_password = _ca_conf[
                    "enrollment_password"] if "enrollment_password" in _ca_conf else None
            except Exception as err:
                _log.error(
                    "runtime_certificate: Failed to parse security configuration in calvin.conf, err={}"
                    .format(err))
                raise
            #AttributeResolver tranforms the attributes, so make a deepcopy instead
            rt_attributes_cpy = copy.deepcopy(rt_attributes)
            attributes = AttributeResolver(rt_attributes_cpy)
            node_name = attributes.get_node_name_as_str()
            nodeid = calvinuuid.uuid("")
            runtime = runtime_credentials.RuntimeCredentials(
                node_name,
                domain_name,
                security_dir=security_dir,
                nodeid=nodeid,
                enrollment_password=enrollment_password)
            certpath, cert, certstr = runtime.get_own_cert()
            if not cert:
                csr_path = os.path.join(runtime.runtime_dir,
                                        node_name + ".csr")
                if is_ca == "True":
                    _log.debug(
                        "No runtime certificate, but node is a CA, just sign csr, domain={}"
                        .format(domain_name))
                    ca = certificate_authority.CA(domain=domain_name,
                                                  security_dir=security_dir)
                    cert_path = ca.sign_csr(csr_path, is_ca=True)
                    runtime.store_own_cert(certpath=cert_path,
                                           security_dir=security_dir)

                else:
                    _log.debug(
                        "No runtime certicificate can be found, send CSR to CA"
                    )
                    truststore_dir = certificate.get_truststore_path(
                        type=certificate.TRUSTSTORE_TRANSPORT,
                        security_dir=security_dir)
                    request_handler = RequestHandler(verify=truststore_dir)
                    ca_control_uris = []
                    #TODO: add support for multiple CA control uris
                    if ca_ctrl_uri:
                        _log.debug(
                            "CA control_uri in config={}".format(ca_ctrl_uri))
                        ca_control_uris.append(ca_ctrl_uri)
                    elif storage_type in ["dht", "securedht"]:
                        _log.debug("Find CA via SSDP")
                        responses = discover()
                        if not responses:
                            _log.error("No responses received")
                        for response in responses:
                            cmd, headers = parse_http_response(response)
                            if 'location' in headers:
                                ca_control_uri, ca_node_id = headers[
                                    'location'].split('/node/')
                                ca_control_uri = ca_control_uri.replace(
                                    "http", "https")
                                ca_control_uris.append(ca_control_uri)
                                _log.debug(
                                    "CA control_uri={}, node_id={}".format(
                                        ca_control_uri, ca_node_id))
                    else:
                        _log.error(
                            "There is no runtime certificate. For automatic certificate enrollment using proxy storage,"
                            "the CA control uri must be configured in the calvin configuration "
                        )
                        raise Exception(
                            "There is no runtime certificate. For automatic certificate enrollment using proxy storage,"
                            "the CA control uri must be configured in the calvin configuration "
                        )
                    cert_available = False
                    # Loop through all CA:s that responded until hopefully one signs our CSR
                    # Potential improvement would be to have domain name in response and only try
                    # appropriate CAs
                    i = 0
                    while not cert_available and i < len(ca_control_uris):
                        certstr = None
                        #Repeatedly (maximum 10 attempts) send CSR to CA until a certificate is returned (this to remove the requirement of the CA
                        #node to be be the first node to start)
                        rsa_encrypted_csr = runtime.get_encrypted_csr()
                        j = 0
                        while not certstr and j < 10:
                            try:
                                certstr = request_handler.sign_csr_request(
                                    ca_control_uris[i],
                                    rsa_encrypted_csr)['certificate']
                            except requests.exceptions.RequestException as err:
                                time_to_sleep = 1 + j * j * j
                                _log.debug(
                                    "RequestException, CSR not accepted or CA not up and running yet, sleep {} seconds and try again, err={}"
                                    .format(time_to_sleep, err))
                                time.sleep(time_to_sleep)
                                j = j + 1
                                pass
                            else:
                                cert_available = True
                        i = i + 1
                    #TODO: check that everything is ok with signed cert, e.g., check that the CA domain
                    # matches the expected and that the CA cert is trusted
                    runtime.store_own_cert(certstring=certstr,
                                           security_dir=security_dir)
            else:
                _log.debug("Runtime certificate available")