mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 02:40:26 -06:00
115 lines
3.2 KiB
Go
115 lines
3.2 KiB
Go
package plugins
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
)
|
|
|
|
// Soon we can fetch keys from:
|
|
// https://grafana.com/api/plugins/ci/keys
|
|
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
|
|
-----END PGP PUBLIC KEY BLOCK-----
|
|
`
|
|
|
|
// PluginManifest holds details for the file manifest
|
|
type PluginManifest struct {
|
|
Plugin string `json:"plugin"`
|
|
Version string `json:"version"`
|
|
KeyID string `json:"keyId"`
|
|
Time int64 `json:"time"`
|
|
Files map[string]string `json:"files"`
|
|
}
|
|
|
|
// 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")
|
|
// }
|
|
|
|
// 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, fmt.Errorf("Error parsing manifest JSON: %s", 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, fmt.Errorf("failed to check signature: %s", err)
|
|
// }
|
|
|
|
// return manifest, nil
|
|
return nil, fmt.Errorf("not yet parsing the manifest")
|
|
}
|
|
|
|
// GetPluginSignatureState returns the signature state for a plugin
|
|
func GetPluginSignatureState(plugin *PluginBase) PluginSignature {
|
|
manifestPath := path.Join(plugin.PluginDir, "MANIFEST.txt")
|
|
|
|
byteValue, err := ioutil.ReadFile(manifestPath)
|
|
if err != nil || len(byteValue) < 10 {
|
|
return PluginSignatureUnsigned
|
|
}
|
|
|
|
manifest, err := readPluginManifest(byteValue)
|
|
if err != nil {
|
|
return PluginSignatureInvalid
|
|
}
|
|
|
|
// Make sure the versions all match
|
|
if manifest.Plugin != plugin.Id || manifest.Version != plugin.Info.Version {
|
|
return PluginSignatureModified
|
|
}
|
|
|
|
// Verify the manifest contents
|
|
for p, hash := range manifest.Files {
|
|
// Open the file
|
|
f, err := os.Open(path.Join(plugin.PluginDir, p))
|
|
if err != nil {
|
|
return PluginSignatureModified
|
|
}
|
|
defer f.Close()
|
|
|
|
h := sha256.New()
|
|
if _, err := io.Copy(h, f); err != nil {
|
|
return PluginSignatureModified
|
|
}
|
|
sum := string(h.Sum(nil))
|
|
if sum != hash {
|
|
return PluginSignatureModified
|
|
}
|
|
}
|
|
|
|
// Everything OK
|
|
return PluginSignatureValid
|
|
}
|