Skip to content

Commit

Permalink
Configurable persistence_directory
Browse files Browse the repository at this point in the history
This allows configuring the persistence_directory OPA should use for persisting
bundles to disk. While this currently only covers bundles I didn't want to close
the door for persisting other type of objects later, so the
persistence_directory option is kept at the top level of the configuration,
defaulting to $PWD/.opa if not provided.

Bundles will be persisted to ${persistence_directory}/bundles.

Closes open-policy-agent#3085

Signed-off-by: Anders Eknert <anders@eknert.com>
  • Loading branch information
anderseknert committed Feb 2, 2021
1 parent 3751200 commit 635d8a5
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 5 deletions.
15 changes: 15 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package config

import (
"encoding/json"
"os"
"path/filepath"

"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/internal/ref"
Expand All @@ -28,6 +30,7 @@ type Config struct {
DefaultDecision *string `json:"default_decision"`
DefaultAuthorizationDecision *string `json:"default_authorization_decision"`
Caching json.RawMessage `json:"caching"`
PersistenceDirectory *string `json:"persistence_directory"`
}

// ParseConfig returns a valid Config object with defaults injected. The id
Expand Down Expand Up @@ -90,6 +93,18 @@ func (c *Config) validateAndInjectDefaults(id string) error {
return nil
}

// GetPersistenceDirectory returns the configured persistence directory, or $PWD/.opa if none is configured
func (c Config) GetPersistenceDirectory() (string, error) {
if c.PersistenceDirectory == nil {
pwd, err := os.Getwd()
if err != nil {
return "", err
}
return filepath.Join(pwd, ".opa"), nil
}
return *c.PersistenceDirectory, nil
}

const (
defaultDecisionPath = "/system/main"
defaultAuthorizationDecisionPath = "/system/authz/allow"
Expand Down
30 changes: 30 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package config

import (
"encoding/json"
"os"
"path/filepath"
"testing"
)

Expand Down Expand Up @@ -68,3 +70,31 @@ func TestConfigPluginsEnabled(t *testing.T) {
})
}
}

func TestPersistDirectory(t *testing.T) {
pwd, err := os.Getwd()
if err != nil {
t.Fatalf("%v", err)
}

c := Config{}
persistDir, err := c.GetPersistenceDirectory()
if err != nil {
t.Fatalf("%v", err)
}

if persistDir != filepath.Join(pwd, ".opa") {
t.Errorf("expected persistDir to be %v, got %v", filepath.Join(pwd, ".opa"), persistDir)
}

dir := "/var/opa"
c.PersistenceDirectory = &dir
persistDir, err = c.GetPersistenceDirectory()
if err != nil {
t.Fatalf("%v", err)
}

if persistDir != dir {
t.Errorf("expected peristDir %v and dir %v to be equal", persistDir, dir)
}
}
3 changes: 3 additions & 0 deletions docs/content/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ status:

default_decision: /http/example/authz/allow

persistence_directory: /var/opa

keys:
global_key:
algorithm: RS256
Expand Down Expand Up @@ -611,6 +613,7 @@ func init() {
| `labels` | `object` | Yes | Set of key-value pairs that uniquely identify the OPA instance. Labels are included when OPA uploads decision logs and status information. |
| `default_decision` | `string` | No (default: `/system/main`) | Set path of default policy decision used to serve queries against OPA's base URL. |
| `default_authorization_decision` | `string` | No (default: `/system/authz/allow`) | Set path of default authorization decision for OPA's API. |
| `persistence_directory` | `string` | No (default `$PWD/.opa`) | Set directory to use for persistence with options like `bundles[_].persist`. |
| `plugins` | `object` | No (default: `{}`) | Location for custom plugin configuration. See [Plugins](../plugins) for details. |

### Keys
Expand Down
9 changes: 5 additions & 4 deletions plugins/bundle/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (p *Plugin) Start(ctx context.Context) error {

var err error

p.bundlePersistPath, err = getDefaultBundlePersistPath()
p.bundlePersistPath, err = p.getBundlePersistPath()
if err != nil {
return err
}
Expand Down Expand Up @@ -593,10 +593,11 @@ func loadBundleFromDisk(path, name string, src *Source) (*bundle.Bundle, error)
}
}

func getDefaultBundlePersistPath() (string, error) {
pwd, err := os.Getwd()
func (p *Plugin) getBundlePersistPath() (string, error) {
persistDir, err := p.manager.Config.GetPersistenceDirectory()
if err != nil {
return "", err
}
return filepath.Join(pwd, ".opa", "bundles"), nil

return filepath.Join(persistDir, "bundles"), nil
}
50 changes: 49 additions & 1 deletion plugins/bundle/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,37 @@ func TestSaveBundleToDiskNew(t *testing.T) {
}
}

func TestSaveBundleToDiskNewConfiguredPersistDir(t *testing.T) {
dir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("unexpected error %v", err)
}
defer os.RemoveAll(dir)

manager := getTestManager()
manager.Config.PersistenceDirectory = &dir
bundles := map[string]*Source{}
plugin := New(&Config{Bundles: bundles}, manager)

err = plugin.Start(context.Background())
if err != nil {
t.Fatalf("unexpected error %v", err)
}

b := getTestBundle(t)

err = plugin.saveBundleToDisk("foo", &b)
if err != nil {
t.Fatalf("unexpected error %v", err)
}

expectBundlePath := filepath.Join(dir, "bundles", "foo", "bundle.tar.gz")
_, err = os.Stat(expectBundlePath)
if err != nil {
t.Errorf("expected bundle persisted at path %v, %v", expectBundlePath, err)
}
}

func TestSaveBundleToDiskOverWrite(t *testing.T) {

manager := getTestManager()
Expand Down Expand Up @@ -1771,7 +1802,8 @@ func TestLoadSignedBundleFromDisk(t *testing.T) {
}

func TestGetDefaultBundlePersistPath(t *testing.T) {
path, err := getDefaultBundlePersistPath()
plugin := New(&Config{}, getTestManager())
path, err := plugin.getBundlePersistPath()
if err != nil {
t.Fatalf("unexpected error %v", err)
}
Expand All @@ -1781,6 +1813,22 @@ func TestGetDefaultBundlePersistPath(t *testing.T) {
}
}

func TestConfiguredBundlePersistPath(t *testing.T) {
persistPath := "/var/opa"
manager := getTestManager()
manager.Config.PersistenceDirectory = &persistPath
plugin := New(&Config{}, manager)

path, err := plugin.getBundlePersistPath()
if err != nil {
t.Fatalf("unexpected error %v", err)
}

if path != "/var/opa/bundles" {
t.Errorf("expected configured persist path '/var/opa/bundles'")
}
}

func writeTestBundleToDisk(t *testing.T, srcDir string, signed bool) bundle.Bundle {
t.Helper()

Expand Down

0 comments on commit 635d8a5

Please sign in to comment.