mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-04-18 05:22:11 +00:00
Integration.
This commit is contained in:
parent
c15947e627
commit
0a6e71d7ce
@ -30,7 +30,11 @@ class Notifier {
|
|||||||
notificationCenter.requestAuthorization(options: .alert) { _, _ in }
|
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 notificationCenter = UNUserNotificationCenter.current()
|
||||||
let notificationContent = UNMutableNotificationContent()
|
let notificationContent = UNMutableNotificationContent()
|
||||||
notificationContent.title = "Signed Request from \(provenance.origin.displayName)"
|
notificationContent.title = "Signed Request from \(provenance.origin.displayName)"
|
||||||
@ -70,11 +74,11 @@ class Notifier {
|
|||||||
|
|
||||||
extension Notifier: SigningWitness {
|
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 {
|
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws {
|
||||||
notify(accessTo: secret, by: provenance, promptToPersist: false)
|
notify(accessTo: secret, from: store, by: provenance)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -104,12 +108,27 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
|
|||||||
|
|
||||||
fileprivate var release: Release?
|
fileprivate var release: Release?
|
||||||
fileprivate var ignore: ((Release) -> Void)?
|
fileprivate var ignore: ((Release) -> Void)?
|
||||||
|
fileprivate var persistAuthentication: ((TimeInterval?) -> Void)?
|
||||||
|
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
|
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
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 }
|
guard let update = release else { return }
|
||||||
switch response.actionIdentifier {
|
switch response.actionIdentifier {
|
||||||
case Notifier.Constants.updateActionIdentitifier, UNNotificationDefaultActionIdentifier:
|
case Notifier.Constants.updateActionIdentitifier, UNNotificationDefaultActionIdentifier:
|
||||||
@ -119,7 +138,24 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
|
|||||||
default:
|
default:
|
||||||
fatalError()
|
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) {
|
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||||
|
@ -89,7 +89,7 @@ extension Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let witness = witness {
|
if let witness = witness {
|
||||||
try witness.speakNowOrForeverHoldYourPeace(forAccessTo: secret, by: provenance)
|
try witness.speakNowOrForeverHoldYourPeace(forAccessTo: secret, from: store, by: provenance)
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataToSign = reader.readNextChunk()
|
let dataToSign = reader.readNextChunk()
|
||||||
@ -134,7 +134,7 @@ extension Agent {
|
|||||||
signedData.append(writer.lengthAndData(of: sub))
|
signedData.append(writer.lengthAndData(of: sub))
|
||||||
|
|
||||||
if let witness = witness {
|
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")
|
Logger().debug("Agent signed request")
|
||||||
|
@ -3,7 +3,7 @@ import SecretKit
|
|||||||
|
|
||||||
public protocol SigningWitness {
|
public protocol 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
|
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ public class AnySecretStore: SecretStore {
|
|||||||
private let _name: () -> String
|
private let _name: () -> String
|
||||||
private let _secrets: () -> [AnySecret]
|
private let _secrets: () -> [AnySecret]
|
||||||
private let _sign: (Data, AnySecret, SigningRequestProvenance) throws -> Data
|
private let _sign: (Data, AnySecret, SigningRequestProvenance) throws -> Data
|
||||||
|
private let _persistAuthentication: (AnySecret, TimeInterval) throws -> Void
|
||||||
|
|
||||||
private var sink: AnyCancellable?
|
private var sink: AnyCancellable?
|
||||||
|
|
||||||
public init<SecretStoreType>(_ secretStore: SecretStoreType) where SecretStoreType: SecretStore {
|
public init<SecretStoreType>(_ secretStore: SecretStoreType) where SecretStoreType: SecretStore {
|
||||||
@ -18,6 +20,7 @@ public class AnySecretStore: SecretStore {
|
|||||||
_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.base as! SecretStoreType.SecretType, for: $2) }
|
_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
|
sink = secretStore.objectWillChange.sink { _ in
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
}
|
}
|
||||||
@ -43,6 +46,10 @@ public class AnySecretStore: SecretStore {
|
|||||||
try _sign(data, secret, provenance)
|
try _sign(data, secret, provenance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func persistAuthentication(secret: AnySecret, forDuration duration: TimeInterval) throws {
|
||||||
|
try _persistAuthentication(secret, duration)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable {
|
public class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable {
|
||||||
@ -69,4 +76,5 @@ public class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable {
|
|||||||
public func update(secret: AnySecret, name: String) throws {
|
public func update(secret: AnySecret, name: String) throws {
|
||||||
try _update(secret, name)
|
try _update(secret, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,9 @@ public protocol SecretStore: ObservableObject, Identifiable {
|
|||||||
|
|
||||||
func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data
|
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 {
|
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 {
|
extension NSNotification.Name {
|
||||||
|
|
||||||
static let secretStoreUpdated = NSNotification.Name("com.maxgoedjen.Secretive.secretStore.updated")
|
static let secretStoreUpdated = NSNotification.Name("com.maxgoedjen.Secretive.secretStore.updated")
|
||||||
|
@ -5,7 +5,7 @@ import LocalAuthentication
|
|||||||
|
|
||||||
extension SecureEnclave {
|
extension SecureEnclave {
|
||||||
|
|
||||||
public class Store: SecretStoreModifiable, SecretStoreAuthenticationPersistable {
|
public class Store: SecretStoreModifiable {
|
||||||
|
|
||||||
public var isAvailable: Bool {
|
public var isAvailable: Bool {
|
||||||
// For some reason, as of build time, CryptoKit.SecureEnclave.isAvailable always returns false
|
// For some reason, as of build time, CryptoKit.SecureEnclave.isAvailable always returns false
|
||||||
|
@ -82,6 +82,9 @@ extension SmartCard {
|
|||||||
return signature as Data
|
return signature as Data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func persistAuthentication(secret: SmartCard.Secret, forDuration: TimeInterval) throws {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user