Share
Embed
waiwai-swiftpm-part2
d_date
February 07, 2022
Transcript
58 slides
-
SE-0303 SE-0325 Build Tool Plugins લճͷ͓͞Β͍ • Ϗϧυதʹ࣮ߦ͢ΔπʔϧΛϓϥάΠϯͱͯ͠ఆٛͰ͖Δɻ e.g.) ίʔυੜ
• Swift package / Xcode྆ํͰαϙʔτ͞Ε͍ͯΔ • App SandboxͷΈΞΫηεΛڐ༰ɻNetwork AccessͰ͖ͳ͍ɻ https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
Examples SwiftGen - Plugin // swift-tools-version: 5.6 import PackageDescription let
package = Package( name: "SwiftGen", targets: [ .plugin( name: "SwiftGenPlugin", capability: .buildTool(), dependencies: ["SwiftGen"] ), .binaryTarget( name: "SwiftGen", url: "https://url/to/the/built/swiftgen-executables.zip", checksum: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ), ] ) SwiftGen ᵓ Package.swift ᵓ Plugins │ └ SwiftGenPlugin │ └ plugin.swift └ Sources └ SwiftGen └ ... -
SE-0305 Artifact archive bundle લճͷ͓͞Β͍ • Swift Ͱͳ͍ CLI πʔϧࣄલʹϏϧυ͓ͯ͘͠ඞཁ͕͋Δ
• Target.binaryTargetͰ artifactbundle ܗࣜΛαϙʔτͯ͠ɺTarget triple͝ͱʹexecutableΛஔɾμϯϩʔυͰ͖ΔΑ͏ʹ͢Δ <name>.artifactbundle ᵓ info.json ᵓ <artifact> │ ᵓ <variant> │ │ ᵓ <executable> │ │ └ <other fi les> │ └ <variant> │ ᵓ <executable> │ └ <other fi les> ᵓ <artifact> │ └ <variant> │ ᵓ <executable> │ └ <other fi les> │ <artifact> ᴽ └ᴻ -
SE-0332 Command Plugins લճͷ͓͞Β͍ • Tool version 5.6Ҏ߱Ͱɺcommand λΠϓͷ Package
pluginΛهࡌͰ͖ΔΑ͏ʹͳ Γɺswift package subcommand Λར༻ͯ͠ݺͼग़ͤΔΑ͏ʹͳͬͨɻ • Prede fi ned: generateDocumentation, codeFormat • Custom: (Build Artifactͷ࡞ͳͲ) • Package managerͷproxyΛͬͯBuild / Test / Symbol graphͷऔಘ͕Ͱ͖Δ • ඞཁʹԠͯ͡ϢʔβʔʹڐՄΛٻΊΔ • writeToPackageDirectory https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
#3649 Enable lenient parsing of Git version tags • ηϚϯςΟοΫόʔδϣϯʹ͓͍ͯɺMajor
ͱ Miner͚ͩΛؚΉ Git tag ʹର͠ ͯґଘؔΛղܾͰ͖ΔΑ͏ʹͳͬͨɻ X.Y ͱ͍͏ tag X.Y.0 ͱͯ͠ѻΘΕɺطଘͷϦϙδτϦͷޓੑ͕վળ͞Ε Δɻ https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
#3686 Correct semantic version parsing and comparison • ηϚϯςΟοΫόʔδϣϯʹ͓͚Δߏจղੳͱൺֱ͕ SemVer
2.0.0ʹݫີʹश͏Α͏ʹͳͬͨɻ ઌߦ͢Δ + ͕ͳ͍߹ͷΈɺ- ΛVersion coreͱpre-release identi fi erͷ۠Γจࣈ (delimiter) ͱ͠ ͯѻ͏Α͏ʹͳͬͨɻͦΕҎ֎ͷ߹ɺBuild metadata identi fi er ͷҰ෦ͱͯ͠ѻ͏Α͏ʹͳͬ ͨ ྫ) 1.2.3+some-meta.data ͍··Ͱɺ1.2.3+some Λ Version core, meta.data Λpre-release identi fi erͱ͍͕ͯͨ͠ɺ 1.2.3 Λ Version core, some-meta.data Λ Build metadata ͱͯ͠औΓѻΘΕΔΑ͏ʹͳͬͨ • ൺֱʹ͍ͭͯɺBuild metadataΛແࢹͯ͠ɺMajor, Minor, Patch, Pre-release identi fi er ͕Ұக͠ ͨ࣌ͷΈ͍͠ͷͱͯ͠ѻ͏ https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
#3641 Deprecate name attribute on package dependencies • .package(name:, url:)͕ඇਪͱͳΓɺ.package(url:)Λར༻͢ΔΑ͏ʹਪ
͞ΕΔΑ͏ʹͳͬͨɻ Swift 5.5 ͰnameΛ໌ࣔతʹࢦఆ͠ͳͯ͘Α͘ͳͬͨͨΊ ※soft deprecated ͱͳ͍ͬͯΔ͕ɺݴޠ্༷ deprecated deprecated • .package(url: String, exact: Version) ͕Ճ • ґଘཁ݅ͷ enum calling convention ͕ඇਪͱͳΓɺϥϕϧ͖ҾͱͳΔ ◦.package(url: String, .branch(String)) -> .package(url: String, branch: String) ◦.package(url: String, .revision(String)) -> .package(url: String, revision: String) ◦.package(url: String, .exact(Version)) -> .package(url: String, exact: Version) https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
#3717 Update the resolved file format Package.resolved ͕ V2
https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 { "pins": [ { "identity": "abseil-cpp-swiftpm", "kind": "remoteSourceControl", "location": "https://github.com/firebase/abseil-cpp-SwiftPM.git", "state": { "revision": "fffc3c2729be5747390ad02d5100291a0d9ad26a", "version": "0.20200225.4" } }, { "identity": "aexml", "kind": "remoteSourceControl", "location": "https://github.com/tadija/AEXML", "state": { "revision": "38f7d00b23ecd891e1ee656fa6aeebd6ba04ecc3", "version": "4.6.1" } }, ], "version": 2 } { "object": { "pins": [ { "package": "abseil", "repositoryURL": "https://github.com/firebase/abseil-cpp-SwiftPM.git", "state": { "branch": null, "revision": "fffc3c2729be5747390ad02d5100291a0d9ad26a", "version": "0.20200225.4" } }, { "package": "AEXML", "repositoryURL": "https://github.com/tadija/AEXML", "state": { "branch": null, "revision": "38f7d00b23ecd891e1ee656fa6aeebd6ba04ecc3", "version": "4.6.1" } } ] }, "version": 1 } -
#3809 Implement TOFU for package downloads Trust-on- fi rst-use (
TOFU 📛 )Ͱ Package ͷηΩϡϦςΟڧԽ • PackageͷηΩϡϦςΟڧԽͷͨΊʹɺSwiftPM trust-on- fi rst-use ( TOFU ) validationΛߦ͏ɻ • Package ͕ Git repository / Package registry͔Β࠷ॳʹμϯϩʔυ͞Εͨͱ͖ ʹɺPackage ͷ fi ngerprint ͕ه͞ΕΔΑ͏ʹͳͬͨɻ • Package Registryͷ߹ɺsource archive checksum • Source controlͷ߹ɺGit revision • ޙଓͷμϯϩʔυʹɺҎલه͞ΕͨͱҰக͢Δ fi nger pin͕ඞཁɻ https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
#3670, #3901, #3942 Config file location changing Package.resolved ͕ V2
• SE-0292 (Package registry)ͳͲʹΑͬͯɺcon fi gurationσΟϨΫτϦʹΑΓݎ ࿚ͳσΟϨΫτϦߏ͕ٻΊΒΕΔΑ͏ʹͳͬͨɻ • <project>/.swiftpm/con fi g (mirrors fi le) -> <project>/.swiftpm/con fi guration/mirrors.json • ~/.swiftpm/con fi g/collections.json (collection fi le) -> ~/.swiftpm/con fi guration/collections.json • Swift 5.6͕ࣗಈͰίϐʔͯ͠ɺϢʔβʔʹݹ͍ͷΛফ͢Α͏ʹwarningΛग़͢ https://github.com/apple/swift-package-manager/blob/main/CHANGELOG.md#swift-56 -
Additional Package APIs • SE-0303ͷ TargetBuildContext Λ PluginContext ͱͯ͠Package graphશମͷใ
ΛؚΉΑ͏ʹҰൠԽ͢Δɻ • PluginContextʹPackageͷࢀর͕ఏڙ͞ΕΔͷͰɺϓϥάΠϯͷεΫϦϓτͰґ ଘ͢ΔαϒάϥϑʹΞΫηεͰ͖Δɻˠ Command Plugin • ༗ඇ८ճάϥϑ(DAG)Ͱ͋ΔґଘؔΛτϙϩδΧϧιʔτ͢ΔΑ͏ͳAPIఏڙ • ͦΕͧΕͷDependency TargetͷSearch PathΛؚΉίϚϯυϥΠϯҾΛੜ ͢ΔΑ͏ͳχʔζʹରԠ͢Δ -
/// Represents a single product defined in a package. public
protocol Product { /// Unique identifier for the product. var id: ID { get } typealias ID = String /// The name of the product, as defined in the package manifest. This name /// is unique among the products of the package in which it is defined. var name: String { get } /// The targets that directly comprise the product, in the order in which /// they are declared in the package manifest. The product will contain the /// transitive closure of the these targets and their dependencies. Some /// kinds of products have further restrictions on the set of targets (for /// example, an executable product must have one and only one target that /// defines the main entry point for an executable). var targets: [Target] { get } } -
/// Represents a single target defined in a package. public
protocol Target { /// Unique identifier for the target. var id: ID { get } typealias ID = String /// The name of the target, as defined in the package manifest. This name /// is unique among the targets of the package in which it is defined. var name: String { get } /// The absolute path of the target directory in the local file system. var directory: Path { get } /// Any other targets on which this target depends, in the same order as /// they are specified in the package manifest. Conditional dependencies /// that do not apply have already been filtered out. var dependencies: [TargetDependency] { get } } /// Represents a dependency of a target on a product or on another target. public enum TargetDependency { /// A dependency on a target in the same package. case target(Target) /// A dependency on a product in another package. case product(Product) } -
extension Target { /// The transitive closure of all the
targets on which the reciver depends, /// ordered such that every dependency appears before any other target that /// depends on it (i.e. in "topological sort order"). public var recursiveTargetDependencies: [Target] { // FIXME: We can rewrite this to use a stack instead of recursion. var result = [Target]() var visited = Set<Target.ID>() func visit(target: Target) { guard !visited.insert(target.id).inserted else { return } target.dependencies.forEach{ visit(dependency: $0) } result.append(target) } func visit(dependency: TargetDependency) { switch dependency { case .target(let target): visit(target: target) case .product(let product): product.targets.forEach{ visit(target: $0) } } } return result } } https://github.com/apple/swift-package-manager/pull/3758/ fi les#di ff -79b44ed51fc53000c5d9cfd941b77065d03a99760a8b1ddd6cf5fafdc5f5835fR417-R440 -
SE-0292 Package Registry Service Accepted • DependencyͷdownloadʹιʔεϦϙδτϦͷURLΛࢦఆͯ͠gitΛ͏ͷద͍ͯ͠ͳ͍ • ࠶ݱੑ: όʔδϣϯλά͍ͭͰผίϛοτʹׂΓͯՄೳͳͷͰɺϏϧυ͞ΕͨλΠϛϯάʹΑͬͯҟͳΔ
ϏϧυՌʹͳΔՄೳੑ͕͋Δ • Մ༻ੑ: ϦϙδτϦҠಈͨ͠Γআ͞ΕͨΓ͢Δ • ޮ: ύοέʔδͷͯ͢ͷόʔδϣϯ͕μϯϩʔυ͞Εͯ͠·͏ • : history͕େ͖͍ͱ͘ͳΔɻΫϩʔϯαʔόʔʹΫϥΠΞϯτʹίετɻ • Package registry: RubyGems / PyPl / npm / crates.io • SwiftPMͷpackage registrygitΑΓߴͰ৴པੑͷߴ͍ґଘؔղܾ͕ΊΔɻ • Package search, Security audit, local o ff l ine cache -
Package registry service Method Path Description GET /{scope}/{name} List package
releases GET /{scope}/{name}/{version} Fetch metadata for a package release GET /{scope}/{name}/{version}/Package.swift{?swift-version} Fetch manifest for a package release GET /{scope}/{name}/{version}.zip Download source archive for a package release GET /identi fi ers{?url} Lookup package identi fi ers registered for a URL -
Changes to Swift Package Manager Package Identity • ݱࡏpackage IDURLͷlast
path components • scope.package-name ʹมߋ͢Δ • scopenamespaceͰ࠷େ39จࣈ • package-namescopeͷϢχʔΫͳ໊લͰ࠷େ100จࣈ -
Changes to Swift Package Manager Dependency graph resolution • PackageContainerΛpackage
resolutionͷtop-level unitͱ͢Δ • RegistryPackageContainer͕HTTPϦ ΫΤετͱಉͷૢ࡞Λߦ͏ public protocol PackageContainer { /// The identifier for the package. var package: PackageReference { get } func isToolsVersionCompatible(at version: Version) -> Bool func toolsVersion(for version: Version) throws -> ToolsVersion /// Get the list of versions which are available for the package. /// /// The list will be returned in sorted order, with the latest version *first*. /// All versions will not be requested at once. Resolver will request the next one only /// if the previous one did not satisfy all constraints. func toolsVersionsAppropriateVersionsDescending() throws -> [Version] /// Get the list of versions in the repository sorted in the ascending order, that is the earliest /// version appears first. func versionsAscending() throws -> [Version] func versionsDescending() throws -> [Version] // FIXME: We should perhaps define some particularly useful error codes // here, so the resolver can handle errors more meaningfully. // /// Fetch the declared dependencies for a particular version. /// /// This property is expected to be efficient to access, and cached by the /// client if necessary. /// /// - Precondition: `versions.contains(version)` /// - Throws: If the version could not be resolved; this will abort /// dependency resolution completely. func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [PackageContainerConstraint] /// Fetch the declared dependencies for a particular revision. /// /// This property is expected to be efficient to access, and cached by the /// client if necessary. /// /// - Throws: If the revision could not be resolved; this will abort /// dependency resolution completely. func getDependencies(at revision: String, productFilter: ProductFilter) throws -> [PackageContainerConstraint] /// Fetch the dependencies of an unversioned package container. /// /// NOTE: This method should not be called on a versioned container. func getUnversionedDependencies(productFilter: ProductFilter) throws -> [PackageContainerConstraint] /// Get the updated identifier at a bound version. /// /// This can be used by the containers to fill in the missing information that is obtained /// after the container is available. The updated identifier is returned in result of the /// dependency resolution. func loadPackageReference(at boundVersion: BoundVersion) throws -> PackageReference } -
Changes to Swift Package Manager Tasks performed by Swift Package
Manager during dependency resolution Task Git operation Registry request Fetch the contents of a package git clone && git checkout GET /{scope}/{name}/{version}.zip List the available tags for a package git tag GET /{scope}/{name} Fetch a package manifest git clone GET /{scope}/{name}/{version}/Package.swift -
Appendix: HTTPClient in SwiftPM • Apple/swift-package-managerͷSources/Basics/HTTPClient • ඪ४తͳHTTPClientͷ࣮ͱͯ͠Α͍͔ • ͦͷଞSwiftPMllbuildͷcommon
infrastructure ͱͯ͠ apple/swift-tools-support-core ͱ͍͏ͷ͋Δ • https://github.com/apple/swift-tools-support-core -
Changes to Package.resolved • Swift Package RegistryͷϦϦʔεZipϑΝΠϧͱͯ͠ΞʔΧΠϒ͞ΕΔɻ • ֎෦ύοέʔδͷґଘ͕ؔRegistryΛհͯ͠μϯϩʔυ͞ΕΔͱɺPackage.resolvedͷchecksum ͱɺswift
package compute-checksumίϚϯυͷchecksumͱൺֱ͢ΔɻPackage.resolvedʹͳ͚Ε هɻ $ swift package compute-checksum LinkedList-1.2.0.zip 1feec3d8d144814e99e694cd1d785928878d8d6892c4e59d12569e179252c535 { "object": { "pins": [ { "package": "mona.LinkedList", "state": { "checksum": "ed008d5af44c1d0ea0e3668033cae9b695235f18b1a99240b7cf0f3d9559a30d", "version": "1.2.0" } } ] }, "version": 1 } -
Changes to Package.resolved • Checksum͕ҟͳ͍ͬͯΕɺμϯϩʔυΛڋ൱͢Δɻ $ swift build error: checksum
of downloaded source archive of dependency 'mona.LinkedList' (c2b934fe66e55747d912f1cfd03150883c4f037370c40ca2ad4203805db79457) does not match checksum speci fi ed by the manifest (ed008d5af44c1d0ea0e3668033cae9b695235f18b1a99240b7cf0f3d9559a30d) -
Archive-source subcommand • ଞͷPackage ManagerͷࣄྫΛݟΔͱɺChecksumͷෆҰகɺِഁଛΑΓɺArchiveͷ࡞ɺ ChecksumͷෆҰக͕ݪҼͷ͜ͱͷํ͕ଟ͍ • swift package archive-source
ίϚϯυඪ४ͷsource archiveΛ࡞͢Δํ๏Λఏڙ͢Δ SYNOPSIS swift package archive-source [--output=< fi le>] OPTIONS -o < fi le>, --output=< fi le> Write the archive to < fi le>. If unspeci fi ed, the package is written to `\(PackageName).zip`. -
Archive-source subcommand • ίϚϯυΛrootͰ࣮ߦ͢ΔͱɺݱࡏͷWorking treeͷsource archiveΛ࡞͢Δ $ tree -a -L
1 LinkedList ᵓ── .git ᵓ── Package.swift ᵓ── README.md ᵓ── Sources └── Tests $ head -n 5 Package.swift // swift-tools-version:5.3 import PackageDescription let package = Package( name: "LinkedList", $ swift package archive-source Created LinkedList.zip -
Archive-source subcommand • σϑΥϧτͰɺ<Package name>.zip ʹͳΔɻ- - outputͰมߋՄೳ • Archive-source
git-archive ʹzip formatΛࢦఆ͠ɺdefault compression levelΛࢦఆͨ͠ͷͱಉɻ Note: export-ignoreଐੑͷϑΝΠϧແࢹ͞ΕΔɻ.git.buildͷΑ͏ͳӅ͠ϑΝΠϧ / σΟϨΫτϦؚ Ήɻ $ git checkout 1.2.0 $ swift package archive-source --output="LinkedList-1.2.0.zip" # Created LinkedList-1.2.0.zip $ git archive --format zip \ --pre fi x LinkedList-1.2.0 --output LinkedList-1.2.0.zip \ 1.2.0 -
Registry configuration subcommands swift package-registry set • GitHubͷΑ͏ͳPublic RegistryҎ֎ʹCustom RegistryΛߏ͢ΔαϒίϚϯυ
• ηϧϑϗετ͍ͨ͠Private Package͕͋Δ • ϛϥʔαΠτΛཱ͍ͯͨ߹ • ঝೝ͢ΈύοέʔδͷΈΛར༻ͤ͞ΔϙϦγʔΛద༻ͤ͞Δ߹ • ύοέʔδͷར༻ঢ়گͷޮՌଌఆΛߦ͍ɺϥϯΩϯάϥΠηϯεྉۚΛٻ͢Δ߹ SYNOPSIS swift package-registry set <url> [options] OPTIONS: --global Apply settings to all projects for this user --scope Associate the registry with a given scope --login Specify a user name for the remote machine --password Supply a password for the remote machine -
Registry configuration subcommands swift package-registry set • PackageͷRootͰ࣮ߦ͢Δͱɺ.swiftpm/con fi guration/registries.json
ϑΝΠϧ͕࡞͞ΕΔ • είʔϓ͕ࢦఆ͞Ε͍ͯͳ͍߹ [default] ʹͳΔɻ • ྫ͑ɺ֎෦ͷωοτϫʔΫಠΛڐՄ͠ͳ͍ϏϧυαʔόʔͰɺInternal registry service Λར༻ ͯ͠ґଘؔΛղܾ͢ΔΑ͏ʹRegistry URLΛߏ͢Δ $ swift package-registry set https://internal.example.com/ { "registries": { "[default]": { "url": "https://internal.example.com" } }, "version": 1 } -
Registry configuration subcommands Associating a registry with a scope •
scopeΦϓγϣϯΛ͚ͭͯPackageͷscopeΛࢦఆ͢ΔͱɺΧελϜϨδε τϦʹؔ࿈͚͢Δ͜ͱ͕Ͱ͖Δɻ • ΧελϜϨδετϦ͕Package scopeͱؔ࿈͚͞Ε͍ͯΔͱɺͦͷείʔ ϓͱͷύοέʔδͷґଘؔɺఏڙ͞ΕͨURLΛհͯ͠ղܾ͞ΕΔɻ ྫ) example.Foo → Package Registryͷexample scopeΛར༻ Foo → git URLΛར༻ $ swift package-registry set https://internal.example.com/ - -scope example { "registries": { "example": { "url": "https://internal.example.com" } }, "version": 1 } -
Registry configuration subcommands Unsetting a custom registry • ΧελϜϨδετϦΛղআ͢Δ SYNOPSIS
swift package-registry unset [options] OPTIONS: --global Apply settings to all projects for this user --scope Removes the registry's association to a given scope -
Registry configuration subcommands Global registry con fi guration • GlobalΦϓγϣϯΛ͚ͭΔͱɺ~/.swiftpm/con
fi guration/registries.json Λߋ৽͢Δ • Local Con fi guration GlobalΑΓ༏ઌ͞ΕΔ ྫ) foo scope https://local.example.com Λར༻͢Δ • ΧϨϯτσΟϨΫτϦͷPackageϚχϑΣετ (./Package.swift) • طଘͷlock fi le (./Package.resolved) • Local con fi guration (./.swiftpm/con fi guration/registries.json) • Global con fi guration (~/.swiftpm/con fi guration/registries.json) SYNOPSIS swift package-registry unset [options] OPTIONS: --global Apply settings to all projects for this user --scope Removes the registry's association to a given scope // Global configuration (~/.swiftpm/configuration/registries.json) { "registries": { "[default]": { "url": "https://global.example.com" }, "foo": { "url": "https://global.example.com" }, }, "version": 1 } // Local configuration (.swiftpm/configuration/registries.json) { "registries": { "foo": { "url": "https://local.example.com" } }, "version": 1 } -
Registry configuration subcommands Credential • - - login / -
-password ΦϓγϣϯΛ͢ͱɺΫϨσϯγϟϧΛఏڙͰ͖Δ • login ΩʔΛؚΉ registries.json ͷରԠ͢ΔΦϒδΣΫτʹ͞ΕͨΛ࣋ͭΩʔ͕Ճ͞ΕΔɻ • .netrcϑΝΠϧʹಛఆͷϚγϯͱϩάΠϯͷطଘͷΤϯτϦ͕͋Εɺpassword͕ߋ৽͞ΕΔɻ $ swift package-registry set https://internal.example.com/ \ --login jappleseed --password alpine $ cat .netrc machine internal.example.com login jappleseed password alpine { "registries": { "[default]": { "url": "https://internal.example.com" "login": "jappleseed" } }, "version": 1 } -
Changes to config subcommand Set-mirror option for package identi fi
ers • ݱࡏઃఆͰ͖Δset-mirrorίϚϯυʹ —original-urlΛஔ͖͑—package-identi fi erΦϓγϣϯΛՃ • .swiftpm/con fi guration/mirrors.json ϑΝΠϧΛੜ͢Δ $ swift package con fi g set-mirror \ --original-url https:///github.com/mona/linkedlist \ --mirror-url https:///github.com/octocorp/swiftlinkedlist { "object": [ { "mirror": "https://github.com/OctoCorp/ SwiftLinkedList.git", "original": "mona.LinkedList" } ], "version": 1 } -
Package Registry Service Publish Point • SE-0292ύοέʔδΛfetch͢ΔΤϯυϙΠϯτΛఆ͕ٛͨ͠ɺެ։ํ๏ʹ͍ͭͯఆٛ͠ͳ͔ͬͨ • ৽͍͠ϦϦʔεΛPackage registryʹެ։͢ΔͨΊͷඪ४ΤϯυϙΠϯτΛ༻ҙͯ͠ɺαʔϏεϓϩόΠ
μؒͷ૬ޓӡ༻ੑΛߴΊΔ Method Path Description PUT /{scope}/{name}/{version} Create a package release -
Package Registry Service Publish Point • swift package archive-source ͰzipϑΝΠϧΛ࡞͢Δɻ
• ࣍ͷϦΫΤετΛߦͳͬͯɺϦϦʔεΛΞοϓϩʔυ͢Δ • ϨδετϦ͕ϦΫΤετʹԠ͠ɺόʔδϣϯΛར༻Մೳʹͨ͠ΒɺGETͰऔಘͰ͖Δ $ curl -X PUT --netrc \ -H "Accept: application/vnd.swift.registry.v1+json" \ -F source-archive="@LinkedList-1.1.1.zip" \ "https://registry.example.com/mona/LinkedList?version=1.1.1" -
Security • ֎෦ʹґଘ͕ؔ͋Ε߈ܸରྖҬ͕૿Ճ͢Δ͕ɺϦεΫܰݮͰ͖ɺGitΛ͏ΑΓ҆શͰηΩϡϦςΟ͕อ ূͰ͖Δ • Package scopeͷจࣈηοτݶఆ͞Ε͓ͯΓɺϗϞάϥϑ߈ܸΛ͙ • ಉ͡จࣈʹݟ͑ͯҧ͏จࣈίʔυͷจࣈΛར༻ِͯ͠ͷURLʹ༠ಋ͢Δख๏ •
ઌ಄ɺඌɺ࿈ଓͷϋΠϑϯΛېࢭɻΞϯμʔείΞશʹېࢭɻ • .ͷېࢭɻείʔϓͷυϝΠϯόϦΞϯτͱͷޡղΛ͙ʢapple.comແޮɻappleͱࠞಉͰ͖ͳ͍ʣ • ύοέʔδείʔϓʹొ͞ΕɺλΠϙεΫϫοτΛܰݮ͢ΔɻޡղΛট͘Α͏ͳείʔϓͷׂΓͯΛ੍ ݶ͢ΔʢG00gleͳͲʣ • ۟ಡۭനจࣈΫϩεαΠτεΫϦϓςΟϯάɺCRLFΠϯδΣΫγϣϯΛট͘ͷͰېࢭɻ -
STRIDE • ͜ͷϓϩϙʔβϧʹ͓͚ΔηΩϡϦςΟͷӨڹͷཧղͷͨΊʹɺSTRIDEχʔϞχοΫΛར༻͢Δɻ ڴҖ ৵͢ΔγεςϜಛੑ Spoo fi ng (ͳΓ͢·͠) Authenticity
(ਅਖ਼ੑ) Tampering (վ͟Μʣ Integrity (શੑ) Repudiation (൱ೝ) Non-repudiation (൱ೝࢭʣ Information disclosure (ใ࿙Ӯʣ Con fi dentiality (ػີੑ) Denial of serviceʢαʔϏεڋ൱ʣ Availability (Մ༻ੑ) Elevation of privilegeʢಛݖͷঢ֨ʣ Authorization (ೝՄ) -
STRIDE Spoo fi ngʢͳΓ͢·͠ʣ • ߈ܸऀɺΫϥΠΞϯτͱύοέʔδϨδετϦͷؒʹϓϩΩγΛૠೖͯ͠ɺͦͷϗετͷࢿ֨ใΛड͠ɺͦΕΒΛ ༻ͯ͠ޙଓͷཁٻͰϢʔβʔʹͳΓ͢·͢Մೳੑ͕͋Γ·͢ɻ • ͜ΕΒͷࢿ֨ใʹؔ࿈͚ΒΕ͍ͯΔಛݖͷൣғͱϨϕϧʹΑͬͯɺ͜ͷ߈ܸͷӨڹ͕େ͖͘ͳΔՄೳੑ͕͋Γ· ͢ɻͨͩ͠ɺHTTPSΛհͨ҆͠શͳଓͷ༻ɺશମతͳϦεΫΛܰݮ͢Δͷʹେ͍ʹཱͪ·͢ɻ
• Swift Package Managerɺ࣍ͷରࡦΛߨ͡Δ͜ͱͰɺ͜ͷϦεΫΛ͞ΒʹܰݮͰ͖·͢ɻ • ͯ͢ͷURLʹHTTPSΛద༻͢Δ • DNS over HTTPSʢDoHʣΛ༻ͨ͠URLͷղܾ • Punycodeͱͯ͠ද͞ΕΔࠃࡍԽυϝΠϯ໊ʢIDNʣͷURLΛཁٻ͢Δ • Publish͢ΔࡍϦΫΤετʹଟཁૉೝূΛར༻͢Δ͜ͱΛਪ͢Δ -
STRIDE Tampering (վ͟Μ) • ߈ܸऀɺΫϥΠΞϯτͱύοέʔδϨδετϦͷؒʹϓϩΩγΛૠೖͯ͠ɺѱҙͷ͋ΔίʔυΛؚΉ ZipϑΝΠϧΛ࡞ͯ͠ૹ৴͢ΔՄೳੑ͕͋Γ·͢ɻ • ͜ͷΑ͏ͳ߈ܸͷӨڹજࡏతʹߴ͘ͳΓ·͕͢ɺμϯϩʔυ͞ΕͨιʔεΞʔΧΠϒͷ߹ੑΛݕ ূ͢ΔͨΊʹ҉߸ԽνΣοΫαϜΛ༻͢Δ͜ͱͰɺϦεΫେ෯ʹܰݮ͞Ε·͢ɻ •
߹ੑνΣοΫ͚ͩͰɺύοέʔδِ͕Ͱͳ͍͜ͱΛอূͰ͖·ͤΜɻ߈ܸऀϗετͷWebα ΠτΛةݥʹ͞Β͠ɺѱҙͷ͋Δύοέʔδʹ༗ޮͳνΣοΫαϜΛఏڙ͢ΔՄೳੑ͕͋Γ·͢ɻ $ echo "$(swift package compute-checksum LinkedList-1.2.0.zip) *LinkedList-1.2.0.zip" | \ shasum -a 256 -c - LinkedList-1.2.0.zip: OK -
STRIDE Tampering (վ͟Μ) ʹର͢ΔTOFUϞσϧ • Package.resolvedʹTrust on First UseʢTOFUʣηΩϡϦςΟϞσϧΛఏڙ͠·͢ɻ͜ΕʹΑΓɺظʹ ΘͨΔґଘؔͷ߹ੑʹ͍ͭͯڧྗͳอূΛఏڙͰ͖·͢ɻϨδετϦɺಁաϩάɺ
νΣοΫαϜ σʔλϕʔεɺ·ͨύοέʔδͷ༰Λೝূ͢ΔͨΊͷผͷಉͷվ͟ΜࢭγεςϜΛ࣮͢Δ͜ ͱʹΑΓɺ͜ͷϞσϧΛ͞ΒʹվળͰ͖·͢ ɻ • ZipϑΝΠϧΛհͨ͠ύοέʔδͷɺ৽͍͠જࡏతͳ߈ܸϕΫτϧΛͨΒ͠·͢ɻͨͱ͑ɺ߈ ܸऀɺZip SlipͷΑ͏ͳطͷ੬ऑੑɺ·ͨZipരʹର͢ΔײडੑͷΑ͏ͳҰൠతͳιϑτΣΞ ͷऑΛѱ༻͠Α͏ͱͯ͠ɺੜ͞ΕͨSource ArchiveΛѱҙΛ࣋ͬͯվ͟Μ͢ΔՄೳੑ͕͋Γ·͢ɻ • Swift Package ManagerɺSource Archive decompression ͷ࣮ʹ͓͍ͯɺ͜ΕΒͷछྨͷ߈ܸΛࣝ ผͯ͠อޢ͢ΔΑ͏ʹҙ͢Δඞཁ͕͋Γ·͢ɻ -
STRIDE Repudiation (൱ೝ) • ৵͞Εͨϗετɺ༗ޮͳνΣοΫαϜΛ༻ͯ͠ѱҙͷ͋ΔύοέʔδΛఏڙ͠ɺِͷؔ༩Λ൱ఆ Ͱ͖ͳ͍Մೳੑ͕͋Γ·͢ɻ • ͜ͷڴҖɺόΠφϦ͓ΑͼSource Artifactʹݻ༗ͷͷͰ͢ɻGitϦϙδτϦཤྺΛࠪ͢Δ͜ͱ͕Ͱ ͖ɺݸʑͷίϛοτ࡞ऀʹΑͬͯ҉߸Ͱॺ໊͞ΕΔ߹͕͋Γ·͢ɻArtifactͱSource
treeͷίϛοτ ͷؒʹଓΛཱ֬Ͱ͖ͳ͍ݶΓɺͦͷArtifactͷग़ॴΛஅ͢Δํ๏͋Γ·ͤΜɻ • Git-archive(1) ʹΑͬͯੜ͞ΕͨιʔεΞʔΧΠϒʹHEADɺίϝϯτͱͯ͠ίϛοτͷνΣοΫαϜ͕ ؚ·Ε͍ͯ·͢ɻϓϩδΣΫτͷཤྺ͕ར༻ՄೳͰ͋ΓɺιʔεΞʔΧΠϒͷੜʹ༻͞ΕΔίϛοτ͕ GPGͰॺ໊͞Ε͍ͯΔ߹ɺ҉߸Խॺ໊Λ༻ͯ͠৴པੑΛݕূͰ͖·͢ • ͦΕҎ֎ͷ߹ɺνΣοΫαϜσʔλϕʔεͱσδλϧॺ໊ͷ༻ͷ྆ํͰɺಉ༷ͷ൱ೝࢭͷอূ͕ఏڙ ͞Ε·͢ɻ -
$ git rev-parse HEAD b7c37c81f164e5dce0f64e3d75c79a48fb1fe00b3 $ swift package archive-source -o
LinkedList-1.2.0.zip Generated LinkedList-1.2.0.zip $ zipnote LinkedList-1.2.0.zip | grep "@ (zip fi le comment below this line)" -A 1 | tail -n 1 b7c37c81f164e5dce0f64e3d75c79a48fb1fe00b3 $ git verify-commit b7c37c81f164e5dce0f64e3d75c79a48fb1fe00b3 gpg: Signature made Tue Dec 16 00:00:00 2020 PST gpg: using RSA key BFAA7114B920808AA4365C203C5C1CF gpg: Good signature from "Mona Lisa Octocat <[email protected]>" [ultimate] -
STRIDE Information disclosure (ใ࿙Ӯ) • ϢʔβʔɺϓϩδΣΫτͷߏϑΝΠϧΛνΣοΫΠϯ͢Δ͜ͱʹΑΓɺޡͬͯΫϨσϯγϟϧΛެ։͢ΔՄೳੑ ͕͋Γ·͢ɻ߈ܸऀɺߏϑΝΠϧͷެ։ίʔυϦϙδτϦΛऔಘ͠ɺࢿ֨ใΛ࠶ར༻ͯ͠ϢʔβʔͷͳΓ͢· ͠ΛࢼΈΔՄೳੑ͕͋Γ·͢ɻ • ΫϨσϯγϟϧΛϓϩδΣΫτσΟϨΫτϦͷ֎෦ʢ௨ৗϢʔβʔͷϗʔϜσΟϨΫτϦʣʹ͋Δ.netrcϑΝΠϧ
ʹอଘ͢Δ͜ͱͰɺ࿙Ӯ͢ΔϦεΫΛݮΒͤ·͢ɻ͔͠͠ɺϢʔβʔswift packageίϚϯυʹ —netrc- fi leΦϓ γϣϯΛ͚ͭΔ͜ͱͰɺϓϩδΣΫτͷ.netrcϑΝΠϧΛࢦఆ͢Δ͔͠Ε·ͤΜɻ͜ͷϦεΫΛܰݮ͢ΔͨΊʹɺ swift package initͰϓϩδΣΫτΛ࡞͢Δͱ͖ʹ.gitignoreʹ.netrcΛՃ͠·͢ɻ • ϗεςΟϯάϓϩόΠμPublic repositoryʹίϛοτ͞Ε͍ͯΔsecretΛݕग़͢Δ͜ͱʹΑΓɺ͜ͷϦεΫΛ࠷খ ݶʹ͑Δ͜ͱ͕Ͱ͖·͢ • ΫϨσϯγϟϧSwift PMଞͷπʔϧͷϩάͰҙਤͤͣ։ࣔ͞ΕΔ͜ͱ͕͋Γ·͢ɻදࣔ͞ΕΔࡍɺϢʔβʔ໊ ύεϫʔυΛฤूͯ͠ݟͤͳ͍Α͏ʹ͢Δඞཁ͕͋Γ·͢ɻ -
STRIDE Denial of Service (αʔϏεڋ൱) • ߈ܸऀΧελϜϨδετϦΛఆٛ͢Δ .swiftpm/con fi guration/registires.jsonΛεΫϨΠϐϯά͠ɺͦ
ͷϦιʔεͷՄ༻ੑΛԼͤ͞ΔαʔϏεڋ൱߈ܸΛߦ͏Մೳੑ͕͋Γ·͢ɻ • Ұൠతʹɺ͜ͷ߈ܸͷՄೳੑ͍Ͱ͕͢ɺॏཁੑ͕ߴ͘ɺίετ͕͔͔ΔϦιʔεʹରͯ͠తΛߜͬ ͯ͘ΔՄೳੑ͕ߟ͑ΒΕ·͢ɻ • ͜ͷछྨͷ߈ܸɺ.gitignoreʹ .swiftpm/con fi gurationΛՃ͢Δ͜ͱͰܰݮͰ͖·͢ɻ -
Package Registry Summary • GitΛΘͣʹɺಛఆͷίϛοτͷιʔεΞʔΧΠϒͷμϯϩʔυʹͳΔͷ Ͱɺґଘղܾ͕ૣ͘ͳΔՄೳੑ͕ߴ͍ • ΧελϜϨδετϦΛߏங͢Δ͜ͱͰɺެ։ϨδετϦΛར༻Ͱ͖ͳ͍Ϣʔε έʔεʹରԠ͢Δ •
ScopeΛಋೖ͢Δ͜ͱͰɺར༻͢ΔϦιʔεΛ۠ผ͢Δ͜ͱ͕Ͱ͖Δ • Author͕શͯGitHubͷํʑ