Add agent support
This commit is contained in:
parent
286e2dc558
commit
a0bd55d1bf
|
@ -4,14 +4,14 @@ import OSLog
|
||||||
import SecretKit
|
import SecretKit
|
||||||
import SecretAgentKit
|
import SecretAgentKit
|
||||||
|
|
||||||
class Agent<StoreType: SecretStore> {
|
class Agent {
|
||||||
|
|
||||||
fileprivate let store: StoreType
|
fileprivate let storeList: SecretStoreList
|
||||||
fileprivate let notifier: Notifier
|
fileprivate let notifier: Notifier
|
||||||
|
|
||||||
public init(store: StoreType, notifier: Notifier) {
|
public init(storeList: SecretStoreList, notifier: Notifier) {
|
||||||
os_log(.debug, "Agent is running")
|
os_log(.debug, "Agent is running")
|
||||||
self.store = store
|
self.storeList = storeList
|
||||||
self.notifier = notifier
|
self.notifier = notifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,17 +57,18 @@ extension Agent {
|
||||||
extension Agent {
|
extension Agent {
|
||||||
|
|
||||||
func identities() throws -> Data {
|
func identities() throws -> Data {
|
||||||
var count = UInt32(store.secrets.count).bigEndian
|
let secrets = storeList.stores.flatMap(\.secrets)
|
||||||
|
var count = UInt32(secrets.count).bigEndian
|
||||||
let countData = Data(bytes: &count, count: UInt32.bitWidth/8)
|
let countData = Data(bytes: &count, count: UInt32.bitWidth/8)
|
||||||
var keyData = Data()
|
var keyData = Data()
|
||||||
let writer = OpenSSHKeyWriter()
|
let writer = OpenSSHKeyWriter()
|
||||||
for secret in store.secrets {
|
for secret in secrets {
|
||||||
let keyBlob = writer.data(secret: secret)
|
let keyBlob = writer.data(secret: secret)
|
||||||
keyData.append(writer.lengthAndData(of: keyBlob))
|
keyData.append(writer.lengthAndData(of: keyBlob))
|
||||||
let curveData = OpenSSHKeyWriter.Constants.curveType.data(using: .utf8)!
|
let curveData = OpenSSHKeyWriter.Constants.curveType.data(using: .utf8)!
|
||||||
keyData.append(writer.lengthAndData(of: curveData))
|
keyData.append(writer.lengthAndData(of: curveData))
|
||||||
}
|
}
|
||||||
os_log(.debug, "Agent enumerated %@ identities", store.secrets.count as NSNumber)
|
os_log(.debug, "Agent enumerated %@ identities", secrets.count as NSNumber)
|
||||||
return countData + keyData
|
return countData + keyData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,10 +76,16 @@ extension Agent {
|
||||||
let reader = OpenSSHReader(data: data)
|
let reader = OpenSSHReader(data: data)
|
||||||
let writer = OpenSSHKeyWriter()
|
let writer = OpenSSHKeyWriter()
|
||||||
let hash = try reader.readNextChunk()
|
let hash = try reader.readNextChunk()
|
||||||
let matching = store.secrets.filter { secret in
|
let matching = storeList.stores.compactMap { store -> (AnySecretStore, AnySecret)? in
|
||||||
hash == writer.data(secret: secret)
|
let allMatching = store.secrets.filter { secret in
|
||||||
|
hash == writer.data(secret: secret)
|
||||||
|
}
|
||||||
|
if let matching = allMatching.first {
|
||||||
|
return (store, matching)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
guard let secret = matching.first else {
|
guard let (store, secret) = matching.first else {
|
||||||
throw AgentError.noMatchingKey
|
throw AgentError.noMatchingKey
|
||||||
}
|
}
|
||||||
let dataToSign = try reader.readNextChunk()
|
let dataToSign = try reader.readNextChunk()
|
||||||
|
|
|
@ -5,10 +5,15 @@ import OSLog
|
||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
let store = SecureEnclave.Store()
|
let storeList: SecretStoreList = {
|
||||||
|
let list = SecretStoreList()
|
||||||
|
list.add(store: SecureEnclave.Store())
|
||||||
|
list.add(store: SmartCard.Store())
|
||||||
|
return list
|
||||||
|
}()
|
||||||
let notifier = Notifier()
|
let notifier = Notifier()
|
||||||
lazy var agent: Agent = {
|
lazy var agent: Agent = {
|
||||||
Agent(store: store, notifier: notifier)
|
Agent(storeList: storeList, notifier: notifier)
|
||||||
}()
|
}()
|
||||||
lazy var socketController: SocketController = {
|
lazy var socketController: SocketController = {
|
||||||
let path = (NSHomeDirectory() as NSString).appendingPathComponent("socket.ssh") as String
|
let path = (NSHomeDirectory() as NSString).appendingPathComponent("socket.ssh") as String
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class AnySecretStore: SecretStore {
|
||||||
_name = { secretStore.name }
|
_name = { secretStore.name }
|
||||||
_id = { secretStore.id }
|
_id = { secretStore.id }
|
||||||
_secrets = { secretStore.secrets.map { AnySecret($0) } }
|
_secrets = { secretStore.secrets.map { AnySecret($0) } }
|
||||||
_sign = { try secretStore.sign(data: $0, with: $1 as! SecretStoreType.SecretType) }
|
_sign = { try secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType) }
|
||||||
sink = secretStore.objectWillChange.sink { _ in
|
sink = secretStore.objectWillChange.sink { _ in
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
}
|
}
|
||||||
|
@ -65,5 +65,3 @@ public class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,11 @@ public class SecretStoreList: ObservableObject {
|
||||||
addInternal(store: modifiable)
|
addInternal(store: modifiable)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addInternal(store: AnySecretStore) {
|
}
|
||||||
|
|
||||||
|
extension SecretStoreList {
|
||||||
|
|
||||||
|
fileprivate func addInternal(store: AnySecretStore) {
|
||||||
stores.append(store)
|
stores.append(store)
|
||||||
let sink = store.objectWillChange.sink {
|
let sink = store.objectWillChange.sink {
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
|
|
Loading…
Reference in New Issue