mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: verify manifest signature (#23519)
* try decode * vendor crypto deps * commited missing vendor deps * Theme: Refactoring theme colors variables (#23513) * Theme: Typography updates * Updated * Updated snapshot * Renamed colors to palette * Introduce colors namespace * Massive theme color move * Removing color selection logic with more abstract concepts * Updates * Minor sidemenu change * Fix example jaeger agent port in docs (#23514) * @grafana/ui: Replace various icons using Icon component (#23442) * Replace icons in dashboard and settings * Replace icons in alerting * Update batch of icons * Implement icons accross various files * Style updates * Search: Fix recent and starred icons * Update styling and details * Replace new icon created by unicons * Fix e2e test, styling * Minor styling updates Co-authored-by: Clarity-89 <homes89@ukr.net> * trying with p512 key * trying with p512 key * lint * update with real signatures * fixes spacing in test files * remove convey from test * use errutil to wrap errors * removes print statement * splitt tests into two run statements * unexport plugin manifest struct Co-authored-by: bergquist <carl.bergquist@gmail.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com> Co-authored-by: Vitaly Zhuravlev <v-zhuravlev@users.noreply.github.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Clarity-89 <homes89@ukr.net>
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"golang.org/x/crypto/openpgp/clearsign"
|
||||
)
|
||||
|
||||
// Soon we can fetch keys from:
|
||||
@@ -15,21 +22,28 @@ var publicKeyText = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: OpenPGP.js v4.10.1
|
||||
Comment: https://openpgpjs.org
|
||||
|
||||
xjMEXo5V+RYJKwYBBAHaRw8BAQdAxIzDC0767A5eOHESiU8ACz5c9BWIrkbJ
|
||||
/5a4m/zsFWnNG0pvbiBTbWl0aCA8am9uQGV4YW1wbGUuY29tPsJ4BBAWCgAg
|
||||
BQJejlX5BgsJBwgDAgQVCAoCBBYCAQACGQECGwMCHgEACgkQ1uNw7xqtn452
|
||||
hQD+LK/+1k5vdVVQDxRDyjN3+6Wiy/jK2wwH1JtHdnTUKKsA/iot3glN57wb
|
||||
gaIQgQSZaE5E9tsIhGYhhNi8R743Oh4GzjgEXo5V+RIKKwYBBAGXVQEFAQEH
|
||||
QCmdY+K50okUPp1NCFJxdje+Icr859fTwwRy9+hq+vUIAwEIB8JhBBgWCAAJ
|
||||
BQJejlX5AhsMAAoJENbjcO8arZ+OpMwBAIcGCY1jMPo64h9G4MmFyPjL+wxn
|
||||
U2YVAvfHQZnN+gD3AP47klt0/0tmSlbNwEvimZxA3tpUfNrtUO1K4E8VxSIn
|
||||
Dg==
|
||||
=PA1c
|
||||
xpMEXpTXXxMFK4EEACMEIwQBiOUQhvGbDLvndE0fEXaR0908wXzPGFpf0P0Z
|
||||
HJ06tsq+0higIYHp7WTNJVEZtcwoYLcPRGaa9OQqbUU63BEyZdgAkPTz3RFd
|
||||
5+TkDWZizDcaVFhzbDd500yTwexrpIrdInwC/jrgs7Zy/15h8KA59XXUkdmT
|
||||
YB6TR+OA9RKME+dCJozNGUdyYWZhbmEgPGVuZ0BncmFmYW5hLmNvbT7CvAQQ
|
||||
EwoAIAUCXpTXXwYLCQcIAwIEFQgKAgQWAgEAAhkBAhsDAh4BAAoJEH5NDGpw
|
||||
iGbnaWoCCQGQ3SQnCkRWrG6XrMkXOKfDTX2ow9fuoErN46BeKmLM4f1EkDZQ
|
||||
Tpq3SE8+My8B5BIH3SOcBeKzi3S57JHGBdFA+wIJAYWMrJNIvw8GeXne+oUo
|
||||
NzzACdvfqXAZEp/HFMQhCKfEoWGJE8d2YmwY2+3GufVRTI5lQnZOHLE8L/Vc
|
||||
1S5MXESjzpcEXpTXXxIFK4EEACMEIwQBtHX/SD5Qm3v4V92qpaIZQgtTX0sT
|
||||
cFPjYWAHqsQ1iENrYN/vg1wU3ADlYATvydOQYvkTyT/tbDvx2Fse8PL84MQA
|
||||
YKKQ6AJ3gLVvmeouZdU03YoV4MYaT8KbnJUkZQZkqdz2riOlySNI9CG3oYmv
|
||||
omjUAtzgAgnCcurfGLZkkMxlmY8DAQoJwqQEGBMKAAkFAl6U118CGwwACgkQ
|
||||
fk0ManCIZuc0jAIJAVw2xdLr4ZQqPUhubrUyFcqlWoW8dQoQagwO8s8ubmby
|
||||
KuLA9FWJkfuuRQr+O9gHkDVCez3aism7zmJBqIOi38aNAgjJ3bo6leSS2jR/
|
||||
x5NqiKVi83tiXDPncDQYPymOnMhW0l7CVA7wj75HrFvvlRI/4MArlbsZ2tBn
|
||||
N1c5v9v/4h6qeA==
|
||||
=DNbR
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
`
|
||||
|
||||
// PluginManifest holds details for the file manifest
|
||||
type PluginManifest struct {
|
||||
// pluginManifest holds details for the file manifest
|
||||
type pluginManifest struct {
|
||||
Plugin string `json:"plugin"`
|
||||
Version string `json:"version"`
|
||||
KeyID string `json:"keyId"`
|
||||
@@ -39,36 +53,31 @@ type PluginManifest struct {
|
||||
|
||||
// readPluginManifest attempts to read and verify the plugin manifest
|
||||
// if any error occurs or the manifest is not valid, this will return an error
|
||||
func readPluginManifest(body []byte) (*PluginManifest, error) {
|
||||
fmt.Printf("TODO... verify: %s", publicKeyText)
|
||||
// block, _ := clearsign.Decode(body)
|
||||
// if block == nil {
|
||||
// return nil, fmt.Errorf("unable to decode manifest")
|
||||
// }
|
||||
func readPluginManifest(body []byte) (*pluginManifest, error) {
|
||||
block, _ := clearsign.Decode(body)
|
||||
if block == nil {
|
||||
return nil, errors.New("unable to decode manifest")
|
||||
}
|
||||
|
||||
// txt := string(block.Plaintext)
|
||||
// fmt.Printf("PLAINTEXT: %s", txt)
|
||||
// Convert to a well typed object
|
||||
manifest := &pluginManifest{}
|
||||
err := json.Unmarshal(block.Plaintext, &manifest)
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("Error parsing manifest JSON", err)
|
||||
}
|
||||
|
||||
// // Convert to a well typed object
|
||||
// manifest := &PluginManifest{}
|
||||
// err := json.Unmarshal(block.Plaintext, &manifest)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("Error parsing manifest JSON: %s", err)
|
||||
// }
|
||||
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(publicKeyText))
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("failed to parse public key", err)
|
||||
}
|
||||
|
||||
// keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(publicKeyText))
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to parse public key: %s", err)
|
||||
// }
|
||||
if _, err := openpgp.CheckDetachedSignature(keyring,
|
||||
bytes.NewBuffer(block.Bytes),
|
||||
block.ArmoredSignature.Body); err != nil {
|
||||
return nil, errutil.Wrap("failed to check signature", err)
|
||||
}
|
||||
|
||||
// if _, err := openpgp.CheckDetachedSignature(keyring,
|
||||
// bytes.NewBuffer(block.Bytes),
|
||||
// block.ArmoredSignature.Body); err != nil {
|
||||
// return nil, fmt.Errorf("failed to check signature: %s", err)
|
||||
// }
|
||||
|
||||
// return manifest, nil
|
||||
return nil, fmt.Errorf("not yet parsing the manifest")
|
||||
return manifest, nil
|
||||
}
|
||||
|
||||
// GetPluginSignatureState returns the signature state for a plugin
|
||||
|
||||
@@ -1,53 +1,56 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestManifestParsing(t *testing.T) {
|
||||
|
||||
Convey("Should validate manifest", t, func() {
|
||||
txt := `
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
txt := `-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA512
|
||||
|
||||
{
|
||||
"plugin": "grafana-googlesheets-datasource",
|
||||
"version": "1.0.0-dev",
|
||||
"files": {
|
||||
"LICENSE": "7df059597099bb7dcf25d2a9aedfaf4465f72d8d",
|
||||
"README.md": "4ebed28a02dc029719296aa847bffcea8eb5b9ff",
|
||||
"gfx_sheets_darwin_amd64": "4493f107eb175b085f020c1afea04614232dc0fd",
|
||||
"gfx_sheets_linux_amd64": "d8b05884e3829d1389a9c0e4b79b0aba8c19ca4a",
|
||||
"gfx_sheets_windows_amd64.exe": "88f33db20182e17c72c2823fe3bed87d8c45b0fd",
|
||||
"img/config-page.png": "e6d8f6704dbe85d5f032d4e8ba44ebc5d4a68c43",
|
||||
"img/dashboard.png": "63d79d0e0f9db21ea168324bd4e180d6892b9d2b",
|
||||
"img/graph.png": "7ea6295954b24be55b27320af2074852fb088fa1",
|
||||
"img/query-editor.png": "262f2bfddb004c7ce567042e8096f9e033c9b1bd",
|
||||
"img/sheets.svg": "f134ab85caff88b59ea903c5491c6a08c221622f",
|
||||
"module.js": "40b8c38cea260caed3cdc01d6e3c1eca483ab5c1",
|
||||
"plugin.json": "bfcae42976f0feca58eed3636655bce51702d3ed"
|
||||
"README.md": "08ec6d704b6115bef57710f6d7e866c050cb50ee",
|
||||
"gfx_sheets_darwin_amd64": "1b8ae92c6e80e502bb0bf2d0ae9d7223805993ab",
|
||||
"gfx_sheets_linux_amd64": "f39e0cc7344d3186b1052e6d356eecaf54d75b49",
|
||||
"gfx_sheets_windows_amd64.exe": "c8825dfec512c1c235244f7998ee95182f9968de",
|
||||
"module.js": "aaec6f51a995b7b843b843cd14041925274d960d",
|
||||
"module.js.LICENSE.txt": "7f822fe9341af8f82ad1b0c69aba957822a377cf",
|
||||
"module.js.map": "c5a524f5c4237f6ed6a016d43cd46938efeadb45",
|
||||
"plugin.json": "55556b845e91935cc48fae3aa67baf0f22694c3f"
|
||||
},
|
||||
"plugin": "grafana-googlesheets-datasource",
|
||||
"version": "1.2.3",
|
||||
"keyId": "ABC",
|
||||
"time": 1586404562862
|
||||
"time": 1586817677115,
|
||||
"keyId": "7e4d0c6a708866e7"
|
||||
}
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: OpenPGP.js v4.10.1
|
||||
Comment: https://openpgpjs.org
|
||||
|
||||
wl4EARYKAAYFAl6OnNMACgkQ1uNw7xqtn45r0QEAqmoB/Q5NsJZNxnM69m2A
|
||||
eQhcWNyo7yxO/4NZhVvBiJkA/iXUtptWbba3aw9TSZLn95LaUjKf4YUov29r
|
||||
qX6kODEP
|
||||
=YjQO
|
||||
-----END PGP SIGNATURE-----
|
||||
`
|
||||
wqEEARMKAAYFAl6U6o0ACgkQfk0ManCIZuevWAIHSvcxOy1SvvL5gC+HpYyG
|
||||
VbSsUvF2FsCoXUCTQflK6VdJfSPNzm8YdCdx7gNrBdly6HEs06ZaRp44F/ve
|
||||
NR7DnB0CCQHO+4FlSPtXFTzNepoc+CytQyDAeOLMLmf2Tqhk2YShk+G/YlVX
|
||||
74uuP5UXZxwK2YKJovdSknDIU7MhfuvvQIP/og==
|
||||
=hBea
|
||||
-----END PGP SIGNATURE-----`
|
||||
|
||||
t.Run("valid manifest", func(t *testing.T) {
|
||||
manifest, err := readPluginManifest([]byte(txt))
|
||||
|
||||
// Always an error for now
|
||||
So(err, ShouldNotBeNil)
|
||||
So(manifest, ShouldBeNil)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, manifest)
|
||||
assert.Equal(t, manifest.Plugin, "grafana-googlesheets-datasource")
|
||||
})
|
||||
|
||||
t.Run("invalid manifest", func(t *testing.T) {
|
||||
modified := strings.ReplaceAll(txt, "README.md", "xxxxxxxxxx")
|
||||
manifest, err := readPluginManifest([]byte(modified))
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, manifest)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user