@@ -76,6 +76,18 @@ def run_mnist_raycluster_sdk_oauth(self):
7676
7777 def assert_jobsubmit_withoutLogin (self , cluster ):
7878 dashboard_url = cluster .cluster_dashboard_uri ()
79+
80+ # Verify that job submission is actually blocked by attempting to submit without auth
81+ # The endpoint path depends on whether we're using HTTPRoute (with path prefix) or not
82+ if "/ray/" in dashboard_url :
83+ # HTTPRoute format: https://hostname/ray/namespace/cluster-name
84+ # API endpoint is at the same base path
85+ api_url = dashboard_url + "/api/jobs/"
86+ else :
87+ # OpenShift Route format: https://hostname
88+ # API endpoint is directly under the hostname
89+ api_url = dashboard_url + "/api/jobs/"
90+
7991 jobdata = {
8092 "entrypoint" : "python mnist.py" ,
8193 "runtime_env" : {
@@ -84,26 +96,83 @@ def assert_jobsubmit_withoutLogin(self, cluster):
8496 "env_vars" : get_setup_env_variables (),
8597 },
8698 }
87- try :
88- response = requests .post (
89- dashboard_url + "/api/jobs/" , verify = False , json = jobdata
90- )
91- if response .status_code == 403 :
92- assert True
99+
100+ # Try to submit a job without authentication
101+ # Follow redirects to see the final response - if it redirects to login, that's still a failure
102+ response = requests .post (api_url , verify = False , json = jobdata , allow_redirects = True )
103+
104+ # Check if the submission was actually blocked
105+ # Success indicators that submission was blocked:
106+ # 1. Status code 403 (Forbidden)
107+ # 2. Status code 302 (Redirect to login) - but we need to verify the final response after redirect
108+ # 3. Status code 200 but with HTML content (login page) instead of JSON (job submission response)
109+ # 4. Status code 401 (Unauthorized)
110+
111+ submission_blocked = False
112+
113+ if response .status_code == 403 :
114+ submission_blocked = True
115+ elif response .status_code == 401 :
116+ submission_blocked = True
117+ elif response .status_code == 302 :
118+ # Redirect happened - check if final response after redirect is also a failure
119+ # If we followed redirects, check the final status
120+ submission_blocked = True # Redirect to login means submission failed
121+ elif response .status_code == 200 :
122+ # Check if response is HTML (login page) instead of JSON (job submission response)
123+ content_type = response .headers .get ('Content-Type' , '' )
124+ if 'text/html' in content_type or 'application/json' not in content_type :
125+ # Got HTML (likely login page) instead of JSON - submission was blocked
126+ submission_blocked = True
93127 else :
94- response .raise_for_status ()
95- assert False
96-
97- except Exception as e :
98- print (f"An unexpected error occurred. Error: { e } " )
99- assert False
128+ # Got JSON response - check if it's an error or actually a successful submission
129+ try :
130+ json_response = response .json ()
131+ # If it's a successful job submission, it should have a 'job_id' or 'submission_id'
132+ # If it's an error, it might have 'error' or 'message'
133+ if 'job_id' in json_response or 'submission_id' in json_response :
134+ # Job was actually submitted - this is a failure!
135+ submission_blocked = False
136+ else :
137+ # Error response - submission was blocked
138+ submission_blocked = True
139+ except ValueError :
140+ # Not JSON - likely HTML login page
141+ submission_blocked = True
142+
143+ if not submission_blocked :
144+ assert False , f"Job submission succeeded without authentication! Status: { response .status_code } , Response: { response .text [:200 ]} "
145+
146+ # Also verify that RayJobClient cannot be used without authentication
147+ try :
148+ client = RayJobClient (address = dashboard_url , verify = False )
149+ # Try to call a method to trigger the connection and authentication check
150+ client .list_jobs ()
151+ assert False , "RayJobClient succeeded without authentication - this should not be possible"
152+ except (requests .exceptions .JSONDecodeError , requests .exceptions .HTTPError , Exception ):
153+ # Any exception is expected when trying to use the client without auth
154+ pass
155+
156+ assert True , "Job submission without authentication was correctly blocked"
100157
101158 def assert_jobsubmit_withlogin (self , cluster ):
102159 auth_token = run_oc_command (["whoami" , "--show-token=true" ])
103160 ray_dashboard = cluster .cluster_dashboard_uri ()
104161 header = {"Authorization" : f"Bearer { auth_token } " }
105162 client = RayJobClient (address = ray_dashboard , headers = header , verify = False )
106163
164+ # Verify that no jobs were submitted during the previous unauthenticated test
165+ # This ensures that the authentication check in assert_jobsubmit_withoutLogin actually worked
166+ existing_jobs = client .list_jobs ()
167+ if existing_jobs :
168+ job_ids = [job .job_id if hasattr (job , 'job_id' ) else str (job ) for job in existing_jobs ]
169+ assert False , (
170+ f"Found { len (existing_jobs )} existing job(s) before authenticated submission: { job_ids } . "
171+ "This indicates that the unauthenticated job submission test failed to properly block submission."
172+ )
173+ else :
174+ print ("Verified: No jobs exist from the previous unauthenticated submission attempt." )
175+
107176 submission_id = client .submit_job (
108177 entrypoint = "python mnist.py" ,
109178 runtime_env = {
0 commit comments