Skip to content
Snippets Groups Projects
Commit 326a494c authored by Lyuben Penkovski's avatar Lyuben Penkovski
Browse files

Merge branch '9-decrease-hard-dependencies' into 'main'

Remove hard dependency on other services

Closes #9

See merge request gaia-x/data-infrastructure-federation-services/tsa/policy!13
parents 23c4bbc5 45c58aab
No related branches found
No related tags found
No related merge requests found
Pipeline #54989 passed with stages
in 3 minutes and 15 seconds
......@@ -58,6 +58,19 @@ func main() {
logger.Info("policy service started", zap.String("version", Version), zap.String("goa", goa.Version()))
httpClient := httpClient()
// Create an HTTP Client which automatically issues and carries an OAuth2 token.
// The token will auto-refresh when its expiration is near.
oauthCtx := context.WithValue(context.Background(), oauth2.HTTPClient, httpClient)
oauthClient := newOAuth2Client(oauthCtx, cfg.OAuth.ClientID, cfg.OAuth.ClientSecret, cfg.OAuth.TokenURL)
// create cache client
cache := cache.New(cfg.Cache.Addr, cache.WithHTTPClient(oauthClient))
// create rego policy cache
regocache := regocache.New()
// connect to mongo db
db, err := mongo.Connect(
context.Background(),
......@@ -71,21 +84,14 @@ func main() {
}
defer db.Disconnect(context.Background()) //nolint:errcheck
httpClient := httpClient()
// Create an HTTP Client which uses an authentication token.
// The token will auto-refresh as necessary.
oauthCtx := context.WithValue(context.Background(), oauth2.HTTPClient, httpClient)
oauthClient := newOAuth2Client(oauthCtx, cfg.OAuth.ClientID, cfg.OAuth.ClientSecret, cfg.OAuth.TokenURL)
// create storage
storage, err := storage.New(db, cfg.Mongo.DB, cfg.Mongo.Collection, logger)
if err != nil {
logger.Fatal("error connecting to database", zap.Error(err))
}
// create rego query cache
regocache := regocache.New()
// subscribe the cache for policy data changes
storage.AddPolicyChangeSubscriber(regocache)
// register rego extension functions
{
......@@ -111,12 +117,6 @@ func main() {
regofunc.Register("urlToDID", rego.Function1(didWebFuncs.URLToDIDFunc()))
}
// subscribe the cache for policy data changes
storage.AddPolicyChangeSubscriber(regocache)
// create cache client
cache := cache.New(cfg.Cache.Addr, cache.WithHTTPClient(oauthClient))
// create services
var (
policySvc goapolicy.Service
......
......@@ -31,6 +31,10 @@ func New(addr string, opts ...Option) *Client {
}
func (c *Client) Set(ctx context.Context, key, namespace, scope string, value []byte, ttl int) error {
if c.addr == "" {
return errors.New(errors.ServiceUnavailable, "trying to use cache service, but address is not set")
}
req, err := http.NewRequestWithContext(ctx, "POST", c.addr+"/v1/cache", bytes.NewReader(value))
if err != nil {
return err
......@@ -60,6 +64,10 @@ func (c *Client) Set(ctx context.Context, key, namespace, scope string, value []
}
func (c *Client) Get(ctx context.Context, key, namespace, scope string) ([]byte, error) {
if c.addr == "" {
return nil, errors.New(errors.ServiceUnavailable, "trying to use cache service, but address is not set")
}
req, err := http.NewRequestWithContext(ctx, "GET", c.addr+"/v1/cache", nil)
req.Header = http.Header{
"x-cache-key": []string{key},
......
......@@ -25,19 +25,19 @@ type httpConfig struct {
}
type cacheConfig struct {
Addr string `envconfig:"CACHE_ADDR" required:"true"`
Addr string `envconfig:"CACHE_ADDR"`
}
type taskConfig struct {
Addr string `envconfig:"TASK_ADDR" required:"true"`
Addr string `envconfig:"TASK_ADDR"`
}
type signerConfig struct {
Addr string `envconfig:"SIGNER_ADDR" required:"true"`
Addr string `envconfig:"SIGNER_ADDR"`
}
type didResolverConfig struct {
Addr string `envconfig:"DID_RESOLVER_ADDR" required:"true"`
Addr string `envconfig:"DID_RESOLVER_ADDR"`
}
type mongoConfig struct {
......
......@@ -30,6 +30,10 @@ func (cf *CacheFuncs) CacheGetFunc() (*rego.Function, rego.Builtin3) {
Memoize: true,
},
func(bctx rego.BuiltinContext, a, b, c *ast.Term) (*ast.Term, error) {
if cf.cacheAddr == "" {
return nil, fmt.Errorf("trying to use cache.get Rego function, but cache address is not set")
}
var key, namespace, scope string
if err := ast.As(a.Value, &key); err != nil {
......@@ -76,6 +80,10 @@ func (cf *CacheFuncs) CacheSetFunc() (*rego.Function, rego.Builtin4) {
Memoize: true,
},
func(bctx rego.BuiltinContext, k, n, s, d *ast.Term) (*ast.Term, error) {
if cf.cacheAddr == "" {
return nil, fmt.Errorf("trying to use cache.set Rego function, but cache address is not set")
}
var key, namespace, scope string
var data map[string]interface{}
......
......@@ -12,13 +12,14 @@ import (
)
type OcmFuncs struct {
addr string
client *ocm.Client
}
func NewOcmFuncs(ocmAddr string, httpClient *http.Client) *OcmFuncs {
ocmClient := ocm.New(ocmAddr, ocm.WithHTTPClient(httpClient))
return &OcmFuncs{client: ocmClient}
return &OcmFuncs{addr: ocmAddr, client: ocmClient}
}
func (of *OcmFuncs) GetLoginProofInvitation() (*rego.Function, rego.Builtin2) {
......@@ -28,6 +29,10 @@ func (of *OcmFuncs) GetLoginProofInvitation() (*rego.Function, rego.Builtin2) {
Memoize: true,
},
func(bctx rego.BuiltinContext, rScopes *ast.Term, scopesMap *ast.Term) (*ast.Term, error) {
if of.addr == "" {
return nil, fmt.Errorf("trying to use ocm.getLoginProofInvitation Rego function, but ocm address is not set")
}
var scopes []string
var scopeToType map[string]string
......@@ -83,6 +88,10 @@ func (of *OcmFuncs) GetLoginProofResult() (*rego.Function, rego.Builtin1) {
Memoize: true,
},
func(bctx rego.BuiltinContext, id *ast.Term) (*ast.Term, error) {
if of.addr == "" {
return nil, fmt.Errorf("trying to use ocm.getLoginProofResult Rego function, but ocm address is not set")
}
var presentationID string
if err := ast.As(id.Value, &presentationID); err != nil {
......
......@@ -39,6 +39,10 @@ func (sf *SignerFuncs) VerificationMethodFunc() (*rego.Function, rego.Builtin3)
Memoize: true,
},
func(bctx rego.BuiltinContext, aDID, aNamespace, aKey *ast.Term) (*ast.Term, error) {
if sf.signerAddr == "" {
return nil, fmt.Errorf("trying to use verification_method Rego function, but signer address is not set")
}
var did, namespace, key string
if err := ast.As(aDID.Value, &did); err != nil {
return nil, fmt.Errorf("invalid did: %s", err)
......@@ -95,6 +99,10 @@ func (sf *SignerFuncs) VerificationMethodsFunc() (*rego.Function, rego.Builtin2)
Memoize: true,
},
func(bctx rego.BuiltinContext, aDID, aNamespace *ast.Term) (*ast.Term, error) {
if sf.signerAddr == "" {
return nil, fmt.Errorf("trying to use verification_methods Rego function, but signer address is not set")
}
var did, namespace string
if err := ast.As(aDID.Value, &did); err != nil {
return nil, fmt.Errorf("invalid did: %s", err)
......@@ -151,6 +159,10 @@ func (sf *SignerFuncs) AddVCProofFunc() (*rego.Function, rego.Builtin3) {
Memoize: true,
},
func(bctx rego.BuiltinContext, aNamespace, aKey, credential *ast.Term) (*ast.Term, error) {
if sf.signerAddr == "" {
return nil, fmt.Errorf("trying to use add_vc_proof Rego function, but signer address is not set")
}
var namespace, key string
if err := ast.As(aNamespace.Value, &namespace); err != nil {
return nil, fmt.Errorf("invalid key namespace: %s", err)
......@@ -233,6 +245,10 @@ func (sf *SignerFuncs) AddVPProofFunc() (*rego.Function, rego.Builtin4) {
Memoize: true,
},
func(bctx rego.BuiltinContext, aDID, aNamespace, aKey, presentation *ast.Term) (*ast.Term, error) {
if sf.signerAddr == "" {
return nil, fmt.Errorf("trying to use add_vp_proof Rego function, but signer address is not set")
}
var did, namespace, key string
if err := ast.As(aDID.Value, &did); err != nil {
return nil, fmt.Errorf("invalid did: %s", err)
......@@ -314,6 +330,10 @@ func (sf *SignerFuncs) VerifyProofFunc() (*rego.Function, rego.Builtin1) {
Memoize: true,
},
func(bctx rego.BuiltinContext, credential *ast.Term) (*ast.Term, error) {
if sf.signerAddr == "" {
return nil, fmt.Errorf("trying to use proof.verify Rego function, but signer address is not set")
}
// cred represents verifiable credential or presentation
var cred map[string]interface{}
if err := ast.As(credential.Value, &cred); err != nil {
......
......@@ -32,6 +32,10 @@ func (t *TaskFuncs) CreateTaskFunc() (*rego.Function, rego.Builtin2) {
Memoize: true,
},
func(bctx rego.BuiltinContext, taskName, taskData *ast.Term) (*ast.Term, error) {
if t.taskAddr == "" {
return nil, fmt.Errorf("trying to use task.create Rego function, but task address is not set")
}
var name string
var data map[string]interface{}
......@@ -84,6 +88,10 @@ func (t *TaskFuncs) CreateTaskListFunc() (*rego.Function, rego.Builtin2) {
Memoize: true,
},
func(bctx rego.BuiltinContext, taskListName, taskListData *ast.Term) (*ast.Term, error) {
if t.taskAddr == "" {
return nil, fmt.Errorf("trying to use tasklist.create Rego function, but task address is not set")
}
var name string
var data map[string]interface{}
......
......@@ -9,22 +9,6 @@ import (
)
type FakeCache struct {
GetStub func(context.Context, string, string, string) ([]byte, error)
getMutex sync.RWMutex
getArgsForCall []struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
}
getReturns struct {
result1 []byte
result2 error
}
getReturnsOnCall map[int]struct {
result1 []byte
result2 error
}
SetStub func(context.Context, string, string, string, []byte, int) error
setMutex sync.RWMutex
setArgsForCall []struct {
......@@ -45,73 +29,6 @@ type FakeCache struct {
invocationsMutex sync.RWMutex
}
func (fake *FakeCache) Get(arg1 context.Context, arg2 string, arg3 string, arg4 string) ([]byte, error) {
fake.getMutex.Lock()
ret, specificReturn := fake.getReturnsOnCall[len(fake.getArgsForCall)]
fake.getArgsForCall = append(fake.getArgsForCall, struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
}{arg1, arg2, arg3, arg4})
stub := fake.GetStub
fakeReturns := fake.getReturns
fake.recordInvocation("Get", []interface{}{arg1, arg2, arg3, arg4})
fake.getMutex.Unlock()
if stub != nil {
return stub(arg1, arg2, arg3, arg4)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeCache) GetCallCount() int {
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
return len(fake.getArgsForCall)
}
func (fake *FakeCache) GetCalls(stub func(context.Context, string, string, string) ([]byte, error)) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = stub
}
func (fake *FakeCache) GetArgsForCall(i int) (context.Context, string, string, string) {
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
argsForCall := fake.getArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
}
func (fake *FakeCache) GetReturns(result1 []byte, result2 error) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = nil
fake.getReturns = struct {
result1 []byte
result2 error
}{result1, result2}
}
func (fake *FakeCache) GetReturnsOnCall(i int, result1 []byte, result2 error) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = nil
if fake.getReturnsOnCall == nil {
fake.getReturnsOnCall = make(map[int]struct {
result1 []byte
result2 error
})
}
fake.getReturnsOnCall[i] = struct {
result1 []byte
result2 error
}{result1, result2}
}
func (fake *FakeCache) Set(arg1 context.Context, arg2 string, arg3 string, arg4 string, arg5 []byte, arg6 int) error {
var arg5Copy []byte
if arg5 != nil {
......@@ -186,8 +103,6 @@ func (fake *FakeCache) SetReturnsOnCall(i int, result1 error) {
func (fake *FakeCache) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
fake.setMutex.RLock()
defer fake.setMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
......
......@@ -21,11 +21,8 @@ import (
//go:generate counterfeiter . Storage
//go:generate counterfeiter . RegoCache
const HeaderKey = "headers"
type Cache interface {
Set(ctx context.Context, key, namespace, scope string, value []byte, ttl int) error
Get(ctx context.Context, key, namespace, scope string) ([]byte, error)
}
type Storage interface {
......@@ -124,9 +121,14 @@ func (s *Service) Evaluate(ctx context.Context, req *policy.EvaluateRequest) (*p
if req.TTL != nil {
ttl = *req.TTL
}
if err := s.cache.Set(ctx, evaluationID, "", "", jsonValue, ttl); err != nil {
logger.Error("error storing policy result in cache", zap.Error(err))
return nil, errors.New("error storing policy result in cache")
err = s.cache.Set(ctx, evaluationID, "", "", jsonValue, ttl)
if err != nil {
// if the cache service is not available, don't stop but continue with returning the result
if !errors.Is(errors.ServiceUnavailable, err) {
logger.Error("error storing policy result in cache", zap.Error(err))
return nil, errors.New("error storing policy result in cache")
}
}
return &policy.EvaluateResult{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment