Skip to content

Commit f1ecea9

Browse files
committed
keep identity certificates in ZitiIdentity
1 parent 2e28d2b commit f1ecea9

File tree

4 files changed

+61
-50
lines changed

4 files changed

+61
-50
lines changed

lib/Ziti.swift

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -329,12 +329,13 @@ import CZitiPrivate
329329
return
330330
}
331331

332-
// Store certificate
333-
let cert = dropFirst("pem:", resp.id.cert)
332+
// Store certificates
333+
let certs = dropFirst("pem:", resp.id.cert)
334334
_ = zkc.deleteCertificate(silent: true)
335-
let (err, cns) = zkc.storeCertificates(cert)
336-
guard err == nil else {
337-
let errStr = "Unable to store certificates\n"
335+
// storeCertificate only stores the first (leaf) certificate in the pem. that's ok - the full chain of certs is stored in the .zid
336+
// file. only the leaf/pubkey needs to be in the keychain.
337+
guard zkc.storeCertificate(fromPem: certs) == nil else {
338+
let errStr = "Unable to store certificate\n"
338339
log.error(errStr, function:"enroll()")
339340
enrollCallback(nil, ZitiError(errStr))
340341
return
@@ -346,8 +347,8 @@ import CZitiPrivate
346347
ca = dropFirst("pem:", idCa)
347348
}
348349

349-
let zid = ZitiIdentity(id: subj, ztAPIs: resp.ztAPIs, certCNs: cns, ca: ca)
350-
log.info("Enrolled id:\(subj) with controller: \(zid.ztAPI) with cns: \(zid.getCertCNs())", function:"enroll()")
350+
let zid = ZitiIdentity(id: subj, ztAPIs: resp.ztAPIs, certs: certs, ca: ca)
351+
log.info("Enrolled id:\(subj) with controller: \(zid.ztAPI)", function:"enroll()")
351352

352353
enrollCallback(zid, nil)
353354
}
@@ -384,14 +385,12 @@ import CZitiPrivate
384385
@objc public func run(_ postureChecks:ZitiPostureChecks?, _ initCallback: @escaping InitCallback) {
385386
// Get certificate
386387
let zkc = ZitiKeychain(tag: id.id)
387-
let (maybeCerts, zErr) = zkc.getCertificates(id.getCertCNs())
388-
guard let certs = maybeCerts, zErr == nil else {
389-
let errStr = zErr != nil ? zErr!.localizedDescription : "unable to retrieve certificates from keychain"
388+
guard let certPEM = id.getCertificates(zkc) else {
389+
let errStr = "unable to retrieve certificates"
390390
log.error(errStr)
391-
initCallback(zErr ?? ZitiError(errStr))
391+
initCallback(ZitiError(errStr))
392392
return
393393
}
394-
let certPEM = zkc.convertToPEM("CERTIFICATE", ders: certs)
395394

396395
// Get private key
397396
guard let privKey = zkc.getPrivateKey() else {
@@ -902,17 +901,20 @@ import CZitiPrivate
902901

903902
// update ourself
904903
if event.type == ZitiEvent.EventType.ConfigEvent {
905-
mySelf.id.ztAPI = event.configEvent!.controllerUrl
906-
mySelf.id.ztAPIs = event.configEvent!.controllers
907-
let zkc = ZitiKeychain(tag: mySelf.id.id)
908-
_ = zkc.deleteCertificate()
909-
let (zErr, certCNs) = zkc.storeCertificates(event.configEvent!.cert)
910-
if zErr != nil {
911-
log.warn("failed to store certificates: \(zErr!.localizedDescription)", function:"onEvent()")
912-
} else {
913-
mySelf.id.certCNs = certCNs
904+
let cfgEvent = event.configEvent!
905+
if !cfgEvent.controllerUrl.isEmpty { mySelf.id.ztAPI = cfgEvent.controllerUrl }
906+
if !cfgEvent.controllers.isEmpty { mySelf.id.ztAPIs = cfgEvent.controllers }
907+
if !cfgEvent.cert.isEmpty {
908+
mySelf.id.certs = cfgEvent.cert
909+
let zkc = ZitiKeychain(tag: mySelf.id.id)
910+
_ = zkc.deleteCertificate()
911+
// store the first/leaf certificate in the keychain so it can be used in a key pair.
912+
let zErr = zkc.storeCertificate(fromPem: event.configEvent!.cert)
913+
if zErr != nil {
914+
log.warn("failed to store certificate: \(zErr!.localizedDescription)", function:"onEvent()")
915+
}
914916
}
915-
mySelf.id.ca = event.configEvent!.caBundle
917+
if !cfgEvent.caBundle.isEmpty { mySelf.id.ca = cfgEvent.caBundle }
916918
}
917919

918920
mySelf.eventCallbacksLock.lock()

lib/ZitiIdentity.swift

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ import Foundation
3434
/// Initially the `sub` field from the one-time enrollment JWT. Used by `Ziti` to store and retrieve identity-related items in the Keychain
3535
@objc public let id:String
3636

37-
/// Certificate CNs
38-
///
39-
/// Common names for the certificates in this identities certificate chain. The first element will always match `id`.
40-
/// Used by `Ziti` to retrieve certificates from the Keychain.
41-
@objc public var certCNs:[String]?
42-
37+
/// Common names for the certificates in this identities certificate chain.
38+
/// This is only set when the identity is decoded from an older representation. When `certs` is not set, this value can be used to
39+
/// retrieve the identity's certificates from the Keychain.
40+
@available(*, deprecated, message: "store certificates in `certs` instead")
41+
@objc private var certCNs:[String]?
42+
4343
/// scheme, host, and port used to communicate with Ziti controller
4444
@objc public var ztAPI:String
4545

@@ -51,6 +51,9 @@ import Foundation
5151
/// Note that this name is unknown until a session with Ziti is active
5252
@objc public var name:String?
5353

54+
/// Certificates (PEM)
55+
@objc public var certs:String?
56+
5457
/// CA pool verified as part of enrollment that can be used to establish trust with of the Ziti controller
5558
@objc public var ca:String?
5659

@@ -65,23 +68,29 @@ import Foundation
6568
/// - certCNs: common names of certififcates
6669
/// - name: name currently configured for this identity
6770
/// - ca: CA pool that can be used to verify trust of the Ziti controller
68-
@objc public init(id:String, ztAPIs:[String], certCNs:[String]?=nil, name:String?=nil, ca:String?=nil) {
71+
@objc public init(id:String, ztAPIs:[String], name:String?=nil, certs:String?=nil, ca:String?=nil) {
6972
self.id = id
70-
self.certCNs = [ id ]
71-
if let certCNs {
72-
for cn in certCNs {
73-
if cn == id { continue }
74-
self.certCNs?.append(cn)
75-
}
76-
}
7773
self.ztAPI = ztAPIs.first ?? ""
7874
self.ztAPIs = ztAPIs
7975
self.name = name
76+
self.certs = certs
8077
self.ca = ca
8178
}
8279

83-
@objc public func getCertCNs() -> [String] {
84-
return certCNs ?? [self.id]
80+
@objc public func getCertificates(_ zkc:ZitiKeychain?) -> String? {
81+
if let certs = self.certs {
82+
log.debug("returning certificates from identity")
83+
return certs
84+
}
85+
// get certs using certCNs and the keychain if available.
86+
let certCNs = self.certCNs ?? [self.id]
87+
if let ders = zkc?.getCertificates(certCNs) {
88+
log.debug("returning certfificates from keychain CNs=\(certCNs)")
89+
self.certs = zkc?.convertToPEM("CERTIFICATE", ders: ders)
90+
self.certCNs = nil
91+
return self.certs
92+
}
93+
return nil
8594
}
8695

8796
/// Save this object to a JSON file

lib/ZitiKeychain.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ public class ZitiKeychain : NSObject {
257257
return sceStatus
258258
}
259259
#endif
260-
261-
@available(*, deprecated, message: "This function only stores the first certificate in `pem`. Use storeCertificates(pem:String) to store all certificates.")
260+
261+
/// This function only stores the first certificate in `pem`. use storeCertificates(pem:String) if you need to store all certificates in the keychain.
262262
func storeCertificate(fromPem pem:String) -> ZitiError? {
263263
let (_, zErr) = storeCertificate(fromDer: convertToDER(pem))
264264
if zErr != nil {
@@ -267,7 +267,6 @@ public class ZitiKeychain : NSObject {
267267
return zErr
268268
}
269269

270-
@available(*, deprecated)
271270
func storeCertificate(fromDer der:Data) -> (SecCertificate?, ZitiError?) {
272271
guard let certificate = SecCertificateCreateWithData(nil, der as CFData) else {
273272
let errStr = "Unable to create certificate from data for \(tag)"
@@ -316,17 +315,17 @@ public class ZitiKeychain : NSObject {
316315
return (certData, nil)
317316
}
318317

319-
func getCertificates(_ certCNs:[String]) -> ([Data]?, ZitiError?) {
318+
func getCertificates(_ certCNs:[String]) -> [Data]? {
320319
var certs:[Data] = []
321320
for cn in certCNs {
322321
let (cert, err) = getCertificate(cn)
323322
guard let cert = cert, err == nil else {
324-
return (nil, err)
323+
return nil
325324
}
326325
certs.append(cert)
327326
}
328327

329-
return (certs, nil)
328+
return certs
330329
}
331330

332331
func deleteCertificate(silent:Bool=false) -> ZitiError? {
@@ -362,12 +361,13 @@ public class ZitiKeychain : NSObject {
362361
return nil
363362
}
364363

365-
func convertToPEM(_ type:String, ders:[Data]) -> String {
364+
func convertToPEM(_ type:String, ders:[Data]) -> String? {
366365
var pem = ""
367366
ders.forEach { der in
368-
pem.append(convertToPEM("CERTIFICATE", der: der))
367+
pem.append(convertToPEM(type, der: der))
369368
}
370-
return pem
369+
if pem.count > 0 { return pem }
370+
return nil
371371
}
372372

373373
func convertToPEM(_ type:String, der:Data) -> String {

lib/ZitiTunnel.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,13 @@ public class ZitiTunnel : NSObject, ZitiUnretained {
350350
ziti.id.ca = event.caBundle
351351
}
352352
if !event.certPEM.isEmpty {
353+
ziti.id.certs = event.certPEM
354+
// store the first/leaf certificate in the keychain so it can be used in a key pair.
353355
let zkc = ZitiKeychain(tag: ziti.id.id)
354356
_ = zkc.deleteCertificate()
355-
let (zErr, certCNs) = zkc.storeCertificates(event.certPEM)
357+
let zErr = zkc.storeCertificate(fromPem: event.certPEM)
356358
if zErr != nil {
357359
log.warn("failed to store certificates: \(zErr!.localizedDescription)", function:"onEventCallback()")
358-
} else {
359-
ziti.id.certCNs = certCNs
360360
}
361361
}
362362
// pass event to application

0 commit comments

Comments
 (0)