mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-05-08 16:38:58 +02:00
WIP
This commit is contained in:
@@ -365,6 +365,16 @@
|
|||||||
},
|
},
|
||||||
"shouldTranslate" : false
|
"shouldTranslate" : false
|
||||||
},
|
},
|
||||||
|
"%@ - %@" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "%1$@ - %2$@"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"about_build_log_button" : {
|
"about_build_log_button" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -19821,6 +19831,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Review" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Review All" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"secret_detail_md5_fingerprint_label" : {
|
"secret_detail_md5_fingerprint_label" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@unsafe @preconcurrency import LocalAuthentication
|
@unsafe @preconcurrency import LocalAuthentication
|
||||||
import SecretKit
|
import SecretKit
|
||||||
|
import OSLog
|
||||||
|
|
||||||
/// A context describing a persisted authentication.
|
/// A context describing a persisted authentication.
|
||||||
public final class AuthenticationContext: AuthenticationContextProtocol {
|
public final class AuthenticationContext: AuthenticationContextProtocol {
|
||||||
@@ -63,26 +64,41 @@ public actor AuthenticationHandler {
|
|||||||
private var activeTask: Task<Void, any Error>?
|
private var activeTask: Task<Void, any Error>?
|
||||||
|
|
||||||
private var lastBatchAuthPresentation: Set<SignatureRequest>?
|
private var lastBatchAuthPresentation: Set<SignatureRequest>?
|
||||||
private var presentBatchAuth: ((Set<SignatureRequest>, @Sendable (Set<SignatureRequest>) async throws -> Void) async throws -> Void)?
|
private var presentBatchAuth: (([[SignatureRequest]], @escaping @Sendable (Set<SignatureRequest>) async throws -> Void) async throws -> Void)?
|
||||||
|
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "Agent")
|
||||||
|
|
||||||
public init(presentBatchAuth: ((Set<SignatureRequest>, @Sendable (Set<SignatureRequest>) async throws -> Void) async throws -> Void)?) {
|
public init() {
|
||||||
self.presentBatchAuth = presentBatchAuth
|
}
|
||||||
|
|
||||||
|
public func setBatchAuthHandler(_ handler: @escaping (@Sendable ([[SignatureRequest]], @escaping @Sendable (Set<SignatureRequest>) async throws -> Void) async throws -> Void)) {
|
||||||
|
self.presentBatchAuth = handler
|
||||||
}
|
}
|
||||||
|
|
||||||
public func waitForAuthentication(for request: SignatureRequest) async throws -> any AuthenticationContextProtocol {
|
public func waitForAuthentication(for request: SignatureRequest) async throws -> any AuthenticationContextProtocol {
|
||||||
if let existing = existingAuthenticationContext(for: request) { return existing }
|
if let existing = existingAuthenticationContext(for: request) {
|
||||||
|
logger.log("Short circuiting wait, existing valid context already exists.")
|
||||||
|
return existing
|
||||||
|
}
|
||||||
holdingRequests.insert(request)
|
holdingRequests.insert(request)
|
||||||
defer { holdingRequests.remove(request) }
|
logger.log("Waiting for authentication for \(request.id)")
|
||||||
|
defer {
|
||||||
|
logger.log("Removed hold for \(request.id)")
|
||||||
|
holdingRequests.remove(request)
|
||||||
|
}
|
||||||
while holdingRequests.count > 1 {
|
while holdingRequests.count > 1 {
|
||||||
if hasBatchableRequests, holdingRequests != lastBatchAuthPresentation {
|
if hasBatchableRequests, holdingRequests != lastBatchAuthPresentation {
|
||||||
|
logger.log("Batchable requests exist, cancelling existing auth prompt")
|
||||||
activeTask?.cancel()
|
activeTask?.cancel()
|
||||||
lastBatchAuthPresentation = holdingRequests
|
lastBatchAuthPresentation = holdingRequests
|
||||||
try await presentBatchAuth?(holdingRequests) {
|
logger.log("Requesting batch auth presentation")
|
||||||
try await persistAuthentication(for: $0)
|
try await presentBatchAuth?(batchableRequests, persistAuthentication(for:))
|
||||||
}
|
logger.log("Requested batch auth presentation")
|
||||||
}
|
}
|
||||||
if let preauthorized = existingAuthenticationContext(for: request) {
|
if let preauthorized = existingAuthenticationContext(for: request) {
|
||||||
|
logger.log("Batch auth context found, proceededing with preauthorized context")
|
||||||
return preauthorized
|
return preauthorized
|
||||||
|
} else {
|
||||||
|
logger.log("Waiting for batch request handling")
|
||||||
}
|
}
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
}
|
}
|
||||||
@@ -92,12 +108,20 @@ public actor AuthenticationHandler {
|
|||||||
let context = AuthenticationContext(secret: request.secret, context: laContext, requestID: request.id)
|
let context = AuthenticationContext(secret: request.secret, context: laContext, requestID: request.id)
|
||||||
|
|
||||||
activeTask = Task {
|
activeTask = Task {
|
||||||
_ = try? await laContext.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: laContext.localizedReason)
|
logger.log("Beginning individual auth prompt")
|
||||||
|
try await Task.sleep(for: .seconds(1000))
|
||||||
|
// _ = try? await laContext.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: laContext.localizedReason)
|
||||||
|
logger.log("Ended individual auth prompt")
|
||||||
}
|
}
|
||||||
_ = try await activeTask?.value
|
_ = try await activeTask?.value
|
||||||
|
// TODO: Check something beyond cancellation? id?
|
||||||
|
// Is this okay? Do we always assume that a cancelled task will be the proceeded on?
|
||||||
if activeTask?.isCancelled ?? false {
|
if activeTask?.isCancelled ?? false {
|
||||||
|
logger.log("Auth prompt was cancelled, waiting for explicit auth")
|
||||||
|
// If we explicitly cancelled the task, hang on until we auth it.
|
||||||
while true {
|
while true {
|
||||||
if let preauthorized = existingAuthenticationContext(for: request) {
|
if let preauthorized = existingAuthenticationContext(for: request) {
|
||||||
|
logger.log("Explicit auth context found")
|
||||||
return preauthorized
|
return preauthorized
|
||||||
}
|
}
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
@@ -106,10 +130,17 @@ public actor AuthenticationHandler {
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var batchableRequests: [[SignatureRequest]] {
|
||||||
|
holdingRequests.reduce(into: [:]) { partialResult, next in
|
||||||
|
partialResult[next.batchID, default: []].append(next)
|
||||||
|
}
|
||||||
|
.values
|
||||||
|
.map { $0.sorted() }
|
||||||
|
}
|
||||||
|
|
||||||
private var hasBatchableRequests: Bool {
|
private var hasBatchableRequests: Bool {
|
||||||
guard presentBatchAuth != nil else { return false }
|
guard presentBatchAuth != nil else { return false }
|
||||||
// FIXME: THIS
|
return batchableRequests.count < holdingRequests.count
|
||||||
return holdingRequests.count > 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func existingAuthenticationContext(for request: SignatureRequest) -> (any AuthenticationContextProtocol)? {
|
private func existingAuthenticationContext(for request: SignatureRequest) -> (any AuthenticationContextProtocol)? {
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ public protocol AuthenticationContextProtocol: Sendable, Identifiable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SignatureRequest: Identifiable, Hashable, Sendable {
|
public struct SignatureRequest: Identifiable, Hashable, Sendable, Comparable {
|
||||||
|
|
||||||
public let id: UUID
|
public let id: UUID
|
||||||
public let date: Date
|
public let date: Date
|
||||||
public let secret: AnySecret
|
public let secret: AnySecret
|
||||||
@@ -25,4 +26,16 @@ public struct SignatureRequest: Identifiable, Hashable, Sendable {
|
|||||||
self.secret = secret
|
self.secret = secret
|
||||||
self.provenance = provenance
|
self.provenance = provenance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var batchID: Int {
|
||||||
|
var hasher = Hasher()
|
||||||
|
provenance.batchID.hash(into: &hasher)
|
||||||
|
secret.id.hash(into: &hasher)
|
||||||
|
return hasher.finalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func < (lhs: SignatureRequest, rhs: SignatureRequest) -> Bool {
|
||||||
|
lhs.date < rhs.date
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ public struct SigningRequestProvenance: Hashable, Sendable {
|
|||||||
self.date = date
|
self.date = date
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var batchID: Int {
|
||||||
|
var hasher = Hasher()
|
||||||
|
chain.map(\.path).hash(into: &hasher)
|
||||||
|
return hasher.finalize()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SigningRequestProvenance {
|
extension SigningRequestProvenance {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ extension ProcessInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard let value = SecTaskCopyValueForEntitlement(task, "com.apple.developer.team-identifier" as CFString, nil) as? String else {
|
guard let value = SecTaskCopyValueForEntitlement(task, "com.apple.developer.team-identifier" as CFString, nil) as? String else {
|
||||||
assertionFailure("SecTaskCopyValueForEntitlement(com.apple.developer.team-identifier) failed")
|
// assertionFailure("SecTaskCopyValueForEntitlement(com.apple.developer.team-identifier) failed")
|
||||||
return fallbackTeamID
|
return fallbackTeamID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
122
Sources/SecretAgent/App.swift
Normal file
122
Sources/SecretAgent/App.swift
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import Cocoa
|
||||||
|
import OSLog
|
||||||
|
import SecretKit
|
||||||
|
import SecureEnclaveSecretKit
|
||||||
|
import SmartCardSecretKit
|
||||||
|
import SecretAgentKit
|
||||||
|
import Brief
|
||||||
|
import Observation
|
||||||
|
import Common
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct SecretAgent: App {
|
||||||
|
|
||||||
|
@MainActor private let storeList: SecretStoreList = {
|
||||||
|
let list = SecretStoreList()
|
||||||
|
let cryptoKit = SecureEnclave.Store()
|
||||||
|
let migrator = SecureEnclave.CryptoKitMigrator()
|
||||||
|
try? migrator.migrate(to: cryptoKit)
|
||||||
|
list.add(store: cryptoKit)
|
||||||
|
list.add(store: SmartCard.Store())
|
||||||
|
return list
|
||||||
|
}()
|
||||||
|
private let updater = Updater(checkOnLaunch: true)
|
||||||
|
private let notifier = Notifier()
|
||||||
|
private let authenticationHandler = AuthenticationHandler()
|
||||||
|
private let publicKeyFileStoreController = PublicKeyFileStoreController(directory: URL.publicKeyDirectory)
|
||||||
|
|
||||||
|
@State var pending: ([[SignatureRequest]], (Set<SignatureRequest>) async throws -> Void)?
|
||||||
|
@Environment(\.openWindow) var openWindow
|
||||||
|
|
||||||
|
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "App")
|
||||||
|
@SceneBuilder var body: some Scene {
|
||||||
|
MenuBarExtra(isInserted: .constant(false)) {
|
||||||
|
EmptyView()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "lock")
|
||||||
|
.task {
|
||||||
|
await notifier.registerPersistenceHandler {
|
||||||
|
try await authenticationHandler.persistAuthentication(secret: $0, forDuration: $1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task {
|
||||||
|
let socketController = SocketController(path: URL.socketPath)
|
||||||
|
let agent = Agent(storeList: storeList, authenticationHandler: authenticationHandler, witness: notifier)
|
||||||
|
for await session in socketController.sessions {
|
||||||
|
Task {
|
||||||
|
let inputParser = try await XPCAgentInputParser()
|
||||||
|
do {
|
||||||
|
for await message in session.messages {
|
||||||
|
let request = try await inputParser.parse(data: message)
|
||||||
|
let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
||||||
|
try session.write(agentResponse)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
try session.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// .task {
|
||||||
|
// let socketController = SocketController(path: URL.agentHomeURL.appendingPathComponent("socket-two.ssh").path())
|
||||||
|
// let socketController = SocketController(path: "/Users/max/Downloads/test.ssh")
|
||||||
|
// let agent = Agent(storeList: storeList, authenticationHandler: authenticationHandler, witness: notifier)
|
||||||
|
// for await session in socketController.sessions {
|
||||||
|
// Task {
|
||||||
|
// let inputParser = try await XPCAgentInputParser()
|
||||||
|
// do {
|
||||||
|
// for await message in session.messages {
|
||||||
|
// let request = try await inputParser.parse(data: message)
|
||||||
|
// let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
||||||
|
// try session.write(agentResponse)
|
||||||
|
// }
|
||||||
|
// } catch {
|
||||||
|
// try session.close()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
.task {
|
||||||
|
for await _ in NotificationCenter.default.notifications(named: .secretStoreReloaded) {
|
||||||
|
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task {
|
||||||
|
await authenticationHandler.setBatchAuthHandler { @MainActor pending, authorize in
|
||||||
|
self.pending = (pending, authorize)
|
||||||
|
openWindow(id: String(describing: BatchedRequestsView.self))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.task {
|
||||||
|
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
||||||
|
notifier.prompt()
|
||||||
|
_ = withObservationTracking {
|
||||||
|
updater.update
|
||||||
|
} onChange: { [updater, notifier] in
|
||||||
|
Task {
|
||||||
|
guard !updater.currentVersion.isTestBuild else { return }
|
||||||
|
await notifier.notify(update: updater.update!) { release in
|
||||||
|
await updater.ignore(release: release)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WindowGroup(id: String(describing: BatchedRequestsView.self)) {
|
||||||
|
pendingView
|
||||||
|
}
|
||||||
|
.windowStyle(.hiddenTitleBar)
|
||||||
|
.windowResizability(.contentSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
var pendingView: some View {
|
||||||
|
if let (requests, authorize) = pending {
|
||||||
|
BatchedRequestsView(pending: requests, review: authorize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import Cocoa
|
|
||||||
import OSLog
|
|
||||||
import SecretKit
|
|
||||||
import SecureEnclaveSecretKit
|
|
||||||
import SmartCardSecretKit
|
|
||||||
import SecretAgentKit
|
|
||||||
import Brief
|
|
||||||
import Observation
|
|
||||||
import Common
|
|
||||||
|
|
||||||
@main
|
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
||||||
|
|
||||||
@MainActor private let storeList: SecretStoreList = {
|
|
||||||
let list = SecretStoreList()
|
|
||||||
let cryptoKit = SecureEnclave.Store()
|
|
||||||
let migrator = SecureEnclave.CryptoKitMigrator()
|
|
||||||
try? migrator.migrate(to: cryptoKit)
|
|
||||||
list.add(store: cryptoKit)
|
|
||||||
list.add(store: SmartCard.Store())
|
|
||||||
return list
|
|
||||||
}()
|
|
||||||
private let updater = Updater(checkOnLaunch: true)
|
|
||||||
private let notifier = Notifier()
|
|
||||||
private let authenticationHandler = AuthenticationHandler { pending, authorize in
|
|
||||||
print(pending)
|
|
||||||
print("Waiting")
|
|
||||||
// Task {
|
|
||||||
try await Task.sleep(for: .seconds(3))
|
|
||||||
try await authorize(pending)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
private let publicKeyFileStoreController = PublicKeyFileStoreController(directory: URL.publicKeyDirectory)
|
|
||||||
private lazy var agent: Agent = {
|
|
||||||
Agent(storeList: storeList, authenticationHandler: authenticationHandler, witness: notifier)
|
|
||||||
}()
|
|
||||||
private lazy var socketController: SocketController = {
|
|
||||||
let path = URL.socketPath as String
|
|
||||||
return SocketController(path: path)
|
|
||||||
}()
|
|
||||||
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "AppDelegate")
|
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
|
||||||
logger.debug("SecretAgent finished launching")
|
|
||||||
Task {
|
|
||||||
for await session in socketController.sessions {
|
|
||||||
Task {
|
|
||||||
let inputParser = try await XPCAgentInputParser()
|
|
||||||
do {
|
|
||||||
for await message in session.messages {
|
|
||||||
let request = try await inputParser.parse(data: message)
|
|
||||||
let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
|
||||||
try session.write(agentResponse)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
try session.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Task { [notifier, authenticationHandler] in
|
|
||||||
await notifier.registerPersistenceHandler {
|
|
||||||
try await authenticationHandler.persistAuthentication(secret: $0, forDuration: $1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Task {
|
|
||||||
for await _ in NotificationCenter.default.notifications(named: .secretStoreReloaded) {
|
|
||||||
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
|
||||||
notifier.prompt()
|
|
||||||
_ = withObservationTracking {
|
|
||||||
updater.update
|
|
||||||
} onChange: { [updater, notifier] in
|
|
||||||
Task {
|
|
||||||
guard !updater.currentVersion.isTestBuild else { return }
|
|
||||||
await notifier.notify(update: updater.update!) { release in
|
|
||||||
await updater.ignore(release: release)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
58
Sources/SecretAgent/BatchedRequestsView.swift
Normal file
58
Sources/SecretAgent/BatchedRequestsView.swift
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import SwiftUI
|
||||||
|
import SecretKit
|
||||||
|
import SecretAgentKit
|
||||||
|
import SmartCardSecretKit
|
||||||
|
|
||||||
|
struct BatchedRequestsView: View {
|
||||||
|
|
||||||
|
let pending: [[SignatureRequest]]
|
||||||
|
let review: (Set<SignatureRequest>) async throws -> Void
|
||||||
|
|
||||||
|
init(pending: [[SignatureRequest]], review: @escaping (Set<SignatureRequest>) async throws -> Void) {
|
||||||
|
self.pending = pending
|
||||||
|
self.review = review
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
// .padding()
|
||||||
|
Form {
|
||||||
|
// Text("Multiple authenticated requests are pending. You can approve them batches, or request they all proceed individually.")
|
||||||
|
ForEach(Array(pending.enumerated()), id: \.offset) { group in
|
||||||
|
Section {
|
||||||
|
ForEach(Array(group.element.enumerated()), id: \.offset) { pending in
|
||||||
|
HStack {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(pending.element.provenance.origin.displayName)
|
||||||
|
.font(.headline)
|
||||||
|
Text(pending.element.provenance.date.formatted())
|
||||||
|
.font(.footnote)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
Button("Review") {
|
||||||
|
Task {
|
||||||
|
try await review([pending.element])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
HStack {
|
||||||
|
Text("\(group.element.first!.provenance.origin.displayName) - \(group.element.first!.secret.name)")
|
||||||
|
Spacer()
|
||||||
|
Button("Review All") {
|
||||||
|
Task {
|
||||||
|
try await review(Set(group.element))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>com.apple.security.hardened-process.hardened-heap</key>
|
<key>com.apple.security.hardened-process.hardened-heap</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.smartcard</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.hardened-process.platform-restrictions-string</key>
|
<key>com.apple.security.hardened-process.platform-restrictions-string</key>
|
||||||
<string>2</string>
|
<string>2</string>
|
||||||
|
<key>com.apple.security.smartcard</key>
|
||||||
|
<true/>
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string>
|
<string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
2C4A9D2F2636FFD3008CC8E2 /* EditSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4A9D2E2636FFD3008CC8E2 /* EditSecretView.swift */; };
|
2C4A9D2F2636FFD3008CC8E2 /* EditSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4A9D2E2636FFD3008CC8E2 /* EditSecretView.swift */; };
|
||||||
50020BB024064869003D4025 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50020BAF24064869003D4025 /* AppDelegate.swift */; };
|
50020BB024064869003D4025 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50020BAF24064869003D4025 /* App.swift */; };
|
||||||
5002C3AB2EEF483300FFAD22 /* XPCWrappers in Frameworks */ = {isa = PBXBuildFile; productRef = 5002C3AA2EEF483300FFAD22 /* XPCWrappers */; };
|
5002C3AB2EEF483300FFAD22 /* XPCWrappers in Frameworks */ = {isa = PBXBuildFile; productRef = 5002C3AA2EEF483300FFAD22 /* XPCWrappers */; };
|
||||||
5003EF3B278005E800DF2006 /* SecretKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5003EF3A278005E800DF2006 /* SecretKit */; };
|
5003EF3B278005E800DF2006 /* SecretKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5003EF3A278005E800DF2006 /* SecretKit */; };
|
||||||
5003EF3D278005F300DF2006 /* Brief in Frameworks */ = {isa = PBXBuildFile; productRef = 5003EF3C278005F300DF2006 /* Brief */; };
|
5003EF3D278005F300DF2006 /* Brief in Frameworks */ = {isa = PBXBuildFile; productRef = 5003EF3C278005F300DF2006 /* Brief */; };
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
50153E22250DECA300525160 /* SecretListItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E21250DECA300525160 /* SecretListItemView.swift */; };
|
50153E22250DECA300525160 /* SecretListItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E21250DECA300525160 /* SecretListItemView.swift */; };
|
||||||
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501578122E6C0479004A37D0 /* XPCInputParser.swift */; };
|
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501578122E6C0479004A37D0 /* XPCInputParser.swift */; };
|
||||||
5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; };
|
5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; };
|
||||||
|
503647482F870B7800977A23 /* BatchedRequestsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 503647472F870B7800977A23 /* BatchedRequestsView.swift */; };
|
||||||
504788F22E681F3A00B4556F /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F12E681F3A00B4556F /* Instructions.swift */; };
|
504788F22E681F3A00B4556F /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F12E681F3A00B4556F /* Instructions.swift */; };
|
||||||
504788F42E681F6900B4556F /* ToolConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F32E681F6900B4556F /* ToolConfigurationView.swift */; };
|
504788F42E681F6900B4556F /* ToolConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F32E681F6900B4556F /* ToolConfigurationView.swift */; };
|
||||||
504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; };
|
504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; };
|
||||||
@@ -181,7 +182,7 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
2C4A9D2E2636FFD3008CC8E2 /* EditSecretView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSecretView.swift; sourceTree = "<group>"; };
|
2C4A9D2E2636FFD3008CC8E2 /* EditSecretView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSecretView.swift; sourceTree = "<group>"; };
|
||||||
50020BAF24064869003D4025 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
50020BAF24064869003D4025 /* App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
||||||
5003EF39278005C800DF2006 /* Packages */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Packages; sourceTree = "<group>"; };
|
5003EF39278005C800DF2006 /* Packages */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Packages; sourceTree = "<group>"; };
|
||||||
500666D02F04786900328939 /* SecretiveUpdater.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SecretiveUpdater.entitlements; sourceTree = "<group>"; };
|
500666D02F04786900328939 /* SecretiveUpdater.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SecretiveUpdater.entitlements; sourceTree = "<group>"; };
|
||||||
500666D12F04787200328939 /* SecretAgentInputParser.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SecretAgentInputParser.entitlements; sourceTree = "<group>"; };
|
500666D12F04787200328939 /* SecretAgentInputParser.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SecretAgentInputParser.entitlements; sourceTree = "<group>"; };
|
||||||
@@ -190,6 +191,7 @@
|
|||||||
50153E21250DECA300525160 /* SecretListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretListItemView.swift; sourceTree = "<group>"; };
|
50153E21250DECA300525160 /* SecretListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretListItemView.swift; sourceTree = "<group>"; };
|
||||||
501578122E6C0479004A37D0 /* XPCInputParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCInputParser.swift; sourceTree = "<group>"; };
|
501578122E6C0479004A37D0 /* XPCInputParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCInputParser.swift; sourceTree = "<group>"; };
|
||||||
5018F54E24064786002EB505 /* Notifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifier.swift; sourceTree = "<group>"; };
|
5018F54E24064786002EB505 /* Notifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifier.swift; sourceTree = "<group>"; };
|
||||||
|
503647472F870B7800977A23 /* BatchedRequestsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchedRequestsView.swift; sourceTree = "<group>"; };
|
||||||
504788F12E681F3A00B4556F /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = "<group>"; };
|
504788F12E681F3A00B4556F /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = "<group>"; };
|
||||||
504788F32E681F6900B4556F /* ToolConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolConfigurationView.swift; sourceTree = "<group>"; };
|
504788F32E681F6900B4556F /* ToolConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolConfigurationView.swift; sourceTree = "<group>"; };
|
||||||
504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; };
|
504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; };
|
||||||
@@ -459,9 +461,10 @@
|
|||||||
50A3B78B24026B7500D209EA /* SecretAgent */ = {
|
50A3B78B24026B7500D209EA /* SecretAgent */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
50020BAF24064869003D4025 /* AppDelegate.swift */,
|
50020BAF24064869003D4025 /* App.swift */,
|
||||||
5018F54E24064786002EB505 /* Notifier.swift */,
|
5018F54E24064786002EB505 /* Notifier.swift */,
|
||||||
501578122E6C0479004A37D0 /* XPCInputParser.swift */,
|
501578122E6C0479004A37D0 /* XPCInputParser.swift */,
|
||||||
|
503647472F870B7800977A23 /* BatchedRequestsView.swift */,
|
||||||
50A3B79524026B7600D209EA /* Main.storyboard */,
|
50A3B79524026B7600D209EA /* Main.storyboard */,
|
||||||
50A3B79824026B7600D209EA /* Info.plist */,
|
50A3B79824026B7600D209EA /* Info.plist */,
|
||||||
508BF29425B4F140009EFB7E /* InternetAccessPolicy.plist */,
|
508BF29425B4F140009EFB7E /* InternetAccessPolicy.plist */,
|
||||||
@@ -740,8 +743,9 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
50020BB024064869003D4025 /* AppDelegate.swift in Sources */,
|
50020BB024064869003D4025 /* App.swift in Sources */,
|
||||||
5018F54F24064786002EB505 /* Notifier.swift in Sources */,
|
5018F54F24064786002EB505 /* Notifier.swift in Sources */,
|
||||||
|
503647482F870B7800977A23 /* BatchedRequestsView.swift in Sources */,
|
||||||
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */,
|
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -1378,6 +1382,7 @@
|
|||||||
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
|
||||||
ENABLE_APP_SANDBOX = YES;
|
ENABLE_APP_SANDBOX = YES;
|
||||||
ENABLE_ENHANCED_SECURITY = YES;
|
ENABLE_ENHANCED_SECURITY = YES;
|
||||||
|
ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readwrite;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
||||||
@@ -1415,6 +1420,7 @@
|
|||||||
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
|
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
|
||||||
ENABLE_APP_SANDBOX = YES;
|
ENABLE_APP_SANDBOX = YES;
|
||||||
ENABLE_ENHANCED_SECURITY = YES;
|
ENABLE_ENHANCED_SECURITY = YES;
|
||||||
|
ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readwrite;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
||||||
@@ -1453,6 +1459,7 @@
|
|||||||
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
|
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
|
||||||
ENABLE_APP_SANDBOX = YES;
|
ENABLE_APP_SANDBOX = YES;
|
||||||
ENABLE_ENHANCED_SECURITY = YES;
|
ENABLE_ENHANCED_SECURITY = YES;
|
||||||
|
ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readwrite;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
||||||
|
|||||||
Reference in New Issue
Block a user