Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save anonymouse64/22fd11b48676e1641eb51bd6d7fe4031 to your computer and use it in GitHub Desktop.
Save anonymouse64/22fd11b48676e1641eb51bd6d7fe4031 to your computer and use it in GitHub Desktop.
Generate a self signed root account-key assertion for snapd
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2021 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 main
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"time"
"github.com/snapcore/snapd/asserts"
"github.com/snapcore/snapd/asserts/sysdb"
"github.com/snapcore/snapd/osutil"
)
func main() {
// create a temporary directory to create our key in
dir, err := ioutil.TempDir("", "test-account-key")
if err != nil {
log.Fatalf("error creating temp dir: %v", err)
}
os.Setenv("SNAP_GNUPG_HOME", dir)
// now create a key with empty passphrase
manager := asserts.NewGPGKeypairManager()
if err := manager.Generate("", "default"); err != nil {
log.Fatalf("error generating new key: %v", err)
}
privKey, err := manager.GetByName("default")
if err != nil {
log.Fatalf("error getting default gpg key: %v", err)
}
db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
KeypairManager: asserts.NewMemoryKeypairManager(),
Backstore: asserts.NewMemoryBackstore(),
Trusted: sysdb.Trusted(),
})
if err != nil {
log.Fatalf("error opening database: %v", err)
}
// for signing itself, import the private key we just created
if err := db.ImportKey(privKey); err != nil {
log.Fatalf("error importing private signing key: %v", err)
}
headers := map[string]interface{}{
"account-id": "testrootrepair",
"name": "test-root-repair",
"since": time.Now().Format(time.RFC3339),
"authority-id": "testrootrepair",
"public-key-sha3-384": privKey.PublicKey().ID(),
}
// the public key is the body of the account key assertion
body, err := asserts.EncodePublicKey(privKey.PublicKey())
if err != nil {
log.Fatalf("error encoding public key of private key: %v", err)
}
// sign the assertion, using the ID of the public part of the private key
a, err := db.Sign(asserts.AccountKeyType, headers, body, privKey.PublicKey().ID())
if err != nil {
log.Fatalf("error signing account-key: %v", err)
}
// output the account-key assertion itself
fmt.Println(string(asserts.Encode(a)))
// also export the private key in ASCII so we can save that somewhere
out, err := exec.Command("gpg", "--homedir", dir, "--export-secret-key", "-a", "default").CombinedOutput()
if err != nil {
log.Fatalf("error exporting private ascii key: %v", osutil.OutputErr(out, err))
}
fmt.Println(string(out))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment