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

     1  package agent
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
     9  	management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1"
    10  	"github.com/Axway/agent-sdk/pkg/jobs"
    11  	"github.com/Axway/agent-sdk/pkg/util"
    12  	hc "github.com/Axway/agent-sdk/pkg/util/healthcheck"
    13  	"github.com/Axway/agent-sdk/pkg/util/log"
    14  )
    15  
    16  const envACLFormat = "%s-agent-acl"
    17  
    18  // aclUpdateHandler - job that handles updates to the ACL in the environment
    19  type aclUpdateJob struct {
    20  	jobs.Job
    21  	logger log.FieldLogger
    22  }
    23  
    24  func newACLUpdateJob() *aclUpdateJob {
    25  	logger := log.NewFieldLogger().
    26  		WithPackage("sdk.agent").
    27  		WithComponent("aclUpdateJob")
    28  	job := &aclUpdateJob{
    29  		logger: logger,
    30  	}
    31  	return job
    32  }
    33  
    34  func (j *aclUpdateJob) Ready() bool {
    35  	status, _ := hc.GetGlobalStatus()
    36  	return status == string(hc.OK)
    37  }
    38  
    39  func (j *aclUpdateJob) Status() error {
    40  	if status, _ := hc.GetGlobalStatus(); status != string(hc.OK) {
    41  		err := fmt.Errorf("agent is marked as not running")
    42  		j.logger.WithError(err).Trace("status failed")
    43  		return err
    44  	}
    45  	return nil
    46  }
    47  
    48  func (j *aclUpdateJob) getACLTeamIDs(ri *v1.ResourceInstance) []string {
    49  	teamIDs := make([]string, 0)
    50  	acl, _ := management.NewAccessControlList("", management.EnvironmentGVK().Kind, agent.cfg.GetEnvironmentName())
    51  	err := acl.FromInstance(ri)
    52  	if err != nil {
    53  		return teamIDs
    54  	}
    55  	for _, subject := range acl.Spec.Subjects {
    56  		if subject.Type == v1.TeamOwner {
    57  			teamIDs = append(teamIDs, subject.ID)
    58  		}
    59  	}
    60  	teamIDs = util.RemoveDuplicateValuesFromStringSlice(teamIDs)
    61  	sort.Strings(teamIDs)
    62  	return teamIDs
    63  }
    64  
    65  func (j *aclUpdateJob) Execute() error {
    66  	currentACL := agent.cacheManager.GetAccessControlList()
    67  	if currentACL == nil {
    68  		currentACL = j.getACLsFromServer()
    69  	}
    70  
    71  	currentTeamIDs := j.getACLTeamIDs(currentACL)
    72  	newTeamIDs := agent.cacheManager.GetTeamsIDsInAPIServices()
    73  	if len(newTeamIDs) == 0 {
    74  		return nil
    75  	}
    76  
    77  	sort.Strings(newTeamIDs)
    78  	if currentTeamIDs != nil && strings.Join(newTeamIDs, "") == strings.Join(currentTeamIDs, "") {
    79  		return nil
    80  	}
    81  	if err := j.updateACL(newTeamIDs); err != nil {
    82  		return fmt.Errorf("acl update job failed: %s", err)
    83  	}
    84  	return nil
    85  }
    86  
    87  func (j aclUpdateJob) getACLsFromServer() *v1.ResourceInstance {
    88  	emptyACL, _ := management.NewAccessControlList("", management.EnvironmentGVK().Kind, agent.cfg.GetEnvironmentName())
    89  	acls, err := agent.apicClient.GetResources(emptyACL)
    90  	if err != nil {
    91  		return nil
    92  	}
    93  
    94  	for _, acl := range acls {
    95  		ri, _ := acl.AsInstance()
    96  		if ri.Name == j.getACLName() {
    97  			agent.cacheManager.SetAccessControlList(ri)
    98  			return ri
    99  		}
   100  	}
   101  	return nil
   102  }
   103  
   104  func (j *aclUpdateJob) getACLName() string {
   105  	return fmt.Sprintf(envACLFormat, GetCentralConfig().GetEnvironmentName())
   106  }
   107  
   108  func (j *aclUpdateJob) initializeACLJob() {
   109  	if acl := agent.cacheManager.GetAccessControlList(); acl != nil {
   110  		return
   111  	}
   112  
   113  	acl, err := agent.apicClient.GetAccessControlList(j.getACLName())
   114  	if err != nil {
   115  		return
   116  	}
   117  
   118  	if aclInstance, err := acl.AsInstance(); err == nil {
   119  		agent.cacheManager.SetAccessControlList(aclInstance)
   120  	}
   121  }
   122  
   123  func (j *aclUpdateJob) createACLResource(teamIDs []string) *management.AccessControlList {
   124  	acl, _ := management.NewAccessControlList(
   125  		j.getACLName(),
   126  		management.EnvironmentGVK().Kind,
   127  		agent.cfg.GetEnvironmentName(),
   128  	)
   129  	acl.Spec = management.AccessControlListSpec{
   130  		Rules: []management.AccessRules{
   131  			{
   132  				Access: []management.AccessLevelScope{
   133  					{
   134  						Level: "scope",
   135  					},
   136  				},
   137  			},
   138  		},
   139  	}
   140  
   141  	// Add all the teams
   142  	acl.Spec.Subjects = make([]v1.Owner, 0)
   143  	for _, id := range teamIDs {
   144  		acl.Spec.Subjects = append(acl.Spec.Subjects, v1.Owner{
   145  			Type: v1.TeamOwner,
   146  			ID:   id,
   147  		})
   148  	}
   149  
   150  	return acl
   151  }
   152  
   153  func (j *aclUpdateJob) updateACL(teamIDs []string) error {
   154  	// do not add an acl if there are no teamIDs and an ACL currently does not exist
   155  	currentACL := agent.cacheManager.GetAccessControlList()
   156  	if len(teamIDs) == 0 && currentACL == nil {
   157  		return nil
   158  	}
   159  
   160  	var err error
   161  	j.logger.Trace("acl about to be updated")
   162  	acl := j.createACLResource(teamIDs)
   163  	if currentACL != nil {
   164  		acl, err = agent.apicClient.UpdateAccessControlList(acl)
   165  	} else {
   166  		acl, err = agent.apicClient.CreateAccessControlList(acl)
   167  	}
   168  
   169  	if err == nil {
   170  		aclInstance, err := acl.AsInstance()
   171  		if err == nil {
   172  			agent.cacheManager.SetAccessControlList(aclInstance)
   173  		}
   174  	}
   175  
   176  	return err
   177  }
   178  
   179  // registerAccessControlListHandler -
   180  func registerAccessControlListHandler() {
   181  	job := newACLUpdateJob()
   182  
   183  	jobs.RegisterIntervalJobWithName(job, agent.cfg.GetPollInterval(), "Access Control List")
   184  }