mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-29 00:10:23 +00:00
b49bf4b987
This commit adds a couple of helper functions to parse the migration request secret and set it for further csi driver operations. More details: The intree secret has a data field called "key" which is the base64 admin secret key. The ceph CSI driver currently expect the secret to contain data field "UserKey" for the equivalant. The CSI driver also expect the "UserID" field which is not available in the in-tree secret by deafult. This missing userID will be filled (if the username differ than 'admin') in the migration secret as 'adminId' field in the migration request, this commit adds the logic to parse this migration secret as below: "key" field value will be picked up from the migraion secret to "UserKey" field. "adminId" field value will be picked up from the migration secret to "UserID" field if `adminId` field is nil or not set, `UserID` field will be filled with default value ie `admin`.The above logic get activated only when the secret is a migration secret, otherwise skipped to the normal workflow as we have today. Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
156 lines
4.6 KiB
Go
156 lines
4.6 KiB
Go
/*
|
|
Copyright 2018 The Ceph-CSI Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package util
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
)
|
|
|
|
const (
|
|
credUserID = "userID"
|
|
credUserKey = "userKey"
|
|
credAdminID = "adminID"
|
|
credAdminKey = "adminKey"
|
|
credMonitors = "monitors"
|
|
tmpKeyFileLocation = "/tmp/csi/keys"
|
|
tmpKeyFileNamePrefix = "keyfile-"
|
|
migUserName = "admin"
|
|
migUserID = "adminId"
|
|
migUserKey = "key"
|
|
)
|
|
|
|
// Credentials struct represents credentials to access the ceph cluster.
|
|
type Credentials struct {
|
|
ID string
|
|
KeyFile string
|
|
}
|
|
|
|
func storeKey(key string) (string, error) {
|
|
tmpfile, err := ioutil.TempFile(tmpKeyFileLocation, tmpKeyFileNamePrefix)
|
|
if err != nil {
|
|
return "", fmt.Errorf("error creating a temporary keyfile: %w", err)
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
// don't complain about unhandled error
|
|
_ = os.Remove(tmpfile.Name())
|
|
}
|
|
}()
|
|
|
|
if _, err = tmpfile.Write([]byte(key)); err != nil {
|
|
return "", fmt.Errorf("error writing key to temporary keyfile: %w", err)
|
|
}
|
|
|
|
keyFile := tmpfile.Name()
|
|
if keyFile == "" {
|
|
err = fmt.Errorf("error reading temporary filename for key: %w", err)
|
|
|
|
return "", err
|
|
}
|
|
|
|
if err = tmpfile.Close(); err != nil {
|
|
return "", fmt.Errorf("error closing temporary filename: %w", err)
|
|
}
|
|
|
|
return keyFile, nil
|
|
}
|
|
|
|
func newCredentialsFromSecret(idField, keyField string, secrets map[string]string) (*Credentials, error) {
|
|
var (
|
|
c = &Credentials{}
|
|
ok bool
|
|
)
|
|
|
|
if len(secrets) == 0 {
|
|
return nil, errors.New("provided secret is empty")
|
|
}
|
|
if c.ID, ok = secrets[idField]; !ok {
|
|
return nil, fmt.Errorf("missing ID field '%s' in secrets", idField)
|
|
}
|
|
|
|
key := secrets[keyField]
|
|
if key == "" {
|
|
return nil, fmt.Errorf("missing key field '%s' in secrets", keyField)
|
|
}
|
|
|
|
keyFile, err := storeKey(key)
|
|
if err == nil {
|
|
c.KeyFile = keyFile
|
|
}
|
|
|
|
return c, err
|
|
}
|
|
|
|
// DeleteCredentials removes the KeyFile.
|
|
func (cr *Credentials) DeleteCredentials() {
|
|
// don't complain about unhandled error
|
|
_ = os.Remove(cr.KeyFile)
|
|
}
|
|
|
|
// NewUserCredentials creates new user credentials from secret.
|
|
func NewUserCredentials(secrets map[string]string) (*Credentials, error) {
|
|
return newCredentialsFromSecret(credUserID, credUserKey, secrets)
|
|
}
|
|
|
|
// NewAdminCredentials creates new admin credentials from secret.
|
|
func NewAdminCredentials(secrets map[string]string) (*Credentials, error) {
|
|
return newCredentialsFromSecret(credAdminID, credAdminKey, secrets)
|
|
}
|
|
|
|
// GetMonValFromSecret returns monitors from secret.
|
|
func GetMonValFromSecret(secrets map[string]string) (string, error) {
|
|
if mons, ok := secrets[credMonitors]; ok {
|
|
return mons, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("missing %q", credMonitors)
|
|
}
|
|
|
|
// ParseAndSetSecretMapFromMigSecret parse the secretmap from the migration request and return
|
|
// newsecretmap with the userID and userKey fields set.
|
|
func ParseAndSetSecretMapFromMigSecret(secretmap map[string]string) (map[string]string, error) {
|
|
newSecretMap := make(map[string]string)
|
|
// parse and set userKey
|
|
if !IsMigrationSecret(secretmap) {
|
|
return nil, errors.New("passed secret map does not contain user key or it is nil")
|
|
}
|
|
newSecretMap[credUserKey] = secretmap[migUserKey]
|
|
// parse and set the userID
|
|
newSecretMap[credUserID] = migUserName
|
|
if secretmap[migUserID] != "" {
|
|
newSecretMap[credUserID] = secretmap[migUserID]
|
|
}
|
|
|
|
return newSecretMap, nil
|
|
}
|
|
|
|
// IsMigrationSecret validates if the passed in secretmap is a secret
|
|
// of a migration volume request. The migration secret carry a field
|
|
// called `key` which is the equivalent of `userKey` which is what we
|
|
// check here for identifying the secret.
|
|
func IsMigrationSecret(passedSecretMap map[string]string) bool {
|
|
// the below 'nil' check is an extra measure as the request validators like
|
|
// ValidateNodeStageVolumeRequest() already does the nil check, however considering
|
|
// this function can be called independently with a map of secret values
|
|
// it is good to have this check in place, also it gives clear error about this
|
|
// was hit on migration request compared to general one.
|
|
return len(passedSecretMap) != 0 && passedSecretMap[migUserKey] != ""
|
|
}
|