-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Signed packages handling in RegistryClient #6184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
e96f649
to
b0fe175
Compare
09e900b
to
594d7d3
Compare
efade1c
to
0554020
Compare
@@ -1606,6 +1667,10 @@ extension RegistryClient { | |||
public let version: String | |||
public let resources: [Resource] | |||
public let metadata: AdditionalMetadata? | |||
|
|||
var sourceArchive: Resource? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great
88b9701
to
3687bb1
Compare
@@ -473,7 +476,7 @@ extension AbsolutePath: ExpressibleByArgument { | |||
} | |||
} | |||
|
|||
extension FingerprintCheckingMode: ExpressibleByArgument { | |||
extension WorkspaceConfiguration.CheckingMode: ExpressibleByArgument { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define a wrapper enum in WorkspaceConfiguration
so we can avoid having PackageFingerprint
and PackageSigning
dependency in this module.
|
||
private let availabilityCache = ThreadSafeKeyValueStore< | ||
URL, | ||
(status: Result<AvailabilityStatus, Error>, expires: DispatchTime) | ||
>() | ||
|
||
private let metadataCache = ThreadSafeKeyValueStore< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an in-memory cache. I wonder if we should use sqlite-backed cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a good start, we can improve later if we see it is a bottle neck
|
||
private let configuration: RegistryConfiguration | ||
private let archiverProvider: (FileSystem) -> Archiver | ||
private let httpClient: LegacyHTTPClient | ||
private let authorizationProvider: LegacyHTTPClientConfiguration.AuthorizationProvider? | ||
private let jsonDecoder: JSONDecoder | ||
|
||
private var checksumTOFU: PackageVersionChecksumTOFU! | ||
private(set) var checksumTOFU: PackageVersionChecksumTOFU! | ||
private(set) var signatureValidation: SignatureValidation! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
signatureValidation
is initialized but not used (yet)
// Or is the package going from having a signer to .none? | ||
case .none: | ||
let versionSigners = signerVersions.versionSigners | ||
// If the given version is semantically newer than any signed version, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👀
On one hand I think we are trying to be too smart here, but I also think that it will be pretty common for a package to sign new versions only and leave older versions unsigned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems correct and reasonable to assume
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yah, I think the switch signed => unsigned is significant enough that it should require manual intervention by the user. Otherwise, any attacker can just publish a new unsigned version to circumvent the entire process.
@@ -0,0 +1,257 @@ | |||
//===----------------------------------------------------------------------===// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is the main change
@@ -0,0 +1,264 @@ | |||
//===----------------------------------------------------------------------===// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is the main change
observabilityScope: ObservabilityScope, | ||
completion: @escaping (Result<SigningEntity?, Error>) -> Void | ||
) { | ||
#if swift(>=5.5.2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need this to workaround CI error
case .warn: | ||
observabilityScope.emit(warning: "\(error)") | ||
completion(.success(.none)) | ||
case .silentAllow: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe debug or info logging here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but then it's not "silent"?
observabilityScope: observabilityScope, | ||
callbackQueue: callbackQueue | ||
) { result in | ||
switch result { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: result.mapError could make this more concise
public var fingerprintCheckingMode: WorkspaceConfiguration.CheckingMode = .strict | ||
|
||
@Option(name: .customLong("resolver-signing-entity-checking")) | ||
public var signingEntityCheckingMode: WorkspaceConfiguration.CheckingMode = .warn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not entirely sure about the naming here. I think it could be reasonable to think of the signing identity check as a form of "fingerprint" and therefore assuming it applies to both. I'd rather differentiate the options on the type of dependency and deprecate the old flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are two different types of checks though--we do fingerprint check for SCM and registry dependency, while signing entity check happens for registry dependency only--and I think we should keep the two options separate, at least initially, because the fingerprint check has been around for some time and is mature enough, while with signing entity check I am more comfortable setting the default level to warn
because it's new and there might be bugs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realize there was a fingerprint check for registry dependencies as well, is that a checksum of the archive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realize there was a fingerprint check for registry dependencies as well, is that a checksum of the archive?
Yep. We implemented fingerprint for both SCM and registry packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean we are grouping two fundamentally different types of fingerprints under one option and is that a potential issue? Registry ones are truly immutable (assuming you can't publish a different archive for an existing version) while SCM ones shouldn't typically change but are technically mutable.
Let's presume someone is regularly changing their SCM tags after the fact for some reason and decides to change the fingerprint checking policy because of that, as it stands that would affect registry dependencies as well even though it may not be intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean we are grouping two fundamentally different types of fingerprints under one option
Yes, though really, neither of the types should be changing regularly.
and is that a potential issue?
I would argue that if a user thinks it's ok to warn instead of error for the uncommon case of regularly changing git hash, then changing checksum is not worse? Checksums are supposed to be immutable, but it depends on registry implementation and thus not guaranteed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worse in the sense that they accepted an uncommon case and that implicitly opted them into also accepting a somewhat unrelated case that is likely an actual problem in most scenarios. It's probably fine, though.
// Or is the package going from having a signer to .none? | ||
case .none: | ||
let versionSigners = signerVersions.versionSigners | ||
// If the given version is semantically newer than any signed version, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yah, I think the switch signed => unsigned is significant enough that it should require manual intervention by the user. Otherwise, any attacker can just publish a new unsigned version to circumvent the entire process.
# See http://swift.org/LICENSE.txt for license information | ||
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors | ||
|
||
add_library(PackageSigning STATIC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @compnerd PackageSigning
is a new module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@compnerd Judging from swiftlang/swift-installer-scripts#76 and #4182 I don't think we need to add PackageSigning
to apple/swift-installer-scripts? But we need to add SwiftCrypto
back (swiftlang/swift-installer-scripts#172)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, if it is statically linked, it doesn't need to be distributed. SwiftCrypto is being statically linked currently, so that is already present.
@@ -351,6 +352,7 @@ def build(args): | |||
] | |||
build_dependency(args, "swift-driver", swift_driver_cmake_flags) | |||
build_dependency(args, "swift-collections") | |||
build_dependency(args, "swift-crypto") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sorry :(
@@ -184,6 +184,7 @@ def parse_global_args(args): | |||
args.source_dirs["tsc"] = os.path.join(args.project_root, "..", "swift-tools-support-core") | |||
args.source_dirs["yams"] = os.path.join(args.project_root, "..", "yams") | |||
args.source_dirs["swift-argument-parser"] = os.path.join(args.project_root, "..", "swift-argument-parser") | |||
args.source_dirs["swift-crypto"] = os.path.join(args.project_root, "..", "swift-crypto") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@neonichu I think we have to add swift-crypto
back since PackageSigning
depends on it and PackageRegistry
depends on PackageSigning
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I think that's true for now. Eventually, PackageRegistry
shouldn't build with CMake at all since it isn't needed for bootstrapping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windows can't bootstrap until we fix the myriad of issues around linking in SPM. We should be adding it to CMake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be adding it to CMake.
I thought I did with https://github.com/apple/swift-package-manager/pull/6184/files#diff-1e7de1ae2d059d21e1dd75d5812d5a34b0222cef273b7c3a2af62eb747f9d20a, or there is something else? The Windows CI is failing with this:
FAILED: lib/SKSwiftPMWorkspace.lib Sources/SKSwiftPMWorkspace/CMakeFiles/SKSwiftPMWorkspace.dir/SwiftPMWorkspace.swift.obj swift/SKSwiftPMWorkspace.swiftmodule
cmd.exe /C "cd . && T:\1\bin\swiftc.exe -output-file-map Sources\SKSwiftPMWorkspace\CMakeFiles\SKSwiftPMWorkspace.dir\Release\output-file-map.json -incremental -j 36 -emit-library -static -o lib\SKSwiftPMWorkspace.lib -module-name SKSwiftPMWorkspace -module-link-name SKSwiftPMWorkspace -emit-module -emit-module-path swift\SKSwiftPMWorkspace.swiftmodule -emit-dependencies -O -libc MD -Xcc -D_CRT_SECURE_NO_WARNINGS -Xcc -FT:/4 -autolink-force-load -Xfrontend -validate-tbd-against-ir=none -I swift -I T:\7\swift -I T:\6\swift -I C:\Users\swift-ci\jenkins\workspace\swiftpm-PR-windows\swift-system\Sources\CSystem\include -I T:\4\swift -I T:\3\src\swift\swift -I T:\3 -I C:\Users\swift-ci\jenkins\workspace\swiftpm-PR-windows\swift-corelibs-libdispatch -I C:\Users\swift-ci\jenkins\workspace\swiftpm-PR-windows\swift-corelibs-libdispatch\src -I T:\3\src -I C:\Users\swift-ci\jenkins\workspace\swiftpm-PR-windows\swift-corelibs-libdispatch\src\BlocksRuntime -I T:\14\swift -I T:\13\swift -I T:\8\products\llbuildSwift -I C:\Users\swift-ci\jenkins\workspace\swiftpm-PR-windows\llbuild\products\libllbuild\include C:\Users\swift-ci\jenkins\workspace\swiftpm-PR-windows\sourcekit-lsp\Sources\SKSwiftPMWorkspace\SwiftPMWorkspace.swift && cd ."
<unknown>:0: error: missing required module 'Crypto'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use a non-@_implementationOnly
import and the module is transitively part of libSwiftPM, we'll probably need to install it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windows can't bootstrap until we fix the myriad of issues around linking in SPM. We should be adding it to CMake.
I don't disagree with this, but we should be careful about what's essential to be build with CMake and what isn't, because otherwise we may end up with ancillary stuff being required for bootstrapping. This goes beyond Windows, btw, e.g. right now we need to build PackagePlugin
with CMake because we weren't conscious of this in the past and haven't fixed it, yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree with this, but we should be careful about what's essential to be build with CMake and what isn't, because otherwise we may end up with ancillary stuff being required for bootstrapping. This goes beyond Windows, btw, e.g. right now we need to build
PackagePlugin
with CMake because we weren't conscious of this in the past and haven't fixed it, yet.
Except we need the full build to distribute SPM on Windows. Otherwise, we end up without support for SPM on Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Except we need the full build to distribute SPM on Windows. Otherwise, we end up without support for SPM on Windows.
Yah, that's why we are keeping the full build for now and the foreseeable future. That doesn't mean we shouldn't be aware of the fact that the way it is supposed to work in the fullness of time is not having everything build with CMake.
Pulling the failure logs:
The problem is that swift-crypto is being linked into SPM and that is being pulled into SK-LSP. SK-LSP doesn't find the file and as a result fails. Are we linking in Crypto statically or dynamically? If it is statically, we should ideally just mark the imports as |
Windows build passes with I created #6217 based on this PR but minus import of swift-crypto to see if we can get that to pass and merge the bulk of the changes. |
No description provided.