[#12] Add lazy-expiry to mem-storage, unify envvars

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2020-01-24 16:33:14 +01:00
parent 1a91a5d34d
commit 990fddff7a
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
3 changed files with 51 additions and 12 deletions

View file

@ -21,12 +21,11 @@
For a better setup you can choose the backend which is used to store the secrets: For a better setup you can choose the backend which is used to store the secrets:
- `mem` - In memory storage (wiped on restart of the daemon) - `mem` - In memory storage (wiped on restart of the daemon)
- `SECRET_EXPIRY` - Expiry of the keys in seconds (Default `0` = no expiry)
- `redis` - Storing the secrets in a hash under one key - `redis` - Storing the secrets in a hash under one key
- `REDIS_URL` - Redis connection string `tcp://auth:PWD@HOST:PORT/DB` - `REDIS_URL` - Redis connection string `tcp://auth:PWD@HOST:PORT/DB`
- `REDIS_EXPIRY` - Expiry of the keys in seconds (Default `0` = no expiry)
- `REDIS_KEY` - Key prefix to store the keys under (Default `io.luzifer.ots`) - `REDIS_KEY` - Key prefix to store the keys under (Default `io.luzifer.ots`)
- `SECRET_EXPIRY` - Expiry of the keys in seconds (Default `0` = no expiry)
**Hint:** Starting in `v0.7.0` the secrets in Redis are no longer stored in a hash but in own keys. This allows for individual expiry. At the first start of `v0.7.0` the old data will be migrated automatically and afterwards be subject of expiry if you set `REDIS_EXPIRY`. My hosted instance uses an expiry of 90d (= 7776000s).
## Localize to your own language ## Localize to your own language

View file

@ -1,20 +1,34 @@
package main package main
import "github.com/gofrs/uuid/v3" import (
"os"
"strconv"
"time"
"github.com/gofrs/uuid/v3"
)
type memStorageSecret struct {
Expiry time.Time
Secret string
}
type storageMem struct { type storageMem struct {
store map[string]string store map[string]memStorageSecret
} }
func newStorageMem() storage { func newStorageMem() storage {
return &storageMem{ return &storageMem{
store: make(map[string]string), store: make(map[string]memStorageSecret),
} }
} }
func (s storageMem) Create(secret string) (string, error) { func (s storageMem) Create(secret string) (string, error) {
id := uuid.Must(uuid.NewV4()).String() id := uuid.Must(uuid.NewV4()).String()
s.store[id] = secret s.store[id] = memStorageSecret{
Expiry: s.expiry(),
Secret: secret,
}
return id, nil return id, nil
} }
@ -25,6 +39,25 @@ func (s storageMem) ReadAndDestroy(id string) (string, error) {
return "", errSecretNotFound return "", errSecretNotFound
} }
delete(s.store, id) defer delete(s.store, id)
return secret, nil
if secret.Expiry.Before(time.Now()) {
return "", errSecretNotFound
}
return secret.Secret, nil
}
func (s storageMem) expiry() time.Time {
exp := os.Getenv("SECRET_EXPIRY")
if exp == "" {
return time.Time{}
}
e, err := strconv.ParseInt(exp, 10, 64)
if err != nil {
return time.Time{}
}
return time.Now().Add(time.Duration(e) * time.Second)
} }

View file

@ -65,12 +65,19 @@ func (s storageRedis) migrate() error {
} }
func (s storageRedis) redisExpiry() int { func (s storageRedis) redisExpiry() int {
exp := os.Getenv("REDIS_EXPIRY") var expStr string
if exp == "" { for _, eVar := range []string{"SECRET_EXPIRY", "REDIS_EXPIRY"} {
if v := os.Getenv(eVar); v != "" {
expStr = v
break
}
}
if expStr == "" {
return 0 return 0
} }
e, err := strconv.ParseInt(exp, 10, 64) e, err := strconv.ParseInt(expStr, 10, 64)
if err != nil { if err != nil {
return 0 return 0
} }