feat: add support for cocoapods (Swift/Objective-C) (#1081)

This commit is contained in:
cpendery
2022-07-11 10:09:08 -04:00
committed by GitHub
parent 2f1aa33ce8
commit 470b13045b
20 changed files with 711 additions and 1 deletions
+17
View File
@@ -0,0 +1,17 @@
/*
Package swift provides a concrete Cataloger implementation for Podfile.lock files.
*/
package swift
import (
"github.com/anchore/syft/syft/pkg/cataloger/common"
)
// NewCocoapodsCataloger returns a new Swift Cocoapods lock file cataloger object.
func NewCocoapodsCataloger() *common.GenericCataloger {
globParsers := map[string]common.ParserFn{
"**/Podfile.lock": parsePodfileLock,
}
return common.NewGenericCataloger(nil, globParsers, "cocoapods-cataloger")
}
@@ -0,0 +1,76 @@
package swift
import (
"fmt"
"io"
"io/ioutil"
"strings"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/common"
"gopkg.in/yaml.v3"
)
// integrity check
var _ common.ParserFn = parsePodfileLock
// parsePodfileLock is a parser function for Podfile.lock contents, returning all cocoapods pods discovered.
func parsePodfileLock(_ string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) {
bytes, err := ioutil.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("unable to read file: %w", err)
}
var podfile map[string]interface{}
if err = yaml.Unmarshal(bytes, &podfile); err != nil {
return nil, nil, fmt.Errorf("unable to parse yaml: %w", err)
}
c, exists := podfile["SPEC CHECKSUMS"]
if !exists {
return nil, nil, fmt.Errorf("malformed podfile.lock: missing checksums")
}
checksums := c.(map[string]interface{})
p, exists := podfile["PODS"]
if !exists {
return nil, nil, fmt.Errorf("malformed podfile.lock: missing checksums")
}
pods := p.([]interface{})
pkgs := []*pkg.Package{}
for _, podInterface := range pods {
var podBlob string
switch v := podInterface.(type) {
case map[string]interface{}:
for k := range v {
podBlob = k
}
case string:
podBlob = v
default:
return nil, nil, fmt.Errorf("malformed podfile.lock")
}
splits := strings.Split(podBlob, " ")
podName := splits[0]
podVersion := strings.TrimSuffix(strings.TrimPrefix(splits[1], "("), ")")
podRootPkg := strings.Split(podName, "/")[0]
pkgHash, exists := checksums[podRootPkg]
if !exists {
return nil, nil, fmt.Errorf("malformed podfile.lock: incomplete checksums")
}
pkgs = append(pkgs, &pkg.Package{
Name: podName,
Version: podVersion,
Type: pkg.CocoapodsPkg,
Language: pkg.Swift,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: podName,
Version: podVersion,
PkgHash: pkgHash.(string),
},
})
}
return pkgs, nil, nil
}
@@ -0,0 +1,306 @@
package swift
import (
"os"
"testing"
"github.com/anchore/syft/syft/pkg"
"github.com/go-test/deep"
)
func TestParsePodfileLock(t *testing.T) {
expected := []*pkg.Package{
{
Name: "GlossButtonNode",
Version: "3.1.2",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "GlossButtonNode",
Version: "3.1.2",
PkgHash: "4ea1197a744f2fb5fb875fe31caf17ded4762e8f",
},
},
{
Name: "PINCache",
Version: "3.0.3",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINCache",
Version: "3.0.3",
PkgHash: "7a8fc1a691173d21dbddbf86cd515de6efa55086",
},
},
{
Name: "PINCache/Arc-exception-safe",
Version: "3.0.3",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINCache/Arc-exception-safe",
Version: "3.0.3",
PkgHash: "7a8fc1a691173d21dbddbf86cd515de6efa55086",
},
},
{
Name: "PINCache/Core",
Version: "3.0.3",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINCache/Core",
Version: "3.0.3",
PkgHash: "7a8fc1a691173d21dbddbf86cd515de6efa55086",
},
},
{
Name: "PINOperation",
Version: "1.2.1",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINOperation",
Version: "1.2.1",
PkgHash: "00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20",
},
},
{
Name: "PINRemoteImage/Core",
Version: "3.0.3",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINRemoteImage/Core",
Version: "3.0.3",
PkgHash: "f1295b29f8c5e640e25335a1b2bd9d805171bd01",
},
},
{
Name: "PINRemoteImage/iOS",
Version: "3.0.3",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINRemoteImage/iOS",
Version: "3.0.3",
PkgHash: "f1295b29f8c5e640e25335a1b2bd9d805171bd01",
},
},
{
Name: "PINRemoteImage/PINCache",
Version: "3.0.3",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "PINRemoteImage/PINCache",
Version: "3.0.3",
PkgHash: "f1295b29f8c5e640e25335a1b2bd9d805171bd01",
},
},
{
Name: "Reveal-SDK",
Version: "33",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Reveal-SDK",
Version: "33",
PkgHash: "effba1c940b8337195563c425a6b5862ec875caa",
},
},
{
Name: "SwiftGen",
Version: "6.5.1",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "SwiftGen",
Version: "6.5.1",
PkgHash: "a6d22010845f08fe18fbdf3a07a8e380fd22e0ea",
},
},
{
Name: "Texture",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "Texture/AssetsLibrary",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture/AssetsLibrary",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "Texture/Core",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture/Core",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "Texture/MapKit",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture/MapKit",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "Texture/Photos",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture/Photos",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "Texture/PINRemoteImage",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture/PINRemoteImage",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "Texture/Video",
Version: "3.1.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "Texture/Video",
Version: "3.1.0",
PkgHash: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3",
},
},
{
Name: "TextureSwiftSupport",
Version: "3.13.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "TextureSwiftSupport",
Version: "3.13.0",
PkgHash: "c515c7927fab92d0d9485f49b885b8c5de34fbfb",
},
},
{
Name: "TextureSwiftSupport/Components",
Version: "3.13.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "TextureSwiftSupport/Components",
Version: "3.13.0",
PkgHash: "c515c7927fab92d0d9485f49b885b8c5de34fbfb",
},
},
{
Name: "TextureSwiftSupport/Experiments",
Version: "3.13.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "TextureSwiftSupport/Experiments",
Version: "3.13.0",
PkgHash: "c515c7927fab92d0d9485f49b885b8c5de34fbfb",
},
},
{
Name: "TextureSwiftSupport/Extensions",
Version: "3.13.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "TextureSwiftSupport/Extensions",
Version: "3.13.0",
PkgHash: "c515c7927fab92d0d9485f49b885b8c5de34fbfb",
},
},
{
Name: "TextureSwiftSupport/LayoutSpecBuilders",
Version: "3.13.0",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "TextureSwiftSupport/LayoutSpecBuilders",
Version: "3.13.0",
PkgHash: "c515c7927fab92d0d9485f49b885b8c5de34fbfb",
},
},
{
Name: "TinyConstraints",
Version: "4.0.2",
Language: pkg.Swift,
Type: pkg.CocoapodsPkg,
MetadataType: pkg.CocoapodsMetadataType,
Metadata: pkg.CocoapodsMetadata{
Name: "TinyConstraints",
Version: "4.0.2",
PkgHash: "7b7ccc0c485bb3bb47082138ff28bc33cd49897f",
},
},
}
fixture, err := os.Open("test-fixtures/Podfile.lock")
if err != nil {
t.Fatalf("failed to open fixture: %+v", err)
}
// TODO: no relationships are under test yet
actual, _, err := parsePodfileLock(fixture.Name(), fixture)
if err != nil {
t.Error(err)
}
differences := deep.Equal(expected, actual)
if differences != nil {
t.Errorf("returned package list differed from expectation: %+v", differences)
}
}
@@ -0,0 +1,92 @@
PODS:
- GlossButtonNode (3.1.2):
- Texture/Core (~> 3)
- TextureSwiftSupport (>= 3.10.0)
- PINCache (3.0.3):
- PINCache/Arc-exception-safe (= 3.0.3)
- PINCache/Core (= 3.0.3)
- PINCache/Arc-exception-safe (3.0.3):
- PINCache/Core
- PINCache/Core (3.0.3):
- PINOperation (~> 1.2.1)
- PINOperation (1.2.1)
- PINRemoteImage/Core (3.0.3):
- PINOperation
- PINRemoteImage/iOS (3.0.3):
- PINRemoteImage/Core
- PINRemoteImage/PINCache (3.0.3):
- PINCache (~> 3.0.3)
- PINRemoteImage/Core
- Reveal-SDK (33)
- SwiftGen (6.5.1)
- Texture (3.1.0):
- Texture/AssetsLibrary (= 3.1.0)
- Texture/Core (= 3.1.0)
- Texture/MapKit (= 3.1.0)
- Texture/Photos (= 3.1.0)
- Texture/PINRemoteImage (= 3.1.0)
- Texture/Video (= 3.1.0)
- Texture/AssetsLibrary (3.1.0):
- Texture/Core
- Texture/Core (3.1.0)
- Texture/MapKit (3.1.0):
- Texture/Core
- Texture/Photos (3.1.0):
- Texture/Core
- Texture/PINRemoteImage (3.1.0):
- PINRemoteImage/iOS (~> 3.0.0)
- PINRemoteImage/PINCache
- Texture/Core
- Texture/Video (3.1.0):
- Texture/Core
- TextureSwiftSupport (3.13.0):
- Texture/Core (>= 3)
- TextureSwiftSupport/Components (= 3.13.0)
- TextureSwiftSupport/Experiments (= 3.13.0)
- TextureSwiftSupport/Extensions (= 3.13.0)
- TextureSwiftSupport/LayoutSpecBuilders (= 3.13.0)
- TextureSwiftSupport/Components (3.13.0):
- Texture/Core (>= 3)
- TextureSwiftSupport/LayoutSpecBuilders
- TextureSwiftSupport/Experiments (3.13.0):
- Texture/Core (>= 3)
- TextureSwiftSupport/Extensions (3.13.0):
- Texture/Core (>= 3)
- TextureSwiftSupport/LayoutSpecBuilders (3.13.0):
- Texture/Core (>= 3)
- TinyConstraints (4.0.2)
DEPENDENCIES:
- GlossButtonNode
- Reveal-SDK
- SwiftGen
- Texture
- TextureSwiftSupport
- TinyConstraints
SPEC REPOS:
trunk:
- GlossButtonNode
- PINCache
- PINOperation
- PINRemoteImage
- Reveal-SDK
- SwiftGen
- Texture
- TextureSwiftSupport
- TinyConstraints
SPEC CHECKSUMS:
GlossButtonNode: 4ea1197a744f2fb5fb875fe31caf17ded4762e8f
PINCache: 7a8fc1a691173d21dbddbf86cd515de6efa55086
PINOperation: 00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20
PINRemoteImage: f1295b29f8c5e640e25335a1b2bd9d805171bd01
Reveal-SDK: effba1c940b8337195563c425a6b5862ec875caa
SwiftGen: a6d22010845f08fe18fbdf3a07a8e380fd22e0ea
Texture: 2e8ab2519452515f7f5a520f5a8f7e0a413abfa3
TextureSwiftSupport: c515c7927fab92d0d9485f49b885b8c5de34fbfb
TinyConstraints: 7b7ccc0c485bb3bb47082138ff28bc33cd49897f
PODFILE CHECKSUM: 07aa55f54421f6e6d3a920c11716a89fc9243d1b
COCOAPODS: 1.11.2