示例#1
0
文件: api.go 项目: clobrano/snappy
func assertsFindMany(c *Command, r *http.Request, user *auth.UserState) Response {
	assertTypeName := muxVars(r)["assertType"]
	assertType := asserts.Type(assertTypeName)
	if assertType == nil {
		return BadRequest("invalid assert type: %q", assertTypeName)
	}
	headers := map[string]string{}
	q := r.URL.Query()
	for k := range q {
		headers[k] = q.Get(k)
	}

	state := c.d.overlord.State()
	state.Lock()
	db := assertstate.DB(state)
	state.Unlock()

	assertions, err := db.FindMany(assertType, headers)
	if err == asserts.ErrNotFound {
		return AssertResponse(nil, true)
	} else if err != nil {
		return InternalError("searching assertions failed: %v", err)
	}
	return AssertResponse(assertions, true)
}
示例#2
0
func downloadAssertion(typeName string, headers map[string]string) ([]asserts.Assertion, error) {
	var user *auth.UserState

	// FIXME: set auth context
	var authContext auth.AuthContext

	at := asserts.Type(typeName)
	if at == nil {
		return nil, fmt.Errorf("cannot find assertion type %q", typeName)
	}
	primaryKeys := make([]string, len(at.PrimaryKey))
	for i, k := range at.PrimaryKey {
		pk, ok := headers[k]
		if !ok {
			return nil, fmt.Errorf("missing primary header %q to query remote assertion", k)
		}
		primaryKeys[i] = pk
	}

	sto := storeNew(nil, authContext)
	as, err := sto.Assertion(at, primaryKeys, user)
	if err != nil {
		return nil, err
	}

	return []asserts.Assertion{as}, nil
}
示例#3
0
文件: sign.go 项目: niemeyer/snapd
// Sign produces the text of a signed assertion as specified by opts.
func Sign(opts *Options, keypairMgr asserts.KeypairManager) ([]byte, error) {
	var headers map[string]interface{}
	err := json.Unmarshal(opts.Statement, &headers)
	if err != nil {
		return nil, fmt.Errorf("cannot parse the assertion input as JSON: %v", err)
	}
	typCand, ok := headers["type"]
	if !ok {
		return nil, fmt.Errorf("missing assertion type header")
	}
	typStr, ok := typCand.(string)
	if !ok {
		return nil, fmt.Errorf("assertion type must be a string, not: %v", typCand)
	}
	typ := asserts.Type(typStr)
	if typ == nil {
		return nil, fmt.Errorf("invalid assertion type: %v", headers["type"])
	}

	var body []byte
	if bodyCand, ok := headers["body"]; ok {
		bodyStr, ok := bodyCand.(string)
		if !ok {
			return nil, fmt.Errorf("body if specified must be a string")
		}
		body = []byte(bodyStr)
		delete(headers, "body")
	}

	adb, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
		KeypairManager: keypairMgr,
	})
	if err != nil {
		return nil, err
	}

	// TODO: teach Sign to cross check keyID and authority-id
	// against an account-key
	a, err := adb.Sign(typ, headers, body, opts.KeyID)
	if err != nil {
		return nil, err
	}

	return asserts.Encode(a), nil
}
示例#4
0
文件: store.go 项目: pedronis/snappy
func (s *Store) assertionsEndpoint(w http.ResponseWriter, req *http.Request) {
	assertPath := strings.TrimPrefix(req.URL.Path, "/assertions/")

	bs, err := s.collectAssertions()
	if err != nil {
		http.Error(w, fmt.Sprintf("internal error collecting assertions: %v", err), http.StatusInternalServerError)
		return
	}

	comps := strings.Split(assertPath, "/")

	if len(comps) == 0 {
		http.Error(w, "missing assertion type", http.StatusBadRequest)
		return

	}

	typ := asserts.Type(comps[0])
	if typ == nil {
		http.Error(w, fmt.Sprintf("unknown assertion type: %s", comps[0]), http.StatusBadRequest)
		return
	}

	if len(typ.PrimaryKey) != len(comps)-1 {
		http.Error(w, fmt.Sprintf("wrong primary key length: %v", comps), http.StatusBadRequest)
		return
	}

	a, err := s.retrieveAssertion(bs, typ, comps[1:])
	if isAssertNotFound(err) {
		w.Header().Set("Content-Type", "application/problem+json")
		w.WriteHeader(404)
		w.Write([]byte(`{"status": 404}`))
		return
	}
	if err != nil {
		http.Error(w, fmt.Sprintf("cannot retrieve assertion %v: %v", comps, err), http.StatusBadRequest)
		return
	}

	w.Header().Set("Content-Type", asserts.MediaType)
	w.WriteHeader(http.StatusOK)
	w.Write(asserts.Encode(a))
}
示例#5
0
func (as *assertsSuite) TestWithAuthority(c *C) {
	withAuthority := []string{
		"account",
		"account-key",
		"snap-declaration",
		"snap-build",
		"snap-revision",
		"model",
		"serial",
		"system-user",
		"validation",
	}
	c.Check(withAuthority, HasLen, asserts.NumAssertionType-4) // excluding device-session-request, serial-request, serial-proof, account-key-request
	for _, name := range withAuthority {
		typ := asserts.Type(name)
		_, err := asserts.AssembleAndSignInTest(typ, nil, nil, testPrivKey1)
		c.Check(err, ErrorMatches, `"authority-id" header is mandatory`)
	}
}
示例#6
0
func (ms *mgrsSuite) mockStore(c *C) *httptest.Server {
	var baseURL string
	fillHit := func() string {
		snapf, err := snap.Open(ms.serveSnapPath)
		if err != nil {
			panic(err)
		}
		info, err := snap.ReadInfoFromSnapFile(snapf, nil)
		if err != nil {
			panic(err)
		}
		hit := strings.Replace(fooSearchHit, "@URL@", baseURL+"/snap", -1)
		hit = strings.Replace(hit, "@ICON@", baseURL+"/icon", -1)
		hit = strings.Replace(hit, "@VERSION@", info.Version, -1)
		hit = strings.Replace(hit, "@REVISION@", ms.serveRevision, -1)
		return hit
	}

	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if strings.HasPrefix(r.URL.Path, "/assertions/") {
			comps := strings.Split(r.URL.Path, "/")
			ref := &asserts.Ref{
				Type:       asserts.Type(comps[2]),
				PrimaryKey: comps[3:],
			}
			a, err := ref.Resolve(ms.storeSigning.Find)
			if err == asserts.ErrNotFound {
				w.Header().Set("Content-Type", "application/json")
				w.WriteHeader(404)
				w.Write([]byte(`{"status": 404}`))
				return
			}
			if err != nil {
				panic(err)
			}
			w.Header().Set("Content-Type", asserts.MediaType)
			w.WriteHeader(200)
			w.Write(asserts.Encode(a))
			return
		}

		switch r.URL.Path {
		case "/details/foo":
			w.WriteHeader(http.StatusOK)
			io.WriteString(w, fillHit())
		case "/metadata":
			w.WriteHeader(http.StatusOK)
			output := `{
    "_embedded": {
	    "clickindex:package": [@HIT@]
    }
}`
			output = strings.Replace(output, "@HIT@", fillHit(), 1)
			io.WriteString(w, output)
		case "/snap":
			snapR, err := os.Open(ms.serveSnapPath)
			if err != nil {
				panic(err)
			}
			io.Copy(w, snapR)
		default:
			panic("unexpected url path: " + r.URL.Path)
		}
	}))
	c.Assert(mockServer, NotNil)

	baseURL = mockServer.URL

	detailsURL, err := url.Parse(baseURL + "/details/")
	c.Assert(err, IsNil)
	bulkURL, err := url.Parse(baseURL + "/metadata")
	c.Assert(err, IsNil)
	assertionsURL, err := url.Parse(baseURL + "/assertions/")
	c.Assert(err, IsNil)
	storeCfg := store.Config{
		DetailsURI:    detailsURL,
		BulkURI:       bulkURL,
		AssertionsURI: assertionsURL,
	}

	mStore := store.New(&storeCfg, nil)
	st := ms.o.State()
	st.Lock()
	snapstate.ReplaceStore(ms.o.State(), mStore)
	st.Unlock()

	return mockServer
}
示例#7
0
func (as *assertsSuite) TestTypeMaxSupportedFormat(c *C) {
	c.Check(asserts.Type("test-only").MaxSupportedFormat(), Equals, 1)
}
示例#8
0
func (as *assertsSuite) TestUnknown(c *C) {
	c.Check(asserts.Type(""), IsNil)
	c.Check(asserts.Type("unknown"), IsNil)
}
示例#9
0
func (as *assertsSuite) TestType(c *C) {
	c.Check(asserts.Type("test-only"), Equals, asserts.TestOnlyType)
}
示例#10
0
func (ms *mgrsSuite) mockStore(c *C) *httptest.Server {
	var baseURL string
	fillHit := func(name string) string {
		snapf, err := snap.Open(ms.serveSnapPath[name])
		if err != nil {
			panic(err)
		}
		info, err := snap.ReadInfoFromSnapFile(snapf, nil)
		if err != nil {
			panic(err)
		}
		hit := strings.Replace(searchHit, "@URL@", baseURL+"/snap/"+name, -1)
		hit = strings.Replace(hit, "@NAME@", name, -1)
		hit = strings.Replace(hit, "@SNAPID@", fakeSnapID(name), -1)
		hit = strings.Replace(hit, "@ICON@", baseURL+"/icon", -1)
		hit = strings.Replace(hit, "@VERSION@", info.Version, -1)
		hit = strings.Replace(hit, "@REVISION@", ms.serveRevision[name], -1)
		return hit
	}

	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		comps := strings.Split(r.URL.Path, "/")
		if len(comps) == 0 {
			panic("unexpected url path: " + r.URL.Path)

		}
		switch comps[1] {
		case "assertions":
			ref := &asserts.Ref{
				Type:       asserts.Type(comps[2]),
				PrimaryKey: comps[3:],
			}
			a, err := ref.Resolve(ms.storeSigning.Find)
			if err == asserts.ErrNotFound {
				w.Header().Set("Content-Type", "application/json")
				w.WriteHeader(404)
				w.Write([]byte(`{"status": 404}`))
				return
			}
			if err != nil {
				panic(err)
			}
			w.Header().Set("Content-Type", asserts.MediaType)
			w.WriteHeader(200)
			w.Write(asserts.Encode(a))
			return
		case "details":
			w.WriteHeader(http.StatusOK)
			io.WriteString(w, fillHit(comps[2]))
		case "metadata":
			dec := json.NewDecoder(r.Body)
			var input struct {
				Snaps []struct {
					SnapID   string `json:"snap_id"`
					Revision int    `json:"revision"`
				} `json:"snaps"`
			}
			err := dec.Decode(&input)
			if err != nil {
				panic(err)
			}
			var hits []json.RawMessage
			for _, s := range input.Snaps {
				name := ms.serveIDtoName[s.SnapID]
				if snap.R(s.Revision) == snap.R(ms.serveRevision[name]) {
					continue
				}
				hits = append(hits, json.RawMessage(fillHit(name)))
			}
			w.WriteHeader(http.StatusOK)
			output, err := json.Marshal(map[string]interface{}{
				"_embedded": map[string]interface{}{
					"clickindex:package": hits,
				},
			})
			if err != nil {
				panic(err)
			}
			w.Write(output)
		case "snap":
			snapR, err := os.Open(ms.serveSnapPath[comps[2]])
			if err != nil {
				panic(err)
			}
			io.Copy(w, snapR)
		default:
			panic("unexpected url path: " + r.URL.Path)
		}
	}))
	c.Assert(mockServer, NotNil)

	baseURL = mockServer.URL

	detailsURL, err := url.Parse(baseURL + "/details/")
	c.Assert(err, IsNil)
	bulkURL, err := url.Parse(baseURL + "/metadata")
	c.Assert(err, IsNil)
	assertionsURL, err := url.Parse(baseURL + "/assertions/")
	c.Assert(err, IsNil)
	storeCfg := store.Config{
		DetailsURI:    detailsURL,
		BulkURI:       bulkURL,
		AssertionsURI: assertionsURL,
	}

	mStore := store.New(&storeCfg, nil)
	st := ms.o.State()
	st.Lock()
	snapstate.ReplaceStore(ms.o.State(), mStore)
	st.Unlock()

	return mockServer
}