Skip to content

Commit 8dcff4c

Browse files
committed
feat: Update Bundle-Version to 15.0.0 across multiple configuration files and add bare reply-to token request tests
1 parent af5e04a commit 8dcff4c

18 files changed

Lines changed: 99 additions & 17 deletions

pnnl.goss.core.itests/bnd.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Bundle-Version: 14.0.0
1+
Bundle-Version: 15.0.0
22

33
# Build dependencies - JUnit 5
44
# Note: Using osgi-core-buildpath only (not full osgi-buildpath) to avoid javax.jms from osgi.enterprise

pnnl.goss.core.itests/itest.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Modern OSGi Integration Test Configuration
2-
Bundle-Version: 14.0.0
2+
Bundle-Version: 15.0.0
33

44
# Use JUnit 5 and OSGi Test
55
# Note: Using osgi-core-buildpath to avoid javax.jms from osgi.enterprise

pnnl.goss.core.itests/src/pnnl/goss/core/itests/test_token_auth.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,50 @@ def request_token(conn_factory, host, port, username, password):
190190
return got_response, token, listener.error
191191

192192

193+
def request_token_bare_reply(conn_factory, host, port, username, password):
194+
"""
195+
Same as request_token but sends reply-to WITHOUT the /queue/ prefix.
196+
197+
This tests that the server correctly handles bare destination names
198+
(e.g., "temp.token_resp.xyz" instead of "/queue/temp.token_resp.xyz").
199+
"""
200+
conn = conn_factory(host, port)
201+
listener = TokenResponseListener()
202+
conn.set_listener("token_listener", listener)
203+
204+
log.info("Connecting to %s:%d as '%s' to request token (bare reply-to)...",
205+
host, port, username)
206+
conn.connect(username, password, wait=True)
207+
assert conn.is_connected(), "Failed to connect with username/password"
208+
209+
bare_dest = f"temp.token_resp.bare.{username}-{uuid.uuid4().hex[:12]}"
210+
auth_payload = base64.b64encode(f"{username}:{password}".encode()).decode()
211+
212+
# Subscribe using /queue/ prefix (STOMP requires it for subscription)
213+
conn.subscribe(destination=f"/queue/{bare_dest}", id="token-sub-bare", ack="auto")
214+
log.info("Subscribed to /queue/%s", bare_dest)
215+
216+
time.sleep(0.3)
217+
218+
# Send with bare reply-to (no /queue/ prefix)
219+
conn.send(
220+
destination=TOKEN_TOPIC,
221+
body=auth_payload,
222+
headers={"reply-to": bare_dest},
223+
)
224+
log.info("Sent token request with bare reply-to: %s", bare_dest)
225+
226+
got_response = listener.wait(TOKEN_TIMEOUT_S)
227+
token = listener.token
228+
229+
try:
230+
conn.disconnect()
231+
except Exception as e:
232+
log.debug("Non-critical error during disconnect: %s", e)
233+
234+
return got_response, token, listener.error
235+
236+
193237
def connect_with_token(conn_factory, host, port, token):
194238
"""Connect using a JWT token as the username with an empty password."""
195239
conn = conn_factory(host, port)
@@ -335,6 +379,25 @@ def test_02_request_token(self):
335379
log.info("STOMP: PASS received valid JWT (%d bytes)", len(token))
336380
TestStompTokenAuth._token = token
337381

382+
def test_02b_request_token_bare_reply_to(self):
383+
"""Request a JWT token with bare reply-to (no /queue/ prefix) over STOMP."""
384+
got_response, token, error = request_token_bare_reply(
385+
self._factory(), self.host, self.port, self.username, self.password
386+
)
387+
assert got_response, (
388+
f"Should get a token response with bare reply-to within {TOKEN_TIMEOUT_S}s"
389+
)
390+
assert error is None, f"Should not get an error: {error}"
391+
assert token is not None, "Token must not be None"
392+
assert len(token.strip()) > 0, "Token must not be empty"
393+
assert token != "authentication failed", "Token request should not fail auth"
394+
395+
parts = token.split(".")
396+
assert len(parts) == 3, (
397+
f"Token should be a JWT with 3 parts, got {len(parts)}: {token[:80]}..."
398+
)
399+
log.info("STOMP: PASS bare reply-to token request (%d bytes)", len(token))
400+
338401
def test_03_connect_with_token(self):
339402
"""Reconnect using the JWT token over STOMP."""
340403
token = TestStompTokenAuth._token
@@ -457,6 +520,25 @@ def test_02_request_token(self):
457520
log.info("WS: PASS received valid JWT (%d bytes)", len(token))
458521
TestWsTokenAuth._token = token
459522

523+
def test_02b_request_token_bare_reply_to(self):
524+
"""Request a JWT token with bare reply-to (no /queue/ prefix) over WebSocket."""
525+
got_response, token, error = request_token_bare_reply(
526+
self._factory(), self.host, self.port, self.username, self.password
527+
)
528+
assert got_response, (
529+
f"Should get a token response with bare reply-to within {TOKEN_TIMEOUT_S}s"
530+
)
531+
assert error is None, f"Should not get an error: {error}"
532+
assert token is not None, "Token must not be None"
533+
assert len(token.strip()) > 0, "Token must not be empty"
534+
assert token != "authentication failed", "Token request should not fail auth"
535+
536+
parts = token.split(".")
537+
assert len(parts) == 3, (
538+
f"Token should be a JWT with 3 parts, got {len(parts)}: {token[:80]}..."
539+
)
540+
log.info("WS: PASS bare reply-to token request (%d bytes)", len(token))
541+
460542
def test_03_connect_with_token(self):
461543
"""Reconnect using the JWT token over WebSocket."""
462544
token = TestWsTokenAuth._token

pnnl.goss.core.runner/bnd.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Bundle-Version: 14.0.0
1+
Bundle-Version: 15.0.0
22
-buildpath: \
33
org.apache.felix.gogo.command,\
44
org.apache.felix.gogo.runtime,\

pnnl.goss.core.testutil/bnd.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Bundle-Version: 14.0.0
1+
Bundle-Version: 15.0.0
22
-buildpath: \
33
${configadmin-buildpath},\
44
pnnl.goss.core.core-api,\

pnnl.goss.core/core-api.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Export-Package: \
22
com.northconcepts.exception,\
33
pnnl.goss.core
4-
Bundle-Version: 14.0.0
4+
Bundle-Version: 15.0.0

pnnl.goss.core/goss-client.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
Export-Package: \
22
pnnl.goss.core.client
3-
Bundle-Version: 14.0.0
3+
Bundle-Version: 15.0.0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
Private-Package: \
22
pnnl.goss.core.commands
3-
Bundle-Version: 14.0.0
3+
Bundle-Version: 15.0.0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Private-Package: \
22
pnnl.goss.core.exception
3-
Bundle-Version: 14.0.0
3+
Bundle-Version: 15.0.0
44
Export-Package: \
55
com.northconcepts.exception

pnnl.goss.core/goss-core-security.bnd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Private-Package: \
55
# The Activator class provides SecurityManager via @Component annotation
66
Export-Package: \
77
pnnl.goss.core.security
8-
Bundle-Version: 14.0.0
8+
Bundle-Version: 15.0.0
99

1010
# Require FileInstall to be present in the runtime
1111
# FileInstall watches the conf directory for .cfg files and loads them into ConfigAdmin

0 commit comments

Comments
 (0)