Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Music Assistant: cannot connect when MA server is correctly SSL-wrapped #132742

Open
Rudd-O opened this issue Dec 9, 2024 · 4 comments
Open

Music Assistant: cannot connect when MA server is correctly SSL-wrapped #132742

Rudd-O opened this issue Dec 9, 2024 · 4 comments

Comments

@Rudd-O
Copy link

Rudd-O commented Dec 9, 2024

UPDATE: it was an SSL CA error. The error is not logged or displayed. It should be. I think this ticket should be closed once the error is displayed.

(For comparison, I had the same error with the Frigate custom integration, and yes, it logs the error to the HA log, although it also says "Cannot connect" and gives no further details in the UI, just like this integration.)

The problem

I've got Music Assistant correctly running with HTTPS proxying of its frontend / server on port 443 (decrypting and proxy-passing to port 8095 locally), served as https://music.dragonfear. I can set up MASS custom integration no problem with that. However, the recently-released built-in HA integration does not seem to support this, and I think I've traced the problem to this code in music_assistant_client/connection.py:


def get_websocket_url(url: str) -> str:
    """Extract Websocket URL from (base) Music Assistant URL."""
    if not url or "://" not in url:
        msg = f"{url} is not a valid url"
        raise RuntimeError(msg)
    ws_url = url.replace("http", "ws")
    if not ws_url.endswith("/ws"):
        ws_url += "/ws"
    return ws_url.replace("//ws", "/ws")


class WebsocketsConnection:
    """Websockets connection to a Music Assistant Server."""

    def __init__(self, server_url: str, aiohttp_session: ClientSession | None) -> None:
        """Initialize."""
        self.ws_server_url = get_websocket_url(server_url)
        self._aiohttp_session_provided = aiohttp_session is not None
        self._aiohttp_session: ClientSession | None = aiohttp_session or ClientSession()
        self._ws_client: ClientWebSocketResponse | None = None

As result of get_websocket_url(), the URL is never actually set up to be wss when the URL passed on the configuration interface is https.

However, wss://music.dragonfear/ws doesn't work either. Nor does wss://music.dragonfear.

I can verify that the HA machine can retrieve https://music.dragonfear just fine, even from the Python used in the HA setup. No errors appear on the log either. It would be fantastic if the actual error was in the log!

What version of Home Assistant Core has the issue?

core-2024.12.1

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Core

Integration causing the issue

music_assistant

Link to integration documentation on our website

No response

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

Sadly no.  The only debug log entry from the integration that I get is `Trying to connect`.  Nothing useful happens after that.

Additional information

No response

@Rudd-O Rudd-O changed the title Music Assistant: cannot connect when server is SSL Music Assistant: cannot connect when MA server is correctly SSL-wrapped Dec 9, 2024
@Rudd-O
Copy link
Author

Rudd-O commented Dec 9, 2024

FYI websockets is working correctly:

[root@penny vhosts]# curl -v wss://music.dragonfear/ws
* Host music.dragonfear:443 was resolved.
* IPv6: (none)
* IPv4: 10.250.7.8
*   Trying 10.250.7.8:443...
* Connected to music.dragonfear (10.250.7.8) port 443
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS
* Server certificate:
*  subject: C=CH; L=Zurich; O=dragonfear host cert; CN=music.dragonfear
*  start date: May 15 16:04:01 2024 GMT
*  expire date: May 15 16:04:01 2025 GMT
*  subjectAltName: host "music.dragonfear" matched cert's "music.dragonfear"
*  issuer: C=CH; L=Zurich; O=DragonFear certificate authority; CN=ca.dragonfear; emailAddress=ca@dragonfear
*  SSL certificate verify ok.
*   Certificate level 0: Public key type RSA (4096/152 Bits/secBits), signed using sha512WithRSAEncryption
*   Certificate level 1: Public key type RSA (4096/152 Bits/secBits), signed using sha512WithRSAEncryption
> GET /ws HTTP/1.1
> Host: music.dragonfear
> User-Agent: curl/8.6.0
> Accept: */*
> Upgrade: websocket
> Connection: Upgrade
> Sec-WebSocket-Version: 13
> Sec-WebSocket-Key: XXXXXX
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/1.1 101 Switching Protocols
< Server: nginx/1.26.2
< Date: Mon, 09 Dec 2024 17:12:15 GMT
< Connection: upgrade
< Upgrade: websocket
< Sec-WebSocket-Accept: XXXXX
* Received 101, switch to WebSocket; mask XXXXX
< 
* WS-DEC: decoded [TEXT payload=0/215]
* WS-DEC: passing [TEXT payload=215/215]

@Rudd-O
Copy link
Author

Rudd-O commented Dec 9, 2024

Funny enough I can write a small asyncio program that works perfectly with the latest music_assistant_client library installed in a venv:

cat > shit.PY <<"EOF"
import asyncio
import logging

logging.basicConfig(level=logging.DEBUG)

async def main():
    import music_assistant_client.connection as c
    conn = c.WebsocketsConnection("https://music.dragonfear", None)
    await conn.connect()
    
asyncio.run(main())
EOF
bin/python3 shit.PY
DEBUG:asyncio:Using selector: EpollSelector
DEBUG:music_assistant_client.connection:Trying to connect
DEBUG:music_assistant_client.connection:Received message:
WSMessage(type=<WSMsgType.TEXT: 1>, data='{"server_id":"a4b1ec2029564727a2a1e480e9842ae6","server_version":"2.4.0b7","schema_version":26,"min_supported_schema_version":24,"base_url":"https://music.dragonfear","homeassistant_addon":false,"onboard_done":true}', extra='')

ERROR:asyncio:Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x780133db0b90>

@Rudd-O
Copy link
Author

Rudd-O commented Dec 11, 2024

The error is being swallowed and not logged, but what was going on is that the HTTPS certificate was not trusted by the Python virtual environment.

Setting ENVIRONMENT=REQUESTS_CA_BUNDLE=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem in the Home Assistant service file solved the problem.

I keep this bug open because this type of error should be logged to the system log in detail, instead of being swallowed.

@home-assistant
Copy link

Hey there @music-assistant, mind taking a look at this issue as it has been labeled with an integration (music_assistant) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of music_assistant can trigger bot actions by commenting:

  • @home-assistant close Closes the issue.
  • @home-assistant rename Awesome new title Renames the issue.
  • @home-assistant reopen Reopen the issue.
  • @home-assistant unassign music_assistant Removes the current integration label and assignees on the issue, add the integration domain after the command.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the issue.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) on the issue.

(message by CodeOwnersMention)


music_assistant documentation
music_assistant source
(message by IssueLinks)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants