Add ssl_cipher_list option to rest (#91078)
parent
59dc0ea2e0
commit
323d16cc21
|
@ -43,7 +43,9 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
|||
|
||||
from .const import (
|
||||
CONF_ENCODING,
|
||||
CONF_SSL_CIPHER_LIST,
|
||||
COORDINATOR,
|
||||
DEFAULT_SSL_CIPHER_LIST,
|
||||
DOMAIN,
|
||||
PLATFORM_IDX,
|
||||
REST,
|
||||
|
@ -185,6 +187,7 @@ def create_rest_data_from_config(hass: HomeAssistant, config: ConfigType) -> Res
|
|||
method: str = config[CONF_METHOD]
|
||||
payload: str | None = config.get(CONF_PAYLOAD)
|
||||
verify_ssl: bool = config[CONF_VERIFY_SSL]
|
||||
ssl_cipher_list: str = config.get(CONF_SSL_CIPHER_LIST, DEFAULT_SSL_CIPHER_LIST)
|
||||
username: str | None = config.get(CONF_USERNAME)
|
||||
password: str | None = config.get(CONF_PASSWORD)
|
||||
headers: dict[str, str] | None = config.get(CONF_HEADERS)
|
||||
|
@ -218,5 +221,6 @@ def create_rest_data_from_config(hass: HomeAssistant, config: ConfigType) -> Res
|
|||
params,
|
||||
payload,
|
||||
verify_ssl,
|
||||
ssl_cipher_list,
|
||||
timeout,
|
||||
)
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
"""The rest component constants."""
|
||||
|
||||
from homeassistant.util.ssl import SSLCipherList
|
||||
|
||||
DOMAIN = "rest"
|
||||
|
||||
DEFAULT_METHOD = "GET"
|
||||
DEFAULT_VERIFY_SSL = True
|
||||
DEFAULT_SSL_CIPHER_LIST = SSLCipherList.PYTHON_DEFAULT
|
||||
DEFAULT_FORCE_UPDATE = False
|
||||
DEFAULT_ENCODING = "UTF-8"
|
||||
CONF_ENCODING = "encoding"
|
||||
CONF_SSL_CIPHER_LIST = "ssl_cipher_list"
|
||||
|
||||
DEFAULT_BINARY_SENSOR_NAME = "REST Binary Sensor"
|
||||
DEFAULT_SENSOR_NAME = "REST Sensor"
|
||||
|
|
|
@ -9,6 +9,7 @@ import httpx
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import template
|
||||
from homeassistant.helpers.httpx_client import create_async_httpx_client
|
||||
from homeassistant.util.ssl import SSLCipherList
|
||||
|
||||
DEFAULT_TIMEOUT = 10
|
||||
|
||||
|
@ -29,6 +30,7 @@ class RestData:
|
|||
params: dict[str, str] | None,
|
||||
data: str | None,
|
||||
verify_ssl: bool,
|
||||
ssl_cipher_list: str,
|
||||
timeout: int = DEFAULT_TIMEOUT,
|
||||
) -> None:
|
||||
"""Initialize the data object."""
|
||||
|
@ -42,6 +44,7 @@ class RestData:
|
|||
self._request_data = data
|
||||
self._timeout = timeout
|
||||
self._verify_ssl = verify_ssl
|
||||
self._ssl_cipher_list = SSLCipherList(ssl_cipher_list)
|
||||
self._async_client: httpx.AsyncClient | None = None
|
||||
self.data: str | None = None
|
||||
self.last_exception: Exception | None = None
|
||||
|
@ -55,7 +58,10 @@ class RestData:
|
|||
"""Get the latest data from REST service with provided method."""
|
||||
if not self._async_client:
|
||||
self._async_client = create_async_httpx_client(
|
||||
self._hass, verify_ssl=self._verify_ssl, default_encoding=self._encoding
|
||||
self._hass,
|
||||
verify_ssl=self._verify_ssl,
|
||||
default_encoding=self._encoding,
|
||||
ssl_cipher_list=self._ssl_cipher_list,
|
||||
)
|
||||
|
||||
rendered_headers = template.render_complex(self._headers, parse_result=False)
|
||||
|
|
|
@ -31,14 +31,17 @@ from homeassistant.helpers.template_entity import (
|
|||
TEMPLATE_ENTITY_BASE_SCHEMA,
|
||||
TEMPLATE_SENSOR_BASE_SCHEMA,
|
||||
)
|
||||
from homeassistant.util.ssl import SSLCipherList
|
||||
|
||||
from .const import (
|
||||
CONF_ENCODING,
|
||||
CONF_JSON_ATTRS,
|
||||
CONF_JSON_ATTRS_PATH,
|
||||
CONF_SSL_CIPHER_LIST,
|
||||
DEFAULT_ENCODING,
|
||||
DEFAULT_FORCE_UPDATE,
|
||||
DEFAULT_METHOD,
|
||||
DEFAULT_SSL_CIPHER_LIST,
|
||||
DEFAULT_VERIFY_SSL,
|
||||
DOMAIN,
|
||||
METHODS,
|
||||
|
@ -58,6 +61,10 @@ RESOURCE_SCHEMA = {
|
|||
vol.Optional(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD): cv.string,
|
||||
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
|
||||
vol.Optional(
|
||||
CONF_SSL_CIPHER_LIST,
|
||||
default=DEFAULT_SSL_CIPHER_LIST,
|
||||
): vol.In([e.value for e in SSLCipherList]),
|
||||
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
|
||||
vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING): cv.string,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import asyncio
|
||||
from http import HTTPStatus
|
||||
import ssl
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
@ -30,6 +30,7 @@ from homeassistant.const import (
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.ssl import SSLCipherList
|
||||
|
||||
from tests.common import get_fixture_path
|
||||
|
||||
|
@ -157,6 +158,44 @@ async def test_setup_encoding(hass: HomeAssistant) -> None:
|
|||
assert hass.states.get("sensor.mysensor").state == "tack själv"
|
||||
|
||||
|
||||
@respx.mock
|
||||
@pytest.mark.parametrize(
|
||||
("ssl_cipher_list", "ssl_cipher_list_expected"),
|
||||
(
|
||||
("python_default", SSLCipherList.PYTHON_DEFAULT),
|
||||
("intermediate", SSLCipherList.INTERMEDIATE),
|
||||
("modern", SSLCipherList.MODERN),
|
||||
),
|
||||
)
|
||||
async def test_setup_ssl_ciphers(
|
||||
hass: HomeAssistant, ssl_cipher_list: str, ssl_cipher_list_expected: SSLCipherList
|
||||
) -> None:
|
||||
"""Test setup with minimum configuration."""
|
||||
with patch(
|
||||
"homeassistant.components.rest.data.create_async_httpx_client",
|
||||
return_value=MagicMock(request=AsyncMock(return_value=respx.MockResponse())),
|
||||
) as httpx:
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
SENSOR_DOMAIN,
|
||||
{
|
||||
SENSOR_DOMAIN: {
|
||||
"platform": DOMAIN,
|
||||
"resource": "http://localhost",
|
||||
"method": "GET",
|
||||
"ssl_cipher_list": ssl_cipher_list,
|
||||
}
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
httpx.assert_called_once_with(
|
||||
hass,
|
||||
verify_ssl=True,
|
||||
default_encoding="UTF-8",
|
||||
ssl_cipher_list=ssl_cipher_list_expected,
|
||||
)
|
||||
|
||||
|
||||
@respx.mock
|
||||
async def test_manual_update(hass: HomeAssistant) -> None:
|
||||
"""Test setup with minimum configuration."""
|
||||
|
|
Loading…
Reference in New Issue