mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 18:17:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			157 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package namespace
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/hashicorp/vault/sdk/helper/consts"
 | |
| )
 | |
| 
 | |
| type contextValues struct{}
 | |
| 
 | |
| type Namespace struct {
 | |
| 	ID             string            `json:"id" mapstructure:"id"`
 | |
| 	Path           string            `json:"path" mapstructure:"path"`
 | |
| 	CustomMetadata map[string]string `json:"custom_metadata" mapstructure:"custom_metadata"`
 | |
| }
 | |
| 
 | |
| func (n *Namespace) String() string {
 | |
| 	return fmt.Sprintf("ID: %s. Path: %s", n.ID, n.Path)
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	RootNamespaceID = "root"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	contextNamespace contextValues = struct{}{}
 | |
| 	ErrNoNamespace   error         = errors.New("no namespace")
 | |
| 	RootNamespace    *Namespace    = &Namespace{
 | |
| 		ID:             RootNamespaceID,
 | |
| 		Path:           "",
 | |
| 		CustomMetadata: make(map[string]string),
 | |
| 	}
 | |
| )
 | |
| 
 | |
| func (n *Namespace) HasParent(possibleParent *Namespace) bool {
 | |
| 	switch {
 | |
| 	case possibleParent.Path == "":
 | |
| 		return true
 | |
| 	case n.Path == "":
 | |
| 		return false
 | |
| 	default:
 | |
| 		return strings.HasPrefix(n.Path, possibleParent.Path)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (n *Namespace) TrimmedPath(path string) string {
 | |
| 	return strings.TrimPrefix(path, n.Path)
 | |
| }
 | |
| 
 | |
| func ContextWithNamespace(ctx context.Context, ns *Namespace) context.Context {
 | |
| 	return context.WithValue(ctx, contextNamespace, ns)
 | |
| }
 | |
| 
 | |
| func RootContext(ctx context.Context) context.Context {
 | |
| 	if ctx == nil {
 | |
| 		return ContextWithNamespace(context.Background(), RootNamespace)
 | |
| 	}
 | |
| 	return ContextWithNamespace(ctx, RootNamespace)
 | |
| }
 | |
| 
 | |
| // FromContext retrieves the namespace from a context, or an error
 | |
| // if there is no namespace in the context.
 | |
| func FromContext(ctx context.Context) (*Namespace, error) {
 | |
| 	if ctx == nil {
 | |
| 		return nil, errors.New("context was nil")
 | |
| 	}
 | |
| 
 | |
| 	nsRaw := ctx.Value(contextNamespace)
 | |
| 	if nsRaw == nil {
 | |
| 		return nil, ErrNoNamespace
 | |
| 	}
 | |
| 
 | |
| 	ns := nsRaw.(*Namespace)
 | |
| 	if ns == nil {
 | |
| 		return nil, ErrNoNamespace
 | |
| 	}
 | |
| 
 | |
| 	return ns, nil
 | |
| }
 | |
| 
 | |
| // Canonicalize trims any prefix '/' and adds a trailing '/' to the
 | |
| // provided string
 | |
| func Canonicalize(nsPath string) string {
 | |
| 	if nsPath == "" {
 | |
| 		return ""
 | |
| 	}
 | |
| 
 | |
| 	// Canonicalize the path to not have a '/' prefix
 | |
| 	nsPath = strings.TrimPrefix(nsPath, "/")
 | |
| 
 | |
| 	// Canonicalize the path to always having a '/' suffix
 | |
| 	if !strings.HasSuffix(nsPath, "/") {
 | |
| 		nsPath += "/"
 | |
| 	}
 | |
| 
 | |
| 	return nsPath
 | |
| }
 | |
| 
 | |
| func SplitIDFromString(input string) (string, string) {
 | |
| 	prefix := ""
 | |
| 	slashIdx := strings.LastIndex(input, "/")
 | |
| 
 | |
| 	switch {
 | |
| 	case strings.HasPrefix(input, consts.LegacyBatchTokenPrefix):
 | |
| 		prefix = consts.LegacyBatchTokenPrefix
 | |
| 		input = input[2:]
 | |
| 
 | |
| 	case strings.HasPrefix(input, consts.LegacyServiceTokenPrefix):
 | |
| 		prefix = consts.LegacyServiceTokenPrefix
 | |
| 		input = input[2:]
 | |
| 	case strings.HasPrefix(input, consts.BatchTokenPrefix):
 | |
| 		prefix = consts.BatchTokenPrefix
 | |
| 		input = input[4:]
 | |
| 	case strings.HasPrefix(input, consts.ServiceTokenPrefix):
 | |
| 		prefix = consts.ServiceTokenPrefix
 | |
| 		input = input[4:]
 | |
| 
 | |
| 	case slashIdx > 0:
 | |
| 		// Leases will never have a b./s. to start
 | |
| 		if slashIdx == len(input)-1 {
 | |
| 			return input, ""
 | |
| 		}
 | |
| 		prefix = input[:slashIdx+1]
 | |
| 		input = input[slashIdx+1:]
 | |
| 	}
 | |
| 
 | |
| 	idx := strings.LastIndex(input, ".")
 | |
| 	if idx == -1 {
 | |
| 		return prefix + input, ""
 | |
| 	}
 | |
| 	if idx == len(input)-1 {
 | |
| 		return prefix + input, ""
 | |
| 	}
 | |
| 
 | |
| 	return prefix + input[:idx], input[idx+1:]
 | |
| }
 | |
| 
 | |
| // MountPathDetails contains the details of a mount's location,
 | |
| // consisting of the namespace of the mount and the path of the
 | |
| // mount within the namespace
 | |
| type MountPathDetails struct {
 | |
| 	Namespace *Namespace
 | |
| 	MountPath string
 | |
| }
 | |
| 
 | |
| func (mpd *MountPathDetails) GetRelativePath(currNs *Namespace) string {
 | |
| 	subNsPath := strings.TrimPrefix(mpd.Namespace.Path, currNs.Path)
 | |
| 	return subNsPath + mpd.MountPath
 | |
| }
 | |
| 
 | |
| func (mpd *MountPathDetails) GetFullPath() string {
 | |
| 	return mpd.Namespace.Path + mpd.MountPath
 | |
| }
 | 
