diff --git a/Sources/Packages/Sources/SecretAgentKit/PublicKeyStandinFileController.swift b/Sources/Packages/Sources/SecretAgentKit/PublicKeyStandinFileController.swift index 51b5421..174d2c8 100644 --- a/Sources/Packages/Sources/SecretAgentKit/PublicKeyStandinFileController.swift +++ b/Sources/Packages/Sources/SecretAgentKit/PublicKeyStandinFileController.swift @@ -1,47 +1,45 @@ import Foundation +import OSLog import SecretKit -public class PublicKeyStandinFileStoreController { +/// Controller responsible for writing public keys to disk, so that they're easily accessible by scripts. +public class PublicKeyFileStoreController { - var files: [PublicKeyStandinFileController] = [] + private let logger = Logger() + private let directory = NSHomeDirectory().appending("/PublicKeys") - public init(secrets: [AnySecret]) { - let directory = NSHomeDirectory().appending("/PublicKeys") - try? FileManager.default.removeItem(at: URL(fileURLWithPath: directory)) - try? FileManager.default.createDirectory(at: URL(fileURLWithPath: directory), withIntermediateDirectories: false, attributes: nil) - // TODO: TEST - files = secrets.filter({ $0.name == "Git Signature"}) - /*files = secrets*/.map { PublicKeyStandinFileController(secret: $0, path: directory.appending("/").appending("test") )} - print("Done") + /// Initializes a PublicKeyFileStoreController + public init() { } - enum Constants { - static var standinExtension = "secretive-public-key" + /// Removes and recreates the directory used to store keys. + public func clear() throws { } -} - -public class PublicKeyStandinFileController { - - private var fileHandle: FileHandle? - private let secret: AnySecret - private let keyWriter = OpenSSHKeyWriter() - - public init(secret: AnySecret, path: String) { - self.secret = secret - resetHandle(path: path) - } - - func resetHandle(path: String) { - try? FileManager.default.removeItem(atPath: path) - let fifo = mkfifo(UnsafePointer(Array(path.utf8CString)), S_IRWXU) - assert(fifo == 0) - fileHandle = nil - fileHandle = FileHandle(forWritingAtPath: path) - fileHandle?.writeabilityHandler = { [self] handle in - try! handle.write(contentsOf: keyWriter.openSSHString(secret: secret).data(using: .utf8)!) - try! fileHandle?.close() -// self.resetHandle(path: path) + /// Writes out the keys specified to disk. + /// - Parameter secrets: The Secrets to generate keys for. + /// - Parameter clear: Whether or not the directory should be erased before writing keys. + public func generatePublicKeys(for secrets: [AnySecret], clear: Bool = false) throws { + logger.log("Writing public keys to disk") + if clear { + try? FileManager.default.removeItem(at: URL(fileURLWithPath: directory)) } + try? FileManager.default.createDirectory(at: URL(fileURLWithPath: directory), withIntermediateDirectories: false, attributes: nil) + let keyWriter = OpenSSHKeyWriter() + for secret in secrets { + let path = path(for: secret) + guard let data = keyWriter.openSSHString(secret: secret).data(using: .utf8) else { continue } + FileManager.default.createFile(atPath: path, contents: data, attributes: nil) + } + logger.log("Finished writing public keys") } + + /// The path for a Secret's public key. + /// - Parameter secret: The Secret to return the path for. + /// - Returns: The path to the Secret's public key. + /// - Warning: This method returning a path does not imply that a key has been written to disk already. This method only describes where it will be written to. + func path(for secret: AnySecret) -> String { + directory.appending("/").appending("\(secret.name.replacingOccurrences(of: " ", with: "-")).pub") + } + } diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift index 4ecd6b4..830401c 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift @@ -4,8 +4,6 @@ import CryptoTokenKit import LocalAuthentication import SecretKit -// TODO: Might need to split this up into "sub-stores?" -// ie, each token has its own Store. extension SmartCard { /// An implementation of Store backed by a Smart Card. diff --git a/Sources/SecretAgent/AppDelegate.swift b/Sources/SecretAgent/AppDelegate.swift index 6769ee7..ce9832d 100644 --- a/Sources/SecretAgent/AppDelegate.swift +++ b/Sources/SecretAgent/AppDelegate.swift @@ -18,6 +18,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { }() private let updater = Updater(checkOnLaunch: false) private let notifier = Notifier() + private let publicKeyFileStoreController = PublicKeyFileStoreController() private lazy var agent: Agent = { Agent(storeList: storeList, witness: notifier) }() @@ -25,10 +26,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { let path = (NSHomeDirectory() as NSString).appendingPathComponent("socket.ssh") as String return SocketController(path: path) }() - // TODO: CLEANUP - private lazy var fakeFile: PublicKeyStandinFileStoreController = { - PublicKeyStandinFileStoreController(secrets: storeList.stores.flatMap({ $0.secrets })) - }() private var updateSink: AnyCancellable? func applicationDidFinishLaunching(_ aNotification: Notification) { @@ -41,12 +38,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { guard let update = update else { return } self.notifier.notify(update: update, ignore: self.updater.ignore(release:)) } - // TODO: CLEANUP - DispatchQueue.main.async { - print(self.fakeFile) - } } + func reloadKeys() { + // TODO: This +// storeList.reloadAll() + try? publicKeyFileStoreController.clear() + try? publicKeyFileStoreController.generatePublicKeys(for: storeList.stores.flatMap({ $0.secrets })) + } } diff --git a/Sources/Secretive/Views/SecretDetailView.swift b/Sources/Secretive/Views/SecretDetailView.swift index e6e335a..bd26675 100644 --- a/Sources/Secretive/Views/SecretDetailView.swift +++ b/Sources/Secretive/Views/SecretDetailView.swift @@ -17,7 +17,10 @@ struct SecretDetailView: View { CopyableView(title: "MD5 Fingerprint", image: Image(systemName: "touchid"), text: keyWriter.openSSHMD5Fingerprint(secret: secret)) Spacer() .frame(height: 20) - CopyableView(title: "Public Key", image: Image(systemName: "key"), text: keyString) + CopyableView(title: "Public Key Contents", image: Image(systemName: "key"), text: keyString) + Spacer() + .frame(height: 20) + CopyableView(title: "Public Key Path", image: Image(systemName: "lock.doc"), text: "/Users/max/whatever") Spacer() } } @@ -40,12 +43,7 @@ struct SecretDetailView: View { var keyString: String { keyWriter.openSSHString(secret: secret, comment: "\(dashedKeyName)@\(dashedHostName)") } - - func copy() { - NSPasteboard.general.declareTypes([.string], owner: nil) - NSPasteboard.general.setString(keyString, forType: .string) - } - + } #if DEBUG