Пример #1
0
 def _call_freetls(self, vhost):
     acme_server = self._get_acme_server()
     logger.info(
         "Calling issue_certificate for %s on %s", vhost, acme_server)
     try:
         freetls.issue_certificate(
             domains=vhost.domains,
             certificate_file=vhost.certificate_file,
             private_key_file=vhost.private_key_file,
             account_cache_directory=vhost.folder,
             acme_server=acme_server,
             agree_to_tos_url=self.tos_url)
         return
     except freetls.NeedToAgreeToTOS as tos_error:
         logger.warning("TOS URL changed to %s", tos_error.url)
         self.tos_url = tos_error.url
     except freetls.WaitABit as wait_error:
         logger.warning("Trying again after: %s", wait_error.until_when)
         t_delta = wait_error.until_when - datetime.datetime.now()
         seconds_to_wait = max(t_delta.total_seconds(), 0)
         # Sleep until we should try it again
         logger.debug("Sleeping for %i seconds", seconds_to_wait)
         time.sleep(seconds_to_wait)
     # Try it again
     self._call_freetls(vhost)
Пример #2
0
 def do_issue(self, domains=domains, validation_method=client.HTTPValidation(port=5002), **kwargs):
     client.issue_certificate(
         domains,
         self.account_dir,
         validation_method=validation_method,
         certificate_file=os.path.join(self.output_dir, "certificate.crt"),
         certificate_chain_file=os.path.join(self.output_dir, "chain.crt"),
         acme_server=ACME_SERVER,
         **kwargs)
Пример #3
0
 def do_issue(self,
              domains=domains,
              validation_method=client.HTTPValidation(port=5002),
              **kwargs):
     client.issue_certificate(
         domains,
         self.account_dir,
         validation_method=validation_method,
         certificate_file=os.path.join(self.output_dir, "certificate.crt"),
         certificate_chain_file=os.path.join(self.output_dir, "chain.crt"),
         acme_server=ACME_SERVER,
         **kwargs)
Пример #4
0
def issue_cert():
	letsencrypt_issued = False
	for vhost in VHost.objects.filter(use_letsencrypt=True):
		if vhost.letsencrypt_state() not in ['REQUEST', 'RENEW']:
			continue
		try:
			data = client.issue_certificate(
				[str(vhost),] + list(vhost.vhostalias_set.values_list('alias', flat=True)),
				settings.LETSENCRYPT_STATE_FOLDER,
				agree_to_tos_url = settings.LETSENCRYPT_TOS,
				acme_server = settings.LETSENCRYPT_ACME_SERVER)

			chain = b"\n".join(data['chain'])
			cert = SSLCert()
			cert.set_cert(cert=data['cert'].decode(), key=data['private_key'].decode(), ca=chain.decode())
			cert.save()

			vhost.cert = cert
			vhost.save()

			vhost.letsencrypt.last_message = ''
			vhost.letsencrypt.save()

			letsencrypt_issued = True

		except client.NeedToTakeAction as e:
			vhost.letsencrypt.last_message = str(e)
			for action in e.actions:
				if isinstance(action, client.NeedToInstallFile):
					file_name = re.sub(r'[^\w-]', '', action.file_name)
					with open(settings.LETSENCRYPT_ACME_FOLDER + '/' + file_name, 'w') as f:
						f.write(action.contents)
					vhost.letsencrypt.last_message = ''
			vhost.letsencrypt.save()
		except Exception as e:
			vhost.letsencrypt.last_message = str(e)
			vhost.letsencrypt.save()

	if letsencrypt_issued and settings.KUMQUAT_USE_0RPC:
		zerorpc.Client(connect_to=settings.KUMQUAT_BACKEND_SOCKET).update_vhosts()
Пример #5
0
def provision_certificates(env,
                           agree_to_tos_url=None,
                           logger=None,
                           show_extended_problems=True,
                           force_domains=None,
                           jsonable=False):
    import requests.exceptions
    import acme.messages

    from free_tls_certificates import client

    # What domains should we provision certificates for? And what
    # errors prevent provisioning for other domains.
    domains, problems = get_certificates_to_provision(
        env,
        force_domains=force_domains,
        show_extended_problems=show_extended_problems)

    # Exit fast if there is nothing to do.
    if len(domains) == 0:
        return {
            "requests": [],
            "problems": problems,
        }

    # Break into groups of up to 100 certificates at a time, which is Let's Encrypt's
    # limit for a single certificate. We'll sort to put related domains together.
    domains = sort_domains(domains, env)
    certs = []
    while len(domains) > 0:
        certs.append(domains[0:100])
        domains = domains[100:]

    # Prepare to provision.

    # Where should we put our Let's Encrypt account info and state cache.
    account_path = os.path.join(env['STORAGE_ROOT'], 'ssl/lets_encrypt')
    if not os.path.exists(account_path):
        os.mkdir(account_path)

    # Where should we put ACME challenge files. This is mapped to /.well-known/acme_challenge
    # by the nginx configuration.
    challenges_path = os.path.join(account_path, 'acme_challenges')
    if not os.path.exists(challenges_path):
        os.mkdir(challenges_path)

    # Read in the private key that we use for all TLS certificates. We'll need that
    # to generate a CSR (done by free_tls_certificates).
    with open(os.path.join(env['STORAGE_ROOT'], 'ssl/ssl_private_key.pem'),
              'rb') as f:
        private_key = f.read()

    # Provision certificates.

    ret = []
    for domain_list in certs:
        # For return.
        ret_item = {
            "domains": domain_list,
            "log": [],
        }
        ret.append(ret_item)

        # Logging for free_tls_certificates.
        def my_logger(message):
            if logger: logger(message)
            ret_item["log"].append(message)

        # Attempt to provision a certificate.
        try:
            try:
                cert = client.issue_certificate(
                    domain_list,
                    account_path,
                    agree_to_tos_url=agree_to_tos_url,
                    private_key=private_key,
                    logger=my_logger)

            except client.NeedToTakeAction as e:
                # Write out the ACME challenge files.
                for action in e.actions:
                    if isinstance(action, client.NeedToInstallFile):
                        fn = os.path.join(challenges_path, action.file_name)
                        with open(fn, 'w') as f:
                            f.write(action.contents)
                    else:
                        raise ValueError(str(action))

                # Try to provision now that the challenge files are installed.

                cert = client.issue_certificate(domain_list,
                                                account_path,
                                                private_key=private_key,
                                                logger=my_logger)

        except client.NeedToAgreeToTOS as e:
            # The user must agree to the Let's Encrypt terms of service agreement
            # before any further action can be taken.
            ret_item.update({
                "result": "agree-to-tos",
                "url": e.url,
            })

        except client.WaitABit as e:
            # We need to hold on for a bit before querying again to see if we can
            # acquire a provisioned certificate.
            import time, datetime
            ret_item.update({
                "result":
                "wait",
                "until":
                e.until_when if not jsonable else e.until_when.isoformat(),
                "seconds":
                (e.until_when - datetime.datetime.now()).total_seconds()
            })

        except client.AccountDataIsCorrupt as e:
            # This is an extremely rare condition.
            ret_item.update({
                "result":
                "error",
                "message":
                "Something unexpected went wrong. It looks like your local Let's Encrypt account data is corrupted. There was a problem with the file "
                + e.account_file_path + ".",
            })

        except (client.InvalidDomainName, client.NeedToTakeAction,
                client.ChallengeFailed, client.RateLimited,
                acme.messages.Error,
                requests.exceptions.RequestException) as e:
            ret_item.update({
                "result":
                "error",
                "message":
                "Something unexpected went wrong: " + str(e),
            })

        else:
            # A certificate was issued.

            install_status = install_cert(domain_list[0],
                                          cert['cert'].decode("ascii"),
                                          b"\n".join(
                                              cert['chain']).decode("ascii"),
                                          env,
                                          raw=True)

            # str indicates the certificate was not installed.
            if isinstance(install_status, str):
                ret_item.update({
                    "result":
                    "error",
                    "message":
                    "Something unexpected was wrong with the provisioned certificate: "
                    + install_status,
                })
            else:
                # A list indicates success and what happened next.
                ret_item["log"].extend(install_status)
                ret_item.update({
                    "result": "installed",
                })

    # Return what happened with each certificate request.
    return {
        "requests": ret,
        "problems": problems,
    }
Пример #6
0
def provision_certificates(env, agree_to_tos_url=None, logger=None, show_extended_problems=True, force_domains=None, jsonable=False):
	import requests.exceptions
	import acme.messages

	from free_tls_certificates import client

	# What domains should we provision certificates for? And what
	# errors prevent provisioning for other domains.
	domains, problems = get_certificates_to_provision(env, force_domains=force_domains, show_extended_problems=show_extended_problems)

	# Exit fast if there is nothing to do.
	if len(domains) == 0:
		return {
			"requests": [],
			"problems": problems,
		}

	# Break into groups of up to 100 certificates at a time, which is Let's Encrypt's
	# limit for a single certificate. We'll sort to put related domains together.
	domains = sort_domains(domains, env)
	certs = []
	while len(domains) > 0:
		certs.append( domains[0:100] )
		domains = domains[100:]

	# Prepare to provision.

	# Where should we put our Let's Encrypt account info and state cache.
	account_path = os.path.join(env['STORAGE_ROOT'], 'ssl/lets_encrypt')
	if not os.path.exists(account_path):
		os.mkdir(account_path)

	# Where should we put ACME challenge files. This is mapped to /.well-known/acme_challenge
	# by the nginx configuration.
	challenges_path = os.path.join(account_path, 'acme_challenges')
	if not os.path.exists(challenges_path):
		os.mkdir(challenges_path)

	# Read in the private key that we use for all TLS certificates. We'll need that
	# to generate a CSR (done by free_tls_certificates).
	with open(os.path.join(env['STORAGE_ROOT'], 'ssl/ssl_private_key.pem'), 'rb') as f:
		private_key = f.read()

	# Provision certificates.

	ret = []
	for domain_list in certs:
		# For return.
		ret_item = {
			"domains": domain_list,
			"log": [],
		}
		ret.append(ret_item)

		# Logging for free_tls_certificates.
		def my_logger(message):
			if logger: logger(message)
			ret_item["log"].append(message)

		# Attempt to provision a certificate.
		try:
			try:
				cert = client.issue_certificate(
					domain_list,
					account_path,
					agree_to_tos_url=agree_to_tos_url,
					private_key=private_key,
					logger=my_logger)

			except client.NeedToTakeAction as e:
				# Write out the ACME challenge files.
				for action in e.actions:
					if isinstance(action, client.NeedToInstallFile):
						fn = os.path.join(challenges_path, action.file_name)
						with open(fn, 'w') as f:
							f.write(action.contents)
					else:
						raise ValueError(str(action))

				# Try to provision now that the challenge files are installed.

				cert = client.issue_certificate(
					domain_list,
					account_path,
					private_key=private_key,
					logger=my_logger)

		except client.NeedToAgreeToTOS as e:
			# The user must agree to the Let's Encrypt terms of service agreement
			# before any further action can be taken.
			ret_item.update({
				"result": "agree-to-tos",
				"url": e.url,
			})

		except client.WaitABit as e:
			# We need to hold on for a bit before querying again to see if we can
			# acquire a provisioned certificate.
			import time, datetime
			ret_item.update({
				"result": "wait",
				"until": e.until_when if not jsonable else e.until_when.isoformat(),
				"seconds": (e.until_when - datetime.datetime.now()).total_seconds()
			})

		except client.AccountDataIsCorrupt as e:
			# This is an extremely rare condition.
			ret_item.update({
				"result": "error",
				"message": "Something unexpected went wrong. It looks like your local Let's Encrypt account data is corrupted. There was a problem with the file " + e.account_file_path + ".",
			})

		except (client.InvalidDomainName, client.NeedToTakeAction, client.ChallengeFailed, acme.messages.Error, requests.exceptions.RequestException) as e:
			ret_item.update({
				"result": "error",
				"message": "Something unexpected went wrong: " + str(e),
			})

		else:
			# A certificate was issued.

			install_status = install_cert(domain_list[0], cert['cert'].decode("ascii"), b"\n".join(cert['chain']).decode("ascii"), env, raw=True)

			# str indicates the certificate was not installed.
			if isinstance(install_status, str):
				ret_item.update({
					"result": "error",
					"message": "Something unexpected was wrong with the provisioned certificate: " + install_status,
				})
			else:
				# A list indicates success and what happened next.
				ret_item["log"].extend(install_status)
				ret_item.update({
					"result": "installed",
				})

	# Return what happened with each certificate request.
	return {
		"requests": ret,
		"problems": problems,
	}
Пример #7
0
def _request_acme_certificate(domain, webroot, nthread):
    nthread.title = "Requesting ACME certificate"
    signals.emit("certificates", "pre_add", id)
    domains = [domain]

    uid = users.get_system("http").uid
    gid = groups.get_system("ssl-cert").gid

    if webroot:
        webroot = os.path.join(webroot, ".well-known", "acme-challenge")

    acme_dir = config.get("certificates", "acme_dir")
    cert_dir = os.path.join(acme_dir, "certs", domain)
    cert_path = os.path.join(cert_dir, "cert.pem")
    key_path = os.path.join(cert_dir, "privkey.pem")

    if not os.path.exists(cert_dir):
        os.makedirs(cert_dir)

    if not webroot:
        sites = websites.get()
        for x in sites:
            if x.port in [80, 443] and x.domain == domain:
                webroot = x.add_acme_challenge()
                break
        else:
            webroot = websites.create_acme_dummy(domain)

    smsg = "Requesting certificate from Let's Encrypt CA..."
    nthread.update(Notification("info", "Certificates", smsg))
    agree_to_tos = None
    has_written_files = False
    while True:
        try:
            leclient.issue_certificate(
                domains,
                acme_dir,
                acme_server=config.get("certificates", "acme_server"),
                certificate_file=cert_path,
                private_key_file=key_path,
                agree_to_tos_url=agree_to_tos)
            break
        except leclient.NeedToAgreeToTOS as e:
            agree_to_tos = e.url
            continue
        except leclient.NeedToTakeAction as e:
            if not has_written_files:
                if not os.path.exists(webroot):
                    os.makedirs(webroot)
                os.chown(webroot, uid, gid)
                for x in e.actions:
                    fn = os.path.join(webroot, x.file_name)
                    with open(fn, 'w') as f:
                        f.write(x.contents)
                    os.chown(fn, uid, gid)
                has_written_files = True
                continue
            else:
                raise errors.InvalidConfigError(
                    "Requesting a certificate failed - it doesn't appear your "
                    "requested domain's DNS is pointing to your server, or "
                    "there was a port problem. Please check these things and "
                    "try again.")
        except leclient.WaitABit as e:
            while e.until_when > datetime.datetime.now():
                until = e.until_when - datetime.datetime.now()
                until_secs = int(round(until.total_seconds())) + 1
                if until_secs > 300:
                    raise errors.InvalidConfigError(
                        "Requesting a certificate failed - LE rate limiting "
                        "detected, for a period of more than five minutes. "
                        "Please try again later."
                    )
                nthread.update(
                    Notification(
                        "warning", "Certificates", "LE rate limiting detected."
                        " Will reattempt in {0} seconds".format(until_secs))
                    )
                time.sleep(until_secs)
            continue
        except leclient.InvalidDomainName:
            raise errors.InvalidConfigError(
                "Requesting a certificate failed - invalid domain name"
            )
        except leclient.RateLimited:
            raise errors.InvalidConfigError(
                "Requesting a certificate failed - LE is refusing to issue "
                "more certificates to you for this domain. Please choose "
                "another domain or try again another time."
            )

    os.chown(cert_path, -1, gid)
    os.chown(key_path, -1, gid)
    os.chmod(cert_path, 0o750)
    os.chmod(key_path, 0o750)

    with open(cert_path, "rb") as f:
        cert = x509.load_pem_x509_certificate(f.read(), default_backend())
    with open(key_path, "rb") as f:
        key = serialization.load_pem_private_key(
            f.read(), password=None, backend=default_backend()
        )
    sha1 = binascii.hexlify(cert.fingerprint(hashes.SHA1())).decode()
    md5 = binascii.hexlify(cert.fingerprint(hashes.MD5())).decode()
    sha1 = ":".join([sha1[i:i+2].upper() for i in range(0, len(sha1), 2)])
    md5 = ":".join([md5[i:i+2].upper() for i in range(0, len(md5), 2)])
    if isinstance(key.public_key(), rsa.RSAPublicKey):
        ktype = "RSA"
    elif isinstance(key.public_key(), dsa.DSAPublicKey):
        ktype = "DSA"
    elif isinstance(key.public_key(), ec.EllipticCurvePublicKey):
        ktype = "EC"
    else:
        ktype = "Unknown"
    ksize = key.key_size
    c = Certificate(domain, domain, cert_path, key_path, ktype, ksize,
                    [], cert.not_valid_after, sha1, md5, is_acme=True)
    storage.certificates[c.id] = c

    with open("/etc/cron.d/arkos-acme-renew", "a") as f:
        f.write("0 4 * * * systemctl reload nginx\n")
        fln = ("30 3 * * * free_tls_certificate {0} {1} {2} {3} {4} "
               ">> /var/log/acme-renew.log\n")
        f.write(fln.format(
            " ".join(domains), key_path, cert_path,
            webroot.split("/.well-known/acme-challenge")[0], acme_dir
        ))

    signals.emit("certificates", "post_add", c)
    msg = "Certificate issued successfully"
    nthread.complete(Notification("success", "Certificates", msg))
    return c
Пример #8
0
def provision_certificate(opts):
    from free_tls_certificates import client
    import requests.exceptions
    import acme.messages

    def logger(msg):
        print(msg)

    # It takes multiple invokations of client.issue_certificate to get the job done.
    agree_to_tos_url = None
    has_installed_files = False
    while True:
        try:
            # Issue request.
            client.issue_certificate(opts["domains"],
                                     opts["acme_account_path"],
                                     certificate_file=opts["certificate_fn"],
                                     private_key_file=opts["private_key_fn"],
                                     agree_to_tos_url=agree_to_tos_url,
                                     acme_server=opts["acme_server"],
                                     self_signed=opts["self_signed"],
                                     logger=logger)

            # A certificate was provisioned!
            return

        ###########################################################################################
        except client.AccountDataIsCorrupt as e:
            # This is an extremely rare condition.
            print("The account data stored in " + e.account_file_path +
                  " is corrupt.")
            print("You should probably delete this file and start over.")
            sys.exit(1)

        ###########################################################################################
        except client.NeedToAgreeToTOS as e:
            # Can't ask user a question interactively if device is not a TTY.
            if not sys.stdin.isatty():
                sys.stderr.write(
                    "You must agree to the Let's Encrypt TOS but input is not a TTY.\n"
                )
                sys.exit(2)

            sys.stdout.write("""Please open this document in your web browser:

%s

It is Let's Encrypt's terms of service agreement. If you agree, I can
provision your TLS certificate. If you don't agree, this program stops.

Do you agree to the agreement? Type Y or N and press <ENTER>: """ % e.url)
            sys.stdout.flush()

            if sys.stdin.readline().strip().upper() != "Y":
                print("\nYou didn't agree. Quitting.")
                sys.exit(1)

            # Okay, indicate agreement on next iteration.
            agree_to_tos_url = e.url

            # Try again.
            continue

        ###########################################################################################
        except client.InvalidDomainName as e:
            # One of the domain names provided is not a domain name the ACME
            # server can issue a certificate for.
            print(e)
            sys.exit(1)

        ###########################################################################################
        except client.NeedToTakeAction as e:
            for action in e.actions:
                if not isinstance(action, client.NeedToInstallFile):
                    raise Exception()

                fn = os.path.join(opts['static_path'], action.file_name)

                # Prevent infinite looping.
                if has_installed_files:
                    print("""
A domain validation challenge file was installed but we couldn't see it on the
second pass. That usually means that the domain name does not resolve to the
machine this program is running on, or the web server is not serving the static
path you specified. Make sure %s
is serving the file at %s.""" % (action.url, fn))
                    sys.exit(1)

                print("Install domain validation challenge file at " +
                      action.url)

                # Ensure the static path exists.
                try:
                    os.makedirs(opts['static_path'])
                except OSError:
                    # directory already exists
                    pass

                # Write file.
                with open(fn, 'w') as f:
                    f.write(action.contents)

            # Try again.
            has_installed_files = True
            continue

        ###########################################################################################
        except client.WaitABit as e:
            # ACME server tells us to try again in a bit.
            while e.until_when > datetime.datetime.now():
                print(
                    "We have to wait %d more seconds for the certificate to be issued..."
                    % int(
                        round((e.until_when -
                               datetime.datetime.now()).total_seconds())))
                time.sleep(15)

            # Try again.
            continue

        ###########################################################################################
        except client.RateLimited as e:
            # The ACME server is refusing to issue more certificates for a second-level domain
            # for your account.
            print(e)
            sys.exit(1)

        ###########################################################################################
        except acme.messages.Error as e:
            # A protocol error occurred. (If a CSR was supplied, it might
            # be for a different set of domains than was specified, for instance.)
            print("Something went wrong: " + str(e))
            sys.exit(1)

        ###########################################################################################
        except requests.exceptions.RequestException as e:
            # A DNS or network error occurred.
            print("Something went wrong:" + str(e))
            sys.exit(1)
Пример #9
0
def provision_certificate(opts):
    from free_tls_certificates import client
    import requests.exceptions
    import acme.messages

    def logger(msg):
        print(msg)

    # It takes multiple invokations of client.issue_certificate to get the job done.
    agree_to_tos_url = None
    has_installed_files = False
    while True:
        try:
            # Issue request.
            client.issue_certificate(
                opts["domains"],
                opts["acme_account_path"],
                certificate_file=opts["certificate_fn"],
                private_key_file=opts["private_key_fn"],
                agree_to_tos_url=agree_to_tos_url,
                acme_server=opts["acme_server"],
                self_signed=opts["self_signed"],
                logger=logger)

            # A certificate was provisioned!
            return

        ###########################################################################################
        except client.AccountDataIsCorrupt as e:
            # This is an extremely rare condition.
            print("The account data stored in " + e.account_file_path + " is corrupt.")
            print("You should probably delete this file and start over.")
            sys.exit(1)

        ###########################################################################################
        except client.NeedToAgreeToTOS as e:
            # Can't ask user a question interactively if device is not a TTY.
            if not sys.stdin.isatty():
                sys.stderr.write("You must agree to the Let's Encrypt TOS but input is not a TTY.\n")
                sys.exit(2)

            sys.stdout.write("""Please open this document in your web browser:

%s

It is Let's Encrypt's terms of service agreement. If you agree, I can
provision your TLS certificate. If you don't agree, this program stops.

Do you agree to the agreement? Type Y or N and press <ENTER>: """
                 % e.url)
            sys.stdout.flush()
            
            if sys.stdin.readline().strip().upper() != "Y":
                print("\nYou didn't agree. Quitting.")
                sys.exit(1)

            # Okay, indicate agreement on next iteration.
            agree_to_tos_url = e.url

            # Try again.
            continue

        ###########################################################################################
        except client.InvalidDomainName as e:
            # One of the domain names provided is not a domain name the ACME
            # server can issue a certificate for.
            print(e)
            sys.exit(1)

        ###########################################################################################
        except client.NeedToTakeAction as e:
            for action in e.actions:
                if not isinstance(action, client.NeedToInstallFile):
                    raise Exception()

                fn = os.path.join(opts['static_path'], action.file_name)

                # Prevent infinite looping.
                if has_installed_files:
                    print("""
A domain validation challenge file was installed but we couldn't see it on the
second pass. That usually means that the domain name does not resolve to the
machine this program is running on, or the web server is not serving the static
path you specified. Make sure %s
is serving the file at %s.""" % (action.url, fn))
                    sys.exit(1)


                print("Install domain validation challenge file at " + action.url)

                # Ensure the static path exists.
                try:
                    os.makedirs(opts['static_path'])
                except OSError:
                    # directory already exists
                    pass

                # Write file.
                with open(fn, 'w') as f:
                    f.write(action.contents)

            # Try again.
            has_installed_files = True
            continue

        ###########################################################################################
        except client.WaitABit as e:
            # ACME server tells us to try again in a bit.
            while e.until_when > datetime.datetime.now():
                print ("We have to wait %d more seconds for the certificate to be issued..."
                    % int(round((e.until_when - datetime.datetime.now()).total_seconds())))
                time.sleep(15)

            # Try again.
            continue

        ###########################################################################################
        except client.RateLimited as e:
            # The ACME server is refusing to issue more certificates for a second-level domain
            # for your account.
            print(e)
            sys.exit(1)

        ###########################################################################################
        except acme.messages.Error as e:
            # A protocol error occurred. (If a CSR was supplied, it might
            # be for a different set of domains than was specified, for instance.)
            print("Something went wrong: " + str(e))
            sys.exit(1)

        ###########################################################################################
        except requests.exceptions.RequestException as e:
            # A DNS or network error occurred.
            print("Something went wrong:" + str(e))
            sys.exit(1)