Skip to content

Commit

Permalink
feat(auth): add policy caching
Browse files Browse the repository at this point in the history
Cache policies when the first authorization request happens and delete them when removing policies

Signed-off-by: Rodney Osodo <[email protected]>
  • Loading branch information
rodneyosodo committed Sep 22, 2024
1 parent e611165 commit bc79284
Show file tree
Hide file tree
Showing 10 changed files with 648 additions and 38 deletions.
70 changes: 37 additions & 33 deletions auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,40 +59,42 @@ Domain consists of the following fields:

The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.

| Variable | Description | Default |
| ------------------------------ | ----------------------------------------------------------------------- | ------------------------------- |
| MG_AUTH_LOG_LEVEL | Log level for the Auth service (debug, info, warn, error) | info |
| MG_AUTH_DB_HOST | Database host address | localhost |
| MG_AUTH_DB_PORT | Database host port | 5432 |
| MG_AUTH_DB_USER | Database user | magistrala |
| MG_AUTH_DB_PASSWORD | Database password | magistrala |
| MG_AUTH_DB_NAME | Name of the database used by the service | auth |
| MG_AUTH_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
| MG_AUTH_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
| MG_AUTH_DB_SSL_KEY | Path to the PEM encoded key file | "" |
| MG_AUTH_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
| MG_AUTH_HTTP_HOST | Auth service HTTP host | "" |
| MG_AUTH_HTTP_PORT | Auth service HTTP port | 8189 |
| MG_AUTH_HTTP_SERVER_CERT | Path to the PEM encoded HTTP server certificate file | "" |
| MG_AUTH_HTTP_SERVER_KEY | Path to the PEM encoded HTTP server key file | "" |
| MG_AUTH_GRPC_HOST | Auth service gRPC host | "" |
| MG_AUTH_GRPC_PORT | Auth service gRPC port | 8181 |
| MG_AUTH_GRPC_SERVER_CERT | Path to the PEM encoded gRPC server certificate file | "" |
| MG_AUTH_GRPC_SERVER_KEY | Path to the PEM encoded gRPC server key file | "" |
| MG_AUTH_GRPC_SERVER_CA_CERTS | Path to the PEM encoded gRPC server CA certificate file | "" |
| MG_AUTH_GRPC_CLIENT_CA_CERTS | Path to the PEM encoded gRPC client CA certificate file | "" |
| MG_AUTH_SECRET_KEY | String used for signing tokens | secret |
| MG_AUTH_ACCESS_TOKEN_DURATION | The access token expiration period | 1h |
| MG_AUTH_REFRESH_TOKEN_DURATION | The refresh token expiration period | 24h |
| MG_AUTH_INVITATION_DURATION | The invitation token expiration period | 168h |
| MG_SPICEDB_HOST | SpiceDB host address | localhost |
| MG_SPICEDB_PORT | SpiceDB host port | 50051 |
| MG_SPICEDB_PRE_SHARED_KEY | SpiceDB pre-shared key | 12345678 |
| MG_SPICEDB_SCHEMA_FILE | Path to SpiceDB schema file | ./docker/spicedb/schema.zed |
| Variable | Description | Default |
| ------------------------------ | ----------------------------------------------------------------------- | ------------------------------ |
| MG_AUTH_LOG_LEVEL | Log level for the Auth service (debug, info, warn, error) | info |
| MG_AUTH_DB_HOST | Database host address | localhost |
| MG_AUTH_DB_PORT | Database host port | 5432 |
| MG_AUTH_DB_USER | Database user | magistrala |
| MG_AUTH_DB_PASSWORD | Database password | magistrala |
| MG_AUTH_DB_NAME | Name of the database used by the service | auth |
| MG_AUTH_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
| MG_AUTH_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
| MG_AUTH_DB_SSL_KEY | Path to the PEM encoded key file | "" |
| MG_AUTH_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
| MG_AUTH_HTTP_HOST | Auth service HTTP host | "" |
| MG_AUTH_HTTP_PORT | Auth service HTTP port | 8189 |
| MG_AUTH_HTTP_SERVER_CERT | Path to the PEM encoded HTTP server certificate file | "" |
| MG_AUTH_HTTP_SERVER_KEY | Path to the PEM encoded HTTP server key file | "" |
| MG_AUTH_GRPC_HOST | Auth service gRPC host | "" |
| MG_AUTH_GRPC_PORT | Auth service gRPC port | 8181 |
| MG_AUTH_GRPC_SERVER_CERT | Path to the PEM encoded gRPC server certificate file | "" |
| MG_AUTH_GRPC_SERVER_KEY | Path to the PEM encoded gRPC server key file | "" |
| MG_AUTH_GRPC_SERVER_CA_CERTS | Path to the PEM encoded gRPC server CA certificate file | "" |
| MG_AUTH_GRPC_CLIENT_CA_CERTS | Path to the PEM encoded gRPC client CA certificate file | "" |
| MG_AUTH_SECRET_KEY | String used for signing tokens | secret |
| MG_AUTH_ACCESS_TOKEN_DURATION | The access token expiration period | 1h |
| MG_AUTH_REFRESH_TOKEN_DURATION | The refresh token expiration period | 24h |
| MG_AUTH_INVITATION_DURATION | The invitation token expiration period | 168h |
| MG_SPICEDB_HOST | SpiceDB host address | localhost |
| MG_SPICEDB_PORT | SpiceDB host port | 50051 |
| MG_SPICEDB_PRE_SHARED_KEY | SpiceDB pre-shared key | 12345678 |
| MG_SPICEDB_SCHEMA_FILE | Path to SpiceDB schema file | ./docker/spicedb/schema.zed |
| MG_AUTH_CACHE_URL | Cache server URL | "redis://localhost:6379/0" |
| MG_AUTH_CACHE_KEY_DURATION | Cache key expiration period | "1h" |
| MG_JAEGER_URL | Jaeger server URL | <http://jaeger:4318/v1/traces> |
| MG_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
| MG_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
| MG_AUTH_ADAPTER_INSTANCE_ID | Adapter instance ID | "" |
| MG_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
| MG_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
| MG_AUTH_ADAPTER_INSTANCE_ID | Adapter instance ID | "" |

## Deployment

Expand Down Expand Up @@ -142,6 +144,8 @@ MG_SPICEDB_HOST=localhost \
MG_SPICEDB_PORT=50051 \
MG_SPICEDB_PRE_SHARED_KEY=12345678 \
MG_SPICEDB_SCHEMA_FILE=./docker/spicedb/schema.zed \
MG_AUTH_CACHE_URL=redis://localhost:6379/0 \
MG_AUTH_CACHE_KEY_DURATION=1h \
MG_JAEGER_URL=http://localhost:14268/api/traces \
MG_JAEGER_TRACE_RATIO=1.0 \
MG_SEND_TELEMETRY=true \
Expand Down
6 changes: 6 additions & 0 deletions auth/cache/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

// Package cache contains the domain concept definitions needed to
// support Magistrala auth cache service functionality.
package cache
87 changes: 87 additions & 0 deletions auth/cache/policies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package cache

import (
"context"
"strings"
"time"

"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
"github.com/redis/go-redis/v9"
)

const defLimit = 100

var _ auth.Cache = (*policiesCache)(nil)

type policiesCache struct {
client *redis.Client
keyDuration time.Duration
}

// NewPoliciesCache returns redis auth cache implementation.
func NewPoliciesCache(client *redis.Client, duration time.Duration) auth.Cache {
return &policiesCache{
client: client,
keyDuration: duration,
}
}

func (pc *policiesCache) Save(ctx context.Context, key, value string) error {
if err := pc.client.Set(ctx, key, value, pc.keyDuration).Err(); err != nil {
return errors.Wrap(repoerr.ErrCreateEntity, err)
}

return nil
}

func (pc *policiesCache) Contains(ctx context.Context, key, value string) bool {
rval, err := pc.client.Get(ctx, key).Result()
if err != nil {
return false
}
if rval == value {
return true
}

return false
}

func (pc *policiesCache) Remove(ctx context.Context, key string) error {
if strings.Contains(key, "*") {
return pc.delete(ctx, key)
}

if err := pc.client.Del(ctx, key).Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}

return nil
}

func (pc *policiesCache) delete(ctx context.Context, key string) error {
keys, cursor, err := pc.client.Scan(ctx, 0, key, defLimit).Result()
if err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
for cursor != 0 {
var newKeys []string
newKeys, cursor, err = pc.client.Scan(ctx, cursor, key, defLimit).Result()
if err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
keys = append(keys, newKeys...)
}

for _, key := range keys {
if err := pc.client.Del(ctx, key).Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
}

return nil
}
Loading

0 comments on commit bc79284

Please sign in to comment.