Use --keyfile option to pass keys to all Ceph CLIs

Every Ceph CLI that is invoked at present passes the key via the
--key option, and hence is exposed to key being displayed on
the host using a ps command or such means.

This commit addresses this issue by stashing the key in a tmp
file, which is again created on a tmpfs (or empty dir backed by
memory). Further using such tmp files as arguments to the --keyfile
option for every CLI that is invoked.

This prevents the key from being visible as part of the argument list
of the invoked program on the system.

Fixes: #318

Signed-off-by: ShyamsundarR <srangana@redhat.com>
This commit is contained in:
ShyamsundarR
2019-06-25 15:29:17 -04:00
committed by mergify[bot]
parent c2835183e5
commit bd204d7d45
24 changed files with 191 additions and 69 deletions

View File

@ -63,7 +63,7 @@ func getPools(monitors string, cr *Credentials) ([]cephStoragePoolSummary, error
"ceph",
"-m", monitors,
"--id", cr.ID,
"--key="+cr.Key,
"--keyfile="+cr.KeyFile,
"-c", CephConfigPath,
"-f", "json",
"osd", "lspools")
@ -122,7 +122,7 @@ func SetOMapKeyValue(monitors string, cr *Credentials, poolName, namespace, oMap
args := []string{
"-m", monitors,
"--id", cr.ID,
"--key=" + cr.Key,
"--keyfile=" + cr.KeyFile,
"-c", CephConfigPath,
"-p", poolName,
"setomapval", oMapName, oMapKey, keyValue,
@ -157,7 +157,7 @@ func GetOMapValue(monitors string, cr *Credentials, poolName, namespace, oMapNam
args := []string{
"-m", monitors,
"--id", cr.ID,
"--key=" + cr.Key,
"--keyfile=" + cr.KeyFile,
"-c", CephConfigPath,
"-p", poolName,
"getomapval", oMapName, oMapKey, tmpFile.Name(),
@ -199,7 +199,7 @@ func RemoveOMapKey(monitors string, cr *Credentials, poolName, namespace, oMapNa
args := []string{
"-m", monitors,
"--id", cr.ID,
"--key=" + cr.Key,
"--keyfile=" + cr.KeyFile,
"-c", CephConfigPath,
"-p", poolName,
"rmomapkey", oMapName, oMapKey,
@ -227,7 +227,7 @@ func CreateObject(monitors string, cr *Credentials, poolName, namespace, objectN
args := []string{
"-m", monitors,
"--id", cr.ID,
"--key=" + cr.Key,
"--keyfile=" + cr.KeyFile,
"-c", CephConfigPath,
"-p", poolName,
"create", objectName,
@ -257,7 +257,7 @@ func RemoveObject(monitors string, cr *Credentials, poolName, namespace, oMapNam
args := []string{
"-m", monitors,
"--id", cr.ID,
"--key=" + cr.Key,
"--keyfile=" + cr.KeyFile,
"-c", CephConfigPath,
"-p", poolName,
"rm", oMapName,

View File

@ -18,22 +18,54 @@ package util
import (
"fmt"
"io/ioutil"
"os"
)
const (
credUserID = "userID"
credUserKey = "userKey"
credAdminID = "adminID"
credAdminKey = "adminKey"
credMonitors = "monitors"
credUserID = "userID"
credUserKey = "userKey"
credAdminID = "adminID"
credAdminKey = "adminKey"
credMonitors = "monitors"
tmpKeyFileLocation = "/tmp/csi/keys"
tmpKeyFileNamePrefix = "keyfile-"
)
type Credentials struct {
ID string
Key string
ID string
KeyFile string
}
func getCredentials(idField, keyField string, secrets map[string]string) (*Credentials, error) {
func storeKey(key string) (string, error) {
tmpfile, err := ioutil.TempFile(tmpKeyFileLocation, tmpKeyFileNamePrefix)
if err != nil {
return "", fmt.Errorf("error creating a temporary keyfile (%s)", err)
}
defer func() {
if err != nil {
os.Remove(tmpfile.Name())
}
}()
if _, err = tmpfile.Write([]byte(key)); err != nil {
return "", fmt.Errorf("error writing key to temporary keyfile (%s)", err)
}
keyFile := tmpfile.Name()
if keyFile == "" {
err = fmt.Errorf("error reading temporary filename for key (%s)", err)
return "", err
}
if err = tmpfile.Close(); err != nil {
return "", fmt.Errorf("error closing temporary filename (%s)", err)
}
return keyFile, nil
}
func newCredentialsFromSecret(idField, keyField string, secrets map[string]string) (*Credentials, error) {
var (
c = &Credentials{}
ok bool
@ -43,19 +75,41 @@ func getCredentials(idField, keyField string, secrets map[string]string) (*Crede
return nil, fmt.Errorf("missing ID field '%s' in secrets", idField)
}
if c.Key, ok = secrets[keyField]; !ok {
key := secrets[keyField]
if key == "" {
return nil, fmt.Errorf("missing key field '%s' in secrets", keyField)
}
return c, nil
keyFile, err := storeKey(key)
if err == nil {
c.KeyFile = keyFile
}
return c, err
}
func GetUserCredentials(secrets map[string]string) (*Credentials, error) {
return getCredentials(credUserID, credUserKey, secrets)
func (cr *Credentials) DeleteCredentials() {
os.Remove(cr.KeyFile)
}
func GetAdminCredentials(secrets map[string]string) (*Credentials, error) {
return getCredentials(credAdminID, credAdminKey, secrets)
func NewUserCredentials(secrets map[string]string) (*Credentials, error) {
return newCredentialsFromSecret(credUserID, credUserKey, secrets)
}
func NewAdminCredentials(secrets map[string]string) (*Credentials, error) {
return newCredentialsFromSecret(credAdminID, credAdminKey, secrets)
}
func NewCredentials(id, key string) (*Credentials, error) {
var c = &Credentials{}
c.ID = id
keyFile, err := storeKey(key)
if err == nil {
c.KeyFile = keyFile
}
return c, err
}
func GetMonValFromSecret(secrets map[string]string) (string, error) {

View File

@ -22,15 +22,17 @@ import (
const (
keyArg = "--key="
keyFileArg = "--keyfile="
secretArg = "secret="
optionsArgSeparator = ','
strippedKey = "--key=***stripped***"
strippedKeyFile = "--keyfile=***stripped***"
strippedSecret = "secret=***stripped***"
)
// StripSecretInArgs strips values of either "--key" or "secret=".
// StripSecretInArgs strips values of either "--key"/"--keyfile" or "secret=".
// `args` is left unchanged.
// Expects only one occurrence of either "--key" or "secret=".
// Expects only one occurrence of either "--key"/"--keyfile" or "secret=".
func StripSecretInArgs(args []string) []string {
out := make([]string, len(args))
copy(out, args)
@ -48,6 +50,11 @@ func stripKey(out []string) bool {
out[i] = strippedKey
return true
}
if strings.HasPrefix(out[i], keyFileArg) {
out[i] = strippedKeyFile
return true
}
}
return false