func (as *assertsSuite) TestDecoderBrokenBodySeparation(c *C) { streamData := strings.Replace(exampleBodyAndExtraHeaders, "THE-BODY\n\n", "THE-BODY", 1) decoder := asserts.NewDecoder(bytes.NewBufferString(streamData)) _, err := decoder.Decode() c.Assert(err, ErrorMatches, "missing content/signature separator") streamData = strings.Replace(exampleBodyAndExtraHeaders, "THE-BODY\n\n", "THE-BODY\n", 1) decoder = asserts.NewDecoder(bytes.NewBufferString(streamData)) _, err = decoder.Decode() c.Assert(err, ErrorMatches, "missing content/signature separator") }
func (as *assertsSuite) TestEncoderOK(c *C) { encoded := []byte("type: test-only\n" + "authority-id: auth-id2\n" + "primary-key: xyzyz\n" + "revision: 5\n" + "header1: value1\n" + "header2: value2\n" + "body-length: 8\n\n" + "THE-BODY" + "\n\n" + "openpgp c2ln") a0, err := asserts.Decode(encoded) c.Assert(err, IsNil) cont0, _ := a0.Signature() stream := new(bytes.Buffer) enc := asserts.NewEncoder(stream) enc.Encode(a0) c.Check(bytes.HasSuffix(stream.Bytes(), []byte{'\n'}), Equals, true) dec := asserts.NewDecoder(stream) a1, err := dec.Decode() c.Assert(err, IsNil) cont1, _ := a1.Signature() c.Check(cont1, DeepEquals, cont0) }
func (as *assertsSuite) TestEncoderDecoderHappy(c *C) { stream := new(bytes.Buffer) enc := asserts.NewEncoder(stream) asserts.EncoderAppend(enc, []byte(exampleEmptyBody2NlNl)) asserts.EncoderAppend(enc, []byte(exampleBodyAndExtraHeaders)) asserts.EncoderAppend(enc, []byte(exampleEmptyBodyAllDefaults)) decoder := asserts.NewDecoder(stream) a, err := decoder.Decode() c.Assert(err, IsNil) c.Check(a.Type(), Equals, asserts.TestOnlyType) _, ok := a.(*asserts.TestOnly) c.Check(ok, Equals, true) checkContent(c, a, exampleEmptyBody2NlNl) a, err = decoder.Decode() c.Assert(err, IsNil) checkContent(c, a, exampleBodyAndExtraHeaders) a, err = decoder.Decode() c.Assert(err, IsNil) checkContent(c, a, exampleEmptyBodyAllDefaults) a, err = decoder.Decode() c.Assert(err, Equals, io.EOF) }
// Asserts queries assertions with type assertTypeName and matching assertion headers. func (client *Client) Asserts(assertTypeName string, headers map[string]string) ([]asserts.Assertion, error) { path := fmt.Sprintf("/2.0/assertions/%s", assertTypeName) q := url.Values{} if len(headers) > 0 { for k, v := range headers { q.Set(k, v) } } response, err := client.raw("GET", path, q, nil) if err != nil { return nil, fmt.Errorf("failed to query assertions: %v", err) } defer response.Body.Close() if response.StatusCode != http.StatusOK { return nil, parseError(response) } sanityCount, err := strconv.Atoi(response.Header.Get("X-Ubuntu-Assertions-Count")) if err != nil { return nil, fmt.Errorf("invalid assertions count") } dec := asserts.NewDecoder(response.Body) asserts := []asserts.Assertion{} // TODO: make sure asserts can decode and deal with unknown types for { a, err := dec.Decode() if err == io.EOF { break } if err != nil { return nil, fmt.Errorf("failed to decode assertions: %v", err) } asserts = append(asserts, a) } if len(asserts) != sanityCount { return nil, fmt.Errorf("response did not have the expected number of assertions") } return asserts, nil }
// Test querying for assertions with "snap" of the given type with filtering by assertion headers. func (s *snapKnownSuite) TestFiltering(c *check.C) { // add an account key cli.ExecCommand(c, "sudo", "snap", "ack", "integration-tests/data/dev1.acckey") defer cli.ExecCommand(c, "sudo", "rm", "-rf", dev1AccKeyFiles) out := cli.ExecCommand(c, "snap", "known", "account-key", "account-id=developer1") dec := asserts.NewDecoder(bytes.NewBufferString(out)) assertions := []asserts.Assertion{} for { a, err := dec.Decode() if err == io.EOF { break } c.Assert(err, check.IsNil) assertions = append(assertions, a) } c.Check(assertions, check.HasLen, 1) c.Check(assertions[0].(*asserts.AccountKey).AccountID(), check.Equals, "developer1") }
// Test querying for assertions with "snap" of the given type without filtering which gives all of them. func (s *snapKnownSuite) TestAll(c *check.C) { // add an account key cli.ExecCommand(c, "sudo", "snap", "ack", "integration-tests/data/dev1.acckey") // XXX: forceful cleanup of relevant assertions until we have a better general approach defer cli.ExecCommand(c, "sudo", "rm", "-rf", dev1AccKeyFiles) out := cli.ExecCommand(c, "snap", "known", "account-key") dec := asserts.NewDecoder(bytes.NewBufferString(out)) assertions := []asserts.Assertion{} for { a, err := dec.Decode() if err == io.EOF { break } c.Assert(err, check.IsNil) assertions = append(assertions, a) } c.Check(assertions, check.HasLen, 2) c.Check(assertions[1].(*asserts.AccountKey).AccountID(), check.Equals, "developer1") }
// Assertion retrivies the assertion for the given type and primary key. func (s *SnapUbuntuStoreRepository) Assertion(assertType *asserts.AssertionType, primaryKey []string, auther Authenticator) (asserts.Assertion, error) { url, err := s.assertionsURI.Parse(path.Join(assertType.Name, path.Join(primaryKey...))) if err != nil { return nil, err } req, err := http.NewRequest("GET", url.String(), nil) if err != nil { return nil, err } if auther != nil { auther.Authenticate(req) } req.Header.Set("Accept", asserts.MediaType) resp, err := s.client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode != 200 { if resp.Header.Get("Content-Type") == "application/json" { var svcErr assertionSvcError dec := json.NewDecoder(resp.Body) if err := dec.Decode(&svcErr); err != nil { return nil, fmt.Errorf("cannot decode assertion service error with HTTP status code %d: %v", resp.StatusCode, err) } if svcErr.Status == 404 { return nil, ErrAssertionNotFound } return nil, fmt.Errorf("assertion service error: [%s] %q", svcErr.Title, svcErr.Detail) } return nil, fmt.Errorf("unexpected HTTP status code %d", resp.StatusCode) } // and decode assertion dec := asserts.NewDecoder(resp.Body) return dec.Decode() }
func (as *assertsSuite) TestDecoderUnexpectedEOF(c *C) { streamData := exampleBodyAndExtraHeaders + "\n" + exampleEmptyBodyAllDefaults fstHeadEnd := strings.Index(exampleBodyAndExtraHeaders, "\n\n") sndHeadEnd := len(exampleBodyAndExtraHeaders) + 1 + strings.Index(exampleEmptyBodyAllDefaults, "\n\n") for _, brk := range []int{1, fstHeadEnd / 2, fstHeadEnd, fstHeadEnd + 1, fstHeadEnd + 2, fstHeadEnd + 6} { stream := bytes.NewBufferString(streamData[:brk]) decoder := asserts.NewDecoderStressed(stream, 16, 1024, 1024, 1024) _, err := decoder.Decode() c.Check(err, Equals, io.ErrUnexpectedEOF, Commentf("brk: %d", brk)) } for _, brk := range []int{sndHeadEnd, sndHeadEnd + 1} { stream := bytes.NewBufferString(streamData[:brk]) decoder := asserts.NewDecoder(stream) _, err := decoder.Decode() c.Assert(err, IsNil) _, err = decoder.Decode() c.Check(err, Equals, io.ErrUnexpectedEOF, Commentf("brk: %d", brk)) } }
func (as *assertsSuite) TestDecodeEmptyStream(c *C) { stream := new(bytes.Buffer) decoder := asserts.NewDecoder(stream) _, err := decoder.Decode() c.Check(err, Equals, io.EOF) }