Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ATOM-2] Moving Access control from AKO to management-lib #59

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
522 changes: 522 additions & 0 deletions accesscontrol/access_control.go

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions accesscontrol/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package accesscontrol

// PrivilegeScope enumerates valid scopes for privileges.
type PrivilegeScope int

const (
// Global scoped privileges.
Global PrivilegeScope = iota

// NamespaceSet is namespace and optional set scoped privilege.
NamespaceSet
)

// Privileges are all privilege string allowed in the spec and associated scopes.
var Privileges = map[string][]PrivilegeScope{
"read": {Global, NamespaceSet},
"write": {Global, NamespaceSet},
"read-write": {Global, NamespaceSet},
"read-write-udf": {Global, NamespaceSet},
"data-admin": {Global},
"sys-admin": {Global},
"user-admin": {Global},
"truncate": {Global, NamespaceSet},
"sindex-admin": {Global},
"udf-admin": {Global},
}

// Post6Privileges are post version 6.0 privilege strings allowed in the spec and associated scopes.
var Post6Privileges = map[string][]PrivilegeScope{
"truncate": {Global, NamespaceSet},
"sindex-admin": {Global},
"udf-admin": {Global},
}
47 changes: 29 additions & 18 deletions asconfig/as_getconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strings"

sets "github.com/deckarep/golang-set/v2"
"github.com/go-logr/logr"

aero "github.com/aerospike/aerospike-client-go/v7"
Expand All @@ -13,44 +14,54 @@ import (
)

// GetASConfig returns the value of the given path from the aerospike config from given host.
func GetASConfig(path *string, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy) (
confToReturn interface{}, err error) {
func GetASConfig(paths []string, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy) (
confToReturn map[string]interface{}, err error) {
h := aero.Host{
Name: conn.AerospikeHostName,
Port: conn.AerospikePort,
TLSName: conn.AerospikeTLSName,
}
asinfo := info.NewAsInfo(conn.Log, &h, aerospikePolicy)
ctxs := sets.NewSet[string]()

var ctxs []string
if path != nil {
for _, path := range paths {
// Get the corresponding sets info also if context is namespace.
ctxs = []string{ContextKey(*path)}
if ctxs[0] == info.ConfigNamespaceContext {
ctxs = append(ctxs, info.ConfigSetContext)
ctx := ContextKey(path)
ctxs.Add(ctx)

if ctx == info.ConfigNamespaceContext {
ctxs.Add(info.ConfigSetContext)
}
}

conf, err := asinfo.GetAsConfig(ctxs...)
conf, err := asinfo.GetAsConfig(ctxs.ToSlice()...)
if err != nil {
conn.Log.Error(err, "failed to get asconfig")
return nil, err
}

if path == nil {
if len(paths) == 0 {
return conf, nil
}

confToReturn = conf[ctxs[0]]
if confToReturn == nil {
conn.Log.Info("Config is nil", "context", ctxs[0])
return nil, nil
}
confToReturn = make(map[string]interface{})

confToReturn, err = traverseConfig(conn.Log, confToReturn, *path, ctxs[0])
if err != nil {
conn.Log.Error(err, "failed to traverse config")
return nil, err
for _, path := range paths {
ctx := ContextKey(path)

ctxConf := conf[ctx]
if ctxConf == nil {
conn.Log.Info("Config is nil", "context", ctxConf)
return nil, nil
}

ctxConf, err = traverseConfig(conn.Log, ctxConf, path, ctx)
if err != nil {
conn.Log.Error(err, "failed to traverse config")
return nil, err
}

confToReturn[path] = ctxConf
}

return confToReturn, nil
Expand Down
117 changes: 109 additions & 8 deletions asconfig/as_setconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (

// convertValueToString converts the value of a config to a string.
// only string type can be used to populate set-config commands with values.
func convertValueToString(v1 map[Operation]interface{}) (map[Operation][]string, error) {
valueMap := make(map[Operation][]string)
func convertValueToString(v1 map[OpType]interface{}) (map[OpType][]string, error) {
valueMap := make(map[OpType][]string)

for k, v := range v1 {
values := make([]string, 0)
Expand Down Expand Up @@ -54,7 +54,7 @@ func convertValueToString(v1 map[Operation]interface{}) (map[Operation][]string,
}

// createSetConfigServiceCmdList creates set-config commands for service context.
func createSetConfigServiceCmdList(tokens []string, operationValueMap map[Operation][]string) []string {
func createSetConfigServiceCmdList(tokens []string, operationValueMap map[OpType][]string) []string {
val := operationValueMap[Update]
cmdList := make([]string, 0, len(val))
cmd := cmdSetConfigService
Expand All @@ -74,7 +74,7 @@ func createSetConfigServiceCmdList(tokens []string, operationValueMap map[Operat
}

// createSetConfigNetworkCmdList creates set-config commands for network context.
func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[Operation][]string) []string {
func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[OpType][]string) []string {
val := operationValueMap[Update]
cmdList := make([]string, 0, len(val))
cmd := cmdSetConfigNetwork
Expand All @@ -94,7 +94,7 @@ func createSetConfigNetworkCmdList(tokens []string, operationValueMap map[Operat
}

// createSetConfigSecurityCmdList creates set-config commands for security context.
func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[Operation][]string) []string {
func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[OpType][]string) []string {
cmdList := make([]string, 0, len(operationValueMap))
cmd := cmdSetConfigSecurity

Expand Down Expand Up @@ -178,7 +178,7 @@ func createSetConfigSecurityCmdList(tokens []string, operationValueMap map[Opera
}

// createSetConfigNamespaceCmdList creates set-config commands for namespace context.
func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[Operation][]string) []string {
func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[OpType][]string) []string {
val := operationValueMap[Update]
cmdList := make([]string, 0, len(val))
cmd := cmdSetConfigNamespace
Expand Down Expand Up @@ -221,7 +221,7 @@ func createSetConfigNamespaceCmdList(tokens []string, operationValueMap map[Oper
}

// createLogSetCmdList creates log-set commands for logging context.
func createLogSetCmdList(tokens []string, operationValueMap map[Operation][]string,
func createLogSetCmdList(tokens []string, operationValueMap map[OpType][]string,
conn deployment.ASConnInterface, aerospikePolicy *aero.ClientPolicy) ([]string, error) {
val := operationValueMap[Update]
cmdList := make([]string, 0, len(val))
Expand Down Expand Up @@ -254,7 +254,7 @@ func createLogSetCmdList(tokens []string, operationValueMap map[Operation][]stri
}

// createSetConfigXDRCmdList creates set-config commands for XDR context.
func createSetConfigXDRCmdList(tokens []string, operationValueMap map[Operation][]string) []string {
func createSetConfigXDRCmdList(tokens []string, operationValueMap map[OpType][]string) []string {
cmdList := make([]string, 0, len(operationValueMap))
cmd := cmdSetConfigXDR
prevToken := ""
Expand Down Expand Up @@ -464,3 +464,104 @@ func rearrangeConfigMap(log logr.Logger, configMap DynamicConfigMap) []string {

return finalList
}

func ValidConfigOperations() []OpType {
return []OpType{Add, Update, Remove}
}

func (o OpType) Validate() error {
switch o {
case Add, Update, Remove:
return nil
}

return fmt.Errorf("invalid operation type: %s, Valid operations: %v", o, ValidConfigOperations())
}

type ConfigOperation struct {
Operation OpType `json:"op"`
Context string `json:"context"`
Config string `json:"config"`
Value string `json:"value,omitempty"`
}

func (p ConfigOperation) Validate() error {
return p.Operation.Validate()
}

func CreateConfigSetCmdsUsingPatch(
configMap map[string]interface{}, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy, version string,
) ([]string, error) {
conf, err := NewMapAsConfig(conn.Log, configMap)
if err != nil {
return nil, err
}

flatConf := conf.GetFlatMap()
asConfChange := make(DynamicConfigMap)

for k, v := range *flatConf {
if strings.HasSuffix(k, sep+KeyName) || strings.HasSuffix(k, sep+keyIndex) {
// skip namespace, dc, etc names
continue
}

if ok, _ := isListField(k); ok {
// Ignore these fields as these operations are not update operations
//TODO: Should we through an error if these fields are present in the configMap patch?
continue
}

valueMap := make(map[OpType]interface{})
valueMap[Update] = v
asConfChange[k] = valueMap
}

isDynamic, err := IsAllDynamicConfig(conn.Log, asConfChange, version)
if err != nil {
return nil, err
}

if !isDynamic {
return nil, fmt.Errorf("static field has been changed, cannot change config dynamically")
}

return CreateSetConfigCmdList(logr.Logger{}, asConfChange, conn, aerospikePolicy)
}

func CreateConfigSetCmdsUsingOperation(
confOp ConfigOperation, conn *deployment.ASConn, aerospikePolicy *aero.ClientPolicy, version string,
) ([]string, error) {
if err := confOp.Validate(); err != nil {
return nil, err
}
// Context: security.log, Config:report-data-op, Value:test set
// Map: security.log.report-data-op:map[remove:"test set"]
path := confOp.Context + sep + confOp.Config
value := confOp.Value

if confOp.Config == KeyName {
if confOp.Operation == Update {
return nil, fmt.Errorf("cannot update name field")
}
// Context: namespaces, Config: name, value: ns1
// Map: namespaces.{testMem}.name:map[remove:testMem]
path = confOp.Context + sep + string(SectionNameStartChar) + value + string(SectionNameEndChar) + sep + KeyName
}

asConfChange := make(DynamicConfigMap)
valueMap := make(map[OpType]interface{})
valueMap[confOp.Operation] = value
asConfChange[path] = valueMap

isDynamic, err := IsAllDynamicConfig(conn.Log, asConfChange, version)
if err != nil {
return nil, err
}

if !isDynamic {
return nil, fmt.Errorf("static field has been changed, cannot change config dynamically")
}

return CreateSetConfigCmdList(logr.Logger{}, asConfChange, conn, aerospikePolicy)
}
10 changes: 5 additions & 5 deletions asconfig/confdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func handleMissingSection(log logr.Logger, key string, desired, current Conf, d
// Whole section which has "name" as key is not present in current
// If token is under "{}", then it is a named section
if _, okay := current[nameKeyPath]; ReCurlyBraces.MatchString(token) && !okay {
operationValueMap := make(map[Operation]interface{})
operationValueMap := make(map[OpType]interface{})

if desiredToActual {
if _, updated := d[key]; !updated {
Expand Down Expand Up @@ -193,7 +193,7 @@ func handlePartialMissingSection(desiredKey, ver string, current Conf, d Dynamic
continue
}

operationValueMap := make(map[Operation]interface{})
operationValueMap := make(map[OpType]interface{})
// If removed subsection is of type slice, then there is no default values to be set.
// eg. current = security.log.report-data-op: []string{test}
// desired = security: {}
Expand All @@ -218,7 +218,7 @@ func handlePartialMissingSection(desiredKey, ver string, current Conf, d Dynamic
}

func handleSliceFields(key string, desired Conf, d DynamicConfigMap, desiredToActual bool) {
operationValueMap := make(map[Operation]interface{})
operationValueMap := make(map[OpType]interface{})

if reflect.ValueOf(desired[key]).Kind() == reflect.Slice {
if desiredToActual {
Expand All @@ -234,7 +234,7 @@ func handleSliceFields(key string, desired Conf, d DynamicConfigMap, desiredToAc
}

func handleValueDiff(key string, desiredValue, currentValue interface{}, d DynamicConfigMap) {
operationValueMap := make(map[Operation]interface{})
operationValueMap := make(map[OpType]interface{})

if reflect.ValueOf(desiredValue).Kind() == reflect.Slice {
currentSet := sets.NewSet[string]()
Expand Down Expand Up @@ -366,7 +366,7 @@ func ConfDiff(
return nil, err
}

valueMap := make(map[Operation]interface{})
valueMap := make(map[OpType]interface{})
valueMap[Update] = getDefaultValue(defaultMap, removedConfigKey)
diffs[removedConfigKey] = valueMap
}
Expand Down
10 changes: 5 additions & 5 deletions asconfig/constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package asconfig

type Operation string
type OpType string

// All the aerospike config related keys
const (
Expand Down Expand Up @@ -33,8 +33,8 @@ const (
equal = "="
colon = ":"

// Enum values for Operation
Add Operation = "add"
Remove Operation = "remove"
Update Operation = "update"
// Enum values for OpType
Add OpType = "add"
Remove OpType = "remove"
Update OpType = "update"
)
2 changes: 1 addition & 1 deletion asconfig/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func IsAllDynamicConfig(log logr.Logger, configMap DynamicConfigMap, version str

// IsDynamicConfig returns true if the given field is dynamically configured.
func IsDynamicConfig(log logr.Logger, dynamic sets.Set[string], conf string,
valueMap map[Operation]interface{}) bool {
valueMap map[OpType]interface{}) bool {
tokens := SplitKey(log, conf, sep)
baseKey := tokens[len(tokens)-1]
context := tokens[0]
Expand Down
2 changes: 1 addition & 1 deletion asconfig/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -1135,4 +1135,4 @@ var ReCurlyBraces = regexp.MustCompile(`^\{.*\}$`)

// DynamicConfigMap is a map of config flatten keys and their operations and values
// for eg: "xdr.dcs.{DC3}.node-address-ports": {Remove: []string{"1.1.2.1 3000"}}
type DynamicConfigMap map[string]map[Operation]interface{}
type DynamicConfigMap map[string]map[OpType]interface{}
10 changes: 10 additions & 0 deletions deployment/aeroinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,13 @@ func GetInfoOnHosts(log logr.Logger, policy *aero.ClientPolicy,

return c.infoOnHosts(getHostIDsFromHostConns(allHosts), cmd)
}

func GetNamespaceStats(hostConns []*HostConn, policy *aero.ClientPolicy,
namespace string) (map[string]InfoResult, error) {
clHosts, err := getHostsFromHostConns(hostConns, policy)
if err != nil {
return nil, err
}

return getNamespaceStats(clHosts, namespace)
}
Loading
Loading