Refactor and simplify etcd helpers used in IAM subsystem (#7980)

master
Harshavardhana 5 years ago committed by kannappanr
parent 007a52b546
commit e871e27562
  1. 53
      cmd/config-common.go
  2. 2
      cmd/config-migrate.go
  3. 72
      cmd/etcd.go
  4. 17
      cmd/iam.go

@ -20,9 +20,7 @@ import (
"bytes" "bytes"
"context" "context"
"errors" "errors"
"fmt"
etcd "github.com/coreos/etcd/clientv3"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/hash" "github.com/minio/minio/pkg/hash"
) )
@ -51,38 +49,10 @@ func readConfig(ctx context.Context, objAPI ObjectLayer, configFile string) ([]b
return buffer.Bytes(), nil return buffer.Bytes(), nil
} }
func deleteConfigEtcd(ctx context.Context, client *etcd.Client, configFile string) error {
timeoutCtx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel()
_, err := client.Delete(timeoutCtx, configFile)
if err != nil {
if err == context.DeadlineExceeded {
return fmt.Errorf("etcd setup is unreachable, please check your endpoints %s",
client.Endpoints())
}
return fmt.Errorf("unexpected error %s returned by etcd setup, please check your endpoints %s",
err, client.Endpoints())
}
return nil
}
func deleteConfig(ctx context.Context, objAPI ObjectLayer, configFile string) error { func deleteConfig(ctx context.Context, objAPI ObjectLayer, configFile string) error {
return objAPI.DeleteObject(ctx, minioMetaBucket, configFile) return objAPI.DeleteObject(ctx, minioMetaBucket, configFile)
} }
func saveConfigEtcd(ctx context.Context, client *etcd.Client, configFile string, data []byte) error {
timeoutCtx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel()
_, err := client.Put(timeoutCtx, configFile, string(data))
if err == context.DeadlineExceeded {
return fmt.Errorf("etcd setup is unreachable, please check your endpoints %s", client.Endpoints())
} else if err != nil {
return fmt.Errorf("unexpected error %s returned by etcd setup, please check your endpoints %s", err, client.Endpoints())
}
return nil
}
func saveConfig(ctx context.Context, objAPI ObjectLayer, configFile string, data []byte) error { func saveConfig(ctx context.Context, objAPI ObjectLayer, configFile string, data []byte) error {
hashReader, err := hash.NewReader(bytes.NewReader(data), int64(len(data)), "", getSHA256Hash(data), int64(len(data)), globalCLIContext.StrictS3Compat) hashReader, err := hash.NewReader(bytes.NewReader(data), int64(len(data)), "", getSHA256Hash(data), int64(len(data)), globalCLIContext.StrictS3Compat)
if err != nil { if err != nil {
@ -93,29 +63,6 @@ func saveConfig(ctx context.Context, objAPI ObjectLayer, configFile string, data
return err return err
} }
func readConfigEtcd(ctx context.Context, client *etcd.Client, configFile string) ([]byte, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel()
resp, err := client.Get(timeoutCtx, configFile)
if err != nil {
if err == context.DeadlineExceeded {
return nil, fmt.Errorf("etcd setup is unreachable, please check your endpoints %s",
client.Endpoints())
}
return nil, fmt.Errorf("unexpected error %s returned by etcd setup, please check your endpoints %s",
err, client.Endpoints())
}
if resp.Count == 0 {
return nil, errConfigNotFound
}
for _, ev := range resp.Kvs {
if string(ev.Key) == configFile {
return ev.Value, nil
}
}
return nil, errConfigNotFound
}
func checkConfig(ctx context.Context, objAPI ObjectLayer, configFile string) error { func checkConfig(ctx context.Context, objAPI ObjectLayer, configFile string) error {
if _, err := objAPI.GetObjectInfo(ctx, minioMetaBucket, configFile, ObjectOptions{}); err != nil { if _, err := objAPI.GetObjectInfo(ctx, minioMetaBucket, configFile, ObjectOptions{}); err != nil {
// Treat object not found as config not found. // Treat object not found as config not found.

@ -2426,7 +2426,7 @@ func migrateConfigToMinioSys(objAPI ObjectLayer) (err error) {
defer func() { defer func() {
if err == nil { if err == nil {
if globalEtcdClient != nil { if globalEtcdClient != nil {
deleteConfigEtcd(context.Background(), globalEtcdClient, configFile) deleteKeyEtcd(context.Background(), globalEtcdClient, configFile)
} else { } else {
// Rename config.json to config.json.deprecated only upon // Rename config.json to config.json.deprecated only upon
// success of this function. // success of this function.

@ -0,0 +1,72 @@
/*
* MinIO Cloud Storage, (C) 2019 MinIO, Inc.
*
* 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 cmd
import (
"context"
"errors"
"fmt"
etcd "github.com/coreos/etcd/clientv3"
)
var errEtcdUnreachable = errors.New("etcd is unreachable, please check your endpoints")
func etcdErrToErr(err error, etcdEndpoints []string) error {
if err == nil {
return nil
}
switch err {
case context.DeadlineExceeded:
return fmt.Errorf("%s %s", errEtcdUnreachable, etcdEndpoints)
default:
return fmt.Errorf("unexpected error %s from etcd, please check your endpoints %s", err, etcdEndpoints)
}
}
func saveKeyEtcd(ctx context.Context, client *etcd.Client, key string, data []byte) error {
timeoutCtx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel()
_, err := client.Put(timeoutCtx, key, string(data))
return etcdErrToErr(err, client.Endpoints())
}
func deleteKeyEtcd(ctx context.Context, client *etcd.Client, key string) error {
timeoutCtx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel()
_, err := client.Delete(timeoutCtx, key)
return etcdErrToErr(err, client.Endpoints())
}
func readKeyEtcd(ctx context.Context, client *etcd.Client, key string) ([]byte, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel()
resp, err := client.Get(timeoutCtx, key)
if err != nil {
return nil, etcdErrToErr(err, client.Endpoints())
}
if resp.Count == 0 {
return nil, errConfigNotFound
}
for _, ev := range resp.Kvs {
if string(ev.Key) == key {
return ev.Value, nil
}
}
return nil, errConfigNotFound
}

@ -194,7 +194,7 @@ func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool,
} }
func loadIAMConfigItemEtcd(ctx context.Context, item interface{}, path string) error { func loadIAMConfigItemEtcd(ctx context.Context, item interface{}, path string) error {
pdata, err := readConfigEtcd(ctx, globalEtcdClient, path) pdata, err := readKeyEtcd(ctx, globalEtcdClient, path)
if err != nil { if err != nil {
return err return err
} }
@ -206,7 +206,7 @@ func saveIAMConfigItemEtcd(ctx context.Context, item interface{}, path string) e
if err != nil { if err != nil {
return err return err
} }
return saveConfigEtcd(context.Background(), globalEtcdClient, path, data) return saveKeyEtcd(ctx, globalEtcdClient, path, data)
} }
// IAMSys - config system. // IAMSys - config system.
@ -601,7 +601,7 @@ func migrateUsersConfigEtcdToV1(isSTS bool) error {
} }
// 3. delete policy file in old loc. // 3. delete policy file in old loc.
deleteConfigEtcd(ctx, globalEtcdClient, oldPolicyPath) deleteKeyEtcd(ctx, globalEtcdClient, oldPolicyPath)
} }
next: next:
@ -793,7 +793,7 @@ func (sys *IAMSys) DeletePolicy(policyName string) error {
var err error var err error
pFile := getPolicyDocPath(policyName) pFile := getPolicyDocPath(policyName)
if globalEtcdClient != nil { if globalEtcdClient != nil {
err = deleteConfigEtcd(context.Background(), globalEtcdClient, pFile) err = deleteKeyEtcd(context.Background(), globalEtcdClient, pFile)
} else { } else {
err = deleteConfig(context.Background(), objectAPI, pFile) err = deleteConfig(context.Background(), objectAPI, pFile)
} }
@ -875,8 +875,8 @@ func (sys *IAMSys) DeleteUser(accessKey string) error {
idPath := getUserIdentityPath(accessKey, false) idPath := getUserIdentityPath(accessKey, false)
if globalEtcdClient != nil { if globalEtcdClient != nil {
// It is okay to ignore errors when deleting policy.json for the user. // It is okay to ignore errors when deleting policy.json for the user.
deleteConfigEtcd(context.Background(), globalEtcdClient, mappingPath) deleteKeyEtcd(context.Background(), globalEtcdClient, mappingPath)
err = deleteConfigEtcd(context.Background(), globalEtcdClient, idPath) err = deleteKeyEtcd(context.Background(), globalEtcdClient, idPath)
} else { } else {
// It is okay to ignore errors when deleting policy.json for the user. // It is okay to ignore errors when deleting policy.json for the user.
_ = deleteConfig(context.Background(), objectAPI, mappingPath) _ = deleteConfig(context.Background(), objectAPI, mappingPath)
@ -1338,10 +1338,9 @@ func loadEtcdUser(ctx context.Context, user string, isSTS bool, m map[string]aut
} }
if u.Credentials.IsExpired() { if u.Credentials.IsExpired() {
idPath := getUserIdentityPath(user, isSTS)
// Delete expired identity. // Delete expired identity.
deleteConfigEtcd(ctx, globalEtcdClient, idPath) deleteKeyEtcd(ctx, globalEtcdClient, getUserIdentityPath(user, isSTS))
deleteConfigEtcd(ctx, globalEtcdClient, getMappedPolicyPath(user, isSTS)) deleteKeyEtcd(ctx, globalEtcdClient, getMappedPolicyPath(user, isSTS))
return nil return nil
} }

Loading…
Cancel
Save