Skip to content
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

Add cataloger for Swift Package Manager. #1919

Merged
merged 1 commit into from
Jul 25, 2023

Conversation

trilleplay
Copy link
Contributor

This PR adds support for parsing Package.resolved files, which are generated by Swift Package Manager.

@trilleplay trilleplay force-pushed the feature/swift-package-manager branch 2 times, most recently from 74ba142 to cc5bc75 Compare July 7, 2023 13:49
@spiffcs spiffcs added the enhancement New feature or request label Jul 12, 2023
@spiffcs spiffcs self-assigned this Jul 12, 2023
@spiffcs
Copy link
Contributor

spiffcs commented Jul 12, 2023

Thanks for the contribution @trilleplay!

I ran this against: https://github.com/mozilla-mobile/firefox-ios to get a better idea of what we are now picking up with this addition. The answer is a ton:

Branch:
Screenshot 2023-07-12 at 3 39 21 PM

VS

Main:
Screenshot 2023-07-12 at 3 41 39 PM

I'm going to go through the PR a bit more in detail to add any comments or questions, but from first glance this is excellent

Copy link
Contributor

@spiffcs spiffcs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comments just getting a discussion going about parts I don't understand - thanks again so much for the PR and the time/effort on this one - looking forward to getting it merged!

@@ -54,6 +54,8 @@ func SourceInfo(p pkg.Package) string {
answer = "acquired package info from nix store path"
case pkg.Rpkg:
answer = "acquired package info from R-package DESCRIPTION file"
case pkg.SwiftPkg:
answer = "acquired package info from resolved Swift package manifest"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this description correct?

I'm pretty inexperienced with the Swift ecosystem, but the docs I've read describe the package manifest file as the Package.swift file. When I run the branch against a swift project I see packages sourced from Package.resolved <-- is there a different name for this file or is this also a manifest?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Package.swift file describes a package (i.e something that would be distributed with Swift Package Manager), meanwhile the Package.resolved file describes dependencies that the project depends on. The Package.resolved file is the result of looking up the dependencies of the given project, so it's a standalone manifest.

*/
package swift

import (
"github.com/anchore/syft/syft/pkg/cataloger/generic"
)

func NewSwiftPackageManagerCataloger() *generic.Cataloger {
return generic.NewCataloger("spm-cataloger").
WithParserByGlobs(parsePackageResolved, "**/Package.resolved", "**/.package.resolved")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any other globs that we should consider for a swift project that would contain dependencies managed by the package manager?

I noticed the command swift package show-dependencies and didn't know if it sourced this graph from other local files.

Example - I ran swift packages show-dependencies for https://github.com/mozilla-mobile/firefox-ios

.
├── swift<https://github.com/danger/swift.git@3.16.0>
│   ├── logger<https://github.com/shibapm/Logger@0.2.3>
│   ├── version<https://github.com/mxcl/Version@2.0.1>
│   └── octokit.swift<https://github.com/nerdishbynature/octokit.swift@0.12.0>
│       └── requestkit<https://github.com/nerdishbynature/RequestKit.git@3.2.1>
└── danger-swift-coverage<https://github.com/f-meloni/danger-swift-coverage@1.2.1>
    └── swift<https://github.com/danger/swift.git@3.16.0>
        ├── logger<https://github.com/shibapm/Logger@0.2.3>
        ├── version<https://github.com/mxcl/Version@2.0.1>
        └── octokit.swift<https://github.com/nerdishbynature/octokit.swift@0.12.0>
            └── requestkit<https://github.com/nerdishbynature/RequestKit.git@3.2.1>

But that seems like it contains a lot less than what we resolved in the SBOM:

➜  firefox-ios git:(main) ✗ syft dir:. --name firefox-ios | grep swift
Flag --name has been deprecated, use: source-name
 ✔ Indexed file system                                                                                       .
 ✔ Cataloged packages              [678 packages]
Commandant                                                                     0.17.0                swift
CwlCatchException                                                              1.2.0                 swift
CwlPreconditionTesting                                                         1.2.0                 swift
DangerXCodeSummary                                                             1.1.0                 swift
Komondor                                                                       1.0.4                 swift
Komondor                                                                       1.1.4                 swift
Logger                                                                         0.2.3                 swift
Nimble                                                                         7.3.1                 swift
Nimble                                                                         8.0.5                 swift
OctoKit                                                                        0.10.0                swift
OctoKit                                                                        0.12.0                swift
PackageConfig                                                                  0.13.0                swift
PackageConfig                                                                  1.1.3                 swift
Quick                                                                          1.3.2                 swift
Quick                                                                          2.2.0                 swift
RequestKit                                                                     2.4.0                 swift
RequestKit                                                                     3.1.0                 swift
RequestKit                                                                     3.2.0                 swift
RequestKit                                                                     3.2.1                 swift
Rocket                                                                         1.0.0                 swift
Rocket                                                                         1.2.1                 swift
SWXMLHash                                                                      5.0.1                 swift
SWXMLHash                                                                      6.0.0                 swift
ShellOut                                                                       2.3.0                 swift
SourceKitten                                                                   0.28.0                swift
SourceKitten                                                                   0.32.0                swift
SwiftFormat                                                                    0.43.5                swift
SwiftFormat                                                                    0.50.5                swift
SwiftLint                                                                      0.38.2                swift
SwiftLint                                                                      0.48.0                swift
SwiftShell                                                                     5.0.1                 swift
SwiftShell                                                                     5.1.0-beta.1          swift
SwiftSyntax                                                                    0.50600.1             swift
SwiftyTextTable                                                                0.9.0                 swift
TestSpy                                                                        0.3.1                 swift
Version                                                                        1.2.0                 swift
Version                                                                        2.0.1                 swift
Yams                                                                           2.0.0                 swift
Yams                                                                           4.0.6                 swift
a-star                                                                         3.0.0-beta-1          swift
danger-swift                                                                   3.0.0                 swift
danger-swift-coverage                                                          1.2.1                 swift
dip                                                                            7.1.1                 swift
fuzi                                                                                                 swift
gcdwebserver                                                                                         swift
glean-swift                                                                    53.0.0                swift
ios_sdk                                                                        4.33.4                swift
kif                                                                            3.8.7                 swift
kingfisher                                                                     7.6.2                 swift
logger                                                                         0.2.3                 swift
mappamundi                                                                                           swift
octokit.swift                                                                  0.12.0                swift
requestkit                                                                     3.2.1                 swift
rust-components-swift                                                          117.0.20230711050401  swift
sentry-cocoa                                                                   8.8.0                 swift
snapkit                                                                        5.6.0                 swift
swift                                                                          3.16.0                swift
swift-argument-parser                                                          1.0.3                 swift
swift-snapshot-testing                                                         1.10.0                swift
swiftybeaver                                                                   2.0.0                 swift
swiftyjson                                                                     5.0.1                 swift
telemetry-ios                                                                  2.0.0                 swift
version                                                                        2.0.1                 swift

Also I noticed that this list is much longer a second time around after running a few swift package commands.

Is the user expected to have resolved/downloaded certain dependency information before generating the SBOM for this cataloger to produce the optimal package output?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user is expected to have resolved packages (this can be done by building an App which depends on SPM packages) otherwise a Package.resolved file is not generated.

Without knowing what you did in those swift package commands, it could be that you resolved more package information, but at a different level. My guess is that a target specific dependency got resolved at the root-project level, this part touches a bit on the question you had about the globs, as far as they go, it's my understanding that .package.resolved file contains the root level dependencies, whilst the Package.resolved files contain the packages that are specific to targets. So could be that one of the commands you added changed the scope of where the dependencies were resolved, is my best guess. I'm by no means an expert of swift package manager.

Version string `json:"version"`
}

// parsePackageResolved is a parser for the contents of a Package.resolved file, which is generated by Xcode after it's resolved Swift Package Manger packages.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any relationships we should consider between Packages that are resolved from the ./Package.resolved vs ./.builds/checkout or other locations that a .resolved file might be found?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The relationship to be considered could be the target specific ones, if a resolved file is in only a certain target directory, it might indicate it's only required for that specific target.

I'm actually a bit uncertain as far as ./.builds/ go (once again no Swift Package Manager expert), I don't remember seeing that in my testing, but I do know that the location of the resolved file does depend on how you resolved, so it differs from CLI and Xcode, when it comes to resolving packages. So could be why I did not see that file in my testing?

Signed-off-by: Tristan Farkas <Tristan.Farkas@axis.com>
@trilleplay trilleplay force-pushed the feature/swift-package-manager branch from cc5bc75 to 13dd2d1 Compare July 20, 2023 08:40
@trilleplay
Copy link
Contributor Author

Rebased on main.

@spiffcs
Copy link
Contributor

spiffcs commented Jul 20, 2023

Thanks for the rebase and comments back on this @trilleplay! I'll bring this up at one of our team sync's today and look to try and get this merged for the next release - thanks again for all the work you put in here!

@spiffcs spiffcs merged commit e1c1832 into anchore:main Jul 25, 2023
9 checks passed
@trilleplay trilleplay deleted the feature/swift-package-manager branch July 25, 2023 21:41
@trilleplay
Copy link
Contributor Author

Thanks for the merge @spiffcs ! 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants