github.com/hashicorp/vault/sdk@v0.13.0/framework/lease.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package framework
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/hashicorp/vault/sdk/logical"
    13  )
    14  
    15  // LeaseExtend is left for backwards compatibility for plugins. This function
    16  // now just passes back the data that was passed into it to be processed in core.
    17  // DEPRECATED
    18  func LeaseExtend(backendIncrement, backendMax time.Duration, systemView logical.SystemView) OperationFunc {
    19  	return func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) {
    20  		switch {
    21  		case req.Auth != nil:
    22  			req.Auth.TTL = backendIncrement
    23  			req.Auth.MaxTTL = backendMax
    24  			return &logical.Response{Auth: req.Auth}, nil
    25  		case req.Secret != nil:
    26  			req.Secret.TTL = backendIncrement
    27  			req.Secret.MaxTTL = backendMax
    28  			return &logical.Response{Secret: req.Secret}, nil
    29  		}
    30  		return nil, fmt.Errorf("no lease options for request")
    31  	}
    32  }
    33  
    34  // CalculateTTL takes all the user-specified, backend, and system inputs and calculates
    35  // a TTL for a lease
    36  func CalculateTTL(sysView logical.SystemView, increment, backendTTL, period, backendMaxTTL, explicitMaxTTL time.Duration, startTime time.Time) (ttl time.Duration, warnings []string, errors error) {
    37  	// Truncate all times to the second since that is the lowest precision for
    38  	// TTLs
    39  	now := time.Now().Truncate(time.Second)
    40  	if startTime.IsZero() {
    41  		startTime = now
    42  	} else {
    43  		startTime = startTime.Truncate(time.Second)
    44  	}
    45  
    46  	// Use the mount's configured max unless the backend specifies
    47  	// something more restrictive (perhaps from a role configuration
    48  	// parameter)
    49  	maxTTL := sysView.MaxLeaseTTL()
    50  	if backendMaxTTL > 0 && backendMaxTTL < maxTTL {
    51  		maxTTL = backendMaxTTL
    52  	}
    53  	if explicitMaxTTL > 0 && explicitMaxTTL < maxTTL {
    54  		maxTTL = explicitMaxTTL
    55  	}
    56  
    57  	// Should never happen, but guard anyways
    58  	if maxTTL <= 0 {
    59  		return 0, nil, fmt.Errorf("max TTL must be greater than zero")
    60  	}
    61  
    62  	var maxValidTime time.Time
    63  	switch {
    64  	case period > 0:
    65  		// Cap the period value to the sys max_ttl value
    66  		if period > maxTTL {
    67  			warnings = append(warnings,
    68  				fmt.Sprintf("period of %q exceeded the effective max_ttl of %q; period value is capped accordingly",
    69  					humanDuration(period), humanDuration(maxTTL)))
    70  			period = maxTTL
    71  		}
    72  		ttl = period
    73  
    74  		if explicitMaxTTL > 0 {
    75  			maxValidTime = startTime.Add(explicitMaxTTL)
    76  		}
    77  	default:
    78  		switch {
    79  		case increment > 0:
    80  			ttl = increment
    81  		case backendTTL > 0:
    82  			ttl = backendTTL
    83  		default:
    84  			ttl = sysView.DefaultLeaseTTL()
    85  		}
    86  
    87  		// We cannot go past this time
    88  		maxValidTime = startTime.Add(maxTTL)
    89  	}
    90  
    91  	if !maxValidTime.IsZero() {
    92  		// Determine the max valid TTL
    93  		maxValidTTL := maxValidTime.Sub(now)
    94  
    95  		// If we are past the max TTL, we shouldn't be in this function...but
    96  		// fast path out if we are
    97  		if maxValidTTL <= 0 {
    98  			return 0, nil, fmt.Errorf("past the max TTL, cannot renew")
    99  		}
   100  
   101  		// If the proposed expiration is after the maximum TTL of the lease,
   102  		// cap the increment to whatever is left
   103  		if maxValidTTL-ttl < 0 {
   104  			warnings = append(warnings,
   105  				fmt.Sprintf("TTL of %q exceeded the effective max_ttl of %q; TTL value is capped accordingly",
   106  					humanDuration(ttl), humanDuration(maxValidTTL)))
   107  			ttl = maxValidTTL
   108  		}
   109  	}
   110  
   111  	return ttl, warnings, nil
   112  }
   113  
   114  // humanDuration prints the time duration without zero elements.
   115  func humanDuration(d time.Duration) string {
   116  	if d == 0 {
   117  		return "0s"
   118  	}
   119  
   120  	s := d.String()
   121  	if strings.HasSuffix(s, "m0s") {
   122  		s = s[:len(s)-2]
   123  	}
   124  	if idx := strings.Index(s, "h0m"); idx > 0 {
   125  		s = s[:idx+1] + s[idx+3:]
   126  	}
   127  	return s
   128  }