From 8d087d09547c1ed2712ce0ca0d75e3e1874e3221 Mon Sep 17 00:00:00 2001 From: Alakesh Haloi Date: Mon, 13 Sep 2021 16:52:27 -0700 Subject: [PATCH 1/9] Add linux kernel keyring based credential helper Implement kernel kerying based credential helper for storing and retrieving secrets. Signed-off-by: Alakesh Haloi Signed-off-by: Sebastiaan van Stijn --- Dockerfile | 4 + Makefile | 3 +- README.md | 3 + go.mod | 6 +- go.sum | 4 + keyctl/cmd/main.go | 10 + keyctl/keyctl.go | 250 +++++++++++++++ keyctl/keyctl_test.go | 74 +++++ vendor/github.com/jsipprell/keyctl/.gitignore | 2 + .../github.com/jsipprell/keyctl/.travis.yml | 17 ++ vendor/github.com/jsipprell/keyctl/LICENSE | 28 ++ vendor/github.com/jsipprell/keyctl/README.md | 70 +++++ vendor/github.com/jsipprell/keyctl/key.go | 81 +++++ vendor/github.com/jsipprell/keyctl/keyring.go | 190 ++++++++++++ vendor/github.com/jsipprell/keyctl/perms.go | 110 +++++++ vendor/github.com/jsipprell/keyctl/reader.go | 45 +++ vendor/github.com/jsipprell/keyctl/ref.go | 160 ++++++++++ .../github.com/jsipprell/keyctl/sys_linux.go | 288 ++++++++++++++++++ .../jsipprell/keyctl/sys_linux_386.go | 7 + .../jsipprell/keyctl/sys_linux_amd64.go | 7 + vendor/github.com/jsipprell/keyctl/writer.go | 70 +++++ vendor/github.com/pkg/errors/.gitignore | 24 ++ vendor/github.com/pkg/errors/.travis.yml | 10 + vendor/github.com/pkg/errors/LICENSE | 23 ++ vendor/github.com/pkg/errors/Makefile | 44 +++ vendor/github.com/pkg/errors/README.md | 59 ++++ vendor/github.com/pkg/errors/appveyor.yml | 32 ++ vendor/github.com/pkg/errors/errors.go | 288 ++++++++++++++++++ vendor/github.com/pkg/errors/go113.go | 38 +++ vendor/github.com/pkg/errors/stack.go | 177 +++++++++++ vendor/modules.txt | 6 + 31 files changed, 2128 insertions(+), 2 deletions(-) create mode 100644 keyctl/cmd/main.go create mode 100644 keyctl/keyctl.go create mode 100644 keyctl/keyctl_test.go create mode 100644 vendor/github.com/jsipprell/keyctl/.gitignore create mode 100644 vendor/github.com/jsipprell/keyctl/.travis.yml create mode 100644 vendor/github.com/jsipprell/keyctl/LICENSE create mode 100644 vendor/github.com/jsipprell/keyctl/README.md create mode 100644 vendor/github.com/jsipprell/keyctl/key.go create mode 100644 vendor/github.com/jsipprell/keyctl/keyring.go create mode 100644 vendor/github.com/jsipprell/keyctl/perms.go create mode 100644 vendor/github.com/jsipprell/keyctl/reader.go create mode 100644 vendor/github.com/jsipprell/keyctl/ref.go create mode 100644 vendor/github.com/jsipprell/keyctl/sys_linux.go create mode 100644 vendor/github.com/jsipprell/keyctl/sys_linux_386.go create mode 100644 vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go create mode 100644 vendor/github.com/jsipprell/keyctl/writer.go create mode 100644 vendor/github.com/pkg/errors/.gitignore create mode 100644 vendor/github.com/pkg/errors/.travis.yml create mode 100644 vendor/github.com/pkg/errors/LICENSE create mode 100644 vendor/github.com/pkg/errors/Makefile create mode 100644 vendor/github.com/pkg/errors/README.md create mode 100644 vendor/github.com/pkg/errors/appveyor.yml create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/go113.go create mode 100644 vendor/github.com/pkg/errors/stack.go diff --git a/Dockerfile b/Dockerfile index 06cfe40f..de5ef07a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -109,6 +109,10 @@ RUN --mount=type=bind,target=. \ make build-pass build-secretservice PACKAGE=$PACKAGE VERSION=$(cat /tmp/.version) REVISION=$(cat /tmp/.revision) DESTDIR=/out xx-verify /out/docker-credential-pass xx-verify /out/docker-credential-secretservice + + # keyctl credential helper + xx-go build -ldflags "$(cat /tmp/.ldflags)" -o /out/docker-credential-keyctl ./keyctl/cmd/ + xx-verify /out/docker-credential-keyctl EOT FROM base AS build-darwin diff --git a/Makefile b/Makefile index 9868445d..db5e4a3f 100644 --- a/Makefile +++ b/Makefile @@ -27,11 +27,12 @@ build-%: # build, can be one of build-osxkeychain build-pass build-secretservice go build -trimpath -ldflags="$(GO_LDFLAGS) -X ${GO_PKG}/credentials.Name=docker-credential-$*" -o "$(DESTDIR)/docker-credential-$*" ./$*/cmd/ # aliases for build-* targets -.PHONY: osxkeychain secretservice pass wincred +.PHONY: osxkeychain secretservice pass wincred keyctl osxkeychain: build-osxkeychain secretservice: build-secretservice pass: build-pass wincred: build-wincred +keyctl: build-keyctl .PHONY: cross cross: # cross build all supported credential helpers diff --git a/README.md b/README.md index 389542a7..1eb55e8a 100644 --- a/README.md +++ b/README.md @@ -84,12 +84,15 @@ You can see examples of each function in the [client](https://godoc.org/github.c 2. secretservice: Provides a helper to use the D-Bus secret service as credentials store. 3. wincred: Provides a helper to use Windows credentials manager as store. 4. pass: Provides a helper to use `pass` as credentials store. +5. keyctl: Provides a kernel keyring based helper as credential store. It is a purely non-file based credential store. #### Note `pass` needs to be configured for `docker-credential-pass` to work properly. It must be initialized with a `gpg2` key ID. Make sure your GPG key exists is in `gpg2` keyring as `pass` uses `gpg2` instead of the regular `gpg`. +`keyctl` does not need any configuration except that kernel should be compiled with CONFIG_KEYS enabled, which is default in most distro kernels. + ## Development A credential helper can be any program that can read values from the standard input. We use the first argument in the command line to differentiate the kind of command to execute. There are four valid values: diff --git a/go.mod b/go.mod index a8ec1cd8..f7bf2f85 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,10 @@ module github.com/docker/docker-credential-helpers go 1.19 -require github.com/danieljoos/wincred v1.2.1 +require ( + github.com/danieljoos/wincred v1.2.1 + github.com/jsipprell/keyctl v1.0.0 + github.com/pkg/errors v0.9.1 +) require golang.org/x/sys v0.15.0 // indirect diff --git a/go.sum b/go.sum index 58cccf26..e1b199fe 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/jsipprell/keyctl v1.0.0 h1:eMMJGk3UEsCXQegACLlfIjnfPlYHV61qfGXZ9/axBn4= +github.com/jsipprell/keyctl v1.0.0/go.mod h1:64s6WpBtruURX3w8W/vhWj1/uh+nOm7vUXSJlK5+KMs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= diff --git a/keyctl/cmd/main.go b/keyctl/cmd/main.go new file mode 100644 index 00000000..b0c161b2 --- /dev/null +++ b/keyctl/cmd/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/docker/docker-credential-helpers/credentials" + "github.com/docker/docker-credential-helpers/keyctl" +) + +func main() { + credentials.Serve(keyctl.Keyctl{}) +} diff --git a/keyctl/keyctl.go b/keyctl/keyctl.go new file mode 100644 index 00000000..d139e71f --- /dev/null +++ b/keyctl/keyctl.go @@ -0,0 +1,250 @@ +// Package keyctl implements a `keyctl` based credential helper. Passwords are stored +// in linux kernel keyring. +package keyctl + +import ( + "bytes" + "encoding/base64" + "fmt" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/docker/docker-credential-helpers/credentials" + "github.com/jsipprell/keyctl" + "github.com/pkg/errors" +) + +// Keyctl based credential helper looks for a default keyring inside +// session keyring. It does all operations inside the default keyring + +const defaultKeyringName string = "keyctlCredsStore" +const persistent int = 1 + +// Keyctl handles secrets using Linux Kernel keyring mechanism +type Keyctl struct{} + +func (k Keyctl) createDefaultPersistentKeyring() (string, error) { + /* Create default persistent keyring. If the keyring for the user + * already exists, then it returns the id of the existing keyring + */ + var errout, out bytes.Buffer + uid := os.Getuid() + cmd := exec.Command("keyctl", "get_persistent", "@u", strconv.Itoa(uid)) + cmd.Stderr = &errout + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return "", errors.Wrapf(err, "cannot run keyctl command to create persistent keyring %+v: %s", err, errout.String()) + } + persistentKeyringID := out.String() + if err != nil { + return "", errors.Wrapf(err, "cannot create or read persistent keyring %+v", err) + } + return persistentKeyringID, nil +} + +func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error) { + var out, errout bytes.Buffer + persistentKeyringID, err := k.createDefaultPersistentKeyring() + if err != nil { + return nil, errors.Wrap(err, "default persistent keyring cannot be created") + } + + defaultSessionKeyring, err := keyctl.SessionKeyring() + if err != nil { + return nil, errors.New("errors getting session keyring") + } + + defaultKeyring, err := keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) + /* if already does not exist we create */ + if err != nil || defaultKeyring == nil { + cmd := exec.Command("keyctl", "newring", defaultKeyringName, strings.TrimSuffix(persistentKeyringID, "\n")) + cmd.Stdout = &out + cmd.Stderr = &errout + err := cmd.Run() + if err != nil { + return nil, errors.Wrapf(err, "cannot run keyctl command to created credstore keyring %s %s %s", cmd.String(), errout.String(), out.String()) + } + } + /* Search for it again and return the default keyring*/ + defaultKeyring, err = keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) + if err != nil { + return nil, errors.Wrap(err, "failed to lookup default session keyring") + } + + return defaultKeyring, nil +} + +// getDefaultCredsStore is a helper function to get the default credsStore keyring +func (k Keyctl) getDefaultCredsStore() (keyctl.NamedKeyring, error) { + if persistent == 1 { + return k.getDefaultCredsStoreFromPersistent() + } + defaultSessionKeyring, err := keyctl.SessionKeyring() + if err != nil { + return nil, errors.Wrap(err, "error getting session keyring") + } + + defaultKeyring, err := keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) + if err != nil || defaultKeyring == nil { + if defaultKeyring == nil { + defaultKeyring, err = keyctl.CreateKeyring(defaultSessionKeyring, defaultKeyringName) + if err != nil { + return nil, errors.Wrap(err, "failed to create default credsStore keyring") + } + } + } + + if defaultKeyring == nil { + return nil, errors.Wrap(errors.New(""), " nil credstore") + } + + return defaultKeyring, nil +} + +// Add adds new credentials to the keychain. +func (k Keyctl) Add(creds *credentials.Credentials) error { + defaultKeyring, err := k.getDefaultCredsStore() + if err != nil || defaultKeyring == nil { + return errors.Wrapf(err, "failed to create credsStore entry for %s", creds.ServerURL) + } + + // create a child keyring under default for given url + encoded := base64.URLEncoding.EncodeToString([]byte(strings.TrimSuffix(creds.ServerURL, "\n"))) + urlKeyring, err := keyctl.CreateKeyring(defaultKeyring, encoded) + if err != nil { + return errors.Wrapf(err, "failed to create keyring for %s", creds.ServerURL) + } + + _, err = urlKeyring.Add(creds.Username, []byte(creds.Secret)) + if err != nil { + return errors.Wrapf(err, "failed to add creds to keryring for %s with error: %+v", creds.ServerURL, err) + } + return err +} + +// searchHelper function searches for an url inside the default keyring. +func (k Keyctl) searchHelper(serverURL string) (keyctl.NamedKeyring, string, error) { + defaultKeyring, err := k.getDefaultCredsStore() + if err != nil || defaultKeyring == nil { + return nil, "", fmt.Errorf("searchHelper failed: cannot read defaultCredsStore") + } + + encoded := base64.URLEncoding.EncodeToString([]byte(strings.TrimSuffix(serverURL, "\n"))) + urlKeyring, err := keyctl.OpenKeyring(defaultKeyring, encoded) + if err != nil { + return nil, "", fmt.Errorf("error in reading credsStore for url %s", serverURL) + } + if urlKeyring == nil { + return nil, "", fmt.Errorf("credsStore entry for suplied url %s not found", serverURL) + } + + refs, err := keyctl.ListKeyring(urlKeyring) + if err != nil { + return nil, "", fmt.Errorf("key for server url not found") + } + if len(refs) < 1 { + return nil, "", fmt.Errorf("no keys in keyring %s", urlKeyring.Name()) + } + + obj := refs[0] + id, err := obj.Get() + if err != nil { + return nil, "", fmt.Errorf("key for server url not found") + } + + info, err := id.Info() + if err != nil { + return nil, "", fmt.Errorf("cannot read info for url key") + } + + return urlKeyring, info.Name, err +} + +// Get returns the username and secret to use for a given registry server URL. +func (k Keyctl) Get(serverURL string) (string, string, error) { + if serverURL == "" { + return "", "", errors.New("missing server url") + } + + serverURL = strings.TrimSuffix(serverURL, "\n") + urlKeyring, searchData, err := k.searchHelper(serverURL) + if err != nil { + return "", "", errors.Wrapf(err, "url not found by searchHelper: %s err: %v", serverURL, err) + } + key, err := urlKeyring.Search(searchData) + if err != nil { + return "", "", errors.Wrapf(err, "url not found in %+v", urlKeyring) + } + secret, err := key.Get() + if err != nil { + return "", "", errors.Wrapf(err, "failed to read credentials for %s:%s", serverURL, searchData) + } + + return searchData, string(secret), nil +} + +// Delete removes credentials from the store. +func (k Keyctl) Delete(serverURL string) error { + serverURL = strings.TrimSuffix(serverURL, "\n") + urlKeyring, searchData, err := k.searchHelper(serverURL) + if err != nil { + return errors.Wrapf(err, "cannot find server url %s", serverURL) + } + + key, err := urlKeyring.Search(searchData) + if err != nil { + return err + } + + err = key.Unlink() + if err != nil { + return err + } + + refs, err := keyctl.ListKeyring(urlKeyring) + if err != nil { + fmt.Printf("cannot list keyring %s", urlKeyring.Name()) + } + if len(refs) == 0 { + keyctl.UnlinkKeyring(urlKeyring) + } else { + return errors.Wrapf(err, "Canot remove keyring as its not empty %s", urlKeyring.Name()) + } + + return err +} + +// List returns the stored URLs and corresponding usernames for a given credentials label +func (k Keyctl) List() (map[string]string, error) { + defaultKeyring, err := k.getDefaultCredsStore() + if err != nil || defaultKeyring == nil { + return nil, errors.Wrap(err, "List() failed: cannot read default credStore") + } + + resp := map[string]string{} + + refs, err := keyctl.ListKeyring(defaultKeyring) + if err != nil { + return nil, err + } + + for _, r := range refs { + id, _ := r.Get() + info, _ := id.Info() + url, _ := base64.URLEncoding.DecodeString(info.Name) + + key, _ := keyctl.OpenKeyring(defaultKeyring, info.Name) + innerRefs, _ := keyctl.ListKeyring(key) + + if len(innerRefs) < 1 { + continue + } + k, _ := innerRefs[0].Get() + i, _ := k.Info() + resp[string(url)] = i.Name + } + return resp, nil +} diff --git a/keyctl/keyctl_test.go b/keyctl/keyctl_test.go new file mode 100644 index 00000000..22505f8e --- /dev/null +++ b/keyctl/keyctl_test.go @@ -0,0 +1,74 @@ +package keyctl + +import ( + "strings" + "testing" + + "github.com/docker/docker-credential-helpers/credentials" + "github.com/pkg/errors" +) + +func TestKeyctlHelper(t *testing.T) { + helper := Keyctl{} + + // remove old stale values from previous failed run if any + credsList, err := helper.List() + if err != nil { + t.Fatal(err) + } + + for s, u := range credsList { + if strings.Contains(s, "amazonecr") || + strings.Contains(s, "docker") { + t.Logf("removing stale test entry for %s:%s", s, u) + helper.Delete(s) + } + } + + creds := &credentials.Credentials{ + ServerURL: "https://foobar.docker.io/v1:tag1", + Username: "nothing", + Secret: "mysecret", + } + helper.Add(creds) + + creds0 := &credentials.Credentials{ + ServerURL: "https://amazonecr.com/v1:tag2", + Username: "nothing0", + Secret: "mysecret0", + } + + creds1 := &credentials.Credentials{ + ServerURL: "https://foobar.docker1.io/v1:tag3", + Username: "nothing1", + Secret: "mysecret1", + } + helper.Add(creds) + helper.Add(creds0) + helper.Add(creds1) + + credsList, err = helper.List() + if err != nil { + t.Fatal(err) + } + + for s, u := range credsList { + if !strings.Contains(s, "amazonecr") && + !strings.Contains(s, "docker") { + t.Fatalf("unrecognized server name found Server: %s Username: %s ", s, u) + } + err = helper.Delete(s) + if err != nil { + errors.Wrapf(err, "error in deleting %s", s) + } + } + + /* Read the list of credentials again */ + credsList, err = helper.List() + if err != nil { + t.Fatal(err) + } + if len(credsList) != 0 { + t.Fatalf("didn't delete all creds? %d", len(credsList)) + } +} diff --git a/vendor/github.com/jsipprell/keyctl/.gitignore b/vendor/github.com/jsipprell/keyctl/.gitignore new file mode 100644 index 00000000..7605460d --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/.gitignore @@ -0,0 +1,2 @@ +c.out +coverage.html diff --git a/vendor/github.com/jsipprell/keyctl/.travis.yml b/vendor/github.com/jsipprell/keyctl/.travis.yml new file mode 100644 index 00000000..97b31165 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/.travis.yml @@ -0,0 +1,17 @@ +branches: + only: + - master +language: go +go: + - 1.4 + - 1.5 + - 1.6 + - tip +install: + - go get golang.org/x/crypto/openpgp + - go get golang.org/x/crypto/cast5 + - go get golang.org/x/crypto/ssh/terminal + - go get golang.org/x/tools/cmd/cover + - go build -v ./... +script: + - go test -v -cover diff --git a/vendor/github.com/jsipprell/keyctl/LICENSE b/vendor/github.com/jsipprell/keyctl/LICENSE new file mode 100644 index 00000000..98e6fd5c --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2015, Jesse Sipprell +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of keyctl nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/jsipprell/keyctl/README.md b/vendor/github.com/jsipprell/keyctl/README.md new file mode 100644 index 00000000..46040392 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/README.md @@ -0,0 +1,70 @@ +[![GoDoc](https://godoc.org/github.com/jsipprell/keyctl?status.svg)](https://godoc.org/github.com/jsipprell/keyctl) +[![Build Status](https://travis-ci.org/jsipprell/keyctl.svg?branch=master)](https://travis-ci.org/jsipprell/keyctl) + +# keyctl + +A native Go API for the security key management system (aka "keyrings") found in Linux 2.6+ + +The keyctl interface is nominally provided by three or so Linux-specific syscalls, however it is almost always wrapped +in a library named `libkeyutils.so`. + +This package interacts directly with the syscall interface and does not require CGO for linkage to the helper library +provided on most systems. + +## Example Usages + +To access the default session keyring (and create it if it doesn't exist) + + +```go +package main + +import ( + "log" + "github.com/jsipprell/keyctl" +) + +func main() { + keyring, err := keyctl.SessionKeyring() + if err != nil { + log.Fatal(err) + } + + // default timeout of 10 seconds for new or updated keys + keyring.SetDefaultTimeout(10) + secureData := []byte{1,2,3,4} + id, err := keyring.Add("some-data", secureData) + if err != nil { + log.Fatal(err) + } + log.Printf("created session key id %v", id) +} +``` + +To search for an existing key by name: + +```go +package main + +import ( + "log" + "github.com/jsipprell/keyctl" +) + +func main() { + keyring, err := keyctl.SessionKeyring() + if err != nil { + log.Fatal(err) + } + key, err := keyring.Search("some-data") + if err != nil { + log.Fatal(err) + } + + data, err := key.Get() + if err != nil { + log.Fatal(err) + } + log.Printf("secure data: %v\n", data) +} +``` diff --git a/vendor/github.com/jsipprell/keyctl/key.go b/vendor/github.com/jsipprell/keyctl/key.go new file mode 100644 index 00000000..7d03c0ca --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/key.go @@ -0,0 +1,81 @@ +package keyctl + +import ( + "time" +) + +// Represents a single key linked to one or more kernel keyrings. +type Key struct { + Name string + + id, ring keyId + size int + ttl time.Duration +} + +func (k *Key) private() {} + +// Returns the 32-bit kernel identifier for a specific key +func (k *Key) Id() int32 { + return int32(k.id) +} + +// To expire a key automatically after some period of time call this method. +func (k *Key) ExpireAfter(nsecs uint) error { + k.ttl = time.Duration(nsecs) * time.Second + + return keyctl_SetTimeout(k.id, nsecs) +} + +// Return information about a key. +func (k *Key) Info() (Info, error) { + return getInfo(k.id) +} + +// Get the key's value as a byte slice +func (k *Key) Get() ([]byte, error) { + var ( + b []byte + err error + sizeRead int + ) + + if k.size == 0 { + k.size = 512 + } + + size := k.size + + b = make([]byte, int(size)) + sizeRead = size + 1 + for sizeRead > size { + r1, err := keyctl_Read(k.id, &b[0], size) + if err != nil { + return nil, err + } + + if sizeRead = int(r1); sizeRead > size { + b = make([]byte, sizeRead) + size = sizeRead + sizeRead = size + 1 + } else { + k.size = sizeRead + } + } + return b[:k.size], err +} + +// Set the key's value from a bytes slice. Expiration, if active, is reset by calling this method. +func (k *Key) Set(b []byte) error { + err := updateKey(k.id, b) + if err == nil && k.ttl > 0 { + err = k.ExpireAfter(uint(k.ttl.Seconds())) + } + return err +} + +// Unlink a key from the keyring it was loaded from (or added to). If the key +// is not linked to any other keyrings, it is destroyed. +func (k *Key) Unlink() error { + return keyctl_Unlink(k.id, k.ring) +} diff --git a/vendor/github.com/jsipprell/keyctl/keyring.go b/vendor/github.com/jsipprell/keyctl/keyring.go new file mode 100644 index 00000000..78966947 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/keyring.go @@ -0,0 +1,190 @@ +// Copyright 2015 Jesse Sipprell. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux + +// A Go interface to linux kernel keyrings (keyctl interface) +package keyctl + +// All Keys and Keyrings have unique 32-bit serial number identifiers. +type Id interface { + Id() int32 + Info() (Info, error) + + private() +} + +// Basic interface to a linux keyctl keyring. +type Keyring interface { + Id + Add(string, []byte) (*Key, error) + Search(string) (*Key, error) + SetDefaultTimeout(uint) +} + +// Named keyrings are user-created keyrings linked to a parent keyring. The +// parent can be either named or one of the in-built keyrings (session, group +// etc). The in-built keyrings have no parents. Keyring searching is performed +// hierarchically. +type NamedKeyring interface { + Keyring + Name() string +} + +type keyring struct { + id keyId + defaultTtl uint +} + +type namedKeyring struct { + *keyring + parent keyId + name string // for non-anonymous keyrings + ttl uint +} + +func (kr *keyring) private() {} + +// Returns the 32-bit kernel identifier of a keyring +func (kr *keyring) Id() int32 { + return int32(kr.id) +} + +// Returns information about a keyring. +func (kr *keyring) Info() (Info, error) { + return getInfo(kr.id) +} + +// Return the name of a NamedKeyring that was set when the keyring was created +// or opened. +func (kr *namedKeyring) Name() string { + return kr.name +} + +// Set a default timeout, in seconds, after which newly added keys will be +// destroyed. +func (kr *keyring) SetDefaultTimeout(nsecs uint) { + kr.defaultTtl = nsecs +} + +// Add a new key to a keyring. The key can be searched for later by name. +func (kr *keyring) Add(name string, key []byte) (*Key, error) { + r, err := add_key("user", name, key, int32(kr.id)) + if err == nil { + key := &Key{Name: name, id: keyId(r), ring: kr.id} + if kr.defaultTtl != 0 { + err = key.ExpireAfter(kr.defaultTtl) + } + return key, err + } + + return nil, err +} + +// Search for a key by name, this also searches child keyrings linked to this +// one. The key, if found, is linked to the top keyring that Search() was called +// from. +func (kr *keyring) Search(name string) (*Key, error) { + id, err := searchKeyring(kr.id, name, "user") + if err == nil { + return &Key{Name: name, id: id, ring: kr.id}, nil + } + return nil, err +} + +// Return the current login session keyring +func SessionKeyring() (Keyring, error) { + return newKeyring(keySpecSessionKeyring) +} + +// Return the current user-session keyring (part of session, but private to +// current user) +func UserSessionKeyring() (Keyring, error) { + return newKeyring(keySpecUserSessionKeyring) +} + +// Return the current group keyring. +func GroupKeyring() (Keyring, error) { + return newKeyring(keySpecGroupKeyring) +} + +// Return the keyring specific to the current executing thread. +func ThreadKeyring() (Keyring, error) { + return newKeyring(keySpecThreadKeyring) +} + +// Return the keyring specific to the current executing process. +func ProcessKeyring() (Keyring, error) { + return newKeyring(keySpecProcessKeyring) +} + +// Creates a new named-keyring linked to a parent keyring. The parent may be +// one of those returned by SessionKeyring(), UserSessionKeyring() and friends +// or it may be an existing named-keyring. When searching is performed, all +// keyrings form a hierarchy and are searched top-down. If the keyring already +// exists it will be destroyed and a new one with the same name created. Named +// sub-keyrings inherit their initial ttl (if set) from the parent but can +// outlive the parent as the timer is restarted at creation. +func CreateKeyring(parent Keyring, name string) (NamedKeyring, error) { + var ttl uint + + parentId := keyId(parent.Id()) + kr, err := createKeyring(parentId, name) + if err != nil { + return nil, err + } + + if pkr, ok := parent.(*namedKeyring); ok { + ttl = pkr.ttl + } + ring := &namedKeyring{ + keyring: kr, + parent: parentId, + name: name, + ttl: ttl, + } + + if ttl > 0 { + err = keyctl_SetTimeout(ring.id, ttl) + } + + return ring, nil +} + +// Search for and open an existing keyring with the given name linked to a +// parent keyring (at any depth). +func OpenKeyring(parent Keyring, name string) (NamedKeyring, error) { + parentId := keyId(parent.Id()) + id, err := searchKeyring(parentId, name, "keyring") + if err != nil { + return nil, err + } + + return &namedKeyring{ + keyring: &keyring{id: id}, + parent: parentId, + name: name, + }, nil +} + +// Set the time to live in seconds for an entire keyring and all of its keys. +// Only named keyrings can have their time-to-live set, the in-built keyrings +// cannot (Session, UserSession, etc). +func SetKeyringTTL(kr NamedKeyring, nsecs uint) error { + err := keyctl_SetTimeout(keyId(kr.Id()), nsecs) + if err == nil { + kr.(*namedKeyring).ttl = nsecs + } + return err +} + +// Unlink an object from a keyring +func Unlink(parent Keyring, child Id) error { + return keyctl_Unlink(keyId(parent.Id()), keyId(child.Id())) +} + +// Unlink a named keyring from its parent. +func UnlinkKeyring(kr NamedKeyring) error { + return keyctl_Unlink(keyId(kr.Id()), kr.(*namedKeyring).parent) +} diff --git a/vendor/github.com/jsipprell/keyctl/perms.go b/vendor/github.com/jsipprell/keyctl/perms.go new file mode 100644 index 00000000..41138203 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/perms.go @@ -0,0 +1,110 @@ +package keyctl + +// KeyPerm represents in-kernel access control permission to keys and keyrings +// as a 32-bit integer broken up into four permission sets, one per byte. +// In MSB order, the perms are: Processor, User, Group, Other. +type KeyPerm uint32 + +const ( + PermOtherView KeyPerm = 1 << iota + PermOtherRead + PermOtherWrite + PermOtherSearch + PermOtherLink + PermOtherSetattr +) + +const ( + PermGroupView KeyPerm = 1 << (8 + iota) + PermGroupRead + PermGroupWrite + PermGroupSearch + PermGroupLink + PermGroupSetattr +) + +const ( + PermUserView KeyPerm = 1 << (16 + iota) + PermUserRead + PermUserWrite + PermUserSearch + PermUserLink + PermUserSetattr +) + +const ( + PermProcessView KeyPerm = 1 << (24 + iota) + PermProcessRead + PermProcessWrite + PermProcessSearch + PermProcessLink + PermProcessSetattr +) + +const ( + PermOtherAll KeyPerm = 0x3f << (8 * iota) + PermGroupAll + PermUserAll + PermProcessAll +) + +var permsChars = []byte("--alswrv") + +func encodePerms(p uint8) string { + l := uint(len(permsChars)) + out := make([]byte, l) + + l-- + for i, c := range permsChars { + if p&(1<<(l-uint(i))) == 0 { + out[i] = '-' + } else { + out[i] = c + } + } + + return string(out) +} + +// Returns processor permissions in symbolic form +func (p KeyPerm) Process() string { + return encodePerms(uint8(uint(p) >> 24)) +} + +// Returns the group permissions in symbolic form +func (p KeyPerm) Group() string { + return encodePerms(uint8(uint(p) >> 8)) +} + +// Returns the user permissions in symbolic form +func (p KeyPerm) User() string { + return encodePerms(uint8(uint(p) >> 16)) +} + +// Returns other (default) permissions in symbolic form +func (p KeyPerm) Other() string { + return encodePerms(uint8(p)) +} + +func (p KeyPerm) String() string { + return p.Process()[2:] + p.User()[2:] + p.Group()[2:] + p.Other()[2:] +} + +// Change user ownership on a key or keyring. +func Chown(k Id, user int) error { + group := -1 + + return keyctl_Chown(keyId(k.Id()), user, group) +} + +// Change group ownership on a key or keyring. +func Chgrp(k Id, group int) error { + user := -1 + + return keyctl_Chown(keyId(k.Id()), user, group) +} + +// Set permissions on a key or keyring. +func SetPerm(k Id, p KeyPerm) error { + return keyctl_SetPerm(keyId(k.Id()), uint32(p)) +} diff --git a/vendor/github.com/jsipprell/keyctl/reader.go b/vendor/github.com/jsipprell/keyctl/reader.go new file mode 100644 index 00000000..c4213d17 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/reader.go @@ -0,0 +1,45 @@ +package keyctl + +import ( + "bytes" + "io" + "sync" +) + +type reader struct { + *bytes.Buffer + key *Key + err error + once sync.Once +} + +func (r *reader) Read(b []byte) (int, error) { + r.once.Do(func() { + buf, err := r.key.Get() + if err != nil { + r.err = err + } else { + r.Buffer = bytes.NewBuffer(buf) + } + }) + if r.err != nil { + return -1, r.err + } + + return r.Buffer.Read(b) +} + +// Returns an io.Reader interface object which will read the key's data from +// the kernel. +func NewReader(key *Key) io.Reader { + return &reader{key: key} +} + +// Open an existing key on a keyring given its name +func OpenReader(name string, ring Keyring) (io.Reader, error) { + key, err := ring.Search(name) + if err == nil { + return NewReader(key), nil + } + return nil, err +} diff --git a/vendor/github.com/jsipprell/keyctl/ref.go b/vendor/github.com/jsipprell/keyctl/ref.go new file mode 100644 index 00000000..6eb00562 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/ref.go @@ -0,0 +1,160 @@ +package keyctl + +import ( + "bytes" + "errors" + "os" + "strconv" +) + +var ( + // Error returned if the Get() method is called on a Reference that doesn't + // represent a key or keychain. + ErrUnsupportedKeyType = errors.New("unsupported keyctl key type") + // Error returned if a reference is stale when Info() or Get() is called on + // it. + ErrInvalidReference = errors.New("invalid keyctl reference") +) + +// Reference is a reference to an unloaded keyctl Key or Keychain. It can be +// dereferenced by calling the Get() method. +type Reference struct { + // Id is the kernel key or keychain identifier referenced. + Id int32 + + info *Info + parent keyId +} + +// Information about a keyctl reference as returned by ref.Info() +type Info struct { + Type, Name string + Uid, Gid int + Perm KeyPerm + + valid bool +} + +func getInfo(id keyId) (i Info, err error) { + var desc []byte + + if desc, err = describeKeyId(id); err != nil { + i.Name = err.Error() + return + } + + fields := bytes.Split(desc, []byte{';'}) + switch len(fields) { + case 5: + i.Name = string(fields[4]) + fallthrough + case 4: + p, _ := strconv.ParseUint(string(fields[3]), 16, 32) + i.Perm = KeyPerm(p) + fallthrough + case 3: + i.Gid, _ = strconv.Atoi(string(fields[2])) + fallthrough + case 2: + i.Uid, _ = strconv.Atoi(string(fields[1])) + fallthrough + case 1: + if i.Type = string(fields[0]); i.Type == "user" { + i.Type = "key" + } + i.valid = true + default: + panic("invalid field count from kernel keyctl describe sysctl") + } + return +} + +// Returns permissions in symbolic format. +func (i Info) Permissions() string { + if i.Uid == os.Geteuid() { + return encodePerms(uint8(i.Perm >> KeyPerm(16))) + } else { + fsgid, err := getfsgid() + if (err == nil && i.Gid == int(fsgid)) || i.Gid == os.Getegid() { + return encodePerms(uint8(i.Perm >> KeyPerm(8))) + } + } + return encodePerms(uint8(i.Perm)) +} + +// Return Information about a keyctl reference. +func (r *Reference) Info() (i Info, err error) { + if r.info == nil { + i, err = getInfo(keyId(r.Id)) + r.info = &i + return + } + + return *r.info, err +} + +// Returns true if the Info fetched by ref.Info() is valid. +func (i Info) Valid() bool { + return i.valid +} + +// Returns true if the keyctl reference is valid. Refererences can become +// invalid if they have expired since the reference was created. +func (r *Reference) Valid() bool { + if r.info == nil { + r.Info() + } + return r.info.valid +} + +// Loads the referenced keyctl object, which must either be a key or a +// keyring otherwise ErrUnsupportedKeyType will be returned. +func (r *Reference) Get() (Id, error) { + if r.info == nil { + _, err := r.Info() + if err != nil { + return nil, err + } + } + + if !r.info.valid { + return nil, ErrInvalidReference + } + + switch r.info.Type { + case "key": + return &Key{Name: r.info.Name, id: keyId(r.Id), ring: r.parent}, nil + case "keyring": + ring := &keyring{id: keyId(r.Id)} + if r.Id > 0 && r.info.Name != "" { + return &namedKeyring{ + keyring: ring, + parent: r.parent, + name: r.info.Name, + }, nil + } + return ring, nil + default: + return nil, ErrUnsupportedKeyType + } +} + +// List the contents of a keyring. Each contained object is represented by a +// Reference struct. Addl information is available by calling ref.Info(), and +// contained objects which are keys or subordinate keyrings can be fetched by +// calling ref.Get() +func ListKeyring(kr Keyring) ([]Reference, error) { + id := keyId(kr.Id()) + keys, err := listKeys(id) + if err != nil { + return nil, err + } + + refs := make([]Reference, len(keys)) + + for i, k := range keys { + refs[i].Id, refs[i].parent = int32(k), id + } + + return refs, nil +} diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux.go b/vendor/github.com/jsipprell/keyctl/sys_linux.go new file mode 100644 index 00000000..85383b4a --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux.go @@ -0,0 +1,288 @@ +package keyctl + +import ( + "syscall" + "unsafe" +) + +type keyctlCommand int + +type keyId int32 + +const ( + keySpecThreadKeyring keyId = -1 + keySpecProcessKeyring keyId = -2 + keySpecSessionKeyring keyId = -3 + keySpecUserKeyring keyId = -4 + keySpecUserSessionKeyring keyId = -5 + keySpecGroupKeyring keyId = -6 + keySpecReqKeyAuthKey keyId = -7 +) + +const ( + keyctlGetKeyringId keyctlCommand = iota + keyctlJoinSessionKeyring + keyctlUpdate + keyctlRevoke + keyctlChown + keyctlSetPerm + keyctlDescribe + keyctlClear + keyctlLink + keyctlUnlink + keyctlSearch + keyctlRead + keyctlInstantiate + keyctlNegate + keyctlSetReqKeyKeyring + keyctlSetTimeout + keyctlAssumeAuthority +) + +var debugSyscalls bool + +func (id keyId) Id() int32 { + return int32(id) +} + +func (cmd keyctlCommand) String() string { + switch cmd { + case keyctlGetKeyringId: + return "keyctlGetKeyringId" + case keyctlJoinSessionKeyring: + return "keyctlJoinSessionKeyring" + case keyctlUpdate: + return "keyctlUpdate" + case keyctlRevoke: + return "keyctlRevoke" + case keyctlChown: + return "keyctlChown" + case keyctlSetPerm: + return "keyctlSetPerm" + case keyctlDescribe: + return "keyctlDescribe" + case keyctlClear: + return "keyctlClear" + case keyctlLink: + return "keyctlLink" + case keyctlUnlink: + return "keyctlUnlink" + case keyctlSearch: + return "keyctlSearch" + case keyctlRead: + return "keyctlRead" + case keyctlInstantiate: + return "keyctlInstantiate" + case keyctlNegate: + return "keyctlNegate" + case keyctlSetReqKeyKeyring: + return "keyctlSetReqKeyKeyring" + case keyctlSetTimeout: + return "keyctlSetTimeout" + case keyctlAssumeAuthority: + return "keyctlAssumeAuthority" + } + panic("bad arg") +} + +func keyctl_SetTimeout(id keyId, nsecs uint) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlSetTimeout), uintptr(id), uintptr(nsecs)) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_Read(id keyId, b *byte, size int) (int32, error) { + v1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlRead), uintptr(id), uintptr(unsafe.Pointer(b)), uintptr(size), 0, 0) + if errno != 0 { + return -1, errno + } + + return int32(v1), nil +} + +func keyctl_Unlink(id, ring keyId) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlUnlink), uintptr(id), uintptr(ring)) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_Chown(id keyId, user, group int) error { + _, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlChown), uintptr(id), uintptr(user), uintptr(group), 0, 0) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_SetPerm(id keyId, perm uint32) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlSetPerm), uintptr(id), uintptr(perm)) + if errno != 0 { + return errno + } + return nil +} + +func add_key(keyType, keyDesc string, payload []byte, id int32) (int32, error) { + var ( + err error + errno syscall.Errno + b1, b2 *byte + r1 uintptr + pptr unsafe.Pointer + ) + + if b1, err = syscall.BytePtrFromString(keyType); err != nil { + return 0, err + } + + if b2, err = syscall.BytePtrFromString(keyDesc); err != nil { + return 0, err + } + + if len(payload) > 0 { + pptr = unsafe.Pointer(&payload[0]) + } + r1, _, errno = syscall.Syscall6(syscall_add_key, + uintptr(unsafe.Pointer(b1)), + uintptr(unsafe.Pointer(b2)), + uintptr(pptr), + uintptr(len(payload)), + uintptr(id), + 0) + + if errno != 0 { + err = errno + return 0, err + } + return int32(r1), nil +} + +func getfsgid() (int32, error) { + var ( + a1 int32 + err error + errno syscall.Errno + r1 uintptr + ) + + a1 = -1 + if r1, _, errno = syscall.Syscall(syscall_setfsgid, uintptr(a1), 0, 0); errno != 0 { + err = errno + return int32(-1), err + } + return int32(r1), nil +} + +func newKeyring(id keyId) (*keyring, error) { + r1, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlGetKeyringId), uintptr(id), uintptr(1)) + if errno != 0 { + return nil, errno + } + + if id >= 0 { + id = keyId(r1) + } + return &keyring{id: id}, nil +} + +func createKeyring(parent keyId, name string) (*keyring, error) { + id, err := add_key("keyring", name, nil, int32(parent)) + if err != nil { + return nil, err + } + + return &keyring{id: keyId(id)}, nil +} + +func searchKeyring(id keyId, name, keyType string) (keyId, error) { + var ( + b1, b2 *byte + err error + ) + + if b1, err = syscall.BytePtrFromString(keyType); err != nil { + return 0, err + } + if b2, err = syscall.BytePtrFromString(name); err != nil { + return 0, err + } + r1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlSearch), uintptr(id), uintptr(unsafe.Pointer(b1)), uintptr(unsafe.Pointer(b2)), 0, 0) + if errno != 0 { + err = errno + } + return keyId(r1), err +} + +func describeKeyId(id keyId) ([]byte, error) { + var ( + b1 []byte + size, sizeRead int + ) + + b1 = make([]byte, 64) + size = len(b1) + sizeRead = size + 1 + for sizeRead > size { + r1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlDescribe), uintptr(id), uintptr(unsafe.Pointer(&b1[0])), uintptr(size), 0, 0) + if errno != 0 { + return nil, errno + } + if sizeRead = int(r1); sizeRead > size { + b1 = make([]byte, sizeRead) + size = sizeRead + sizeRead++ + } else { + size = sizeRead + } + } + + return b1[:size-1], nil +} + +func listKeys(id keyId) ([]keyId, error) { + var ( + b1 []byte + size, sizeRead int + ) + + bsz := 4 + b1 = make([]byte, 16*bsz) + size = len(b1) + sizeRead = size + 1 + for sizeRead > size { + r1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlRead), uintptr(id), uintptr(unsafe.Pointer(&b1[0])), uintptr(size), 0, 0) + if errno != 0 { + return nil, errno + } + + if sizeRead = int(r1); sizeRead > size { + b1 = make([]byte, sizeRead) + size = sizeRead + sizeRead++ + } else { + size = sizeRead + } + } + keys := make([]keyId, size/bsz) + for i := range keys { + keys[i] = *((*keyId)(unsafe.Pointer(&b1[i*bsz]))) + } + + return keys, nil +} + +func updateKey(id keyId, payload []byte) error { + size := len(payload) + if size == 0 { + payload = make([]byte, 1) + } + _, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlUpdate), uintptr(id), uintptr(unsafe.Pointer(&payload[0])), uintptr(size), 0, 0) + if errno != 0 { + return errno + } + return nil +} diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux_386.go b/vendor/github.com/jsipprell/keyctl/sys_linux_386.go new file mode 100644 index 00000000..0442bee5 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux_386.go @@ -0,0 +1,7 @@ +package keyctl + +const ( + syscall_keyctl uintptr = 288 + syscall_add_key uintptr = 286 + syscall_setfsgid uintptr = 139 +) diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go b/vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go new file mode 100644 index 00000000..f36f316b --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go @@ -0,0 +1,7 @@ +package keyctl + +const ( + syscall_keyctl uintptr = 250 + syscall_add_key uintptr = 248 + syscall_setfsgid uintptr = 123 +) diff --git a/vendor/github.com/jsipprell/keyctl/writer.go b/vendor/github.com/jsipprell/keyctl/writer.go new file mode 100644 index 00000000..35736889 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/writer.go @@ -0,0 +1,70 @@ +package keyctl + +import ( + "bytes" + "errors" + "io" +) + +type Flusher interface { + io.Writer + io.Closer + Flush() error +} + +// Error returned when attempting to close or flush an already closed stream +var ErrStreamClosed = errors.New("keyctl write stream closed") + +type writer struct { + *bytes.Buffer + key Id + name string + closed bool +} + +// Close a stream writer. *This or Flush() MUST be called in order to flush +// the key value to the kernel. +func (w *writer) Close() error { + if !w.closed { + defer setClosed(w) + return w.Flush() + } + return ErrStreamClosed +} + +// Flush the current stream writer buffer key data to the kernel. New writes +// after this will need to be re-flushed or have Close() called. +func (w *writer) Flush() (err error) { + if !w.closed { + switch t := w.key.(type) { + case Keyring: + var key Id + key, err = t.Add(w.name, w.Bytes()) + if err == nil { + w.key = key + } + case *Key: + err = updateKey(t.id, w.Bytes()) + if err == nil && t.ttl != 0 { + err = t.ExpireAfter(uint(t.ttl.Seconds())) + } + } + return + } + return ErrStreamClosed +} + +func setClosed(w *writer) { + w.closed = true +} + +// Create a new stream writer to write key data to. The writer MUST Close() or +// Flush() the stream before the data will be flushed to the kernel. +func NewWriter(key *Key) Flusher { + return &writer{Buffer: bytes.NewBuffer(make([]byte, 0, 1024)), key: key} +} + +// Create a new key and stream writer with a given name on an open keyring. +func CreateWriter(name string, ring Keyring) (Flusher, error) { + return &writer{Buffer: bytes.NewBuffer(make([]byte, 0, 1024)), key: ring, name: name}, nil +} diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/pkg/errors/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml new file mode 100644 index 00000000..9159de03 --- /dev/null +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -0,0 +1,10 @@ +language: go +go_import_path: github.com/pkg/errors +go: + - 1.11.x + - 1.12.x + - 1.13.x + - tip + +script: + - make check diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE new file mode 100644 index 00000000..835ba3e7 --- /dev/null +++ b/vendor/github.com/pkg/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile new file mode 100644 index 00000000..ce9d7cde --- /dev/null +++ b/vendor/github.com/pkg/errors/Makefile @@ -0,0 +1,44 @@ +PKGS := github.com/pkg/errors +SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) +GO := go + +check: test vet gofmt misspell unconvert staticcheck ineffassign unparam + +test: + $(GO) test $(PKGS) + +vet: | test + $(GO) vet $(PKGS) + +staticcheck: + $(GO) get honnef.co/go/tools/cmd/staticcheck + staticcheck -checks all $(PKGS) + +misspell: + $(GO) get github.com/client9/misspell/cmd/misspell + misspell \ + -locale GB \ + -error \ + *.md *.go + +unconvert: + $(GO) get github.com/mdempsky/unconvert + unconvert -v $(PKGS) + +ineffassign: + $(GO) get github.com/gordonklaus/ineffassign + find $(SRCDIRS) -name '*.go' | xargs ineffassign + +pedantic: check errcheck + +unparam: + $(GO) get mvdan.cc/unparam + unparam ./... + +errcheck: + $(GO) get github.com/kisielk/errcheck + errcheck $(PKGS) + +gofmt: + @echo Checking code is gofmted + @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 00000000..54dfdcb1 --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,59 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Roadmap + +With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: + +- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) +- 1.0. Final release. + +## Contributing + +Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. + +Before sending a PR, please discuss your change by raising an issue. + +## License + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 00000000..a932eade --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go new file mode 100644 index 00000000..161aea25 --- /dev/null +++ b/vendor/github.com/pkg/errors/errors.go @@ -0,0 +1,288 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which when applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Wrap function returns a new error that adds context to the +// original error by recording a stack trace at the point Wrap is called, +// together with the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Wrap(err, "read failed") +// } +// +// If additional control is required, the errors.WithStack and +// errors.WithMessage functions destructure errors.Wrap into its component +// operations: annotating an error with a stack trace and with a message, +// respectively. +// +// Retrieving the cause of an error +// +// Using errors.Wrap constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Wrap to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error that does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// Although the causer interface is not exported by this package, it is +// considered a part of its stable public interface. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported: +// +// %s print the error. If the error has a Cause it will be +// printed recursively. +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are +// invoked. This information can be retrieved with the following interface: +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// The returned errors.StackTrace type is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if err, ok := err.(stackTracer); ok { +// for _, f := range err.StackTrace() { +// fmt.Printf("%+s:%d\n", f, f) +// } +// } +// +// Although the stackTracer interface is not exported by this package, it is +// considered a part of its stable public interface. +// +// See the documentation for Frame.Format for more details. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil + } + return &withStack{ + err, + callers(), + } +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withStack) Unwrap() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is called, and the format specifier. +// If err is nil, Wrapf returns nil. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +// WithMessagef annotates err with the format specifier. +// If err is nil, WithMessagef returns nil. +func WithMessagef(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withMessage) Unwrap() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go new file mode 100644 index 00000000..be0d10d0 --- /dev/null +++ b/vendor/github.com/pkg/errors/go113.go @@ -0,0 +1,38 @@ +// +build go1.13 + +package errors + +import ( + stderrors "errors" +) + +// Is reports whether any error in err's chain matches target. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error is considered to match a target if it is equal to that target or if +// it implements a method Is(error) bool such that Is(target) returns true. +func Is(err, target error) bool { return stderrors.Is(err, target) } + +// As finds the first error in err's chain that matches target, and if so, sets +// target to that error value and returns true. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error matches target if the error's concrete value is assignable to the value +// pointed to by target, or if the error has a method As(interface{}) bool such that +// As(target) returns true. In the latter case, the As method is responsible for +// setting target. +// +// As will panic if target is not a non-nil pointer to either a type that implements +// error, or to any interface type. As returns false if err is nil. +func As(err error, target interface{}) bool { return stderrors.As(err, target) } + +// Unwrap returns the result of calling the Unwrap method on err, if err's +// type contains an Unwrap method returning error. +// Otherwise, Unwrap returns nil. +func Unwrap(err error) error { + return stderrors.Unwrap(err) +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go new file mode 100644 index 00000000..779a8348 --- /dev/null +++ b/vendor/github.com/pkg/errors/stack.go @@ -0,0 +1,177 @@ +package errors + +import ( + "fmt" + "io" + "path" + "runtime" + "strconv" + "strings" +) + +// Frame represents a program counter inside a stack frame. +// For historical reasons if Frame is interpreted as a uintptr +// its value represents the program counter + 1. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// name returns the name of this function, if known. +func (f Frame) name() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + return fn.Name() +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s function name and path of source file relative to the compile time +// GOPATH separated by \n\t (\n\t) +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + switch verb { + case 's': + switch { + case s.Flag('+'): + io.WriteString(s, f.name()) + io.WriteString(s, "\n\t") + io.WriteString(s, f.file()) + default: + io.WriteString(s, path.Base(f.file())) + } + case 'd': + io.WriteString(s, strconv.Itoa(f.line())) + case 'n': + io.WriteString(s, funcname(f.name())) + case 'v': + f.Format(s, 's') + io.WriteString(s, ":") + f.Format(s, 'd') + } +} + +// MarshalText formats a stacktrace Frame as a text string. The output is the +// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. +func (f Frame) MarshalText() ([]byte, error) { + name := f.name() + if name == "unknown" { + return []byte(name), nil + } + return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +// Format formats the stack of Frames according to the fmt.Formatter interface. +// +// %s lists source files for each Frame in the stack +// %v lists the source file and line number for each Frame in the stack +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+v Prints filename, function, and line number for each Frame in the stack. +func (st StackTrace) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case s.Flag('+'): + for _, f := range st { + io.WriteString(s, "\n") + f.Format(s, verb) + } + case s.Flag('#'): + fmt.Fprintf(s, "%#v", []Frame(st)) + default: + st.formatSlice(s, verb) + } + case 's': + st.formatSlice(s, verb) + } +} + +// formatSlice will format this StackTrace into the given buffer as a slice of +// Frame, only valid when called with '%s' or '%v'. +func (st StackTrace) formatSlice(s fmt.State, verb rune) { + io.WriteString(s, "[") + for i, f := range st { + if i > 0 { + io.WriteString(s, " ") + } + f.Format(s, verb) + } + io.WriteString(s, "]") +} + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 20b4760a..491d354c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,6 +1,12 @@ # github.com/danieljoos/wincred v1.2.1 ## explicit; go 1.18 github.com/danieljoos/wincred +# github.com/jsipprell/keyctl v1.0.0 +## explicit +github.com/jsipprell/keyctl +# github.com/pkg/errors v0.9.1 +## explicit +github.com/pkg/errors # golang.org/x/sys v0.15.0 ## explicit; go 1.18 golang.org/x/sys/windows From 0ef4c73bd998e576a49203fcb07afc82e82ea1a8 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 21 Aug 2022 17:05:23 +0200 Subject: [PATCH 2/9] remove uses of pkg/errors While pkg/errors is a great package, it's probably not needed for how it's used in this project, so let's replace with Go's native error wrapping. Signed-off-by: Sebastiaan van Stijn --- go.mod | 1 - go.sum | 2 - keyctl/keyctl.go | 58 +++-- keyctl/keyctl_test.go | 4 +- vendor/github.com/pkg/errors/.gitignore | 24 -- vendor/github.com/pkg/errors/.travis.yml | 10 - vendor/github.com/pkg/errors/LICENSE | 23 -- vendor/github.com/pkg/errors/Makefile | 44 ---- vendor/github.com/pkg/errors/README.md | 59 ----- vendor/github.com/pkg/errors/appveyor.yml | 32 --- vendor/github.com/pkg/errors/errors.go | 288 ---------------------- vendor/github.com/pkg/errors/go113.go | 38 --- vendor/github.com/pkg/errors/stack.go | 177 ------------- vendor/modules.txt | 3 - 14 files changed, 34 insertions(+), 729 deletions(-) delete mode 100644 vendor/github.com/pkg/errors/.gitignore delete mode 100644 vendor/github.com/pkg/errors/.travis.yml delete mode 100644 vendor/github.com/pkg/errors/LICENSE delete mode 100644 vendor/github.com/pkg/errors/Makefile delete mode 100644 vendor/github.com/pkg/errors/README.md delete mode 100644 vendor/github.com/pkg/errors/appveyor.yml delete mode 100644 vendor/github.com/pkg/errors/errors.go delete mode 100644 vendor/github.com/pkg/errors/go113.go delete mode 100644 vendor/github.com/pkg/errors/stack.go diff --git a/go.mod b/go.mod index f7bf2f85..492a44ad 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.19 require ( github.com/danieljoos/wincred v1.2.1 github.com/jsipprell/keyctl v1.0.0 - github.com/pkg/errors v0.9.1 ) require golang.org/x/sys v0.15.0 // indirect diff --git a/go.sum b/go.sum index e1b199fe..52ba4454 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,6 @@ github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/jsipprell/keyctl v1.0.0 h1:eMMJGk3UEsCXQegACLlfIjnfPlYHV61qfGXZ9/axBn4= github.com/jsipprell/keyctl v1.0.0/go.mod h1:64s6WpBtruURX3w8W/vhWj1/uh+nOm7vUXSJlK5+KMs= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= diff --git a/keyctl/keyctl.go b/keyctl/keyctl.go index d139e71f..9d3fe263 100644 --- a/keyctl/keyctl.go +++ b/keyctl/keyctl.go @@ -13,7 +13,6 @@ import ( "github.com/docker/docker-credential-helpers/credentials" "github.com/jsipprell/keyctl" - "github.com/pkg/errors" ) // Keyctl based credential helper looks for a default keyring inside @@ -36,11 +35,11 @@ func (k Keyctl) createDefaultPersistentKeyring() (string, error) { cmd.Stdout = &out err := cmd.Run() if err != nil { - return "", errors.Wrapf(err, "cannot run keyctl command to create persistent keyring %+v: %s", err, errout.String()) + return "", fmt.Errorf("cannot run keyctl command to create persistent keyring: %s: %w", errout.String(), err) } persistentKeyringID := out.String() if err != nil { - return "", errors.Wrapf(err, "cannot create or read persistent keyring %+v", err) + return "", fmt.Errorf("cannot create or read persistent keyring: %w", err) } return persistentKeyringID, nil } @@ -49,12 +48,12 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error var out, errout bytes.Buffer persistentKeyringID, err := k.createDefaultPersistentKeyring() if err != nil { - return nil, errors.Wrap(err, "default persistent keyring cannot be created") + return nil, fmt.Errorf("default persistent keyring cannot be created: %w", err) } defaultSessionKeyring, err := keyctl.SessionKeyring() if err != nil { - return nil, errors.New("errors getting session keyring") + return nil, fmt.Errorf("errors getting session keyring: %w", err) } defaultKeyring, err := keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) @@ -65,13 +64,13 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error cmd.Stderr = &errout err := cmd.Run() if err != nil { - return nil, errors.Wrapf(err, "cannot run keyctl command to created credstore keyring %s %s %s", cmd.String(), errout.String(), out.String()) + return nil, fmt.Errorf("cannot run keyctl command to created credstore keyring (%s): %s %s: %w", cmd.String(), errout.String(), out.String(), err) } } /* Search for it again and return the default keyring*/ defaultKeyring, err = keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) if err != nil { - return nil, errors.Wrap(err, "failed to lookup default session keyring") + return nil, fmt.Errorf("failed to lookup default session keyring: %w", err) } return defaultKeyring, nil @@ -80,11 +79,18 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error // getDefaultCredsStore is a helper function to get the default credsStore keyring func (k Keyctl) getDefaultCredsStore() (keyctl.NamedKeyring, error) { if persistent == 1 { - return k.getDefaultCredsStoreFromPersistent() + cs, err := k.getDefaultCredsStoreFromPersistent() + if err != nil { + return nil, err + } + if cs == nil { + return nil, fmt.Errorf("nil credstore") + } + return cs, err } defaultSessionKeyring, err := keyctl.SessionKeyring() if err != nil { - return nil, errors.Wrap(err, "error getting session keyring") + return nil, fmt.Errorf("error getting session keyring: %w", err) } defaultKeyring, err := keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) @@ -92,13 +98,13 @@ func (k Keyctl) getDefaultCredsStore() (keyctl.NamedKeyring, error) { if defaultKeyring == nil { defaultKeyring, err = keyctl.CreateKeyring(defaultSessionKeyring, defaultKeyringName) if err != nil { - return nil, errors.Wrap(err, "failed to create default credsStore keyring") + return nil, fmt.Errorf("failed to create default credsStore keyring: %w", err) } } } if defaultKeyring == nil { - return nil, errors.Wrap(errors.New(""), " nil credstore") + return nil, fmt.Errorf("nil credstore") } return defaultKeyring, nil @@ -107,20 +113,20 @@ func (k Keyctl) getDefaultCredsStore() (keyctl.NamedKeyring, error) { // Add adds new credentials to the keychain. func (k Keyctl) Add(creds *credentials.Credentials) error { defaultKeyring, err := k.getDefaultCredsStore() - if err != nil || defaultKeyring == nil { - return errors.Wrapf(err, "failed to create credsStore entry for %s", creds.ServerURL) + if err != nil { + return fmt.Errorf("failed to create credsStore entry for %s: %w", creds.ServerURL, err) } // create a child keyring under default for given url encoded := base64.URLEncoding.EncodeToString([]byte(strings.TrimSuffix(creds.ServerURL, "\n"))) urlKeyring, err := keyctl.CreateKeyring(defaultKeyring, encoded) if err != nil { - return errors.Wrapf(err, "failed to create keyring for %s", creds.ServerURL) + return fmt.Errorf("failed to create keyring for %s: %w", creds.ServerURL, err) } _, err = urlKeyring.Add(creds.Username, []byte(creds.Secret)) if err != nil { - return errors.Wrapf(err, "failed to add creds to keryring for %s with error: %+v", creds.ServerURL, err) + return fmt.Errorf("failed to add creds to keryring for %s: %w", creds.ServerURL, err) } return err } @@ -128,8 +134,8 @@ func (k Keyctl) Add(creds *credentials.Credentials) error { // searchHelper function searches for an url inside the default keyring. func (k Keyctl) searchHelper(serverURL string) (keyctl.NamedKeyring, string, error) { defaultKeyring, err := k.getDefaultCredsStore() - if err != nil || defaultKeyring == nil { - return nil, "", fmt.Errorf("searchHelper failed: cannot read defaultCredsStore") + if err != nil { + return nil, "", fmt.Errorf("searchHelper failed: cannot read defaultCredsStore: %w", err) } encoded := base64.URLEncoding.EncodeToString([]byte(strings.TrimSuffix(serverURL, "\n"))) @@ -166,21 +172,21 @@ func (k Keyctl) searchHelper(serverURL string) (keyctl.NamedKeyring, string, err // Get returns the username and secret to use for a given registry server URL. func (k Keyctl) Get(serverURL string) (string, string, error) { if serverURL == "" { - return "", "", errors.New("missing server url") + return "", "", fmt.Errorf("missing server url") } serverURL = strings.TrimSuffix(serverURL, "\n") urlKeyring, searchData, err := k.searchHelper(serverURL) if err != nil { - return "", "", errors.Wrapf(err, "url not found by searchHelper: %s err: %v", serverURL, err) + return "", "", fmt.Errorf("url (%s) not found by searchHelper: %w", serverURL, err) } key, err := urlKeyring.Search(searchData) if err != nil { - return "", "", errors.Wrapf(err, "url not found in %+v", urlKeyring) + return "", "", fmt.Errorf("url (%s) not found in %+v: %w", serverURL, urlKeyring, err) } secret, err := key.Get() if err != nil { - return "", "", errors.Wrapf(err, "failed to read credentials for %s:%s", serverURL, searchData) + return "", "", fmt.Errorf("failed to read credentials for url (%s): %s: %w", serverURL, searchData, err) } return searchData, string(secret), nil @@ -191,7 +197,7 @@ func (k Keyctl) Delete(serverURL string) error { serverURL = strings.TrimSuffix(serverURL, "\n") urlKeyring, searchData, err := k.searchHelper(serverURL) if err != nil { - return errors.Wrapf(err, "cannot find server url %s", serverURL) + return fmt.Errorf("cannot find server url (%s): %w", serverURL, err) } key, err := urlKeyring.Search(searchData) @@ -209,9 +215,9 @@ func (k Keyctl) Delete(serverURL string) error { fmt.Printf("cannot list keyring %s", urlKeyring.Name()) } if len(refs) == 0 { - keyctl.UnlinkKeyring(urlKeyring) + _ = keyctl.UnlinkKeyring(urlKeyring) } else { - return errors.Wrapf(err, "Canot remove keyring as its not empty %s", urlKeyring.Name()) + return fmt.Errorf("canot remove keyring as its not empty %s", urlKeyring.Name()) } return err @@ -220,8 +226,8 @@ func (k Keyctl) Delete(serverURL string) error { // List returns the stored URLs and corresponding usernames for a given credentials label func (k Keyctl) List() (map[string]string, error) { defaultKeyring, err := k.getDefaultCredsStore() - if err != nil || defaultKeyring == nil { - return nil, errors.Wrap(err, "List() failed: cannot read default credStore") + if err != nil { + return nil, fmt.Errorf("failed to list credentials: cannot read default credStore: %w", err) } resp := map[string]string{} diff --git a/keyctl/keyctl_test.go b/keyctl/keyctl_test.go index 22505f8e..af0a7283 100644 --- a/keyctl/keyctl_test.go +++ b/keyctl/keyctl_test.go @@ -1,11 +1,11 @@ package keyctl import ( + "fmt" "strings" "testing" "github.com/docker/docker-credential-helpers/credentials" - "github.com/pkg/errors" ) func TestKeyctlHelper(t *testing.T) { @@ -59,7 +59,7 @@ func TestKeyctlHelper(t *testing.T) { } err = helper.Delete(s) if err != nil { - errors.Wrapf(err, "error in deleting %s", s) + t.Error(fmt.Errorf("error in deleting %s: %w", s, err)) } } diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore deleted file mode 100644 index daf913b1..00000000 --- a/vendor/github.com/pkg/errors/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml deleted file mode 100644 index 9159de03..00000000 --- a/vendor/github.com/pkg/errors/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -go_import_path: github.com/pkg/errors -go: - - 1.11.x - - 1.12.x - - 1.13.x - - tip - -script: - - make check diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE deleted file mode 100644 index 835ba3e7..00000000 --- a/vendor/github.com/pkg/errors/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2015, Dave Cheney -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile deleted file mode 100644 index ce9d7cde..00000000 --- a/vendor/github.com/pkg/errors/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PKGS := github.com/pkg/errors -SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) -GO := go - -check: test vet gofmt misspell unconvert staticcheck ineffassign unparam - -test: - $(GO) test $(PKGS) - -vet: | test - $(GO) vet $(PKGS) - -staticcheck: - $(GO) get honnef.co/go/tools/cmd/staticcheck - staticcheck -checks all $(PKGS) - -misspell: - $(GO) get github.com/client9/misspell/cmd/misspell - misspell \ - -locale GB \ - -error \ - *.md *.go - -unconvert: - $(GO) get github.com/mdempsky/unconvert - unconvert -v $(PKGS) - -ineffassign: - $(GO) get github.com/gordonklaus/ineffassign - find $(SRCDIRS) -name '*.go' | xargs ineffassign - -pedantic: check errcheck - -unparam: - $(GO) get mvdan.cc/unparam - unparam ./... - -errcheck: - $(GO) get github.com/kisielk/errcheck - errcheck $(PKGS) - -gofmt: - @echo Checking code is gofmted - @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md deleted file mode 100644 index 54dfdcb1..00000000 --- a/vendor/github.com/pkg/errors/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) - -Package errors provides simple error handling primitives. - -`go get github.com/pkg/errors` - -The traditional error handling idiom in Go is roughly akin to -```go -if err != nil { - return err -} -``` -which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. - -## Adding context to an error - -The errors.Wrap function returns a new error that adds context to the original error. For example -```go -_, err := ioutil.ReadAll(r) -if err != nil { - return errors.Wrap(err, "read failed") -} -``` -## Retrieving the cause of an error - -Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. -```go -type causer interface { - Cause() error -} -``` -`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: -```go -switch err := errors.Cause(err).(type) { -case *MyError: - // handle specifically -default: - // unknown error -} -``` - -[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). - -## Roadmap - -With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: - -- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) -- 1.0. Final release. - -## Contributing - -Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. - -Before sending a PR, please discuss your change by raising an issue. - -## License - -BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml deleted file mode 100644 index a932eade..00000000 --- a/vendor/github.com/pkg/errors/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: build-{build}.{branch} - -clone_folder: C:\gopath\src\github.com\pkg\errors -shallow_clone: true # for startup speed - -environment: - GOPATH: C:\gopath - -platform: - - x64 - -# http://www.appveyor.com/docs/installed-software -install: - # some helpful output for debugging builds - - go version - - go env - # pre-installed MinGW at C:\MinGW is 32bit only - # but MSYS2 at C:\msys64 has mingw64 - - set PATH=C:\msys64\mingw64\bin;%PATH% - - gcc --version - - g++ --version - -build_script: - - go install -v ./... - -test_script: - - set PATH=C:\gopath\bin;%PATH% - - go test -v ./... - -#artifacts: -# - path: '%GOPATH%\bin\*.exe' -deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go deleted file mode 100644 index 161aea25..00000000 --- a/vendor/github.com/pkg/errors/errors.go +++ /dev/null @@ -1,288 +0,0 @@ -// Package errors provides simple error handling primitives. -// -// The traditional error handling idiom in Go is roughly akin to -// -// if err != nil { -// return err -// } -// -// which when applied recursively up the call stack results in error reports -// without context or debugging information. The errors package allows -// programmers to add context to the failure path in their code in a way -// that does not destroy the original value of the error. -// -// Adding context to an error -// -// The errors.Wrap function returns a new error that adds context to the -// original error by recording a stack trace at the point Wrap is called, -// together with the supplied message. For example -// -// _, err := ioutil.ReadAll(r) -// if err != nil { -// return errors.Wrap(err, "read failed") -// } -// -// If additional control is required, the errors.WithStack and -// errors.WithMessage functions destructure errors.Wrap into its component -// operations: annotating an error with a stack trace and with a message, -// respectively. -// -// Retrieving the cause of an error -// -// Using errors.Wrap constructs a stack of errors, adding context to the -// preceding error. Depending on the nature of the error it may be necessary -// to reverse the operation of errors.Wrap to retrieve the original error -// for inspection. Any error value which implements this interface -// -// type causer interface { -// Cause() error -// } -// -// can be inspected by errors.Cause. errors.Cause will recursively retrieve -// the topmost error that does not implement causer, which is assumed to be -// the original cause. For example: -// -// switch err := errors.Cause(err).(type) { -// case *MyError: -// // handle specifically -// default: -// // unknown error -// } -// -// Although the causer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// Formatted printing of errors -// -// All error values returned from this package implement fmt.Formatter and can -// be formatted by the fmt package. The following verbs are supported: -// -// %s print the error. If the error has a Cause it will be -// printed recursively. -// %v see %s -// %+v extended format. Each Frame of the error's StackTrace will -// be printed in detail. -// -// Retrieving the stack trace of an error or wrapper -// -// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are -// invoked. This information can be retrieved with the following interface: -// -// type stackTracer interface { -// StackTrace() errors.StackTrace -// } -// -// The returned errors.StackTrace type is defined as -// -// type StackTrace []Frame -// -// The Frame type represents a call site in the stack trace. Frame supports -// the fmt.Formatter interface that can be used for printing information about -// the stack trace of this error. For example: -// -// if err, ok := err.(stackTracer); ok { -// for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d\n", f, f) -// } -// } -// -// Although the stackTracer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// See the documentation for Frame.Format for more details. -package errors - -import ( - "fmt" - "io" -) - -// New returns an error with the supplied message. -// New also records the stack trace at the point it was called. -func New(message string) error { - return &fundamental{ - msg: message, - stack: callers(), - } -} - -// Errorf formats according to a format specifier and returns the string -// as a value that satisfies error. -// Errorf also records the stack trace at the point it was called. -func Errorf(format string, args ...interface{}) error { - return &fundamental{ - msg: fmt.Sprintf(format, args...), - stack: callers(), - } -} - -// fundamental is an error that has a message and a stack, but no caller. -type fundamental struct { - msg string - *stack -} - -func (f *fundamental) Error() string { return f.msg } - -func (f *fundamental) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - io.WriteString(s, f.msg) - f.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, f.msg) - case 'q': - fmt.Fprintf(s, "%q", f.msg) - } -} - -// WithStack annotates err with a stack trace at the point WithStack was called. -// If err is nil, WithStack returns nil. -func WithStack(err error) error { - if err == nil { - return nil - } - return &withStack{ - err, - callers(), - } -} - -type withStack struct { - error - *stack -} - -func (w *withStack) Cause() error { return w.error } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withStack) Unwrap() error { return w.error } - -func (w *withStack) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v", w.Cause()) - w.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, w.Error()) - case 'q': - fmt.Fprintf(s, "%q", w.Error()) - } -} - -// Wrap returns an error annotating err with a stack trace -// at the point Wrap is called, and the supplied message. -// If err is nil, Wrap returns nil. -func Wrap(err error, message string) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: message, - } - return &withStack{ - err, - callers(), - } -} - -// Wrapf returns an error annotating err with a stack trace -// at the point Wrapf is called, and the format specifier. -// If err is nil, Wrapf returns nil. -func Wrapf(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } - return &withStack{ - err, - callers(), - } -} - -// WithMessage annotates err with a new message. -// If err is nil, WithMessage returns nil. -func WithMessage(err error, message string) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: message, - } -} - -// WithMessagef annotates err with the format specifier. -// If err is nil, WithMessagef returns nil. -func WithMessagef(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } -} - -type withMessage struct { - cause error - msg string -} - -func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } -func (w *withMessage) Cause() error { return w.cause } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withMessage) Unwrap() error { return w.cause } - -func (w *withMessage) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v\n", w.Cause()) - io.WriteString(s, w.msg) - return - } - fallthrough - case 's', 'q': - io.WriteString(s, w.Error()) - } -} - -// Cause returns the underlying cause of the error, if possible. -// An error value has a cause if it implements the following -// interface: -// -// type causer interface { -// Cause() error -// } -// -// If the error does not implement Cause, the original error will -// be returned. If the error is nil, nil will be returned without further -// investigation. -func Cause(err error) error { - type causer interface { - Cause() error - } - - for err != nil { - cause, ok := err.(causer) - if !ok { - break - } - err = cause.Cause() - } - return err -} diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go deleted file mode 100644 index be0d10d0..00000000 --- a/vendor/github.com/pkg/errors/go113.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.13 - -package errors - -import ( - stderrors "errors" -) - -// Is reports whether any error in err's chain matches target. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error is considered to match a target if it is equal to that target or if -// it implements a method Is(error) bool such that Is(target) returns true. -func Is(err, target error) bool { return stderrors.Is(err, target) } - -// As finds the first error in err's chain that matches target, and if so, sets -// target to that error value and returns true. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error matches target if the error's concrete value is assignable to the value -// pointed to by target, or if the error has a method As(interface{}) bool such that -// As(target) returns true. In the latter case, the As method is responsible for -// setting target. -// -// As will panic if target is not a non-nil pointer to either a type that implements -// error, or to any interface type. As returns false if err is nil. -func As(err error, target interface{}) bool { return stderrors.As(err, target) } - -// Unwrap returns the result of calling the Unwrap method on err, if err's -// type contains an Unwrap method returning error. -// Otherwise, Unwrap returns nil. -func Unwrap(err error) error { - return stderrors.Unwrap(err) -} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go deleted file mode 100644 index 779a8348..00000000 --- a/vendor/github.com/pkg/errors/stack.go +++ /dev/null @@ -1,177 +0,0 @@ -package errors - -import ( - "fmt" - "io" - "path" - "runtime" - "strconv" - "strings" -) - -// Frame represents a program counter inside a stack frame. -// For historical reasons if Frame is interpreted as a uintptr -// its value represents the program counter + 1. -type Frame uintptr - -// pc returns the program counter for this frame; -// multiple frames may have the same PC value. -func (f Frame) pc() uintptr { return uintptr(f) - 1 } - -// file returns the full path to the file that contains the -// function for this Frame's pc. -func (f Frame) file() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - file, _ := fn.FileLine(f.pc()) - return file -} - -// line returns the line number of source code of the -// function for this Frame's pc. -func (f Frame) line() int { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return 0 - } - _, line := fn.FileLine(f.pc()) - return line -} - -// name returns the name of this function, if known. -func (f Frame) name() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - return fn.Name() -} - -// Format formats the frame according to the fmt.Formatter interface. -// -// %s source file -// %d source line -// %n function name -// %v equivalent to %s:%d -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+s function name and path of source file relative to the compile time -// GOPATH separated by \n\t (\n\t) -// %+v equivalent to %+s:%d -func (f Frame) Format(s fmt.State, verb rune) { - switch verb { - case 's': - switch { - case s.Flag('+'): - io.WriteString(s, f.name()) - io.WriteString(s, "\n\t") - io.WriteString(s, f.file()) - default: - io.WriteString(s, path.Base(f.file())) - } - case 'd': - io.WriteString(s, strconv.Itoa(f.line())) - case 'n': - io.WriteString(s, funcname(f.name())) - case 'v': - f.Format(s, 's') - io.WriteString(s, ":") - f.Format(s, 'd') - } -} - -// MarshalText formats a stacktrace Frame as a text string. The output is the -// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. -func (f Frame) MarshalText() ([]byte, error) { - name := f.name() - if name == "unknown" { - return []byte(name), nil - } - return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil -} - -// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). -type StackTrace []Frame - -// Format formats the stack of Frames according to the fmt.Formatter interface. -// -// %s lists source files for each Frame in the stack -// %v lists the source file and line number for each Frame in the stack -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+v Prints filename, function, and line number for each Frame in the stack. -func (st StackTrace) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case s.Flag('+'): - for _, f := range st { - io.WriteString(s, "\n") - f.Format(s, verb) - } - case s.Flag('#'): - fmt.Fprintf(s, "%#v", []Frame(st)) - default: - st.formatSlice(s, verb) - } - case 's': - st.formatSlice(s, verb) - } -} - -// formatSlice will format this StackTrace into the given buffer as a slice of -// Frame, only valid when called with '%s' or '%v'. -func (st StackTrace) formatSlice(s fmt.State, verb rune) { - io.WriteString(s, "[") - for i, f := range st { - if i > 0 { - io.WriteString(s, " ") - } - f.Format(s, verb) - } - io.WriteString(s, "]") -} - -// stack represents a stack of program counters. -type stack []uintptr - -func (s *stack) Format(st fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case st.Flag('+'): - for _, pc := range *s { - f := Frame(pc) - fmt.Fprintf(st, "\n%+v", f) - } - } - } -} - -func (s *stack) StackTrace() StackTrace { - f := make([]Frame, len(*s)) - for i := 0; i < len(f); i++ { - f[i] = Frame((*s)[i]) - } - return f -} - -func callers() *stack { - const depth = 32 - var pcs [depth]uintptr - n := runtime.Callers(3, pcs[:]) - var st stack = pcs[0:n] - return &st -} - -// funcname removes the path prefix component of a function's name reported by func.Name(). -func funcname(name string) string { - i := strings.LastIndex(name, "/") - name = name[i+1:] - i = strings.Index(name, ".") - return name[i+1:] -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 491d354c..1213d06a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -4,9 +4,6 @@ github.com/danieljoos/wincred # github.com/jsipprell/keyctl v1.0.0 ## explicit github.com/jsipprell/keyctl -# github.com/pkg/errors v0.9.1 -## explicit -github.com/pkg/errors # golang.org/x/sys v0.15.0 ## explicit; go 1.18 golang.org/x/sys/windows From eb6f6c419bc1908a3ee69cef85c4f5fa68bdaaf9 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 21 Aug 2022 21:59:27 +0200 Subject: [PATCH 3/9] keyctl: fix some nits Signed-off-by: Sebastiaan van Stijn --- keyctl/keyctl.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/keyctl/keyctl.go b/keyctl/keyctl.go index 9d3fe263..c6c8148a 100644 --- a/keyctl/keyctl.go +++ b/keyctl/keyctl.go @@ -24,10 +24,10 @@ const persistent int = 1 // Keyctl handles secrets using Linux Kernel keyring mechanism type Keyctl struct{} +// createDefaultPersistentKeyring creates the default persistent keyring. If the +// keyring for the user already exists, then it returns the id of the existing +// keyring. func (k Keyctl) createDefaultPersistentKeyring() (string, error) { - /* Create default persistent keyring. If the keyring for the user - * already exists, then it returns the id of the existing keyring - */ var errout, out bytes.Buffer uid := os.Getuid() cmd := exec.Command("keyctl", "get_persistent", "@u", strconv.Itoa(uid)) @@ -57,7 +57,7 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error } defaultKeyring, err := keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) - /* if already does not exist we create */ + // create keyring if it does not exist if err != nil || defaultKeyring == nil { cmd := exec.Command("keyctl", "newring", defaultKeyringName, strings.TrimSuffix(persistentKeyringID, "\n")) cmd.Stdout = &out @@ -67,7 +67,7 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error return nil, fmt.Errorf("cannot run keyctl command to created credstore keyring (%s): %s %s: %w", cmd.String(), errout.String(), out.String(), err) } } - /* Search for it again and return the default keyring*/ + // Search for it again and return the default keyring defaultKeyring, err = keyctl.OpenKeyring(defaultSessionKeyring, defaultKeyringName) if err != nil { return nil, fmt.Errorf("failed to lookup default session keyring: %w", err) @@ -78,7 +78,7 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error // getDefaultCredsStore is a helper function to get the default credsStore keyring func (k Keyctl) getDefaultCredsStore() (keyctl.NamedKeyring, error) { - if persistent == 1 { + if persistent == 1 { // TODO(thaJeztah) persistent is a const, and always 1, what's this check for? cs, err := k.getDefaultCredsStoreFromPersistent() if err != nil { return nil, err From ef5076f386c1dea2d8481e23088552e9db4d889c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 21 Aug 2022 22:00:34 +0200 Subject: [PATCH 4/9] keyctl: move files to linux-only Signed-off-by: Sebastiaan van Stijn --- keyctl/cmd/{main.go => main_linux.go} | 0 keyctl/{keyctl.go => keyctl_linux.go} | 0 keyctl/{keyctl_test.go => keyctl_linux_test.go} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename keyctl/cmd/{main.go => main_linux.go} (100%) rename keyctl/{keyctl.go => keyctl_linux.go} (100%) rename keyctl/{keyctl_test.go => keyctl_linux_test.go} (100%) diff --git a/keyctl/cmd/main.go b/keyctl/cmd/main_linux.go similarity index 100% rename from keyctl/cmd/main.go rename to keyctl/cmd/main_linux.go diff --git a/keyctl/keyctl.go b/keyctl/keyctl_linux.go similarity index 100% rename from keyctl/keyctl.go rename to keyctl/keyctl_linux.go diff --git a/keyctl/keyctl_test.go b/keyctl/keyctl_linux_test.go similarity index 100% rename from keyctl/keyctl_test.go rename to keyctl/keyctl_linux_test.go From 14e24cebb9819ff91e7ca6ce474e8090247e4bcc Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 21 Aug 2022 22:02:10 +0200 Subject: [PATCH 5/9] vendor github.com/jsipprell/keyctl v1.0.3 full diff: https://github.com/jsipprell/keyctl/compare/v1.0.0...v1.0.3 Signed-off-by: Sebastiaan van Stijn --- go.mod | 2 +- go.sum | 4 ++-- vendor/github.com/jsipprell/keyctl/.travis.yml | 4 +--- vendor/github.com/jsipprell/keyctl/keyring.go | 7 ++++++- vendor/github.com/jsipprell/keyctl/ref.go | 2 +- vendor/github.com/jsipprell/keyctl/sys_linux.go | 8 ++++++++ vendor/github.com/jsipprell/keyctl/sys_linux_arm.go | 7 +++++++ vendor/modules.txt | 2 +- 8 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 vendor/github.com/jsipprell/keyctl/sys_linux_arm.go diff --git a/go.mod b/go.mod index 492a44ad..d65ee7bc 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/danieljoos/wincred v1.2.1 - github.com/jsipprell/keyctl v1.0.0 + github.com/jsipprell/keyctl v1.0.3 ) require golang.org/x/sys v0.15.0 // indirect diff --git a/go.sum b/go.sum index 52ba4454..1c43f96d 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/jsipprell/keyctl v1.0.0 h1:eMMJGk3UEsCXQegACLlfIjnfPlYHV61qfGXZ9/axBn4= -github.com/jsipprell/keyctl v1.0.0/go.mod h1:64s6WpBtruURX3w8W/vhWj1/uh+nOm7vUXSJlK5+KMs= +github.com/jsipprell/keyctl v1.0.3 h1:o72tppb3ZhP5B/v9FGUtMqJWx+S1Gs0elQ7AZmiNhsM= +github.com/jsipprell/keyctl v1.0.3/go.mod h1:64s6WpBtruURX3w8W/vhWj1/uh+nOm7vUXSJlK5+KMs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= diff --git a/vendor/github.com/jsipprell/keyctl/.travis.yml b/vendor/github.com/jsipprell/keyctl/.travis.yml index 97b31165..911fc446 100644 --- a/vendor/github.com/jsipprell/keyctl/.travis.yml +++ b/vendor/github.com/jsipprell/keyctl/.travis.yml @@ -3,9 +3,7 @@ branches: - master language: go go: - - 1.4 - - 1.5 - - 1.6 + - 1.11 - tip install: - go get golang.org/x/crypto/openpgp diff --git a/vendor/github.com/jsipprell/keyctl/keyring.go b/vendor/github.com/jsipprell/keyctl/keyring.go index 78966947..5c5a9b93 100644 --- a/vendor/github.com/jsipprell/keyctl/keyring.go +++ b/vendor/github.com/jsipprell/keyctl/keyring.go @@ -179,9 +179,14 @@ func SetKeyringTTL(kr NamedKeyring, nsecs uint) error { return err } +// Link an object to a keyring +func Link(parent Keyring, child Id) error { + return keyctl_Link(keyId(child.Id()), keyId(parent.Id())) +} + // Unlink an object from a keyring func Unlink(parent Keyring, child Id) error { - return keyctl_Unlink(keyId(parent.Id()), keyId(child.Id())) + return keyctl_Unlink(keyId(child.Id()), keyId(parent.Id())) } // Unlink a named keyring from its parent. diff --git a/vendor/github.com/jsipprell/keyctl/ref.go b/vendor/github.com/jsipprell/keyctl/ref.go index 6eb00562..ea82f768 100644 --- a/vendor/github.com/jsipprell/keyctl/ref.go +++ b/vendor/github.com/jsipprell/keyctl/ref.go @@ -122,7 +122,7 @@ func (r *Reference) Get() (Id, error) { } switch r.info.Type { - case "key": + case "key", "big_key": return &Key{Name: r.info.Name, id: keyId(r.Id), ring: r.parent}, nil case "keyring": ring := &keyring{id: keyId(r.Id)} diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux.go b/vendor/github.com/jsipprell/keyctl/sys_linux.go index 85383b4a..0c4c1943 100644 --- a/vendor/github.com/jsipprell/keyctl/sys_linux.go +++ b/vendor/github.com/jsipprell/keyctl/sys_linux.go @@ -102,6 +102,14 @@ func keyctl_Read(id keyId, b *byte, size int) (int32, error) { return int32(v1), nil } +func keyctl_Link(id, ring keyId) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlLink), uintptr(id), uintptr(ring)) + if errno != 0 { + return errno + } + return nil +} + func keyctl_Unlink(id, ring keyId) error { _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlUnlink), uintptr(id), uintptr(ring)) if errno != 0 { diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux_arm.go b/vendor/github.com/jsipprell/keyctl/sys_linux_arm.go new file mode 100644 index 00000000..0542a614 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux_arm.go @@ -0,0 +1,7 @@ +package keyctl + +const ( + syscall_keyctl uintptr = 311 + syscall_add_key uintptr = 309 + syscall_setfsgid uintptr = 139 +) diff --git a/vendor/modules.txt b/vendor/modules.txt index 1213d06a..42c9df81 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,7 +1,7 @@ # github.com/danieljoos/wincred v1.2.1 ## explicit; go 1.18 github.com/danieljoos/wincred -# github.com/jsipprell/keyctl v1.0.0 +# github.com/jsipprell/keyctl v1.0.3 ## explicit github.com/jsipprell/keyctl # golang.org/x/sys v0.15.0 From 904727c9f2041c6ad6bf82ef91bc1817a3cf4832 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 21 Aug 2022 22:05:28 +0200 Subject: [PATCH 6/9] Dockerfile: install keyutils Signed-off-by: Sebastiaan van Stijn --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index de5ef07a..66d10421 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,7 +68,7 @@ RUN xx-apt-get install -y binutils gcc libc6-dev libgcc-10-dev libsecret-1-dev p FROM base AS test ARG DEBIAN_FRONTEND -RUN xx-apt-get install -y dbus-x11 gnome-keyring gpg-agent gpgconf libsecret-1-dev pass +RUN xx-apt-get install -y dbus-x11 gnome-keyring gpg-agent gpgconf keyutils libsecret-1-dev pass RUN --mount=type=bind,target=. \ --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/go/pkg/mod < Date: Sun, 21 Aug 2022 22:22:34 +0200 Subject: [PATCH 7/9] keyctl: improve some errors Signed-off-by: Sebastiaan van Stijn --- keyctl/keyctl_linux.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keyctl/keyctl_linux.go b/keyctl/keyctl_linux.go index c6c8148a..f218138d 100644 --- a/keyctl/keyctl_linux.go +++ b/keyctl/keyctl_linux.go @@ -35,7 +35,7 @@ func (k Keyctl) createDefaultPersistentKeyring() (string, error) { cmd.Stdout = &out err := cmd.Run() if err != nil { - return "", fmt.Errorf("cannot run keyctl command to create persistent keyring: %s: %w", errout.String(), err) + return "", fmt.Errorf("cannot run keyctl command (%s) to create persistent keyring: %s: %w", cmd.String(), errout.String(), err) } persistentKeyringID := out.String() if err != nil { @@ -64,7 +64,7 @@ func (k Keyctl) getDefaultCredsStoreFromPersistent() (keyctl.NamedKeyring, error cmd.Stderr = &errout err := cmd.Run() if err != nil { - return nil, fmt.Errorf("cannot run keyctl command to created credstore keyring (%s): %s %s: %w", cmd.String(), errout.String(), out.String(), err) + return nil, fmt.Errorf("cannot run keyctl command to create credstore keyring (%s): %s %s: %w", cmd.String(), errout.String(), out.String(), err) } } // Search for it again and return the default keyring From 0f7aebdf6bb19af4f2a203edee48c58b16d607e0 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 26 Aug 2022 23:12:12 +0200 Subject: [PATCH 8/9] WIP: try to fix the generate Signed-off-by: Sebastiaan van Stijn --- .github/workflows/fixtures/generate.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) mode change 100644 => 100755 .github/workflows/fixtures/generate.sh diff --git a/.github/workflows/fixtures/generate.sh b/.github/workflows/fixtures/generate.sh old mode 100644 new mode 100755 index 2f2af822..17ffd777 --- a/.github/workflows/fixtures/generate.sh +++ b/.github/workflows/fixtures/generate.sh @@ -1,7 +1,9 @@ #!/usr/bin/env sh set -ex -gpg --batch --gen-key <<-EOF +# shellcheck disable=SC2155 +export GPG_TTY=$(tty) +gpg --batch --gen-key --no-tty <<-EOF %echo Generating a standard key Key-Type: DSA Key-Length: 1024 @@ -9,8 +11,18 @@ Subkey-Type: ELG-E Subkey-Length: 1024 Name-Real: Meshuggah Rocks Name-Email: meshuggah@example.com +Passphrase: with stupid passphrase Expire-Date: 0 # Do a commit here, so that we can later print "done" :-) %commit %echo done EOF + +# doesn't work; still asks for passphrase interactively +# gpg --output private.pgp --armor --export-secret-key meshuggah@example.com + +# doesn't work; still asks for passphrase interactively +# gpg --passphrase 'with stupid passphrase' --output private.pgp --armor --export-secret-key meshuggah@example.com + +# doesn't work; still asks for passphrase interactively +# gpg --batch --passphrase 'with stupid passphrase' --no-tty --output private.pgp --armor --export-secret-key meshuggah@example.com From f9cb88eae989cc5422dd111625febb11f0554228 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 27 May 2023 16:41:49 +0200 Subject: [PATCH 9/9] Dockerfile: use make target Signed-off-by: Sebastiaan van Stijn --- Dockerfile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 66d10421..488b9789 100644 --- a/Dockerfile +++ b/Dockerfile @@ -106,13 +106,10 @@ RUN --mount=type=bind,target=. \ --mount=type=bind,source=/tmp/.revision,target=/tmp/.revision,from=version <