github.com/Axway/agent-sdk@v1.1.101/pkg/agent/credendtialvalidator.go (about)

     1  package agent
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
     8  	management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1"
     9  	"github.com/Axway/agent-sdk/pkg/apic/provisioning"
    10  	"github.com/Axway/agent-sdk/pkg/config"
    11  	"github.com/Axway/agent-sdk/pkg/jobs"
    12  	"github.com/Axway/agent-sdk/pkg/util/log"
    13  )
    14  
    15  const (
    16  	status = "status"
    17  	state  = "state"
    18  )
    19  
    20  type cacheManager interface {
    21  	GetWatchResourceCacheKeys(group, kind string) []string
    22  	GetWatchResourceByKey(key string) *v1.ResourceInstance
    23  }
    24  
    25  type apicClient interface {
    26  	UpdateResourceInstance(ri v1.Interface) (*v1.ResourceInstance, error)
    27  	CreateSubResource(rm v1.ResourceMeta, subs map[string]interface{}) error
    28  }
    29  
    30  type credentialValidator struct {
    31  	jobs.Job
    32  	id           string
    33  	logger       log.FieldLogger
    34  	cacheManager cacheManager
    35  	client       apicClient
    36  }
    37  
    38  func newCredentialChecker(cacheManager cacheManager, client apicClient) *credentialValidator {
    39  	return &credentialValidator{
    40  		logger:       log.NewFieldLogger().WithComponent("credentialValidator"),
    41  		cacheManager: cacheManager,
    42  		client:       client,
    43  	}
    44  }
    45  
    46  // Ready -
    47  func (j *credentialValidator) Ready() bool {
    48  	return true
    49  }
    50  
    51  // Status -
    52  func (j *credentialValidator) Status() error {
    53  	return nil
    54  }
    55  
    56  // Execute -
    57  func (j *credentialValidator) Execute() error {
    58  	j.logger.Debug("validating credentials for expiration")
    59  
    60  	if agent.cfg.GetCredentialConfig() == nil ||
    61  		!agent.cfg.GetCredentialConfig().ShouldDeprovisionExpired() {
    62  		return nil
    63  	}
    64  
    65  	// Get all of the credentials from the cache
    66  	credKeys := j.cacheManager.GetWatchResourceCacheKeys(management.CredentialGVK().Group, management.CredentialGVK().Kind)
    67  
    68  	// loop all the keys in the cache and check if any have expired
    69  	now := time.Now()
    70  	wg := &sync.WaitGroup{}
    71  	for _, k := range credKeys {
    72  		wg.Add(1)
    73  		func(credKey string) {
    74  			j.validateCredential(credKey, now)
    75  		}(k)
    76  	}
    77  
    78  	return nil
    79  }
    80  
    81  func (j *credentialValidator) validateCredential(credKey string, now time.Time) {
    82  	logger := j.logger.WithField("cacheKey", credKey)
    83  	res := j.cacheManager.GetWatchResourceByKey(credKey)
    84  	if res == nil {
    85  		logger.Error("could not get resource by key")
    86  		return
    87  	}
    88  
    89  	cred := &management.Credential{}
    90  	err := cred.FromInstance(res)
    91  	if err != nil {
    92  		logger.WithError(err).Error("could not convert resource instance to credential")
    93  		return
    94  	}
    95  
    96  	if cred.Policies.Expiry == nil {
    97  		return
    98  	}
    99  
   100  	expTime := time.Time(cred.Policies.Expiry.Timestamp)
   101  	if expTime.IsZero() {
   102  		// cred does not expire
   103  		return
   104  	}
   105  
   106  	logger = logger.WithField("credName", cred.Name).WithField("expiration", expTime.Format(v1.APIServerTimeFormat))
   107  	logger.Trace("validating credential")
   108  
   109  	if expTime.Before(now) {
   110  		logger.Info("Credential has expired, updating Central")
   111  		cred.Status.Level = provisioning.Pending.String()
   112  
   113  		// update state so the inactivated credential will come back for removal
   114  		cred.Spec.State = management.CredentialSpecState{
   115  			Name:   v1.Inactive,
   116  			Reason: provisioning.CredExpDetail,
   117  		}
   118  
   119  		// only update a subset of the sub resources
   120  		subResources := map[string]interface{}{
   121  			status: cred.Status,
   122  			state:  cred.State,
   123  		}
   124  
   125  		_, err = j.client.UpdateResourceInstance(cred)
   126  		if err != nil {
   127  			logger.WithError(err).Error("error update credential resources")
   128  		}
   129  
   130  		err = j.client.CreateSubResource(cred.ResourceMeta, subResources)
   131  		if err != nil {
   132  			logger.WithError(err).Error("error creating subresources")
   133  		}
   134  	}
   135  }
   136  
   137  func registerCredentialChecker() *credentialValidator {
   138  	c := newCredentialChecker(agent.cacheManager, agent.apicClient)
   139  
   140  	err := agent.cfg.SetWatchResourceFilters([]config.ResourceFilter{
   141  		{
   142  			Group:            management.CredentialGVK().Group,
   143  			Kind:             management.CredentialGVK().Kind,
   144  			Name:             "*",
   145  			IsCachedResource: true,
   146  		},
   147  	})
   148  	if err != nil {
   149  		c.logger.WithError(err).Error("could not watch for the credential resource in the credential validator job")
   150  		return nil
   151  	}
   152  
   153  	id, err := jobs.RegisterScheduledJobWithName(c, "@hourly", "CredentialValidator")
   154  	if err != nil {
   155  		c.logger.WithError(err).Error("could not start the credential validator job")
   156  		return nil
   157  	}
   158  	c.logger.Debug("registered the credential validator")
   159  	c.id = id
   160  
   161  	return c
   162  }