Skip to content

Commit

Permalink
Merge pull request #683 from QiWang19/rm_all_keyring
Browse files Browse the repository at this point in the history
move keyctl to internal & func remove auth from keyring
  • Loading branch information
rhatdan authored Sep 16, 2019
2 parents b344f2f + d033863 commit 9bafe00
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 3 deletions.
9 changes: 9 additions & 0 deletions pkg/keyctl/key.go → internal/pkg/keyctl/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,12 @@ 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
}
41 changes: 41 additions & 0 deletions pkg/keyctl/keyring.go → internal/pkg/keyctl/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
package keyctl

import (
"unsafe"

"golang.org/x/sys/unix"
)

Expand Down Expand Up @@ -77,3 +79,42 @@ 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
}
58 changes: 58 additions & 0 deletions pkg/keyctl/keyring_test.go → internal/pkg/keyctl/keyring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package keyctl

import (
"crypto/rand"
"strings"
"testing"
)

Expand Down Expand Up @@ -143,3 +144,60 @@ func TestUnlink(t *testing.T) {
t.Fatal(err)
}
}

func TestReadKeyring(t *testing.T) {
token := make([]byte, 20)
rand.Read(token)

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)
rand.Read(token)

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)
}
}
File renamed without changes.
File renamed without changes.
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
40 changes: 38 additions & 2 deletions pkg/docker/config/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import (
"fmt"
"strings"

"github.com/containers/image/pkg/keyctl"
"github.com/containers/image/internal/pkg/keyctl"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)

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 +44,39 @@ func deleteAuthFromKernelKeyring(registry string) error {
return key.Unlink()
}

func removeAllAuthFromKernelKeyring() error {
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 avaliable", k.ID())
}
keyDescribe := keyAttrs[4]
if strings.HasPrefix(keyDescribe, keyDescribePrefix) {
err := keyctl.Unlink(userkeyring, k)
if err != nil {
return errors.Wrapf(err, "error unlinking key %d", k.ID())
}
logrus.Debugf("unlinked key %d:%s", k.ID(), keyAttr)
}
}
return nil
}

func setAuthToKernelKeyring(registry, username, password string) error {
keyring, err := keyctl.SessionKeyring()
if err != nil {
Expand Down Expand Up @@ -75,5 +111,5 @@ 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)
}
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
}

0 comments on commit 9bafe00

Please sign in to comment.