github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/policy.go (about)

     1  package gateway
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"os"
     9  
    10  	"github.com/TykTechnologies/tyk/rpc"
    11  
    12  	"github.com/sirupsen/logrus"
    13  
    14  	"github.com/TykTechnologies/tyk/user"
    15  )
    16  
    17  type DBAccessDefinition struct {
    18  	APIName     string            `json:"apiname"`
    19  	APIID       string            `json:"apiid"`
    20  	Versions    []string          `json:"versions"`
    21  	AllowedURLs []user.AccessSpec `bson:"allowed_urls" json:"allowed_urls"` // mapped string MUST be a valid regex
    22  	Limit       *user.APILimit    `json:"limit"`
    23  }
    24  
    25  func (d *DBAccessDefinition) ToRegularAD() user.AccessDefinition {
    26  	return user.AccessDefinition{
    27  		APIName:     d.APIName,
    28  		APIID:       d.APIID,
    29  		Versions:    d.Versions,
    30  		AllowedURLs: d.AllowedURLs,
    31  		Limit:       d.Limit,
    32  	}
    33  }
    34  
    35  type DBPolicy struct {
    36  	user.Policy
    37  	AccessRights map[string]DBAccessDefinition `bson:"access_rights" json:"access_rights"`
    38  }
    39  
    40  func (d *DBPolicy) ToRegularPolicy() user.Policy {
    41  	policy := d.Policy
    42  	policy.AccessRights = make(map[string]user.AccessDefinition)
    43  
    44  	for k, v := range d.AccessRights {
    45  		policy.AccessRights[k] = v.ToRegularAD()
    46  	}
    47  	return policy
    48  }
    49  
    50  func LoadPoliciesFromFile(filePath string) map[string]user.Policy {
    51  	f, err := os.Open(filePath)
    52  	if err != nil {
    53  		log.WithFields(logrus.Fields{
    54  			"prefix": "policy",
    55  		}).Error("Couldn't open policy file: ", err)
    56  		return nil
    57  	}
    58  	defer f.Close()
    59  
    60  	var policies map[string]user.Policy
    61  	if err := json.NewDecoder(f).Decode(&policies); err != nil {
    62  		log.WithFields(logrus.Fields{
    63  			"prefix": "policy",
    64  		}).Error("Couldn't unmarshal policies: ", err)
    65  	}
    66  	return policies
    67  }
    68  
    69  // LoadPoliciesFromDashboard will connect and download Policies from a Tyk Dashboard instance.
    70  func LoadPoliciesFromDashboard(endpoint, secret string, allowExplicit bool) map[string]user.Policy {
    71  
    72  	// Get the definitions
    73  	newRequest, err := http.NewRequest("GET", endpoint, nil)
    74  	if err != nil {
    75  		log.Error("Failed to create request: ", err)
    76  	}
    77  
    78  	newRequest.Header.Set("authorization", secret)
    79  	newRequest.Header.Set("x-tyk-nodeid", GetNodeID())
    80  
    81  	newRequest.Header.Set("x-tyk-nonce", ServiceNonce)
    82  
    83  	log.WithFields(logrus.Fields{
    84  		"prefix": "policy",
    85  	}).Info("Mutex lock acquired... calling")
    86  	c := initialiseClient()
    87  
    88  	log.WithFields(logrus.Fields{
    89  		"prefix": "policy",
    90  	}).Info("Calling dashboard service for policy list")
    91  	resp, err := c.Do(newRequest)
    92  	if err != nil {
    93  		log.Error("Policy request failed: ", err)
    94  		return nil
    95  	}
    96  	defer resp.Body.Close()
    97  
    98  	if resp.StatusCode == http.StatusForbidden {
    99  		body, _ := ioutil.ReadAll(resp.Body)
   100  		log.Error("Policy request login failure, Response was: ", string(body))
   101  		reLogin()
   102  		return nil
   103  	}
   104  
   105  	// Extract Policies
   106  	var list struct {
   107  		Message []DBPolicy
   108  		Nonce   string
   109  	}
   110  	if err := json.NewDecoder(resp.Body).Decode(&list); err != nil {
   111  		log.Error("Failed to decode policy body: ", err)
   112  		return nil
   113  	}
   114  
   115  	ServiceNonce = list.Nonce
   116  	log.Debug("Loading Policies Finished: Nonce Set: ", ServiceNonce)
   117  
   118  	policies := make(map[string]user.Policy, len(list.Message))
   119  
   120  	log.WithFields(logrus.Fields{
   121  		"prefix": "policy",
   122  	}).Info("Processing policy list")
   123  	for _, p := range list.Message {
   124  		id := p.MID.Hex()
   125  		if allowExplicit && p.ID != "" {
   126  			id = p.ID
   127  		}
   128  		p.ID = id
   129  		if _, ok := policies[id]; ok {
   130  			log.WithFields(logrus.Fields{
   131  				"prefix":   "policy",
   132  				"policyID": p.ID,
   133  				"OrgID":    p.OrgID,
   134  			}).Warning("--> Skipping policy, new item has a duplicate ID!")
   135  			continue
   136  		}
   137  		policies[id] = p.ToRegularPolicy()
   138  	}
   139  
   140  	return policies
   141  }
   142  
   143  func parsePoliciesFromRPC(list string) (map[string]user.Policy, error) {
   144  	var dbPolicyList []user.Policy
   145  
   146  	if err := json.Unmarshal([]byte(list), &dbPolicyList); err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	policies := make(map[string]user.Policy, len(dbPolicyList))
   151  
   152  	for _, p := range dbPolicyList {
   153  		p.ID = p.MID.Hex()
   154  		policies[p.MID.Hex()] = p
   155  	}
   156  
   157  	return policies, nil
   158  }
   159  
   160  func LoadPoliciesFromRPC(orgId string) (map[string]user.Policy, error) {
   161  	if rpc.IsEmergencyMode() {
   162  		return LoadPoliciesFromRPCBackup()
   163  	}
   164  
   165  	store := &RPCStorageHandler{}
   166  	if !store.Connect() {
   167  		return nil, errors.New("Policies backup: Failed connecting to database")
   168  	}
   169  
   170  	rpcPolicies := store.GetPolicies(orgId)
   171  
   172  	policies, err := parsePoliciesFromRPC(rpcPolicies)
   173  
   174  	if err != nil {
   175  		log.WithFields(logrus.Fields{
   176  			"prefix": "policy",
   177  		}).Error("Failed decode: ", err, rpcPolicies)
   178  		return nil, err
   179  	}
   180  
   181  	if err := saveRPCPoliciesBackup(rpcPolicies); err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	return policies, nil
   186  }