From 6c3b211c477bf1095a6a190795be7a2ffe414f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20Zu=CC=81n=CC=83iga=20Lagunas?= Date: Thu, 23 May 2024 14:01:42 -0600 Subject: [PATCH] added keychain creation log --- MODULE.bazel.lock | 6 +- .../Commands/CreateKeychainCommand.swift | 48 +++++++++++ .../CreateKeychainCommandTests.swift | 84 ++++++++++++++++++- ...reateKeychainCommandTests_testErrors.4.txt | 3 + ...reateKeychainCommandTests_testErrors.5.txt | 4 + ...ests_test_execute_cannotFindKeychain.1.txt | 39 +++++++++ ...ests_test_execute_cannotListKeychain.1.txt | 39 +++++++++ 7 files changed, 217 insertions(+), 6 deletions(-) create mode 100644 Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.4.txt create mode 100644 Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.5.txt create mode 100644 Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotFindKeychain.1.txt create mode 100644 Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotListKeychain.1.txt diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index f7d77c3..77615c6 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -1379,7 +1379,7 @@ "moduleExtensions": { "//:extensions.bzl%non_module_dependencies": { "general": { - "bzlTransitiveDigest": "P1JUpq+Gnkii3uIYNOJ8g2c/SfGD8pMGSizap66ROpo=", + "bzlTransitiveDigest": "Ep7fmfOBPzREF045u058BTSSHGEnXMIpN7hhvedcJHw=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -1585,7 +1585,7 @@ }, "@@rules_java~//java:extensions.bzl%toolchains": { "general": { - "bzlTransitiveDigest": "tJHbmWnq7m+9eUBnUdv7jZziQ26FmcGL9C5/hU3Q9UQ=", + "bzlTransitiveDigest": "0N5b5J9fUzo0sgvH4F3kIEaeXunz4Wy2/UtSFV/eXUY=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -2090,7 +2090,7 @@ }, "@@rules_swift~//swift:extensions.bzl%non_module_deps": { "general": { - "bzlTransitiveDigest": "m78FIsmmvFalZmXxi26P0AW5U6W6G+u5KGknjClFU/0=", + "bzlTransitiveDigest": "2HjojbikzYbmbwZ2N19uSSpcNJ002txg/QLUMC0rEYk=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, diff --git a/Sources/SignHereLibrary/Commands/CreateKeychainCommand.swift b/Sources/SignHereLibrary/Commands/CreateKeychainCommand.swift index e5d3044..3b9fd04 100644 --- a/Sources/SignHereLibrary/Commands/CreateKeychainCommand.swift +++ b/Sources/SignHereLibrary/Commands/CreateKeychainCommand.swift @@ -23,6 +23,8 @@ internal struct CreateKeychainCommand: ParsableCommand { case unableToUnlockKeychain(keychainName: String, output: ShellOutput) case unableToUpdateKeychainLockTimeout(keychainName: String, output: ShellOutput) case unableToCreateKeychain(keychainName: String, output: ShellOutput) + case unableToListKeychains(output: ShellOutput) + case unableToFindKeychain(keychainName: String, output: ShellOutput) var description: String { switch self { @@ -47,6 +49,19 @@ internal struct CreateKeychainCommand: ParsableCommand { - Output: \(output.outputString) - Error: \(output.errorString) """ + case let .unableToListKeychains(output: output): + return """ + [CreateKeychainCommand] Unable to list keychains + - Output: \(output.outputString) + - Error: \(output.errorString) + """ + case let .unableToFindKeychain(keychainName: keychainName, output: output): + return """ + [CreateKeychainCommand] Unable to find keychain + - Keychain Name: \(keychainName) + - Output: \(output.outputString) + - Error: \(output.errorString) + """ } } } @@ -64,21 +79,25 @@ internal struct CreateKeychainCommand: ParsableCommand { private let shell: Shell private let keychain: Keychain + private let log: Log internal init() { let shellImp: Shell = ShellImp() shell = shellImp keychain = KeychainImp(shell: shellImp, processInfo: ProcessInfoImp()) + log = LogImp() } internal init( shell: Shell, keychain: Keychain, + log: Log, keychainName: String, keychainPassword: String ) { self.shell = shell self.keychain = keychain + self.log = log self.keychainName = keychainName self.keychainPassword = keychainPassword } @@ -89,6 +108,7 @@ internal struct CreateKeychainCommand: ParsableCommand { self.init( shell: shellImp, keychain: KeychainImp(shell: shellImp, processInfo: ProcessInfoImp()), + log: LogImp(), keychainName: try container.decode(String.self, forKey: .keychainName), keychainPassword: try container.decode(String.self, forKey: .keychainPassword) ) @@ -104,6 +124,7 @@ internal struct CreateKeychainCommand: ParsableCommand { try keychain.setDefaultKeychain(keychainName: keychainName) try updateKeychainLockTimeout() try unlockKeychain() + try logKeychainPath() } private func createKeychain() throws { @@ -157,4 +178,31 @@ internal struct CreateKeychainCommand: ParsableCommand { ) } } + + private func logKeychainPath() throws { + let output: ShellOutput = shell.execute([ + "security", + "list-keychains" + ]) + guard output.isSuccessful + else { + throw Error.unableToListKeychains( + output: output + ) + } + guard let keychainLine = output + .outputString + .components(separatedBy: "\n") + .first(where: { $0.contains(keychainName) }) + else { + throw Error.unableToFindKeychain( + keychainName: keychainName, + output: output + ) + } + let keychainPath = keychainLine + .trimmingCharacters(in: .whitespacesAndNewlines) + .replacingOccurrences(of:"\"", with: "") + log.append("Keychain created in the path: \(keychainPath)") + } } diff --git a/Tests/SignHereLibraryTests/CreateKeychainCommandTests.swift b/Tests/SignHereLibraryTests/CreateKeychainCommandTests.swift index b71e396..cc85138 100644 --- a/Tests/SignHereLibraryTests/CreateKeychainCommandTests.swift +++ b/Tests/SignHereLibraryTests/CreateKeychainCommandTests.swift @@ -16,15 +16,18 @@ import XCTest final class CreateKeychainCommandTests: XCTestCase { var shell: ShellMock! var keychain: KeychainMock! + var log: LogMock! var subject: CreateKeychainCommand! override func setUp() { super.setUp() shell = .init() keychain = .init() + log = .init() subject = .init( shell: shell, keychain: keychain, + log: log, keychainName: "keychainName", keychainPassword: "keychainPassword" ) @@ -33,6 +36,7 @@ final class CreateKeychainCommandTests: XCTestCase { override func tearDown() { shell = nil keychain = nil + log = nil subject = nil super.tearDown() } @@ -69,6 +73,21 @@ final class CreateKeychainCommandTests: XCTestCase { ).description, as: .lines ) + + assertSnapshot( + matching: CreateKeychainCommand.Error.unableToListKeychains( + output: .init(status: 0, data: .init("output".utf8), errorData: .init("errorOutput".utf8)) + ).description, + as: .lines + ) + + assertSnapshot( + matching: CreateKeychainCommand.Error.unableToFindKeychain( + keychainName: "keychainName", + output: .init(status: 0, data: .init("output".utf8), errorData: .init("errorOutput".utf8)) + ).description, + as: .lines + ) } func test_initDecoder() throws { @@ -92,7 +111,8 @@ final class CreateKeychainCommandTests: XCTestCase { var executeLaunchPaths: [ShellOutput] = [ .init(status: 1, data: .init("createKeychain".utf8), errorData: .init()), .init(status: 0, data: .init("updateKeychainLockTimeout".utf8), errorData: .init()), - .init(status: 0, data: .init("unlockKeychain".utf8), errorData: .init()) + .init(status: 0, data: .init("unlockKeychain".utf8), errorData: .init()), + .init(status: 0, data: .init("listKeychain".utf8), errorData: .init()) ] shell.executeLaunchPathHandler = { _, _, _, _ in executeLaunchPaths.removeFirst() @@ -119,7 +139,8 @@ final class CreateKeychainCommandTests: XCTestCase { var executeLaunchPaths: [ShellOutput] = [ .init(status: 0, data: .init("createKeychain".utf8), errorData: .init()), .init(status: 1, data: .init("updateKeychainLockTimeout".utf8), errorData: .init()), - .init(status: 0, data: .init("unlockKeychain".utf8), errorData: .init()) + .init(status: 0, data: .init("unlockKeychain".utf8), errorData: .init()), + .init(status: 0, data: .init("listKeychain".utf8), errorData: .init()) ] shell.executeLaunchPathHandler = { _, _, _, _ in executeLaunchPaths.removeFirst() @@ -146,7 +167,8 @@ final class CreateKeychainCommandTests: XCTestCase { var executeLaunchPaths: [ShellOutput] = [ .init(status: 0, data: .init("createKeychain".utf8), errorData: .init()), .init(status: 0, data: .init("updateKeychainLockTimeout".utf8), errorData: .init()), - .init(status: 1, data: .init("unlockKeychain".utf8), errorData: .init()) + .init(status: 1, data: .init("unlockKeychain".utf8), errorData: .init()), + .init(status: 0, data: .init("listKeychain".utf8), errorData: .init()), ] shell.executeLaunchPathHandler = { _, _, _, _ in executeLaunchPaths.removeFirst() @@ -167,4 +189,60 @@ final class CreateKeychainCommandTests: XCTestCase { as: .dump ) } + + func test_execute_cannotListKeychain() throws { + // GIVEN + var executeLaunchPaths: [ShellOutput] = [ + .init(status: 0, data: .init("createKeychain".utf8), errorData: .init()), + .init(status: 0, data: .init("updateKeychainLockTimeout".utf8), errorData: .init()), + .init(status: 0, data: .init("unlockKeychain".utf8), errorData: .init()), + .init(status: 1, data: .init("listKeychain".utf8), errorData: .init()), + ] + shell.executeLaunchPathHandler = { _, _, _, _ in + executeLaunchPaths.removeFirst() + } + + // WHEN + XCTAssertThrowsError(try subject.run()) { + if case CreateKeychainCommand.Error.unableToListKeychains(output: _) = $0 { + XCTAssertTrue(true) + } else { + XCTFail($0.localizedDescription) + } + } + + // THEN + assertSnapshot( + matching: shell.executeLaunchPathArgValues, + as: .dump + ) + } + + func test_execute_cannotFindKeychain() throws { + // GIVEN + var executeLaunchPaths: [ShellOutput] = [ + .init(status: 0, data: .init("createKeychain".utf8), errorData: .init()), + .init(status: 0, data: .init("updateKeychainLockTimeout".utf8), errorData: .init()), + .init(status: 0, data: .init("unlockKeychain".utf8), errorData: .init()), + .init(status: 0, data: .init("listKeychain".utf8), errorData: .init()), + ] + shell.executeLaunchPathHandler = { _, _, _, _ in + executeLaunchPaths.removeFirst() + } + + // WHEN + XCTAssertThrowsError(try subject.run()) { + if case CreateKeychainCommand.Error.unableToFindKeychain(keychainName: _, output: _) = $0 { + XCTAssertTrue(true) + } else { + XCTFail($0.localizedDescription) + } + } + + // THEN + assertSnapshot( + matching: shell.executeLaunchPathArgValues, + as: .dump + ) + } } diff --git a/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.4.txt b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.4.txt new file mode 100644 index 0000000..9de4dab --- /dev/null +++ b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.4.txt @@ -0,0 +1,3 @@ +[CreateKeychainCommand] Unable to list keychains +- Output: output +- Error: errorOutput \ No newline at end of file diff --git a/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.5.txt b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.5.txt new file mode 100644 index 0000000..9e7d178 --- /dev/null +++ b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_testErrors.5.txt @@ -0,0 +1,4 @@ +[CreateKeychainCommand] Unable to find keychain +- Keychain Name: keychainName +- Output: output +- Error: errorOutput \ No newline at end of file diff --git a/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotFindKeychain.1.txt b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotFindKeychain.1.txt new file mode 100644 index 0000000..6a07a69 --- /dev/null +++ b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotFindKeychain.1.txt @@ -0,0 +1,39 @@ +▿ 4 elements + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 5 elements + - "security" + - "create-keychain" + - "-p" + - "keychainPassword" + - "keychainName" + - .2: Optional>.none + - .3: Optional.none + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 6 elements + - "security" + - "set-keychain-settings" + - "-t" + - "7200" + - "-l" + - "keychainName" + - .2: Optional>.none + - .3: Optional.none + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 5 elements + - "security" + - "unlock-keychain" + - "-p" + - "keychainPassword" + - "keychainName" + - .2: Optional>.none + - .3: Optional.none + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 2 elements + - "security" + - "list-keychains" + - .2: Optional>.none + - .3: Optional.none diff --git a/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotListKeychain.1.txt b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotListKeychain.1.txt new file mode 100644 index 0000000..6a07a69 --- /dev/null +++ b/Tests/SignHereLibraryTests/__Snapshots__/CreateKeychainCommandTests/CreateKeychainCommandTests_test_execute_cannotListKeychain.1.txt @@ -0,0 +1,39 @@ +▿ 4 elements + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 5 elements + - "security" + - "create-keychain" + - "-p" + - "keychainPassword" + - "keychainName" + - .2: Optional>.none + - .3: Optional.none + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 6 elements + - "security" + - "set-keychain-settings" + - "-t" + - "7200" + - "-l" + - "keychainName" + - .2: Optional>.none + - .3: Optional.none + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 5 elements + - "security" + - "unlock-keychain" + - "-p" + - "keychainPassword" + - "keychainName" + - .2: Optional>.none + - .3: Optional.none + ▿ (4 elements) + - .0: "/usr/bin/env" + ▿ .1: 2 elements + - "security" + - "list-keychains" + - .2: Optional>.none + - .3: Optional.none