From 576c8dbc05c5fa92b673fa24aca8e5a4540e0520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Wed, 23 Feb 2022 14:57:24 +0100 Subject: [PATCH] Remove keyring support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The package is not used, noone is currently working on wiring it up, and it started failing in CI (apparently because it assumes the user's keyring is empty when tests start, which is now not reliably the case). Instead of fixing the tests, just remove it; we can always restore the code from Git history. Signed-off-by: Miloslav Trmač --- internal/pkg/keyctl/key.go | 74 -------- internal/pkg/keyctl/keyring.go | 118 ------------- internal/pkg/keyctl/keyring_test.go | 222 ------------------------ internal/pkg/keyctl/perm.go | 34 ---- internal/pkg/keyctl/sys_linux.go | 26 --- pkg/docker/config/config_linux.go | 119 ------------- pkg/docker/config/config_unsupported.go | 21 --- 7 files changed, 614 deletions(-) delete mode 100644 internal/pkg/keyctl/key.go delete mode 100644 internal/pkg/keyctl/keyring.go delete mode 100644 internal/pkg/keyctl/keyring_test.go delete mode 100644 internal/pkg/keyctl/perm.go delete mode 100644 internal/pkg/keyctl/sys_linux.go delete mode 100644 pkg/docker/config/config_linux.go delete mode 100644 pkg/docker/config/config_unsupported.go diff --git a/internal/pkg/keyctl/key.go b/internal/pkg/keyctl/key.go deleted file mode 100644 index bf6cc87d4..000000000 --- a/internal/pkg/keyctl/key.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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. - -//go:build linux -// +build linux - -package keyctl - -import ( - "golang.org/x/sys/unix" -) - -// Key represents a single key linked to one or more kernel keyrings. -type Key struct { - Name string - - id, ring keyID - size int -} - -// ID returns the 32-bit kernel identifier for a specific key -func (k *Key) ID() int32 { - return int32(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 := unix.KeyctlBuffer(unix.KEYCTL_READ, int(k.id), b, 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 -} - -// 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 { - _, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, int(k.id), int(k.ring), 0, 0) - return err -} - -// Describe returns a string describing the attributes of a specified key -func (k *Key) Describe() (string, error) { - keyAttr, err := unix.KeyctlString(unix.KEYCTL_DESCRIBE, int(k.id)) - if err != nil { - return "", err - } - return keyAttr, nil -} diff --git a/internal/pkg/keyctl/keyring.go b/internal/pkg/keyctl/keyring.go deleted file mode 100644 index 5eaad615c..000000000 --- a/internal/pkg/keyctl/keyring.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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. - -//go:build linux -// +build linux - -// Package keyctl is a Go interface to linux kernel keyrings (keyctl interface) -package keyctl - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -// Keyring is the basic interface to a linux keyctl keyring. -type Keyring interface { - ID - Add(string, []byte) (*Key, error) - Search(string) (*Key, error) -} - -type keyring struct { - id keyID -} - -// ID is unique 32-bit serial number identifiers for all Keys and Keyrings have. -type ID interface { - ID() int32 -} - -// 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 := unix.AddKey("user", name, key, int(kr.id)) - if err == nil { - key := &Key{Name: name, id: keyID(r), ring: kr.id} - return key, nil - } - 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 := unix.KeyctlSearch(int(kr.id), "user", name, 0) - if err == nil { - return &Key{Name: name, id: keyID(id), ring: kr.id}, nil - } - return nil, err -} - -// ID returns the 32-bit kernel identifier of a keyring -func (kr *keyring) ID() int32 { - return int32(kr.id) -} - -// SessionKeyring returns the current login session keyring -func SessionKeyring() (Keyring, error) { - return newKeyring(unix.KEY_SPEC_SESSION_KEYRING) -} - -// UserKeyring returns the keyring specific to the current user. -func UserKeyring() (Keyring, error) { - return newKeyring(unix.KEY_SPEC_USER_KEYRING) -} - -// Unlink an object from a keyring -func Unlink(parent Keyring, child ID) error { - _, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, int(child.ID()), int(parent.ID()), 0, 0) - return err -} - -// Link a key into a keyring -func Link(parent Keyring, child ID) error { - _, err := unix.KeyctlInt(unix.KEYCTL_LINK, int(child.ID()), int(parent.ID()), 0, 0) - return err -} - -// ReadUserKeyring reads user keyring and returns slice of key with id(key_serial_t) representing the IDs of all the keys that are linked to it -func ReadUserKeyring() ([]*Key, error) { - var ( - b []byte - err error - sizeRead int - ) - krSize := 4 - size := krSize - b = make([]byte, size) - sizeRead = size + 1 - for sizeRead > size { - r1, err := unix.KeyctlBuffer(unix.KEYCTL_READ, unix.KEY_SPEC_USER_KEYRING, b, size) - if err != nil { - return nil, err - } - - if sizeRead = int(r1); sizeRead > size { - b = make([]byte, sizeRead) - size = sizeRead - sizeRead = size + 1 - } else { - krSize = sizeRead - } - } - keyIDs := getKeyIDsFromByte(b[:krSize]) - return keyIDs, err -} - -func getKeyIDsFromByte(byteKeyIDs []byte) []*Key { - idSize := 4 - var keys []*Key - for idx := 0; idx+idSize <= len(byteKeyIDs); idx = idx + idSize { - tempID := *(*int32)(unsafe.Pointer(&byteKeyIDs[idx])) - keys = append(keys, &Key{id: keyID(tempID)}) - } - return keys -} diff --git a/internal/pkg/keyctl/keyring_test.go b/internal/pkg/keyctl/keyring_test.go deleted file mode 100644 index 3a1c27449..000000000 --- a/internal/pkg/keyctl/keyring_test.go +++ /dev/null @@ -1,222 +0,0 @@ -//go:build linux -// +build linux - -package keyctl - -import ( - "crypto/rand" - "strings" - "testing" -) - -func TestSessionKeyring(t *testing.T) { - - token := make([]byte, 20) - _, err := rand.Read(token) - if err != nil { - t.Fatal(err) - } - - testname := "testname" - keyring, err := SessionKeyring() - if err != nil { - t.Fatal(err) - } - _, err = keyring.Add(testname, token) - if err != nil { - t.Fatal(err) - } - key, err := keyring.Search(testname) - if err != nil { - t.Fatal(err) - } - data, err := key.Get() - if err != nil { - t.Fatal(err) - } - if string(data) != string(token) { - t.Errorf("Expected data %v, but get %v", token, data) - } - err = key.Unlink() - if err != nil { - t.Fatal(err) - } -} - -func TestUserKeyring(t *testing.T) { - token := make([]byte, 20) - _, err := rand.Read(token) - if err != nil { - t.Fatal(err) - } - - testname := "testuser" - - userKeyring, err := UserKeyring() - if err != nil { - t.Fatal(err) - } - - userKey, err := userKeyring.Add(testname, token) - if err != nil { - t.Fatal(err, userKey) - } - - searchRet, err := userKeyring.Search(testname) - if err != nil { - t.Fatal(err) - } - if searchRet.Name != testname { - t.Errorf("Expected data %v, but get %v", testname, searchRet.Name) - } - - err = userKey.Unlink() - if err != nil { - t.Fatal(err) - } -} - -func TestLink(t *testing.T) { - token := make([]byte, 20) - _, err := rand.Read(token) - if err != nil { - t.Fatal(err) - } - - testname := "testlink" - - userKeyring, err := UserKeyring() - if err != nil { - t.Fatal(err) - } - - sessionKeyring, err := SessionKeyring() - if err != nil { - t.Fatal(err) - } - - key, err := sessionKeyring.Add(testname, token) - if err != nil { - t.Fatal(err) - } - - _, err = userKeyring.Search(testname) - if err == nil { - t.Fatalf("Expected error, but got key %v", testname) - } - ExpectedError := "required key not available" - if err.Error() != ExpectedError { - t.Fatal(err) - } - - err = Link(userKeyring, key) - if err != nil { - t.Fatal(err) - } - _, err = userKeyring.Search(testname) - if err != nil { - t.Fatal(err) - } - - err = key.Unlink() - if err != nil { - t.Fatal(err) - } - - err = Unlink(userKeyring, key) - if err != nil { - t.Fatal(err) - } -} - -func TestUnlink(t *testing.T) { - token := make([]byte, 20) - _, err := rand.Read(token) - if err != nil { - t.Fatal(err) - } - - testname := "testunlink" - keyring, err := SessionKeyring() - if err != nil { - t.Fatal(err) - } - key, err := keyring.Add(testname, token) - if err != nil { - t.Fatal(err) - } - - err = Unlink(keyring, key) - if err != nil { - t.Fatal(err) - } - - _, err = keyring.Search(testname) - ExpectedError := "required key not available" - if err.Error() != ExpectedError { - t.Fatal(err) - } -} - -func TestReadKeyring(t *testing.T) { - token := make([]byte, 20) - _, err := rand.Read(token) - if err != nil { - t.Fatal(err) - } - - testname := "testuser" - - userKeyring, err := UserKeyring() - if err != nil { - t.Fatal(err) - } - - userKey, err := userKeyring.Add(testname, token) - if err != nil { - t.Fatal(err, userKey) - } - keys, err := ReadUserKeyring() - if err != nil { - t.Fatal(err) - } - expectedKeyLen := 1 - if len(keys) != 1 { - t.Errorf("expected to read %d userkeyring, but get %d", expectedKeyLen, len(keys)) - } - err = Unlink(userKeyring, userKey) - if err != nil { - t.Fatal(err) - } -} - -func TestDescribe(t *testing.T) { - token := make([]byte, 20) - _, err := rand.Read(token) - if err != nil { - t.Fatal(err) - } - - testname := "testuser" - - userKeyring, err := UserKeyring() - if err != nil { - t.Fatal(err) - } - - userKey, err := userKeyring.Add(testname, token) - if err != nil { - t.Fatal(err, userKey) - } - keyAttr, err := userKey.Describe() - if err != nil { - t.Fatal(err) - } - if !strings.Contains(keyAttr, testname) { - t.Errorf("expect description contains %s, but get %s", testname, keyAttr) - } - err = Unlink(userKeyring, userKey) - if err != nil { - t.Fatal(err) - } -} diff --git a/internal/pkg/keyctl/perm.go b/internal/pkg/keyctl/perm.go deleted file mode 100644 index 5f4d2157a..000000000 --- a/internal/pkg/keyctl/perm.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -//go:build linux -// +build linux - -package keyctl - -import ( - "golang.org/x/sys/unix" -) - -// 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 ( - // PermOtherAll sets all permission for Other - PermOtherAll KeyPerm = 0x3f << (8 * iota) - // PermGroupAll sets all permission for Group - PermGroupAll - // PermUserAll sets all permission for User - PermUserAll - // PermProcessAll sets all permission for Processor - PermProcessAll -) - -// SetPerm sets the permissions on a key or keyring. -func SetPerm(k ID, p KeyPerm) error { - err := unix.KeyctlSetperm(int(k.ID()), uint32(p)) - return err -} diff --git a/internal/pkg/keyctl/sys_linux.go b/internal/pkg/keyctl/sys_linux.go deleted file mode 100644 index f61666e42..000000000 --- a/internal/pkg/keyctl/sys_linux.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -//go:build linux -// +build linux - -package keyctl - -import ( - "golang.org/x/sys/unix" -) - -type keyID int32 - -func newKeyring(id keyID) (*keyring, error) { - r1, err := unix.KeyctlGetKeyringID(int(id), true) - if err != nil { - return nil, err - } - - if id < 0 { - r1 = int(id) - } - return &keyring{id: keyID(r1)}, nil -} diff --git a/pkg/docker/config/config_linux.go b/pkg/docker/config/config_linux.go deleted file mode 100644 index 0bf161259..000000000 --- a/pkg/docker/config/config_linux.go +++ /dev/null @@ -1,119 +0,0 @@ -package config - -import ( - "fmt" - "strings" - - "github.com/containers/image/v5/internal/pkg/keyctl" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// NOTE: none of the functions here are currently used. If we ever want to -// re-enable keyring support, we should introduce a similar built-in credential -// helpers as for `sysregistriesv2.AuthenticationFileHelper`. - -const keyDescribePrefix = "container-registry-login:" //nolint:deadcode,unused - -func getAuthFromKernelKeyring(registry string) (string, string, error) { //nolint:deadcode,unused - userkeyring, err := keyctl.UserKeyring() - if err != nil { - return "", "", err - } - key, err := userkeyring.Search(genDescription(registry)) - if err != nil { - return "", "", err - } - authData, err := key.Get() - if err != nil { - return "", "", err - } - parts := strings.SplitN(string(authData), "\x00", 2) - if len(parts) != 2 { - return "", "", nil - } - return parts[0], parts[1], nil -} - -func deleteAuthFromKernelKeyring(registry string) error { //nolint:deadcode,unused - userkeyring, err := keyctl.UserKeyring() - - if err != nil { - return err - } - key, err := userkeyring.Search(genDescription(registry)) - if err != nil { - return err - } - return key.Unlink() -} - -func removeAllAuthFromKernelKeyring() error { //nolint:deadcode,unused - keys, err := keyctl.ReadUserKeyring() - if err != nil { - return err - } - - userkeyring, err := keyctl.UserKeyring() - if err != nil { - return err - } - - for _, k := range keys { - keyAttr, err := k.Describe() - if err != nil { - return err - } - // split string "type;uid;gid;perm;description" - keyAttrs := strings.SplitN(keyAttr, ";", 5) - if len(keyAttrs) < 5 { - return errors.Errorf("Key attributes of %d are not available", k.ID()) - } - keyDescribe := keyAttrs[4] - if strings.HasPrefix(keyDescribe, keyDescribePrefix) { - err := keyctl.Unlink(userkeyring, k) - if err != nil { - return errors.Wrapf(err, "unlinking key %d", k.ID()) - } - logrus.Debugf("unlinked key %d:%s", k.ID(), keyAttr) - } - } - return nil -} - -func setAuthToKernelKeyring(registry, username, password string) error { //nolint:deadcode,unused - keyring, err := keyctl.SessionKeyring() - if err != nil { - return err - } - id, err := keyring.Add(genDescription(registry), []byte(fmt.Sprintf("%s\x00%s", username, password))) - if err != nil { - return err - } - - // sets all permission(view,read,write,search,link,set attribute) for current user - // it enables the user to search the key after it linked to user keyring and unlinked from session keyring - err = keyctl.SetPerm(id, keyctl.PermUserAll) - if err != nil { - return err - } - // link the key to userKeyring - userKeyring, err := keyctl.UserKeyring() - if err != nil { - return errors.Wrapf(err, "getting user keyring") - } - err = keyctl.Link(userKeyring, id) - if err != nil { - return errors.Wrapf(err, "linking the key to user keyring") - } - // unlink the key from session keyring - err = keyctl.Unlink(keyring, id) - if err != nil { - return errors.Wrapf(err, "unlinking the key from session keyring") - } - return nil -} - -func genDescription(registry string) string { //nolint:deadcode,unused - return fmt.Sprintf("%s%s", keyDescribePrefix, registry) -} diff --git a/pkg/docker/config/config_unsupported.go b/pkg/docker/config/config_unsupported.go deleted file mode 100644 index d9827d8ed..000000000 --- a/pkg/docker/config/config_unsupported.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build !linux && (!386 || !amd64) -// +build !linux -// +build !386 !amd64 - -package config - -func getAuthFromKernelKeyring(registry string) (string, string, error) { //nolint:deadcode,unused - return "", "", ErrNotSupported -} - -func deleteAuthFromKernelKeyring(registry string) error { //nolint:deadcode,unused - return ErrNotSupported -} - -func setAuthToKernelKeyring(registry, username, password string) error { //nolint:deadcode,unused - return ErrNotSupported -} - -func removeAllAuthFromKernelKeyring() error { //nolint:deadcode,unused - return ErrNotSupported -}