Ai
1 Star 0 Fork 1

mysnapcore/mysnapd

forked from tupelo-shen/mysnapd 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
assertstest.go 19.15 KB
一键复制 编辑 原始数据 按行查看 历史
tupelo-shen 提交于 2022-11-07 17:55 +08:00 . fix: aspects & asserts commit
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2016 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Package assertstest provides helpers for testing code that involves assertions.
package assertstest
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"encoding/base64"
"fmt"
"io"
"os/exec"
"strings"
"time"
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/packet"
"gitee.com/mysnapcore/mysnapd/asserts"
"gitee.com/mysnapcore/mysnapd/randutil"
)
// GenerateKey generates a private/public key pair of the given bits. It panics on error.
func GenerateKey(bits int) (asserts.PrivateKey, *rsa.PrivateKey) {
priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
panic(fmt.Errorf("failed to create private key: %v", err))
}
return asserts.RSAPrivateKey(priv), priv
}
// ReadPrivKey reads a PGP private key (either armored or simply base64 encoded). It panics on error.
func ReadPrivKey(pk string) (asserts.PrivateKey, *rsa.PrivateKey) {
rd := bytes.NewReader([]byte(pk))
blk, err := armor.Decode(rd)
var body io.Reader
if err == nil {
body = blk.Body
} else {
rd.Seek(0, 0)
// try unarmored
body = base64.NewDecoder(base64.StdEncoding, rd)
}
pkt, err := packet.Read(body)
if err != nil {
panic(err)
}
pkPkt := pkt.(*packet.PrivateKey)
rsaPrivKey, ok := pkPkt.PrivateKey.(*rsa.PrivateKey)
if !ok {
panic("not a RSA key")
}
return asserts.RSAPrivateKey(rsaPrivKey), rsaPrivKey
}
// A sample developer key.
// See systestkeys for a prebuilt set of trusted keys and assertions.
const (
DevKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1
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
=5Myf
-----END PGP PRIVATE KEY BLOCK-----
`
DevKeyID = "EAD4DbLxK_kn0gzNCXOs3kd6DeMU3f-L6BEsSEuJGBqCORR0gXkdDxMbOm11mRFu"
DevKeyPGPFingerprint = "966e70f4b9f257a2772f8f354a423d28aaea4b4f"
)
// GPGImportKey imports the given PGP armored key into the GnuPG setup at homedir. It panics on error.
func GPGImportKey(homedir, armoredKey string) {
path, err := exec.LookPath("gpg1")
if err != nil {
path, err = exec.LookPath("gpg")
}
if err != nil {
panic(err)
}
gpg := exec.Command(path, "--homedir", homedir, "-q", "--batch", "--import", "--armor")
gpg.Stdin = bytes.NewBufferString(armoredKey)
out, err := gpg.CombinedOutput()
if err != nil {
panic(fmt.Errorf("cannot import test key into GPG setup at %q: %v (%q)", homedir, err, out))
}
}
// A SignerDB can sign assertions using its key pairs.
type SignerDB interface {
Sign(assertType *asserts.AssertionType, headers map[string]interface{}, body []byte, keyID string) (asserts.Assertion, error)
}
// NewAccount creates an account assertion for username, it fills in values for
// other missing headers as needed. It panics on error.
func NewAccount(db SignerDB, username string, otherHeaders map[string]interface{}, keyID string) *asserts.Account {
if otherHeaders == nil {
otherHeaders = make(map[string]interface{})
}
otherHeaders["username"] = username
if otherHeaders["account-id"] == nil {
otherHeaders["account-id"] = randutil.RandomString(32)
}
if otherHeaders["display-name"] == nil {
otherHeaders["display-name"] = strings.ToTitle(username[:1]) + username[1:]
}
if otherHeaders["validation"] == nil {
otherHeaders["validation"] = "unproven"
}
if otherHeaders["timestamp"] == nil {
otherHeaders["timestamp"] = time.Now().Format(time.RFC3339)
}
a, err := db.Sign(asserts.AccountType, otherHeaders, nil, keyID)
if err != nil {
panic(err)
}
return a.(*asserts.Account)
}
// NewAccountKey creates an account-key assertion for the account, it fills in
// values for missing headers as needed. In panics on error.
func NewAccountKey(db SignerDB, acct *asserts.Account, otherHeaders map[string]interface{}, pubKey asserts.PublicKey, keyID string) *asserts.AccountKey {
if otherHeaders == nil {
otherHeaders = make(map[string]interface{})
}
otherHeaders["account-id"] = acct.AccountID()
otherHeaders["public-key-sha3-384"] = pubKey.ID()
if otherHeaders["name"] == nil {
otherHeaders["name"] = "default"
}
if otherHeaders["since"] == nil {
otherHeaders["since"] = time.Now().Format(time.RFC3339)
}
encodedPubKey, err := asserts.EncodePublicKey(pubKey)
if err != nil {
panic(err)
}
a, err := db.Sign(asserts.AccountKeyType, otherHeaders, encodedPubKey, keyID)
if err != nil {
panic(err)
}
return a.(*asserts.AccountKey)
}
// SigningDB embeds a signing assertion database with a default private key and assigned authority id.
// Sign will use the assigned authority id.
// "" can be passed for keyID to Sign and PublicKey to use the default key.
type SigningDB struct {
AuthorityID string
KeyID string
*asserts.Database
}
// NewSigningDB creates a test signing assertion db with the given defaults. It panics on error.
func NewSigningDB(authorityID string, privKey asserts.PrivateKey) *SigningDB {
db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{})
if err != nil {
panic(err)
}
err = db.ImportKey(privKey)
if err != nil {
panic(err)
}
return &SigningDB{
AuthorityID: authorityID,
KeyID: privKey.PublicKey().ID(),
Database: db,
}
}
func (db *SigningDB) Sign(assertType *asserts.AssertionType, headers map[string]interface{}, body []byte, keyID string) (asserts.Assertion, error) {
if _, ok := headers["authority-id"]; !ok {
// copy before modifying
headers2 := make(map[string]interface{}, len(headers)+1)
for h, v := range headers {
headers2[h] = v
}
headers = headers2
headers["authority-id"] = db.AuthorityID
}
if keyID == "" {
keyID = db.KeyID
}
return db.Database.Sign(assertType, headers, body, keyID)
}
func (db *SigningDB) PublicKey(keyID string) (asserts.PublicKey, error) {
if keyID == "" {
keyID = db.KeyID
}
return db.Database.PublicKey(keyID)
}
// StoreStack realises a store-like set of founding trusted assertions and signing setup.
type StoreStack struct {
// Trusted authority assertions.
TrustedAccount *asserts.Account
TrustedKey *asserts.AccountKey
Trusted []asserts.Assertion
// Generic authority assertions.
GenericAccount *asserts.Account
GenericKey *asserts.AccountKey
GenericModelsKey *asserts.AccountKey
Generic []asserts.Assertion
GenericClassicModel *asserts.Model
// Signing assertion db that signs with the root private key.
RootSigning *SigningDB
// The store-like signing functionality that signs with a store key, setup to also store assertions if desired. It stores a default account-key for the store private key, see also the StoreStack.Key method.
*SigningDB
}
// StoreKeys holds a set of store private keys.
type StoreKeys struct {
Root asserts.PrivateKey
Store asserts.PrivateKey
Generic asserts.PrivateKey
GenericModels asserts.PrivateKey
}
var (
rootPrivKey, _ = GenerateKey(1024)
storePrivKey, _ = GenerateKey(752)
genericPrivKey, _ = GenerateKey(752)
genericModelsPrivKey, _ = GenerateKey(752)
pregenKeys = StoreKeys{
Root: rootPrivKey,
Store: storePrivKey,
Generic: genericPrivKey,
GenericModels: genericModelsPrivKey,
}
)
// NewStoreStack creates a new store assertion stack. It panics on error.
// Optional keys specify private keys to use for the various roles.
func NewStoreStack(authorityID string, keys *StoreKeys) *StoreStack {
if keys == nil {
keys = &pregenKeys
}
rootSigning := NewSigningDB(authorityID, keys.Root)
ts := time.Now().Format(time.RFC3339)
trustedAcct := NewAccount(rootSigning, authorityID, map[string]interface{}{
"account-id": authorityID,
"validation": "verified",
"timestamp": ts,
}, "")
trustedKey := NewAccountKey(rootSigning, trustedAcct, map[string]interface{}{
"name": "root",
"since": ts,
}, keys.Root.PublicKey(), "")
trusted := []asserts.Assertion{trustedAcct, trustedKey}
genericAcct := NewAccount(rootSigning, "generic", map[string]interface{}{
"account-id": "generic",
"validation": "verified",
"timestamp": ts,
}, "")
err := rootSigning.ImportKey(keys.GenericModels)
if err != nil {
panic(err)
}
genericModelsKey := NewAccountKey(rootSigning, genericAcct, map[string]interface{}{
"name": "models",
"since": ts,
}, keys.GenericModels.PublicKey(), "")
generic := []asserts.Assertion{genericAcct, genericModelsKey}
db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
Backstore: asserts.NewMemoryBackstore(),
Trusted: trusted,
OtherPredefined: generic,
})
if err != nil {
panic(err)
}
err = db.ImportKey(keys.Store)
if err != nil {
panic(err)
}
storeKey := NewAccountKey(rootSigning, trustedAcct, map[string]interface{}{
"name": "store",
}, keys.Store.PublicKey(), "")
err = db.Add(storeKey)
if err != nil {
panic(err)
}
err = db.ImportKey(keys.Generic)
if err != nil {
panic(err)
}
genericKey := NewAccountKey(rootSigning, genericAcct, map[string]interface{}{
"name": "serials",
"since": ts,
}, keys.Generic.PublicKey(), "")
err = db.Add(genericKey)
if err != nil {
panic(err)
}
a, err := rootSigning.Sign(asserts.ModelType, map[string]interface{}{
"authority-id": "generic",
"series": "16",
"brand-id": "generic",
"model": "generic-classic",
"classic": "true",
"timestamp": ts,
}, nil, genericModelsKey.PublicKeyID())
if err != nil {
panic(err)
}
genericClassicMod := a.(*asserts.Model)
return &StoreStack{
TrustedAccount: trustedAcct,
TrustedKey: trustedKey,
Trusted: trusted,
GenericAccount: genericAcct,
GenericKey: genericKey,
GenericModelsKey: genericModelsKey,
Generic: generic,
GenericClassicModel: genericClassicMod,
RootSigning: rootSigning,
SigningDB: &SigningDB{
AuthorityID: authorityID,
KeyID: storeKey.PublicKeyID(),
Database: db,
},
}
}
// StoreAccountKey retrieves one of the account-key assertions for the signing keys of the simulated store signing database.
// "" for keyID means the default one. It panics on error.
func (ss *StoreStack) StoreAccountKey(keyID string) *asserts.AccountKey {
if keyID == "" {
keyID = ss.KeyID
}
key, err := ss.Find(asserts.AccountKeyType, map[string]string{
"account-id": ss.AuthorityID,
"public-key-sha3-384": keyID,
})
if asserts.IsNotFound(err) {
return nil
}
if err != nil {
panic(err)
}
return key.(*asserts.AccountKey)
}
// MockBuiltinBaseDeclaration mocks the builtin base-declaration exposed by asserts.BuiltinBaseDeclaration.
func MockBuiltinBaseDeclaration(headers []byte) (restore func()) {
var prevHeaders []byte
decl := asserts.BuiltinBaseDeclaration()
if decl != nil {
prevHeaders, _ = decl.Signature()
}
err := asserts.InitBuiltinBaseDeclaration(headers)
if err != nil {
panic(err)
}
return func() {
err := asserts.InitBuiltinBaseDeclaration(prevHeaders)
if err != nil {
panic(err)
}
}
}
// FakeAssertionWithBody builds a fake assertion with the given body
// and layered headers. A fake assertion cannot be verified or added
// to a database or properly encoded. It can still be useful for unit
// tests but shouldn't be used in integration tests.
func FakeAssertionWithBody(body []byte, headerLayers ...map[string]interface{}) asserts.Assertion {
headers := map[string]interface{}{
"sign-key-sha3-384": "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij",
}
for _, h := range headerLayers {
for k, v := range h {
headers[k] = v
}
}
_, hasTimestamp := headers["timestamp"]
_, hasSince := headers["since"]
if !(hasTimestamp || hasSince) {
headers["timestamp"] = time.Now().Format(time.RFC3339)
}
a, err := asserts.Assemble(headers, body, nil, []byte("AXNpZw=="))
if err != nil {
panic(fmt.Sprintf("cannot build fake assertion: %v", err))
}
return a
}
// FakeAssertion builds a fake assertion with given layered headers
// and an empty body. A fake assertion cannot be verified or added to
// a database or properly encoded. It can still be useful for unit
// tests but shouldn't be used in integration tests.
func FakeAssertion(headerLayers ...map[string]interface{}) asserts.Assertion {
return FakeAssertionWithBody(nil, headerLayers...)
}
type accuDB interface {
Add(asserts.Assertion) error
}
// AddMany conveniently adds the given assertions to the db.
// It is idempotent but otherwise panics on error.
func AddMany(db accuDB, assertions ...asserts.Assertion) {
for _, a := range assertions {
err := db.Add(a)
if _, ok := err.(*asserts.RevisionError); !ok {
if err != nil {
panic(fmt.Sprintf("cannot add test assertions: %v", err))
}
}
}
}
// SigningAccounts manages a set of brand or user accounts,
// with their keys that can sign models etc.
type SigningAccounts struct {
store *StoreStack
signing map[string]*SigningDB
accts map[string]*asserts.Account
acctKeys map[string]*asserts.AccountKey
}
// NewSigningAccounts creates a new SigningAccounts instance.
func NewSigningAccounts(store *StoreStack) *SigningAccounts {
return &SigningAccounts{
store: store,
signing: make(map[string]*SigningDB),
accts: make(map[string]*asserts.Account),
acctKeys: make(map[string]*asserts.AccountKey),
}
}
func (sa *SigningAccounts) Register(accountID string, brandPrivKey asserts.PrivateKey, extra map[string]interface{}) *SigningDB {
brandSigning := NewSigningDB(accountID, brandPrivKey)
sa.signing[accountID] = brandSigning
acctHeaders := map[string]interface{}{
"account-id": accountID,
}
for k, v := range extra {
acctHeaders[k] = v
}
brandAcct := NewAccount(sa.store, accountID, acctHeaders, "")
sa.accts[accountID] = brandAcct
brandPubKey, err := brandSigning.PublicKey("")
if err != nil {
panic(err)
}
brandAcctKey := NewAccountKey(sa.store, brandAcct, nil, brandPubKey, "")
sa.acctKeys[accountID] = brandAcctKey
return brandSigning
}
func (sa *SigningAccounts) Account(accountID string) *asserts.Account {
if acct := sa.accts[accountID]; acct != nil {
return acct
}
panic(fmt.Sprintf("unknown test account-id: %s", accountID))
}
func (sa *SigningAccounts) AccountKey(accountID string) *asserts.AccountKey {
if acctKey := sa.acctKeys[accountID]; acctKey != nil {
return acctKey
}
panic(fmt.Sprintf("unknown test account-id: %s", accountID))
}
func (sa *SigningAccounts) PublicKey(accountID string) asserts.PublicKey {
pubKey, err := sa.Signing(accountID).PublicKey("")
if err != nil {
panic(err)
}
return pubKey
}
func (sa *SigningAccounts) Signing(accountID string) *SigningDB {
// convenience
if accountID == sa.store.RootSigning.AuthorityID {
return sa.store.RootSigning
}
if signer := sa.signing[accountID]; signer != nil {
return signer
}
panic(fmt.Sprintf("unknown test account-id: %s", accountID))
}
// Model creates a new model for accountID. accountID can also be the account-id of the underlying store stack.
func (sa *SigningAccounts) Model(accountID, model string, extras ...map[string]interface{}) *asserts.Model {
headers := map[string]interface{}{
"series": "16",
"brand-id": accountID,
"model": model,
"timestamp": time.Now().Format(time.RFC3339),
}
for _, extra := range extras {
for k, v := range extra {
headers[k] = v
}
}
signer := sa.Signing(accountID)
modelAs, err := signer.Sign(asserts.ModelType, headers, nil, "")
if err != nil {
panic(err)
}
return modelAs.(*asserts.Model)
}
// AccountsAndKeys returns the account and account-key for each given
// accountID in that order.
func (sa *SigningAccounts) AccountsAndKeys(accountIDs ...string) []asserts.Assertion {
res := make([]asserts.Assertion, 0, 2*len(accountIDs))
for _, accountID := range accountIDs {
res = append(res, sa.Account(accountID))
res = append(res, sa.AccountKey(accountID))
}
return res
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/mysnapcore/mysnapd.git
git@gitee.com:mysnapcore/mysnapd.git
mysnapcore
mysnapd
mysnapd
v0.1.0

搜索帮助