Skip to content

Commit

Permalink
add keyctl read&describe to remove auth from keyring
Browse files Browse the repository at this point in the history
Add method removeAllAuthFromKeyring.
Get key describes from keyring using KEYCTL_READ and KEYCTL_DESCRIBE, and remove them from keyring if the decription has prefix 'container-registry-login:'.

Signed-off-by: Qi Wang <qiwan@redhat.com>
  • Loading branch information
QiWang19 committed Aug 20, 2019
1 parent 7136ea7 commit cacda0d
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 8 deletions.
10 changes: 9 additions & 1 deletion pkg/docker/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,17 @@ func RemoveAuthentication(sys *types.SystemContext, registry string) error {
})
}

// RemoveAllAuthentication deletes all the credentials stored in auth.json
// RemoveAllAuthentication deletes all the credentials stored in auth.json and kernel keyring
func RemoveAllAuthentication(sys *types.SystemContext) error {
return modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
if enableKeyring {
err := removeAllAuthFromKernelKeyring()
if err == nil {
logrus.Debugf("removing all credentials from kernel keyring")
return false, nil
}
logrus.Debugf("error removing credentials from kernel keyring")
}
auths.CredHelpers = make(map[string]string)
auths.AuthConfigs = make(map[string]dockerAuthConfig)
return true, nil
Expand Down
49 changes: 48 additions & 1 deletion pkg/docker/config/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ package config
import (
"fmt"
"strings"
"unsafe"

"github.com/containers/image/pkg/keyctl"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)

const keyDescribePrefix = "container-registry-login:"

func getAuthFromKernelKeyring(registry string) (string, string, error) {
userkeyring, err := keyctl.UserKeyring()
if err != nil {
Expand Down Expand Up @@ -41,6 +46,38 @@ func deleteAuthFromKernelKeyring(registry string) error {
return key.Unlink()
}

func removeAllAuthFromKernelKeyring() error {
keyring := keyctl.Key{
Id: unix.KEY_SPEC_USER_KEYRING,
}

byteKIDs, err := keyring.Get()
if err != nil {
return err
}
keyIDs := getKeyIDsFromByte(byteKIDs)
for _, kID := range keyIDs {
keyAttr, err := unix.KeyctlString(unix.KEYCTL_DESCRIBE, int(kID))
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 avaliable", kID)
}
keyDescribe := keyAttrs[4]
if strings.HasPrefix(keyDescribe, keyDescribePrefix) {
_, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, int(kID), int(unix.KEY_SPEC_USER_KEYRING), 0, 0)
if err != nil {
return errors.Wrapf(err, "error unlinking key %d", kID)
}
logrus.Debugf("unlink key %d:%s", kID, keyAttr)
}
}
return nil
}

func setAuthToKernelKeyring(registry, username, password string) error {
keyring, err := keyctl.SessionKeyring()
if err != nil {
Expand Down Expand Up @@ -75,5 +112,15 @@ func setAuthToKernelKeyring(registry, username, password string) error {
}

func genDescription(registry string) string {
return fmt.Sprintf("container-registry-login:%s", registry)
return fmt.Sprintf("%s%s", keyDescribePrefix, registry)
}

func getKeyIDsFromByte(byteKeyIDs []byte) []int32 {
idSize := 4
var keyIDs []int32
for idx := 0; idx+idSize <= len(byteKeyIDs); idx = idx + idSize {
tempID := *(*int32)(unsafe.Pointer(&byteKeyIDs[idx]))
keyIDs = append(keyIDs, tempID)
}
return keyIDs
}
4 changes: 4 additions & 0 deletions pkg/docker/config/config_unsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ func deleteAuthFromKernelKeyring(registry string) error {
func setAuthToKernelKeyring(registry, username, password string) error {
return ErrNotSupported
}

func removeAllAuthFromKernelKeyring() error {
return ErrNotSupported
}
8 changes: 4 additions & 4 deletions pkg/keyctl/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import (
type Key struct {
Name string

id, ring keyID
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)
return int32(k.Id)
}

// Get the key's value as a byte slice
Expand All @@ -40,7 +40,7 @@ func (k *Key) Get() ([]byte, error) {
b = make([]byte, int(size))
sizeRead = size + 1
for sizeRead > size {
r1, err := unix.KeyctlBuffer(unix.KEYCTL_READ, int(k.id), b, size)
r1, err := unix.KeyctlBuffer(unix.KEYCTL_READ, int(k.Id), b, size)
if err != nil {
return nil, err
}
Expand All @@ -59,6 +59,6 @@ func (k *Key) Get() ([]byte, error) {
// 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)
_, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, int(k.Id), int(k.ring), 0, 0)
return err
}
4 changes: 2 additions & 2 deletions pkg/keyctl/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type ID interface {
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}
key := &Key{Name: name, Id: keyID(r), ring: kr.id}
return key, nil
}
return nil, err
Expand All @@ -46,7 +46,7 @@ func (kr *keyring) Add(name string, key []byte) (*Key, error) {
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 &Key{Name: name, Id: keyID(id), ring: kr.id}, nil
}
return nil, err
}
Expand Down

0 comments on commit cacda0d

Please sign in to comment.