Integration.

This commit is contained in:
Max Goedjen 2021-11-06 19:53:43 -07:00
parent c15947e627
commit 0a6e71d7ce
No known key found for this signature in database
GPG Key ID: E58C21DD77B9B8E8
7 changed files with 60 additions and 16 deletions

View File

@ -30,7 +30,11 @@ class Notifier {
notificationCenter.requestAuthorization(options: .alert) { _, _ in }
}
func notify(accessTo secret: AnySecret, by provenance: SigningRequestProvenance, promptToPersist: Bool) {
func notify(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) {
notificationDelegate.persistAuthentication = { duration in
guard let duration = duration else { return }
try? store.persistAuthentication(secret: secret, forDuration: duration)
}
let notificationCenter = UNUserNotificationCenter.current()
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "Signed Request from \(provenance.origin.displayName)"
@ -70,11 +74,11 @@ class Notifier {
extension Notifier: SigningWitness {
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws {
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws {
}
func witness(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws {
notify(accessTo: secret, by: provenance, promptToPersist: false)
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws {
notify(accessTo: secret, from: store, by: provenance)
}
}
@ -104,12 +108,27 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
fileprivate var release: Release?
fileprivate var ignore: ((Release) -> Void)?
fileprivate var persistAuthentication: ((TimeInterval?) -> Void)?
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let category = response.notification.request.content.categoryIdentifier
switch category {
case Notifier.Constants.updateCategoryIdentitifier:
handleUpdateResponse(response: response)
case Notifier.Constants.persistAuthenticationCategoryIdentitifier:
handlePersistAuthenticationResponse(response: response)
default:
fatalError()
}
completionHandler()
}
func handleUpdateResponse(response: UNNotificationResponse) {
guard let update = release else { return }
switch response.actionIdentifier {
case Notifier.Constants.updateActionIdentitifier, UNNotificationDefaultActionIdentifier:
@ -119,7 +138,24 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
default:
fatalError()
}
completionHandler()
}
func handlePersistAuthenticationResponse(response: UNNotificationResponse) {
switch response.actionIdentifier {
case Notifier.Constants.doNotPersistActionIdentitifier, UNNotificationDefaultActionIdentifier:
break
case Notifier.Constants.persistForOneMinuteActionIdentitifier:
// TODO: CLEANUP CONSTANTS
persistAuthentication?(60)
case Notifier.Constants.persistForFiveMinutesActionIdentitifier:
persistAuthentication?(60 * 5)
case Notifier.Constants.persistForOneHourActionIdentitifier:
persistAuthentication?(60 * 60)
case Notifier.Constants.persistForOneDayActionIdentitifier:
persistAuthentication?(60 * 60 * 24)
default:
fatalError()
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

View File

@ -89,7 +89,7 @@ extension Agent {
}
if let witness = witness {
try witness.speakNowOrForeverHoldYourPeace(forAccessTo: secret, by: provenance)
try witness.speakNowOrForeverHoldYourPeace(forAccessTo: secret, from: store, by: provenance)
}
let dataToSign = reader.readNextChunk()
@ -134,7 +134,7 @@ extension Agent {
signedData.append(writer.lengthAndData(of: sub))
if let witness = witness {
try witness.witness(accessTo: secret, by: provenance)
try witness.witness(accessTo: secret, from: store, by: provenance)
}
Logger().debug("Agent signed request")

View File

@ -3,7 +3,7 @@ import SecretKit
public protocol SigningWitness {
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws
func witness(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws
}

View File

@ -9,6 +9,8 @@ public class AnySecretStore: SecretStore {
private let _name: () -> String
private let _secrets: () -> [AnySecret]
private let _sign: (Data, AnySecret, SigningRequestProvenance) throws -> Data
private let _persistAuthentication: (AnySecret, TimeInterval) throws -> Void
private var sink: AnyCancellable?
public init<SecretStoreType>(_ secretStore: SecretStoreType) where SecretStoreType: SecretStore {
@ -18,6 +20,7 @@ public class AnySecretStore: SecretStore {
_id = { secretStore.id }
_secrets = { secretStore.secrets.map { AnySecret($0) } }
_sign = { try secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType, for: $2) }
_persistAuthentication = { try secretStore.persistAuthentication(secret: $0.base as! SecretStoreType.SecretType, forDuration: $1) }
sink = secretStore.objectWillChange.sink { _ in
self.objectWillChange.send()
}
@ -43,6 +46,10 @@ public class AnySecretStore: SecretStore {
try _sign(data, secret, provenance)
}
public func persistAuthentication(secret: AnySecret, forDuration duration: TimeInterval) throws {
try _persistAuthentication(secret, duration)
}
}
public class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable {
@ -69,4 +76,5 @@ public class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable {
public func update(secret: AnySecret, name: String) throws {
try _update(secret, name)
}
}

View File

@ -11,6 +11,9 @@ public protocol SecretStore: ObservableObject, Identifiable {
func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data
// TODO: MOVE TO SEPARATE PROTOCOL?
func persistAuthentication(secret: SecretType, forDuration: TimeInterval) throws
}
public protocol SecretStoreModifiable: SecretStore {
@ -21,12 +24,6 @@ public protocol SecretStoreModifiable: SecretStore {
}
public protocol SecretStoreAuthenticationPersistable: SecretStore {
func persistAuthentication(secret: SecretType, forDuration: TimeInterval) throws
}
extension NSNotification.Name {
static let secretStoreUpdated = NSNotification.Name("com.maxgoedjen.Secretive.secretStore.updated")

View File

@ -5,7 +5,7 @@ import LocalAuthentication
extension SecureEnclave {
public class Store: SecretStoreModifiable, SecretStoreAuthenticationPersistable {
public class Store: SecretStoreModifiable {
public var isAvailable: Bool {
// For some reason, as of build time, CryptoKit.SecureEnclave.isAvailable always returns false

View File

@ -82,6 +82,9 @@ extension SmartCard {
return signature as Data
}
public func persistAuthentication(secret: SmartCard.Secret, forDuration: TimeInterval) throws {
}
}
}