Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
468f5d15
Unverified
Commit
468f5d15
authored
Apr 09, 2020
by
Ryan McKinley
Committed by
GitHub
Apr 09, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Plugins: add a signature status flag (#23420)
parent
73296717
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
200 additions
and
15 deletions
+200
-15
pkg/api/dtos/plugins.go
+16
-14
pkg/api/plugins.go
+2
-0
pkg/plugins/manifest.go
+114
-0
pkg/plugins/manifest_test.go
+53
-0
pkg/plugins/models.go
+11
-0
pkg/plugins/plugins.go
+4
-1
No files found.
pkg/api/dtos/plugins.go
View file @
468f5d15
...
...
@@ -19,23 +19,25 @@ type PluginSetting struct {
JsonData
map
[
string
]
interface
{}
`json:"jsonData"`
DefaultNavUrl
string
`json:"defaultNavUrl"`
LatestVersion
string
`json:"latestVersion"`
HasUpdate
bool
`json:"hasUpdate"`
State
plugins
.
PluginState
`json:"state"`
LatestVersion
string
`json:"latestVersion"`
HasUpdate
bool
`json:"hasUpdate"`
State
plugins
.
PluginState
`json:"state"`
Signature
plugins
.
PluginSignature
`json:"signature"`
}
type
PluginListItem
struct
{
Name
string
`json:"name"`
Type
string
`json:"type"`
Id
string
`json:"id"`
Enabled
bool
`json:"enabled"`
Pinned
bool
`json:"pinned"`
Info
*
plugins
.
PluginInfo
`json:"info"`
LatestVersion
string
`json:"latestVersion"`
HasUpdate
bool
`json:"hasUpdate"`
DefaultNavUrl
string
`json:"defaultNavUrl"`
Category
string
`json:"category"`
State
plugins
.
PluginState
`json:"state"`
Name
string
`json:"name"`
Type
string
`json:"type"`
Id
string
`json:"id"`
Enabled
bool
`json:"enabled"`
Pinned
bool
`json:"pinned"`
Info
*
plugins
.
PluginInfo
`json:"info"`
LatestVersion
string
`json:"latestVersion"`
HasUpdate
bool
`json:"hasUpdate"`
DefaultNavUrl
string
`json:"defaultNavUrl"`
Category
string
`json:"category"`
State
plugins
.
PluginState
`json:"state"`
Signature
plugins
.
PluginSignature
`json:"signature"`
}
type
PluginList
[]
PluginListItem
...
...
pkg/api/plugins.go
View file @
468f5d15
...
...
@@ -100,6 +100,7 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) Response {
HasUpdate
:
pluginDef
.
GrafanaNetHasUpdate
,
DefaultNavUrl
:
pluginDef
.
DefaultNavUrl
,
State
:
pluginDef
.
State
,
Signature
:
pluginDef
.
Signature
,
}
if
pluginSetting
,
exists
:=
pluginSettingsMap
[
pluginDef
.
Id
];
exists
{
...
...
@@ -151,6 +152,7 @@ func GetPluginSettingByID(c *models.ReqContext) Response {
LatestVersion
:
def
.
GrafanaNetVersion
,
HasUpdate
:
def
.
GrafanaNetHasUpdate
,
State
:
def
.
State
,
Signature
:
def
.
Signature
,
}
query
:=
models
.
GetPluginSettingByIdQuery
{
PluginId
:
pluginID
,
OrgId
:
c
.
OrgId
}
...
...
pkg/plugins/manifest.go
0 → 100644
View file @
468f5d15
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
}
pkg/plugins/manifest_test.go
0 → 100644
View file @
468f5d15
package
plugins
import
(
"testing"
.
"github.com/smartystreets/goconvey/convey"
)
func
TestManifestParsing
(
t
*
testing
.
T
)
{
Convey
(
"Should validate manifest"
,
t
,
func
()
{
txt
:=
`
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
{
"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"
},
"plugin": "grafana-googlesheets-datasource",
"version": "1.2.3",
"keyId": "ABC",
"time": 1586404562862
}
-----BEGIN PGP SIGNATURE-----
Version: OpenPGP.js v4.10.1
Comment: https://openpgpjs.org
wl4EARYKAAYFAl6OnNMACgkQ1uNw7xqtn45r0QEAqmoB/Q5NsJZNxnM69m2A
eQhcWNyo7yxO/4NZhVvBiJkA/iXUtptWbba3aw9TSZLn95LaUjKf4YUov29r
qX6kODEP
=YjQO
-----END PGP SIGNATURE-----
`
manifest
,
err
:=
readPluginManifest
([]
byte
(
txt
))
// Always an error for now
So
(
err
,
ShouldNotBeNil
)
So
(
manifest
,
ShouldBeNil
)
})
}
pkg/plugins/models.go
View file @
468f5d15
...
...
@@ -24,6 +24,16 @@ var (
PluginStateBeta
PluginState
=
"beta"
)
type
PluginSignature
string
const
(
PluginSignatureInternal
PluginSignature
=
"internal"
// core plugin, no signature
PluginSignatureValid
PluginSignature
=
"valid"
// signed and accurate MANIFEST
PluginSignatureInvalid
PluginSignature
=
"invalid"
// invalid signature
PluginSignatureModified
PluginSignature
=
"modified"
// valid signature, but content mismatch
PluginSignatureUnsigned
PluginSignature
=
"unsigned"
// no MANIFEST file
)
type
PluginNotFoundError
struct
{
PluginId
string
}
...
...
@@ -49,6 +59,7 @@ type PluginBase struct {
HideFromList
bool
`json:"hideFromList,omitempty"`
Preload
bool
`json:"preload"`
State
PluginState
`json:"state,omitempty"`
Signature
PluginSignature
`json:"signature"`
IncludedInAppId
string
`json:"-"`
PluginDir
string
`json:"-"`
...
...
pkg/plugins/plugins.go
View file @
468f5d15
...
...
@@ -122,7 +122,10 @@ func (pm *PluginManager) Init() error {
}
for
_
,
p
:=
range
Plugins
{
if
!
p
.
IsCorePlugin
{
if
p
.
IsCorePlugin
{
p
.
Signature
=
PluginSignatureInternal
}
else
{
p
.
Signature
=
GetPluginSignatureState
(
p
)
metrics
.
SetPluginBuildInformation
(
p
.
Id
,
p
.
Type
,
p
.
Info
.
Version
)
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment