@@ -336,6 +336,72 @@ private extension AuthInfo {
336
336
} catch {
337
337
logger? . warning ( " Error initializing authentication from client certificate: \( error) " )
338
338
}
339
+
340
+ #if os(Linux) || os(macOS)
341
+ do {
342
+ if let exec {
343
+ let outputData = try run ( command: exec. command, arguments: exec. args)
344
+
345
+ let decoder = JSONDecoder ( )
346
+ decoder. dateDecodingStrategy = . iso8601
347
+ let credential = try decoder. decode ( ExecCredential . self, from: outputData)
348
+
349
+ return . bearer( token: credential. status. token)
350
+ }
351
+ } catch {
352
+ logger? . warning ( " Error initializing authentication from exec \( error) " )
353
+ }
354
+ #endif
339
355
return nil
340
356
}
341
357
}
358
+
359
+ // MARK: - ExecCredential
360
+
361
+ // It seems that AWS doesn't implement properly the model for client.authentication.k8s.io/v1beta1
362
+ // Acordingly with the doc https://kubernetes.io/docs/reference/config-api/client-authentication.v1beta1/
363
+ // ExecCredential.Spec.interactive is required as long as the ones in the Status object.
364
+ internal struct ExecCredential : Decodable {
365
+ let apiVersion : String
366
+ let kind : String
367
+ let spec : Spec
368
+ let status : Status
369
+ }
370
+
371
+ internal extension ExecCredential {
372
+ struct Spec : Decodable {
373
+ let cluster : Cluster ?
374
+ let interactive : Bool ?
375
+ }
376
+
377
+ struct Status : Decodable {
378
+ let expirationTimestamp : Date
379
+ let token : String
380
+ let clientCertificateData : String ?
381
+ let clientKeyData : String ?
382
+ }
383
+ }
384
+
385
+ #if os(Linux) || os(macOS)
386
+ internal func run( command: String , arguments: [ String ] ? = nil ) throws -> Data {
387
+ func run( _ command: String , _ arguments: [ String ] ? ) throws -> Data {
388
+ let task = Process ( )
389
+ task. executableURL = URL ( fileURLWithPath: command)
390
+ task. arguments = arguments
391
+
392
+ let pipe = Pipe ( )
393
+ task. standardOutput = pipe
394
+
395
+ try task. run ( )
396
+
397
+ return pipe. fileHandleForReading. availableData
398
+ }
399
+
400
+ func resolve( command: String ) throws -> String {
401
+ try String ( decoding:
402
+ run ( " /usr/bin/which " , [ " \( command) " ] ) , as: UTF8 . self) . trimmingCharacters ( in: . whitespacesAndNewlines)
403
+ }
404
+
405
+ return try run ( resolve ( command: command) , arguments)
406
+ }
407
+ #endif
0 commit comments