@@ -93,11 +93,13 @@ import CZitiPrivate
9393 var jwtFile_c : UnsafeMutablePointer < Int8 > ?
9494 var privatePem_c : UnsafeMutablePointer < Int8 > ?
9595 var url_c : UnsafeMutablePointer < Int8 > ?
96+ var token_c : UnsafeMutablePointer < Int8 > ?
9697
9798 deinit {
9899 jwtFile_c? . deallocate ( )
99100 privatePem_c? . deallocate ( )
100101 url_c? . deallocate ( )
102+ token_c? . deallocate ( )
101103 }
102104 }
103105
@@ -180,23 +182,66 @@ import CZitiPrivate
180182 }
181183 }
182184
185+ static func enroll( withLoop loop: UnsafeMutablePointer < uv_loop_t > ? ,
186+ token: String ,
187+ cb: @escaping EnrollmentCallback ) {
188+ let enrollData = UnsafeMutablePointer< EnrollmentRequestData> . allocate( capacity: 1 )
189+ enrollData. initialize ( to: EnrollmentRequestData ( ) )
190+ enrollData. pointee. enrollmentCallback = cb
191+ enrollData. pointee. token_c = UnsafeMutablePointer< Int8> . allocate( capacity: token. count + 1 )
192+ enrollData. pointee. token_c!. initialize ( from: token. cString ( using: . utf8) !, count: token. count + 1 )
193+
194+
195+ var enroll_opts = ziti_enroll_opts ( url: nil , token: enrollData. pointee. token_c, key: nil ,
196+ cert: nil , name: nil , use_keychain: false )
197+ let status = ziti_enroll ( & enroll_opts, loop, ZitiEnroller . on_enroll, enrollData)
198+ guard status == ZITI_OK else {
199+ let errStr = String ( cString: ziti_errorstr ( status) )
200+ log. error ( errStr)
201+ cb ( nil , nil , ZitiError ( errStr, errorCode: Int ( status) ) )
202+ return
203+ }
204+ }
205+
206+ struct NetworkJwtsResponse : Codable {
207+ struct Data : Codable {
208+ var name : String ?
209+ var token : String ?
210+ }
211+
212+ var data : [ NetworkJwtsResponse . Data ] ?
213+ }
214+
183215 @objc public static func enroll( url: String , cb: @escaping EnrollmentCallback ) {
184216 // test the connection to avoid assertion in ziti-sdk-c/libuv
185- guard let ctrlUrl = URL ( string: url) else {
217+ // also get /network-jwts so we can use apple's ca store to trust the provided url (tlsuv/openssl does not load trusted certs on iOS).
218+ // if the response includes a token we use that for the enrollment instead of the url.
219+ guard let jwtUrl = URL ( string: url + ( url. hasSuffix ( " / " ) ? " " : " / " ) + " /network-jwts " ) else {
186220 let zErr = ZitiError ( " cannot parse \( url) as URL " )
187221 log. error ( String ( describing: zErr) , function: " enroll() " )
188222 cb ( nil , nil , zErr)
189223 return
190224 }
191- let ( data, response, error) = URLSession . shared. syncRequest ( with: ctrlUrl)
225+
226+ let ( data, response, error) = URLSession . shared. syncRequest ( with: jwtUrl)
192227 if let error = error {
193228 let zErr = ZitiError ( " connection to \( url) failed: \( error. localizedDescription) " )
194229 log. error ( String ( describing: zErr) , function: " enroll() " )
195230 cb ( nil , nil , zErr)
196231 return
197232 }
198-
199- self . enroll ( withLoop: ZitiEnroller . loop, controllerURL: url, cb: cb)
233+
234+ guard let httpResp = response as? HTTPURLResponse , ( 200 ... 299 ) . contains ( httpResp. statusCode) , let data = data,
235+ let decodedResp = try ? JSONDecoder ( ) . decode ( NetworkJwtsResponse . self, from: data) ,
236+ let token = decodedResp. data? . first? . token else {
237+ let zErr = ZitiError ( " invalid response from \( jwtUrl) " )
238+ log. error ( String ( describing: zErr) , function: " enroll() " )
239+ cb ( nil , nil , zErr)
240+ return
241+ }
242+
243+ log. debug ( " fetched token \( token) from \( jwtUrl) " )
244+ self . enroll ( withLoop: ZitiEnroller . loop, token: token, cb: cb)
200245
201246 let runStatus = uv_run ( ZitiEnroller . loop, UV_RUN_DEFAULT)
202247 guard runStatus == 0 else {
0 commit comments