如何在我的 iOS 模拟器上自动安装自定义 CA 根证书以进行测试?

Posted

技术标签:

【中文标题】如何在我的 iOS 模拟器上自动安装自定义 CA 根证书以进行测试?【英文标题】:How can I automatically install a custom CA root certificate on my iOS simulators for testing? 【发布时间】:2017-10-25 19:45:00 【问题描述】:

我的 ios 应用程序与具有有效证书的后端服务器通信。在开发过程中,我的 iOS 应用程序配置为与我的内部测试服务器通信,该服务器具有由我的自签名根证书签名的证书。

在 iOS 11 之前,我可以使用此处列出的说明将我的应用配置为信任由我的自签名根签名的连接:https://developer.apple.com/library/content/technotes/tn2232/_index.html#//apple_ref/doc/uid/DTS40012884-CH1-SECCUSTOMCERT

但是,在 iOS 11 中,应用程序不再可能绕过 ATS,而不在 info.plist 中创建 ATS 异常。此线程包含来自 Apple 的一些解释:https://forums.developer.apple.com/thread/89694

那么现在在 iOS 中,我如何以某种自动化方式在我的所有 iOS 模拟器上安装我的自定义 CA 根?

【问题讨论】:

【参考方案1】:

由于 iOS 11 支持多应用 UI 测试,我创建了一个 UI 测试,它使 iOS 系统使用 Safari 和“设置”应用安装我的自定义 CA 的根。 UI测试的源码如下:

import XCTest

class InstallRootCerts: XCTestCase 

    override func setUp() 
        super.setUp()
        continueAfterFailure = false
        XCUIApplication().launch()
    

    override func tearDown() 
        super.tearDown()
    

    func testInstallTestingRootCertOnDevice() 

        // Set test time env var ROOT_CA to point to your custom CA's .cer file.
        let cert = ProcessInfo.processInfo.environment["ROOT_CA"]
        // Set test time env var ROOT_CA_NAME to contain the name of your CA.
        let caName = ProcessInfo.processInfo.environment["ROOT_CA_NAME"]

        let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")

        let settings = XCUIApplication(bundleIdentifier: "com.apple.Preferences")

        safari.activate()

        XCTAssertNotNil(cert)

        let certUrl = "file://\(cert!)"

        if safari.otherElements["URL"].exists 
            safari.otherElements["URL"].tap()
        

        let addressBar = safari.textFields["URL"]

        addressBar.typeText(certUrl)

        safari.buttons["Go"].tap()

        safari.buttons["Allow"].tap()

        XCTAssertTrue( settings.wait(for: .runningForeground, timeout: 30) )

        if !settings.staticTexts["Verified"].exists 
            settings.buttons["Install"].tap()
            settings.buttons["Install"].tap()
            settings.sheets.buttons["Install"].tap()
        

        // Now trust the root certificate
        settings.buttons["Cancel"].tap()
        XCTAssertTrue( safari.wait(for: .runningForeground, timeout: 120) )
        settings.activate()
        XCTAssertTrue( settings.wait(for: .runningForeground, timeout: 120) )

        settings.buttons["General"].tap()
        settings.cells["About"].tap()
        settings.cells["Certificate Trust Settings"].tap()
        let cell = settings.cells.containing(.staticText, identifier: caName)
        let toggle = cell.switches.firstMatch
        if toggle.value as? String != "1" 
            toggle.tap()
            settings.buttons["Continue"].tap()
        

    


此测试用例仅适用于运行 iOS 11.0 的模拟器。如果您将 .cer 文件放在网络服务器上并通过 http 打开它,我认为它可以与实际设备一起使用。

然后,此测试用例可以在您的 Xcode 服务器上作为 Bot 运行,或者您可以在本地的任何模拟器上运行它来进行设置。这是我知道的一个 hack。

【讨论】:

这在 iOS 12.2 中不再有效,因为证书工作流程略有变化。在 Safari 中点击“允许”按钮后,会打开一个系统警报对话框,似乎没有办法自动将其关闭以继续使用“设置”应用程序。 我遇到了和上面一模一样的问题,你找到解决方法了吗? @Reijer 遗憾的是,不,我还没有找到任何解决这个问题的方法。

以上是关于如何在我的 iOS 模拟器上自动安装自定义 CA 根证书以进行测试?的主要内容,如果未能解决你的问题,请参考以下文章

自定义字体在 iOS 8 中不起作用

如何在Android设备上安装可信CA证书?

Mac 上的 iOS 7 模拟器不适用于自定义位置(也不会请求许可)

如何更改iOS模拟器目录

如何让 Docker 中的 GitLab Runner 看到自定义 CA 根证书

点击自定义键盘按钮时如何播放铃声