@@ -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,98 @@ 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
93- else :
94- response .raise_for_status ()
95- assert False
9699
97- except Exception as e :
98- print (f"An unexpected error occurred. Error: { e } " )
99- assert False
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 (
103+ api_url , verify = False , json = jobdata , allow_redirects = True
104+ )
105+
106+ # Check if the submission was actually blocked
107+ # Success indicators that submission was blocked:
108+ # 1. Status code 403 (Forbidden)
109+ # 2. Status code 302 (Redirect to login) - but we need to verify the final response after redirect
110+ # 3. Status code 200 but with HTML content (login page) instead of JSON (job submission response)
111+ # 4. Status code 401 (Unauthorized)
112+
113+ submission_blocked = False
114+
115+ if response .status_code == 403 :
116+ submission_blocked = True
117+ elif response .status_code == 401 :
118+ submission_blocked = True
119+ elif response .status_code == 302 :
120+ # Redirect happened - check if final response after redirect is also a failure
121+ # If we followed redirects, check the final status
122+ submission_blocked = True # Redirect to login means submission failed
123+ elif response .status_code == 200 :
124+ # Check if response is HTML (login page) instead of JSON (job submission response)
125+ content_type = response .headers .get ("Content-Type" , "" )
126+ if "text/html" in content_type or "application/json" not in content_type :
127+ # Got HTML (likely login page) instead of JSON - submission was blocked
128+ submission_blocked = True
129+ else :
130+ # Got JSON response - check if it's an error or actually a successful submission
131+ try :
132+ json_response = response .json ()
133+ # If it's a successful job submission, it should have a 'job_id' or 'submission_id'
134+ # If it's an error, it might have 'error' or 'message'
135+ if "job_id" in json_response or "submission_id" in json_response :
136+ # Job was actually submitted - this is a failure!
137+ submission_blocked = False
138+ else :
139+ # Error response - submission was blocked
140+ submission_blocked = True
141+ except ValueError :
142+ # Not JSON - likely HTML login page
143+ submission_blocked = True
144+
145+ if not submission_blocked :
146+ assert (
147+ False
148+ ), f"Job submission succeeded without authentication! Status: { response .status_code } , Response: { response .text [:200 ]} "
149+
150+ # Also verify that RayJobClient cannot be used without authentication
151+ try :
152+ client = RayJobClient (address = dashboard_url , verify = False )
153+ # Try to call a method to trigger the connection and authentication check
154+ client .list_jobs ()
155+ assert (
156+ False
157+ ), "RayJobClient succeeded without authentication - this should not be possible"
158+ except (
159+ requests .exceptions .JSONDecodeError ,
160+ requests .exceptions .HTTPError ,
161+ Exception ,
162+ ):
163+ # Any exception is expected when trying to use the client without auth
164+ pass
165+
166+ assert True , "Job submission without authentication was correctly blocked"
100167
101168 def assert_jobsubmit_withlogin (self , cluster ):
102169 auth_token = run_oc_command (["whoami" , "--show-token=true" ])
103170 ray_dashboard = cluster .cluster_dashboard_uri ()
104171 header = {"Authorization" : f"Bearer { auth_token } " }
105172 client = RayJobClient (address = ray_dashboard , headers = header , verify = False )
106173
174+ # Verify that no jobs were submitted during the previous unauthenticated test
175+ # This ensures that the authentication check in assert_jobsubmit_withoutLogin actually worked
176+ existing_jobs = client .list_jobs ()
177+ if existing_jobs :
178+ job_ids = [
179+ job .job_id if hasattr (job , "job_id" ) else str (job )
180+ for job in existing_jobs
181+ ]
182+ assert False , (
183+ f"Found { len (existing_jobs )} existing job(s) before authenticated submission: { job_ids } . "
184+ "This indicates that the unauthenticated job submission test failed to properly block submission."
185+ )
186+ else :
187+ print (
188+ "Verified: No jobs exist from the previous unauthenticated submission attempt."
189+ )
190+
107191 submission_id = client .submit_job (
108192 entrypoint = "python mnist.py" ,
109193 runtime_env = {
0 commit comments