Giter Club home page Giter Club logo

packageurl-go's People

Contributors

antgamdia avatar ashcrow avatar darthhater avatar furuholm avatar imjasonh avatar magnusbaeck avatar mcombuechen avatar noqcks avatar octogonapus avatar petergardfjall avatar pombredanne avatar ridhoq avatar shibumi avatar sschuberth avatar tommyknows avatar wetterjames4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

packageurl-go's Issues

New Versioning Scheme

Currently, our README.md defines the following versioning scheme:

The versions will follow the spec. So if the spec is released at 1.0. 
Then all versions in the 1.x.y will follow the 1.x spec.

In #57 we realized how impractical this is, hence I thought about releasing a v1.0.0 and creating a v1.1.0 release after merging the aforementioned PR.

Also, I thought about dropping this version scheme in general and instead we could go with version directories: v1/ or v2/, like some other APIs do.

WDYT? @pombredanne @sschuberth

Cut a release

Right now we are not doing releases of packageurl-go. We should. Cut a release once the current set of issues have been run through and travis is passing.

Escaping Rules

Hi again!

I've started wondering about the correct escaping-rules for all the different components of the purl. As far as I can tell, the current implementation doesn't actually match the spec in a couple of edge-cases, as it uses PathEncode instead of QueryEncode.

(I'd argue that using PathEncode is the right thing for namespace, name and version, but it creates a couple of difficulties that I've written down on an issue on the spec).

Here's the escapes that are required:

  • namespace: separate on / to get the individual segments, escape every segment with Path/QueryEscape. Currently this is implemented by the usage of JoinPath and then EscapedPath, I believe this is correct.
  • name: simply escape with Path/QueryEscape: #55
  • version: escape with Path/QueryEscape
  • qualifier: use QueryEscape

The current implementation calls EscapedPathon namespace, name and version, so technically implements the above points, except for one difference: the name isn't escaped by itself, meaning that if it contains a /, it will not be escaped.

Additionally, it won't "fully" escape versions, which could create ambiguities if the version contains an @, e.g. pkg:deb/debian/[email protected]@alpha-1. However, this question I think needs to be answered by the spec, see my linked comment. As a workaround, I guess we could query-escape it...

The name issue can be solved by PathEscapeing (and unescaping) it, I think I'll raise a PR to fix this.

It would be good to know however what to do with the version as well :)

packageurl.ToString() is not deterministic

When qualifiers are included in a purl, the ToString method no longer provides deterministic results.

The following loop:

uri := "pkg:deb/debian/[email protected]?arch=i386&distro=jessie"
purl, _ := packageurl.FromString(uri)
for i := 0; i < 20; i++ {
    fmt.Printf("%s\n", purl.ToString())
}

yields results similar to:

pkg:deb/debian/[email protected]?distro=jessie&arch=i386
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?distro=jessie&arch=i386
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?distro=jessie&arch=i386
pkg:deb/debian/[email protected]?distro=jessie&arch=i386
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?arch=i386&distro=jessie
pkg:deb/debian/[email protected]?distro=jessie&arch=i386

Note how the ToString method fails to produce a consistent result. Qualifiers are not ordered. This can be highly problematic for users of this package, in particular in testing scenarios.

The problem is the use of a map to store qualifiers. This does not capture the ordering of qualifier fields.

Rather than using

type Qualifiers map[string]string

I would suggest using:

// Qualifier represens a single key=value qualifier in the package url
type Qualifier struct {
       Key   string
       Value string
}

 // Qualifiers houses each key=value pair in the package url
type Qualifiers []Qualifier

packageurl.FromString() fails to parse subpaths

The packageurl.FromString() function does not properly parse subpaths. It strips the result of slashes. The following code:

package main

import (
	"fmt"

	packageurl "github.com/package-url/packageurl-go"
)

func main() {
	p, _ := packageurl.FromString("pkg:golang/google.golang.org/genproto#googleapis/api/annotations")
	fmt.Printf("subpath: %v\n", p.Subpath)
}

results in

subpath: googleapisapiannotations

Note that the example purl is taken from the purl-spec repo.

Add exported field containing all the currently supported types

As the PURL spec is evolving, other purl-dependant projects might fail to detect whether a given purl type is a valid type or just a random string that looks like a purl.

For instance, if we want to check from "test:ok/name@version", test is a supported type or not, we would have to check if it is one of purl.TypeBitbucket, purl.TypeCocoapods, purl.TypeCargo... etc., as the FromString func does not seem to validate the type,

packageurl-go/packageurl.go

Lines 239 to 243 in 3587d8c

typ, p, ok := strings.Cut(p, "/")
if !ok {
return PackageURL{}, fmt.Errorf("purl is missing type or name")
}
typ = strings.ToLower(typ)

A simplistic approach I can think of is just having an exported SupportedTypes map[string]struct{} like:

var SupportedTypes = map[string]struct{}{
	purl.TypeBitbucket:   {},
	purl.TypeCargo:       {},
	purl.TypeCocoapods:   {},
	purl.TypeComposer:    {},
        ...
}

This way, one could just do sth like: if _, ok := purl.SupportedTypes[myTypeToCheck]; !ok { ... to handle unsupported types.

Do you think it makes sense? If so, I can raise a PR.

Failing test `TestToStringExamples`

Running make test from a fresh clone of this repo results in a test failure

go test -v -cover ./...
=== RUN   TestFromStringExamples
--- PASS: TestFromStringExamples (0.00s)
=== RUN   TestToStringExamples
    packageurl_test.go:213: MLflow model with unique identifiers failed: pkg:mlflow/trafficsigns@10?model_uuid=36233173b22f4c89b451f1228d700d49&run_id=410a3121-2709-4f88-98dd-dba0ef056b0a&repository_url=https:%2F%2Fadb-5245952564735461.0.azuredatabricks.net%2Fapi%2F2.0%2Fmlflow != pkg:mlflow/trafficsigns@10?model_uuid=36233173b22f4c89b451f1228d700d49&repository_url=https://adb-5245952564735461.0.azuredatabricks.net/api/2.0/mlflow&run_id=410a3121-2709-4f88-98dd-dba0ef056b0a
--- FAIL: TestToStringExamples (0.00s)
=== RUN   TestStringer
--- PASS: TestStringer (0.00s)
=== RUN   TestQualifiersMapConversion
--- PASS: TestQualifiersMapConversion (0.00s)
FAIL
coverage: 58.0% of statements
FAIL	github.com/package-url/packageurl-go	0.139s
FAIL
make: *** [test] Error 1

purl with name contain whitespace can not be built from purl string

import (
	"testing"

	"github.com/package-url/packageurl-go"
)

func TestPURL(t *testing.T) {
	p := packageurl.NewPackageURL("generic", "", "a b", "", nil, "")
	u := p.ToString()
	got, err := packageurl.FromString(u)
	t.Log(err)              // <nil>
	t.Log(p.Name, got.Name) // a b a+b
}

Improve release management

I would like to do some improvements regarding release management. This involves several software supply chain security improvements:

  1. Creating a changelog with every release
  2. Creating a SBOM for every release (Software Bill of Materials)
  3. Create signed releases with the chainguard stack

An example project for such a project can be found here: https://github.com/shibumi/secure-supply-chain-example

Would be nice if we manage to be SLSA compliant with our releases.

Please create a new release with the test data

Hello,

@another-rex and I are attempting to package packageurl-go for Debian as we need it for a build dependency.

The Debian packaging tooling is grabbing the v0.1.0 tagged release, which does not include the subsequent addition of the testdata (added most recently in ab67608) so the package build fails.

Could you please make a new release that includes ab67608?

Thanks

Andrew

Version component is incorrectly lowercased

For types such as github, the specification states that name should be lowercased, but not the version.
https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#github

Git tags and branches however can be case sensitive.

Looking at the code the functiontypeAdjustName not only passes the name, but is passing name and version, eg. purl-spec@244fd47e07d1004 and as such the version gets lowercased along with the name.

https://github.com/package-url/packageurl-go/blob/master/packageurl.go#L267

Unit tests never actually verify the fields of the parsed PackageURL

At the moment, the TestFromStringExamples [1] parsing unit test does little else than verify that the parsing completes without an error. For each parsed purl, the purl's struct fields should be compared against the expected field values of the TestFixture.

[1]

func TestFromStringExamples(t *testing.T) {
// Read the json file
data, err := ioutil.ReadFile("testdata/test-suite-data.json")
if err != nil {
t.Fatal(err)
}
// Load the json file contents into a structure
testData := []TestFixture{}
err = json.Unmarshal(data, &testData)
if err != nil {
t.Fatal(err)
}
// Use FromString on each item in the test set
for _, tc := range testData {
// Should parse without issue
result, err := packageurl.FromString(tc.Purl)
if tc.IsInvalid == false {
if err != nil {
t.Logf("%s failed: %s", tc.Description, err)
t.Fail()
}
} else {
// Invalid cases
if err == nil {
t.Logf("%s did not fail and returned %#v", tc.Description, result)
t.Fail()
}
}
}
}

I have code that solves this but it relies on PR #13 being merged. Let me know if you need help on this.

Qualifiers Ordering

Hi again!

After #52, there seems to be a "bug" about the ordering of the qualifiers.
The code says:

// Qualifiers is a slice of key=value pairs, with order preserved as it appears
// in the package URL.

However, with the switch to the url.URL type, when encoding the qualifiers they actually get ordered lexicographically.

Now I've started to wonder what the "correct" behaviour for this is. The PURL Spec even says:

If the qualifiers are not empty and not composed only of key/value pairs where the value is empty:
...

  • sort this list of qualifier strings lexicographically
    ...

So admittedly, according to the spec, the "new" behaviour is correct.
Should I submit a PR to remove the comment that the order is being preserved? I'm wondering if this should be considered a breaking change.

Or do you have an opinion / better idea on what to do here?

Thanks!

Create a new release

The latest release is v0.1.1, released 2 months ago, and is missing several types in the spec (added in #43). Can this not block on #47, and get a new release

PackageURL should implement the Stringer interface

At the moment, the PackageURL type provides a ToString method to output a textual representation of the package URL.

A more idiomatic approach would be to implement the Stringer interface.

To not break backwards compatability, String should be implemented as a forwarding call to ToString.

purl-spec test-suite-data.json should be the source of truth for all libraries.

Rather than maintain diverging sources of truth, the local test-suite-data.json should be removed with all libraries referring to the purl-spec test-suite-data.json as the source of truth. An example of this is seen in #44 introducing a Julia test not mirrored in the purl-spec test-suite. #32 introduced the local test-suite-data.json copied from the packageurl-js repo instead of the purl-spec reflecting a problem with maintaining multiple divergent copies. While #46 updated the local copy from the purl-spec repo, it disables the github action workflow pulling the latest copy from the purl-spec. If the purl-spec test-suite is updated and the library is non-compliant, it won't be obvious until the someone updates the local copy and possibly resolves merge conflicts between the revisions.

Inconsistent URL encoding

There are inconsistencies with how namespace, subpath and name components are URL encoded by FromString and how they are decoded by ToString. See #22 for more details and proposed fixes.

Make packageurl-go a go module

Finally Go has a prescribed standard for managing project dependencies. With Go 1.11, support for modules was introduced. Starting in Go 1.13, module mode will be the default for all development.

For any project that wishes to be a part of the Go community, it makes a lot of sense to make use of modules. packageurl-go should be no exception.

[bug] ./ and ../ are not valid subpath prefix

A bug was discovered after upgrading to v0.1.2 where ./ and ../ are not valid prefixes as seen here: guacsec/guac#1545. It appears to be due to this logic:

if s == "." || s == ".." {
	return fmt.Errorf("invalid Package URL subpath: %q", p.Subpath)
}

As per the SPDX spec, file paths are generally prefixed with ./. If a purl was to be constructed using the files read in from an SPDX SBOM, it would throw an error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.