gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

credentials.go (5407B)


      1 /*
      2  * MinIO Go Library for Amazon S3 Compatible Cloud Storage
      3  * Copyright 2017 MinIO, Inc.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package credentials
     19 
     20 import (
     21 	"sync"
     22 	"time"
     23 )
     24 
     25 const (
     26 	// STSVersion sts version string
     27 	STSVersion = "2011-06-15"
     28 
     29 	// How much duration to slash from the given expiration duration
     30 	defaultExpiryWindow = 0.8
     31 )
     32 
     33 // A Value is the AWS credentials value for individual credential fields.
     34 type Value struct {
     35 	// AWS Access key ID
     36 	AccessKeyID string
     37 
     38 	// AWS Secret Access Key
     39 	SecretAccessKey string
     40 
     41 	// AWS Session Token
     42 	SessionToken string
     43 
     44 	// Signature Type.
     45 	SignerType SignatureType
     46 }
     47 
     48 // A Provider is the interface for any component which will provide credentials
     49 // Value. A provider is required to manage its own Expired state, and what to
     50 // be expired means.
     51 type Provider interface {
     52 	// Retrieve returns nil if it successfully retrieved the value.
     53 	// Error is returned if the value were not obtainable, or empty.
     54 	Retrieve() (Value, error)
     55 
     56 	// IsExpired returns if the credentials are no longer valid, and need
     57 	// to be retrieved.
     58 	IsExpired() bool
     59 }
     60 
     61 // A Expiry provides shared expiration logic to be used by credentials
     62 // providers to implement expiry functionality.
     63 //
     64 // The best method to use this struct is as an anonymous field within the
     65 // provider's struct.
     66 //
     67 // Example:
     68 //
     69 //	type IAMCredentialProvider struct {
     70 //	    Expiry
     71 //	    ...
     72 //	}
     73 type Expiry struct {
     74 	// The date/time when to expire on
     75 	expiration time.Time
     76 
     77 	// If set will be used by IsExpired to determine the current time.
     78 	// Defaults to time.Now if CurrentTime is not set.
     79 	CurrentTime func() time.Time
     80 }
     81 
     82 // SetExpiration sets the expiration IsExpired will check when called.
     83 //
     84 // If window is greater than 0 the expiration time will be reduced by the
     85 // window value.
     86 //
     87 // Using a window is helpful to trigger credentials to expire sooner than
     88 // the expiration time given to ensure no requests are made with expired
     89 // tokens.
     90 func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
     91 	if e.CurrentTime == nil {
     92 		e.CurrentTime = time.Now
     93 	}
     94 	cut := window
     95 	if cut < 0 {
     96 		expireIn := expiration.Sub(e.CurrentTime())
     97 		cut = time.Duration(float64(expireIn) * (1 - defaultExpiryWindow))
     98 	}
     99 	e.expiration = expiration.Add(-cut)
    100 }
    101 
    102 // IsExpired returns if the credentials are expired.
    103 func (e *Expiry) IsExpired() bool {
    104 	if e.CurrentTime == nil {
    105 		e.CurrentTime = time.Now
    106 	}
    107 	return e.expiration.Before(e.CurrentTime())
    108 }
    109 
    110 // Credentials - A container for synchronous safe retrieval of credentials Value.
    111 // Credentials will cache the credentials value until they expire. Once the value
    112 // expires the next Get will attempt to retrieve valid credentials.
    113 //
    114 // Credentials is safe to use across multiple goroutines and will manage the
    115 // synchronous state so the Providers do not need to implement their own
    116 // synchronization.
    117 //
    118 // The first Credentials.Get() will always call Provider.Retrieve() to get the
    119 // first instance of the credentials Value. All calls to Get() after that
    120 // will return the cached credentials Value until IsExpired() returns true.
    121 type Credentials struct {
    122 	sync.Mutex
    123 
    124 	creds        Value
    125 	forceRefresh bool
    126 	provider     Provider
    127 }
    128 
    129 // New returns a pointer to a new Credentials with the provider set.
    130 func New(provider Provider) *Credentials {
    131 	return &Credentials{
    132 		provider:     provider,
    133 		forceRefresh: true,
    134 	}
    135 }
    136 
    137 // Get returns the credentials value, or error if the credentials Value failed
    138 // to be retrieved.
    139 //
    140 // Will return the cached credentials Value if it has not expired. If the
    141 // credentials Value has expired the Provider's Retrieve() will be called
    142 // to refresh the credentials.
    143 //
    144 // If Credentials.Expire() was called the credentials Value will be force
    145 // expired, and the next call to Get() will cause them to be refreshed.
    146 func (c *Credentials) Get() (Value, error) {
    147 	if c == nil {
    148 		return Value{}, nil
    149 	}
    150 
    151 	c.Lock()
    152 	defer c.Unlock()
    153 
    154 	if c.isExpired() {
    155 		creds, err := c.provider.Retrieve()
    156 		if err != nil {
    157 			return Value{}, err
    158 		}
    159 		c.creds = creds
    160 		c.forceRefresh = false
    161 	}
    162 
    163 	return c.creds, nil
    164 }
    165 
    166 // Expire expires the credentials and forces them to be retrieved on the
    167 // next call to Get().
    168 //
    169 // This will override the Provider's expired state, and force Credentials
    170 // to call the Provider's Retrieve().
    171 func (c *Credentials) Expire() {
    172 	c.Lock()
    173 	defer c.Unlock()
    174 
    175 	c.forceRefresh = true
    176 }
    177 
    178 // IsExpired returns if the credentials are no longer valid, and need
    179 // to be refreshed.
    180 //
    181 // If the Credentials were forced to be expired with Expire() this will
    182 // reflect that override.
    183 func (c *Credentials) IsExpired() bool {
    184 	c.Lock()
    185 	defer c.Unlock()
    186 
    187 	return c.isExpired()
    188 }
    189 
    190 // isExpired helper method wrapping the definition of expired credentials.
    191 func (c *Credentials) isExpired() bool {
    192 	return c.forceRefresh || c.provider.IsExpired()
    193 }