Ejemplo n.º 1
0
    def session(self):
        """Get an instance of ``requests.Session``.

        By default, the session will not use certificate verification.

        To enable certificate verification:

        - set ``CN_COUCHBASE_VERIFY`` environment variable to ``true`` (default to ``false``)
        - ensure ``CN_COUCHBASE_CERT_FILE`` pointed to valid Couchbase cluster
          certificate (default to ``/etc/certs/couchbase.crt``)
        - optionally, set ``CN_COUCHBASE_HOST_HEADER`` to match Common Name
          or any of SubjectAltName defined in certificate (default to ``localhost``)
        """
        suppress_verification_warning()

        if not self._session:
            self._session = requests.Session()
            self._session.verify = False

            verify = as_boolean(os.environ.get("CN_COUCHBASE_VERIFY", False))
            if verify:
                self._session.mount("https://", HostHeaderSSLAdapter())
                self._session.verify = os.environ.get("CN_COUCHBASE_CERT_FILE") or "/etc/certs/couchbase.crt"
                self._session.headers["Host"] = os.environ.get("CN_COUCHBASE_HOST_HEADER") or "localhost"
        return self._session
Ejemplo n.º 2
0
def https(q,
          where,
          timeout=None,
          port=443,
          af=None,
          source=None,
          source_port=0,
          one_rr_per_rrset=False,
          ignore_trailing=False,
          session=None,
          path='/dns-query',
          post=True,
          bootstrap_address=None,
          verify=True):
    """Return the response obtained after sending a query via DNS-over-HTTPS.

    *q*, a ``dns.message.Message``, the query to send.

    *where*, a ``str``, the nameserver IP address or the full URL. If an IP
    address is given, the URL will be constructed using the following schema:
    https://<IP-address>:<port>/<path>.

    *timeout*, a ``float`` or ``None``, the number of seconds to
    wait before the query times out. If ``None``, the default, wait forever.

    *port*, a ``int``, the port to send the query to. The default is 443.

    *af*, an ``int``, the address family to use.  The default is ``None``,
    which causes the address family to use to be inferred from the form of
    *where*, or uses the system default.  Setting this to AF_INET or
    AF_INET6 currently has no effect.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
    junk at end of the received message.

    *session*, a ``requests.session.Session``.  If provided, the session to use
    to send the queries.

    *path*, a ``str``. If *where* is an IP address, then *path* will be used to
    construct the URL to send the DNS query to.

    *post*, a ``bool``. If ``True``, the default, POST method will be used.

    *bootstrap_address*, a ``str``, the IP address to use to bypass the
    system's DNS resolver.

    *verify*, a ``str`, containing a path to a certificate file or directory.

    Returns a ``dns.message.Message``.
    """

    wire = q.to_wire()
    (af, destination,
     source) = _destination_and_source(af, where, port, source, source_port,
                                       False)
    transport_adapter = None
    headers = {"accept": "application/dns-message"}
    try:
        _ = ipaddress.ip_address(where)
        url = 'https://{}:{}{}'.format(where, port, path)
    except ValueError:
        if bootstrap_address is not None:
            split_url = urllib.parse.urlsplit(where)
            headers['Host'] = split_url.hostname
            url = where.replace(split_url.hostname, bootstrap_address)
            transport_adapter = HostHeaderSSLAdapter()
        else:
            url = where
    if source is not None:
        # set source port and source address
        transport_adapter = SourceAddressAdapter(source)

    if session:
        close_session = False
    else:
        session = requests.sessions.Session()
        close_session = True

    try:
        if transport_adapter:
            session.mount(url, transport_adapter)

        # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
        # GET and POST examples
        if post:
            headers.update({
                "content-type": "application/dns-message",
                "content-length": str(len(wire))
            })
            response = session.post(url,
                                    headers=headers,
                                    data=wire,
                                    stream=True,
                                    timeout=timeout,
                                    verify=verify)
        else:
            wire = base64.urlsafe_b64encode(wire).decode('utf-8').strip("=")
            url += "?dns={}".format(wire)
            response = session.get(url,
                                   headers=headers,
                                   stream=True,
                                   timeout=timeout,
                                   verify=verify)
    finally:
        if close_session:
            session.close()

    # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
    # status codes
    if response.status_code < 200 or response.status_code > 299:
        raise ValueError('{} responded with status code {}'
                         '\nResponse body: {}'.format(where,
                                                      response.status_code,
                                                      response.content))
    r = dns.message.from_wire(response.content,
                              keyring=q.keyring,
                              request_mac=q.request_mac,
                              one_rr_per_rrset=one_rr_per_rrset,
                              ignore_trailing=ignore_trailing)
    r.time = response.elapsed
    if not q.is_response(r):
        raise BadResponse
    return r
Ejemplo n.º 3
0
def https(q, where, timeout=None, port=443, source=None, source_port=0,
          one_rr_per_rrset=False, ignore_trailing=False,
          session=None, path='/dns-query', post=True,
          bootstrap_address=None, verify=True):
    """Return the response obtained after sending a query via DNS-over-HTTPS.

    *q*, a ``dns.message.Message``, the query to send.

    *where*, a ``str``, the nameserver IP address or the full URL. If an IP
    address is given, the URL will be constructed using the following schema:
    https://<IP-address>:<port>/<path>.

    *timeout*, a ``float`` or ``None``, the number of seconds to
    wait before the query times out. If ``None``, the default, wait forever.

    *port*, a ``int``, the port to send the query to. The default is 443.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
    junk at end of the received message.

    *session*, an ``httpx.Client`` or ``requests.session.Session``.  If
    provided, the client/session to use to send the queries.

    *path*, a ``str``. If *where* is an IP address, then *path* will be used to
    construct the URL to send the DNS query to.

    *post*, a ``bool``. If ``True``, the default, POST method will be used.

    *bootstrap_address*, a ``str``, the IP address to use to bypass the
    system's DNS resolver.

    *verify*, a ``str``, containing a path to a certificate file or directory.

    Returns a ``dns.message.Message``.
    """

    if not have_doh:
        raise NoDOH('Neither httpx nor requests is available.')  # pragma: no cover

    _httpx_ok = _have_httpx

    wire = q.to_wire()
    (af, _, source) = _destination_and_source(where, port, source, source_port,
                                              False)
    transport_adapter = None
    transport = None
    headers = {
        "accept": "application/dns-message"
    }
    if af is not None:
        if af == socket.AF_INET:
            url = 'https://{}:{}{}'.format(where, port, path)
        elif af == socket.AF_INET6:
            url = 'https://[{}]:{}{}'.format(where, port, path)
    elif bootstrap_address is not None:
        _httpx_ok = False
        split_url = urllib.parse.urlsplit(where)
        headers['Host'] = split_url.hostname
        url = where.replace(split_url.hostname, bootstrap_address)
        if _have_requests:
            transport_adapter = HostHeaderSSLAdapter()
    else:
        url = where
    if source is not None:
        # set source port and source address
        if _have_httpx:
            if source_port == 0:
                transport = httpx.HTTPTransport(local_address=source[0])
            else:
                _httpx_ok = False
        if _have_requests:
            transport_adapter = SourceAddressAdapter(source)

    if session:
        if _have_httpx:
            _is_httpx = isinstance(session, httpx.Client)
        else:
            _is_httpx = False
        if _is_httpx and not _httpx_ok:
            raise NoDOH('Session is httpx, but httpx cannot be used for '
                        'the requested operation.')
    else:
        _is_httpx = _httpx_ok

    if not _httpx_ok and not _have_requests:
        raise NoDOH('Cannot use httpx for this operation, and '
                    'requests is not available.')

    with contextlib.ExitStack() as stack:
        if not session:
            if _is_httpx:
                session = stack.enter_context(httpx.Client(http1=True,
                                                           http2=_have_http2,
                                                           verify=verify,
                                                           transport=transport))
            else:
                session = stack.enter_context(requests.sessions.Session())

        if transport_adapter:
            session.mount(url, transport_adapter)

        # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
        # GET and POST examples
        if post:
            headers.update({
                "content-type": "application/dns-message",
                "content-length": str(len(wire))
            })
            if _is_httpx:
                response = session.post(url, headers=headers, content=wire,
                                        timeout=timeout)
            else:
                response = session.post(url, headers=headers, data=wire,
                                        timeout=timeout, verify=verify)
        else:
            wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
            if _is_httpx:
                wire = wire.decode()  # httpx does a repr() if we give it bytes
                response = session.get(url, headers=headers,
                                       timeout=timeout,
                                       params={"dns": wire})
            else:
                response = session.get(url, headers=headers,
                                       timeout=timeout, verify=verify,
                                       params={"dns": wire})

    # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
    # status codes
    if response.status_code < 200 or response.status_code > 299:
        raise ValueError('{} responded with status code {}'
                         '\nResponse body: {}'.format(where,
                                                      response.status_code,
                                                      response.content))
    r = dns.message.from_wire(response.content,
                              keyring=q.keyring,
                              request_mac=q.request_mac,
                              one_rr_per_rrset=one_rr_per_rrset,
                              ignore_trailing=ignore_trailing)
    r.time = response.elapsed
    if not q.is_response(r):
        raise BadResponse
    return r
Ejemplo n.º 4
0
def create_session():
    session = requests.Session()
    session.mount("https://", HostHeaderSSLAdapter())
    session.headers.update({"Host": "alpha"})
    session.verify = cert_file
    return session
Ejemplo n.º 5
0
    username = os.environ.get("WAPI_USERNAME")
    password = os.environ.get("WAPI_PASSWORD")
    domain = os.environ.get("WEDOS_DOMAIN")

    # poskládám autntizační token podle kuchařky od Wedosu
    auththingy = sha1()
    auththingy.update(username.encode("ascii"))
    auththingy.update(
        sha1(password.encode("ascii")).hexdigest().encode("ascii"))
    auththingy.update(str(datetime.now().hour).encode("ascii"))

    auth_token = auththingy.hexdigest()

    # Tvorba sezení pro requests s oním SSL adaptérem umožňujícím funkčnost SSL i při adresování pomocí IP
    s = Session()
    s.mount('https://', HostHeaderSSLAdapter())
    s.headers = {"host": "api.wedos.com"}

    response = simple_request(s, username, auth_token, domain, "dns-rows-list")

    rows = response.json()["response"]["data"]["row"]

    # Tady se prochází záznamy a kouká se který měnit
    # V if řádku je filtrování podle jména a typu záznamu
    # Pod tím se pak volá funkce co sestrojí požadavek pro úpravu. Zajímavá proměnná je actual_ip

    for row in rows:
        if row["name"] == "" and row["rdtype"] == "A":
            change_row(s, username, auth_token, row["ID"], actual_ip, domain)
        if row["name"] == "*" and row["rdtype"] == "A":
            change_row(s, username, auth_token, row["ID"], actual_ip, domain)