...

Source file src/github.com/theupdateframework/go-tuf/data/types_test.go

Documentation: github.com/theupdateframework/go-tuf/data

     1  package data
     2  
     3  import (
     4  	"encoding/json"
     5  	"testing"
     6  
     7  	"github.com/secure-systems-lab/go-securesystemslib/cjson"
     8  	"github.com/stretchr/testify/assert"
     9  	. "gopkg.in/check.v1"
    10  )
    11  
    12  const (
    13  	// This public key is from the TUF specs:
    14  	//
    15  	// https://github.com/theupdateframework/specification
    16  	//
    17  	public       = `"72378e5bc588793e58f81c8533da64a2e8f1565c1fcc7f253496394ffc52542c"`
    18  	keyid10      = "1bf1c6e3cdd3d3a8420b19199e27511999850f4b376c4547b2f32fba7e80fca3"
    19  	keyid10algos = "506a349b85945d0d99c7289c3f0f1f6c550218089d1d38a3f64824db31e827ac"
    20  )
    21  
    22  type TypesSuite struct{}
    23  
    24  var _ = Suite(&TypesSuite{})
    25  
    26  type ed25519Public struct {
    27  	PublicKey HexBytes `json:"public"`
    28  }
    29  
    30  func (TypesSuite) TestKeyIDs(c *C) {
    31  	var hexbytes HexBytes
    32  	err := json.Unmarshal([]byte(public), &hexbytes)
    33  	c.Assert(err, IsNil)
    34  	keyValBytes, err := json.Marshal(ed25519Public{PublicKey: hexbytes})
    35  	c.Assert(err, IsNil)
    36  
    37  	key := PublicKey{
    38  		Type:   KeyTypeEd25519,
    39  		Scheme: KeySchemeEd25519,
    40  		Value:  keyValBytes,
    41  	}
    42  	c.Assert(key.IDs(), DeepEquals, []string{keyid10})
    43  
    44  	key = PublicKey{
    45  		Type:       KeyTypeEd25519,
    46  		Scheme:     KeySchemeEd25519,
    47  		Algorithms: HashAlgorithms,
    48  		Value:      keyValBytes,
    49  	}
    50  	c.Assert(key.IDs(), DeepEquals, []string{keyid10algos})
    51  }
    52  
    53  func (TypesSuite) TestRootAddKey(c *C) {
    54  	var hexbytes HexBytes
    55  	err := json.Unmarshal([]byte(public), &hexbytes)
    56  	c.Assert(err, IsNil)
    57  	keyValBytes, err := json.Marshal(ed25519Public{PublicKey: hexbytes})
    58  	c.Assert(err, IsNil)
    59  
    60  	key := &PublicKey{
    61  		Type:   KeyTypeEd25519,
    62  		Scheme: KeySchemeEd25519,
    63  		Value:  keyValBytes,
    64  	}
    65  
    66  	root := NewRoot()
    67  
    68  	c.Assert(root.AddKey(key), Equals, true)
    69  	c.Assert(root.AddKey(key), Equals, false)
    70  }
    71  
    72  func (TypesSuite) TestRoleAddKeyIDs(c *C) {
    73  	var hexbytes HexBytes
    74  	err := json.Unmarshal([]byte(public), &hexbytes)
    75  	c.Assert(err, IsNil)
    76  	keyValBytes, err := json.Marshal(ed25519Public{PublicKey: hexbytes})
    77  	c.Assert(err, IsNil)
    78  
    79  	key := &PublicKey{
    80  		Type:   KeyTypeEd25519,
    81  		Scheme: KeySchemeEd25519,
    82  		Value:  keyValBytes,
    83  	}
    84  
    85  	role := &Role{}
    86  	c.Assert(role.KeyIDs, HasLen, 0)
    87  
    88  	c.Assert(role.AddKeyIDs(key.IDs()), Equals, true)
    89  	c.Assert(role.KeyIDs, DeepEquals, []string{keyid10})
    90  
    91  	// Adding the key again doesn't modify the array.
    92  	c.Assert(role.AddKeyIDs(key.IDs()), Equals, false)
    93  	c.Assert(role.KeyIDs, DeepEquals, []string{keyid10})
    94  
    95  	// Add another key.
    96  	key = &PublicKey{
    97  		Type:       KeyTypeEd25519,
    98  		Scheme:     KeySchemeEd25519,
    99  		Algorithms: HashAlgorithms,
   100  		Value:      keyValBytes,
   101  	}
   102  
   103  	// Adding the key again doesn't modify the array.
   104  	c.Assert(role.AddKeyIDs(key.IDs()), Equals, true)
   105  	c.Assert(role.KeyIDs, DeepEquals, []string{keyid10, keyid10algos})
   106  }
   107  
   108  func TestDelegatedRolePathMatch(t *testing.T) {
   109  	var tts = []struct {
   110  		testName         string
   111  		pathPatterns     []string
   112  		pathHashPrefixes []string
   113  		file             string
   114  		shouldMatch      bool
   115  	}{
   116  		{
   117  			testName: "no path",
   118  			file:     "licence.txt",
   119  		},
   120  		{
   121  			testName:     "match path *",
   122  			pathPatterns: []string{"null", "targets/*.tgz"},
   123  			file:         "targets/foo.tgz",
   124  			shouldMatch:  true,
   125  		},
   126  		{
   127  			testName:     "does not match path *",
   128  			pathPatterns: []string{"null", "targets/*.tgz"},
   129  			file:         "targets/foo.txt",
   130  			shouldMatch:  false,
   131  		},
   132  		{
   133  			testName:     "match path ?",
   134  			pathPatterns: []string{"foo-version-?.tgz"},
   135  			file:         "foo-version-a.tgz",
   136  			shouldMatch:  true,
   137  		},
   138  		{
   139  			testName:     "does not match ?",
   140  			pathPatterns: []string{"foo-version-?.tgz"},
   141  			file:         "foo-version-alpha.tgz",
   142  			shouldMatch:  false,
   143  		},
   144  		// picked from https://github.com/theupdateframework/tuf/blob/30ba6e9f9ab25e0370e29ce574dada2d8809afa0/tests/test_updater.py#L1726-L1734
   145  		{
   146  			testName:         "match hash prefix",
   147  			pathHashPrefixes: []string{"badd", "8baf"},
   148  			file:             "/file3.txt",
   149  			shouldMatch:      true,
   150  		},
   151  		{
   152  			testName:         "does not match hash prefix",
   153  			pathHashPrefixes: []string{"badd"},
   154  			file:             "/file3.txt",
   155  			shouldMatch:      false,
   156  		},
   157  		{
   158  			testName:         "hash prefix first char",
   159  			pathHashPrefixes: []string{"2"},
   160  			file:             "/a/b/c/file_d.txt",
   161  			shouldMatch:      true,
   162  		},
   163  		{
   164  			testName:         "full hash prefix",
   165  			pathHashPrefixes: []string{"34c85d1ee84f61f10d7dc633472a49096ed87f8f764bd597831eac371f40ac39"},
   166  			file:             "/e/f/g.txt",
   167  			shouldMatch:      true,
   168  		},
   169  	}
   170  	for _, tt := range tts {
   171  		t.Run(tt.testName, func(t *testing.T) {
   172  			d := DelegatedRole{
   173  				Paths:            tt.pathPatterns,
   174  				PathHashPrefixes: tt.pathHashPrefixes,
   175  			}
   176  			assert.NoError(t, d.validatePaths())
   177  
   178  			matchesPath, err := d.MatchesPath(tt.file)
   179  			assert.NoError(t, err)
   180  			assert.Equal(t, tt.shouldMatch, matchesPath)
   181  		})
   182  
   183  	}
   184  }
   185  
   186  func TestDelegatedRoleJSON(t *testing.T) {
   187  	var tts = []struct {
   188  		testName string
   189  		d        *DelegatedRole
   190  		rawCJSON string
   191  	}{{
   192  		testName: "all fields with hashes",
   193  		d: &DelegatedRole{
   194  			Name:             "n1",
   195  			KeyIDs:           []string{"k1"},
   196  			Threshold:        5,
   197  			Terminating:      true,
   198  			PathHashPrefixes: []string{"8f"},
   199  		},
   200  		rawCJSON: `{"keyids":["k1"],"name":"n1","path_hash_prefixes":["8f"],"paths":null,"terminating":true,"threshold":5}`,
   201  	},
   202  		{
   203  			testName: "paths only",
   204  			d: &DelegatedRole{
   205  				Name:      "n2",
   206  				KeyIDs:    []string{"k1", "k3"},
   207  				Threshold: 12,
   208  				Paths:     []string{"*.txt"},
   209  			},
   210  			rawCJSON: `{"keyids":["k1","k3"],"name":"n2","paths":["*.txt"],"terminating":false,"threshold":12}`,
   211  		},
   212  		{
   213  			testName: "default",
   214  			d:        &DelegatedRole{},
   215  			rawCJSON: `{"keyids":null,"name":"","paths":null,"terminating":false,"threshold":0}`,
   216  		},
   217  	}
   218  
   219  	for _, tt := range tts {
   220  		t.Run(tt.testName, func(t *testing.T) {
   221  			b, err := cjson.EncodeCanonical(tt.d)
   222  			assert.NoError(t, err)
   223  			assert.Equal(t, tt.rawCJSON, string(b))
   224  
   225  			newD := &DelegatedRole{}
   226  			err = json.Unmarshal(b, newD)
   227  			assert.NoError(t, err)
   228  			assert.Equal(t, tt.d, newD)
   229  		})
   230  	}
   231  }
   232  
   233  func TestDelegatedRoleUnmarshalErr(t *testing.T) {
   234  	targetsWithBothMatchers := []byte(`{"keyids":null,"name":"","paths":["*.txt"],"path_hash_prefixes":["8f"],"terminating":false,"threshold":0}`)
   235  	var d DelegatedRole
   236  	assert.Equal(t, ErrPathsAndPathHashesSet, json.Unmarshal(targetsWithBothMatchers, &d))
   237  
   238  	// test for type errors
   239  	err := json.Unmarshal([]byte(`{"keyids":"a"}`), &d)
   240  	assert.Equal(t, "keyids", err.(*json.UnmarshalTypeError).Field)
   241  }
   242  
   243  func TestCustomField(t *testing.T) {
   244  	testCustomJSON := json.RawMessage([]byte(`{"test":true}`))
   245  
   246  	root := Root{
   247  		Type:               "root",
   248  		SpecVersion:        "1.0",
   249  		Keys:               make(map[string]*PublicKey),
   250  		Roles:              make(map[string]*Role),
   251  		ConsistentSnapshot: true,
   252  		Custom:             &testCustomJSON,
   253  	}
   254  	rootJSON, err := json.Marshal(&root)
   255  	assert.NoError(t, err)
   256  	assert.Equal(t, []byte("{\"_type\":\"root\",\"spec_version\":\"1.0\",\"version\":0,\"expires\":\"0001-01-01T00:00:00Z\",\"keys\":{},\"roles\":{},\"custom\":{\"test\":true},\"consistent_snapshot\":true}"), rootJSON)
   257  
   258  	targets := Targets{
   259  		Type:        "targets",
   260  		SpecVersion: "1.0",
   261  		Targets:     make(TargetFiles),
   262  		Custom:      &testCustomJSON,
   263  	}
   264  	targetsJSON, err := json.Marshal(&targets)
   265  	assert.NoError(t, err)
   266  	assert.Equal(t, []byte("{\"_type\":\"targets\",\"spec_version\":\"1.0\",\"version\":0,\"expires\":\"0001-01-01T00:00:00Z\",\"targets\":{},\"custom\":{\"test\":true}}"), targetsJSON)
   267  
   268  	snapshot := Snapshot{
   269  		Type:        "snapshot",
   270  		SpecVersion: "1.0",
   271  		Meta:        make(SnapshotFiles),
   272  		Custom:      &testCustomJSON,
   273  	}
   274  	snapshotJSON, err := json.Marshal(&snapshot)
   275  	assert.NoError(t, err)
   276  	assert.Equal(t, []byte("{\"_type\":\"snapshot\",\"spec_version\":\"1.0\",\"version\":0,\"expires\":\"0001-01-01T00:00:00Z\",\"meta\":{},\"custom\":{\"test\":true}}"), snapshotJSON)
   277  
   278  	timestamp := Timestamp{
   279  		Type:        "timestamp",
   280  		SpecVersion: "1.0",
   281  		Meta:        make(TimestampFiles),
   282  		Custom:      &testCustomJSON,
   283  	}
   284  	timestampJSON, err := json.Marshal(&timestamp)
   285  	assert.NoError(t, err)
   286  	assert.Equal(t, []byte("{\"_type\":\"timestamp\",\"spec_version\":\"1.0\",\"version\":0,\"expires\":\"0001-01-01T00:00:00Z\",\"meta\":{},\"custom\":{\"test\":true}}"), timestampJSON)
   287  }
   288  

View as plain text