SecretsManager

使用代码生成为 Swift 项目提供轻松的 Secrets 管理。一种比 NSHipster 文章 中关于使用 Swift Build Tool Plugin (Swift 5.6+) 在 iOS 上进行 Secrets 管理所概述的 GYB 文件更简单的方法。

功能

用法

使用 .env bash 脚本导出您希望在源代码中可用的 Secrets。

#prefix ORG

export ORG_API_CLIENT_SECRET=hrFL6LpsGQPsEQdipfTSlosI6topYTfhLNCfIvbfUz5r6nc72DMRbLL3msjuAFnY
export ORG_ANALYTICS_KEY=dak37Qv5KGwNsQxVJxjJY2OtbUnGKXlm3mkDApSRfrAsTHQdFRSEfrA9yin5T4YT
export ORG_BACKEND_KEY='KwphtrRhgOXcRd=p!73QnrQLuOj=rx8edJhMy52sWeQPKMxOxA8hNcDrG9=XRvAw'
export ORG_LOGGER_KEY='oW7YQKg2eNcVjzRdmCtmgCCSBp2dpJlL5NC-Pj!asS5XdPG/--R2hE?/=I/TlotP'

使用此插件,将生成以下 Swift 代码,并可直接用于您的目标源代码,无需导入。

// This file is automatically generated

import struct Foundation.Data

private func secret(_ secret: String) -> String {
    let data = Data(base64Encoded: secret)
    guard let data else {
        fatalError("Failed to decode a secret!")
    }

    func decrypt(_ data: Data) -> String {
        let key = Data(base64Encoded: "JbiOFqC+jH3l8pwCLE4Nca4f19M7YAbeTUo7rhnSSG7ctZMlc+dg5FI9o3zrSbCgFLtDd0uC9EcCC+jd6hlVDA==")!
        var output: [UTF8.CodeUnit] = []
        for (offset, ch) in data.enumerated() {
            output.append(ch ^ key[offset % key.count])
        }
        return String(bytes: output, encoding: .utf8)!
    }

    return decrypt(data)
}

enum Secrets {
    static let apiClientSecret = secret("TcrIWpby/A6io8xxaR9pGN55g4BXD3WXez5U3kCGLgaQ+9BDOpECggdHlg7dJ9OXJv8OJSnOuHRveIKoq187VQ==")
    static let analyticsKey = secret("QdnlJZfv+kiutetMXx91J+RnvZliUkmqLx9V6VKKJAPv2PhhMpcztjRP4g+/AeHEUukQMi3wtX57Yobovi0MWA==")
    static let backendKey = secret("bs/+ftTM3hWCvcRhfiowAY8o5IJVEleSOAVRk2uqcAu4//toCtJSlwVY8iygBMjvbPp7HwXhsDVFMtWFuG8Uew==")
    static let loggerKey = secret("Su+5T/H160+AvP9URjRfFcNco75cI0WNDzoJymmYJCLp+9AII41BhSFuliSPGfePOZYRRSPHy2g/QseJhnYhXA==")
}

设置

需要 Swift 5.6 (Xcode 13.3+)

在您的根目录(与 Package.swift 或您的 *.xcodeproj 并行)中创建一个 .env 文件。您可以使用 #prefix 定义要从所有导出的键中剥离的前缀。请参阅 用法 以获取 .env 文件示例。

Xcode 项目

可视化指南

  1. 添加 SecretsManager 包
    • 当提示 为 SecretsManager 选择 Package 产品 时,请勿选择任何产品
  2. Targets > Build Phases 中,将 SecretsManagerPlugin 添加到 Run Build Tool Plug-ins
  3. 构建,触发提示信任插件
    • 从问题导航器中,您可以转到插件并阅读源代码,然后再信任它

Swift Package Manager

将以下内容添加到您的 Package.swift 文件依赖项数组中

.package(url: "https://github.com/vdka/SecretsManager.git", from: "1.0.0"),

并添加到 Secrets 应该可用的目标中,在其 dependencies 之后

plugins: [
    .plugin(name: "SecretsManagerPlugin", package: "SecretsManager"),
]

Xcode Cloud

在 Xcode Cloud 中运行时,您将希望 secret 值来自实际环境。为了告诉插件从哪个环境中读取键,您可以创建一个 .env 文件,该文件仅导出键,而不导出关联的值。

#prefix ORG

export ORG_API_CLIENT_SECRET
export ORG_ANALYTICS_KEY
export ORG_BACKEND_KEY
export ORG_LOGGER_KEY

安全性

此软件包的目的不是保护您的 Secrets 免受蓄意攻击。它的目的是使在 Swift 项目中方便地采用最佳实践 Secrets 管理。它通过确保将您的 secrets 保存在源代码之外不会牺牲可用性,并且在编译到您的应用程序中时,它们不会以明文形式存储来实现这一点。请记住 客户端保密是不可能的