Skip to content

Commit

Permalink
feature: Introduce Admin API (#135)
Browse files Browse the repository at this point in the history
* chore(test): Add tests for admin add/update API

* Add admin API
  • Loading branch information
charithe committed Jun 8, 2021
1 parent 098318f commit 1370261
Show file tree
Hide file tree
Showing 60 changed files with 2,986 additions and 1,043 deletions.
16 changes: 16 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ github.com/beorn7/perks/quantile https://github
github.com/cespare/xxhash https://github.com/cespare/xxhash/blob/master/LICENSE.txt MIT
github.com/cespare/xxhash/v2 https://github.com/cespare/xxhash/blob/master/v2/LICENSE.txt MIT
github.com/davecgh/go-spew/spew https://github.com/davecgh/go-spew/blob/master/spew/LICENSE ISC
github.com/doug-martin/goqu/v9 https://github.com/doug-martin/goqu/blob/master/v9/LICENSE MIT
github.com/emirpasic/gods https://github.com/emirpasic/gods/blob/master/LICENSE BSD-2-Clause
github.com/envoyproxy/protoc-gen-validate/validate https://github.com/envoyproxy/protoc-gen-validate/blob/master/validate/LICENSE Apache-2.0
github.com/fatih/color https://github.com/fatih/color/blob/master/LICENSE.md MIT
github.com/felixge/httpsnoop https://github.com/felixge/httpsnoop/blob/master/LICENSE.txt MIT
github.com/fsnotify/fsnotify https://github.com/fsnotify/fsnotify/blob/master/LICENSE BSD-3-Clause
github.com/ghodss/yaml https://github.com/ghodss/yaml/blob/master/LICENSE MIT
github.com/gobwas/glob https://github.com/gobwas/glob/blob/master/LICENSE MIT
github.com/go-git/gcfg https://github.com/go-git/gcfg/blob/master/LICENSE BSD-3-Clause
github.com/go-git/go-billy/v5 https://github.com/go-git/go-billy/blob/master/v5/LICENSE Apache-2.0
github.com/go-git/go-git/v5 https://github.com/go-git/go-git/blob/master/v5/LICENSE Apache-2.0
github.com/golang/groupcache/lru https://github.com/golang/groupcache/blob/master/lru/LICENSE Apache-2.0
github.com/golang/protobuf https://github.com/golang/protobuf/blob/master/LICENSE BSD-3-Clause
github.com/google/cel-go https://github.com/google/cel-go/blob/master/LICENSE Apache-2.0
Expand All @@ -32,10 +37,16 @@ github.com/gorilla/mux https://github
github.com/grpc-ecosystem/go-grpc-middleware https://github.com/grpc-ecosystem/go-grpc-middleware/blob/master/LICENSE Apache-2.0
github.com/grpc-ecosystem/grpc-gateway/v2 https://github.com/grpc-ecosystem/grpc-gateway/blob/master/v2/LICENSE.txt BSD-3-Clause
github.com/hashicorp/golang-lru https://github.com/hashicorp/golang-lru/blob/master/LICENSE MPL-2.0
github.com/imdario/mergo https://github.com/imdario/mergo/blob/master/LICENSE BSD-3-Clause
github.com/jbenet/go-context/io https://github.com/jbenet/go-context/blob/master/io/LICENSE MIT
github.com/jmoiron/sqlx https://github.com/jmoiron/sqlx/blob/master/LICENSE MIT
github.com/kavu/go_reuseport https://github.com/kavu/go_reuseport/blob/master/LICENSE MIT
github.com/kevinburke/ssh_config https://github.com/kevinburke/ssh_config/blob/master/LICENSE MIT
github.com/mattn/go-colorable https://github.com/mattn/go-colorable/blob/master/LICENSE MIT
github.com/mattn/go-isatty https://github.com/mattn/go-isatty/blob/master/LICENSE MIT
github.com/mattn/go-sqlite3 https://github.com/mattn/go-sqlite3/blob/master/LICENSE MIT
github.com/matttproud/golang_protobuf_extensions/pbutil https://github.com/matttproud/golang_protobuf_extensions/blob/master/pbutil/LICENSE Apache-2.0
github.com/mitchellh/go-homedir https://github.com/mitchellh/go-homedir/blob/master/LICENSE MIT
github.com/OneOfOne/xxhash https://github.com/OneOfOne/xxhash/blob/master/LICENSE Apache-2.0
github.com/open-policy-agent/opa https://github.com/open-policy-agent/opa/blob/master/LICENSE Apache-2.0
github.com/open-policy-agent/opa/internal/jwx https://github.com/open-policy-agent/opa/blob/master/internal/jwx/LICENSE MIT
Expand All @@ -48,8 +59,10 @@ github.com/prometheus/common https://github
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg https://github.com/prometheus/common/blob/master/internal/bitbucket.org/ww/goautoneg/README.txt BSD-3-Clause
github.com/prometheus/procfs https://github.com/prometheus/procfs/blob/master/LICENSE Apache-2.0
github.com/prometheus/statsd_exporter/pkg/mapper https://github.com/prometheus/statsd_exporter/blob/master/pkg/mapper/LICENSE Apache-2.0
github.com/ProtonMail/go-crypto https://github.com/ProtonMail/go-crypto/blob/master/LICENSE BSD-3-Clause
github.com/rcrowley/go-metrics https://github.com/rcrowley/go-metrics/blob/master/LICENSE BSD-2-Clause-FreeBSD
github.com/rjeczalik/notify https://github.com/rjeczalik/notify/blob/master/LICENSE MIT
github.com/sergi/go-diff/diffmatchpatch https://github.com/sergi/go-diff/blob/master/diffmatchpatch/LICENSE MIT
github.com/sirupsen/logrus https://github.com/sirupsen/logrus/blob/master/LICENSE MIT
github.com/spf13/afero https://github.com/spf13/afero/blob/master/LICENSE.txt Apache-2.0
github.com/spf13/cobra https://github.com/spf13/cobra/blob/master/LICENSE.txt Apache-2.0
Expand All @@ -61,10 +74,12 @@ github.com/tidwall/match https://github
github.com/tidwall/pretty https://github.com/tidwall/pretty/blob/master/LICENSE MIT
github.com/tidwall/sjson https://github.com/tidwall/sjson/blob/master/LICENSE MIT
github.com/uber/jaeger-client-go/thrift https://github.com/uber/jaeger-client-go/blob/master/thrift/LICENSE Apache-2.0
github.com/xanzy/ssh-agent https://github.com/xanzy/ssh-agent/blob/master/LICENSE Apache-2.0
github.com/xeipuuv/gojsonpointer Unknown Unknown
github.com/xeipuuv/gojsonreference Unknown Unknown
github.com/yashtewari/glob-intersection https://github.com/yashtewari/glob-intersection/blob/master/LICENSE Apache-2.0
go.elastic.co/ecszap Unknown Apache-2.0
golang.org/x/crypto Unknown BSD-3-Clause
golang.org/x/net Unknown BSD-3-Clause
golang.org/x/sync Unknown BSD-3-Clause
golang.org/x/sys Unknown BSD-3-Clause
Expand All @@ -75,6 +90,7 @@ google.golang.org/grpc Unknown
google.golang.org/protobuf Unknown BSD-3-Clause
go.opencensus.io Unknown Apache-2.0
gopkg.in/alecthomas/kingpin.v2 Unknown MIT
gopkg.in/warnings.v0 Unknown BSD-2-Clause
gopkg.in/yaml.v2 Unknown Apache-2.0
gopkg.in/yaml.v3 Unknown MIT
go.uber.org/atomic Unknown MIT
Expand Down
39 changes: 14 additions & 25 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,23 @@ import (
"github.com/cerbos/cerbos/internal/compile"
"github.com/cerbos/cerbos/internal/engine"
"github.com/cerbos/cerbos/internal/server"
"github.com/cerbos/cerbos/internal/storage"
"github.com/cerbos/cerbos/internal/storage/disk"
"github.com/cerbos/cerbos/internal/svc"
"github.com/cerbos/cerbos/internal/test"
)

func TestClient(t *testing.T) {
test.SkipIfGHActions(t) // TODO (cell) Servers don't work inside GH Actions for some reason.

eng, cancelFunc := mkEngine(t)
dir := test.PathToDir(t, "store")
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

cerbosSvc := svc.NewCerbosService(eng)
store, err := disk.NewStore(ctx, &disk.Conf{Directory: dir, ScratchDir: t.TempDir()})
require.NoError(t, err)

eng, err := engine.New(ctx, compile.NewCompiler(ctx, store))
require.NoError(t, err)

t.Run("with_tls", func(t *testing.T) {
testdataDir := test.PathToDir(t, "server")
Expand All @@ -46,7 +51,7 @@ func TestClient(t *testing.T) {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

startServer(ctx, conf, cerbosSvc)
startServer(ctx, conf, store, eng)

c, err := client.New(conf.GRPCListenAddr, client.WithTLSInsecure())
require.NoError(t, err)
Expand All @@ -69,7 +74,7 @@ func TestClient(t *testing.T) {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

startServer(ctx, conf, cerbosSvc)
startServer(ctx, conf, store, eng)

c, err := client.New(conf.GRPCListenAddr, client.WithTLSInsecure())
require.NoError(t, err)
Expand All @@ -88,7 +93,7 @@ func TestClient(t *testing.T) {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

startServer(ctx, conf, cerbosSvc)
startServer(ctx, conf, store, eng)

c, err := client.New(conf.GRPCListenAddr, client.WithPlaintext())
require.NoError(t, err)
Expand All @@ -107,7 +112,7 @@ func TestClient(t *testing.T) {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

startServer(ctx, conf, cerbosSvc)
startServer(ctx, conf, store, eng)

c, err := client.New(conf.GRPCListenAddr, client.WithPlaintext())
require.NoError(t, err)
Expand Down Expand Up @@ -180,22 +185,6 @@ func testGRPCClient(c client.Client) func(*testing.T) {
}
}

func mkEngine(t *testing.T) (*engine.Engine, context.CancelFunc) {
t.Helper()

dir := test.PathToDir(t, "store")

ctx, cancelFunc := context.WithCancel(context.Background())

store, err := disk.NewStore(ctx, &disk.Conf{Directory: dir, ScratchDir: t.TempDir()})
require.NoError(t, err)

eng, err := engine.New(ctx, compile.NewCompiler(ctx, store))
require.NoError(t, err)

return eng, cancelFunc
}

func getFreeListenAddr(t *testing.T) string {
t.Helper()

Expand All @@ -208,10 +197,10 @@ func getFreeListenAddr(t *testing.T) string {
return addr
}

func startServer(ctx context.Context, conf *server.Conf, cerbosSvc *svc.CerbosService) {
func startServer(ctx context.Context, conf *server.Conf, store storage.Store, eng *engine.Engine) {
s := server.NewServer(conf)
go func() {
if err := s.Start(ctx, cerbosSvc, false); err != nil {
if err := s.Start(ctx, store, eng, false); err != nil {
panic(err)
}
}()
Expand Down
1 change: 1 addition & 0 deletions docs/modules/api/nav.adoc
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.Cerbos API
* xref:index.adoc[Using the API]
* xref:admin_api.adoc[Admin API]
62 changes: 62 additions & 0 deletions docs/modules/api/pages/admin_api.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
include::ROOT:partial$attributes.adoc[]

= The Cerbos Admin API

The Admin API is an optional component of the Cerbos PDP that must be enabled by setting the `server.adminAPI.enabled` to `true` in the configuration. (See xref:configuration:server.adoc#admin-api[Admin API configuration] for details).

Authentication is mandatory for the Admin API. Currently only basic authentication with a single admin user is supported. If no credentials are configured using the xref:configuration:server.adoc#admin-api[configuration], the default username and password is `cerbos` and `cerbosAdmin`.

IMPORTANT: Always change the default credentials and enable TLS for the endpoint when enabling the Admin API. See xref:configuration:server.adoc[Server configuration] for more information.

== Add/update policies [`/admin/policy`]

NOTE: This endpoint requires a mutable storage driver such as xref:configuration:storage.adoc#sqlite3[sqlite3] to be configured.

.Request
[source,json,linenums]
----
{
"policies": [ <1>
{
"apiVersion": "api.cerbos.dev/v1",
"principalPolicy": {
"principal": "donald_duck",
"version": "20210210",
"rules": [
{
"resource": "leave_request",
"actions": [
{
"action": "*",
"condition": {
"match": {
"expr": "request.resource.attr.dev_record == true"
}
},
"effect": "EFFECT_ALLOW"
}
]
},
{
"resource": "salary_record",
"actions": [
{
"action": "*",
"effect": "EFFECT_DENY"
}
]
}
]
}
}
]
}
----
<1> List of policy definitions


.Response
[source,json,linenums]
----
{"success":{}}
----
9 changes: 8 additions & 1 deletion docs/modules/configuration/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ server:
disabled: false
allowedOrigins: ['*']
allowedHeaders: []
adminAPI:
enabled: true
adminCredentials:
username: cerbos
passwordHash: $2y$10$6v.PIn0zJ1xFdIDPlX3yheDZHM2iXI8CSKT5a3d35djtOxnOATxFi
engine: # Optional
defaultPolicyVersion: "default" # Default policy version to assume if the request does not specify one.
Expand All @@ -45,7 +50,7 @@ tracing: # Optional
collectorEndpoint: "http://localhost:14268" # Export to Jaeger collector.
storage:
driver: "disk" # Valid values are "disk" or "git"
driver: "disk" # Valid values are "disk", "git" or "sqlite3"
disk: # Only required if "driver" is "disk"
directory: pkg/test/testdata/store
watchForChanges: false
Expand All @@ -64,6 +69,8 @@ storage:
ssh: # Only required if the "protocol" is "ssh"
user: git
privateKeyFile: ${HOME}/.ssh/id_rsa
sqlite3: # Only required if the "driver" is "sqlite3"
dsn: ":memory:?_fk=true"
----


30 changes: 30 additions & 0 deletions docs/modules/configuration/pages/server.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,36 @@ server:
- X-CUSTOM
----


[#admin-api]
== Enable Admin API

The xref:api:admin_api.adoc[Cerbos Admin API] provides administration functions such as adding or updating policies (if the underlying storage engine supports it) to the running Cerbos instance. It is disabled by default.

Authentication is mandatory for the Admin API. See xref:api:admin_api.adoc[Cerbos Admin API documentation] for more details.

IMPORTANT: TLS should be enabled to ensure that credentials are transmitted securely over the network. We also highly recommend changing the default username and password when deploying Cerbos.

[source,yaml,linenums]
----
server:
adminAPI:
enabled: true
adminCredentials:
username: cerbos
passwordHash: $2y$10$6v.PIn0zJ1xFdIDPlX3yheDZHM2iXI8CSKT5a3d35djtOxnOATxFi
----

=== Generating a password hash

Cerbos expects the password to be hashed with bcrypt. This can be achieved using the `htpasswd` utility available on most operating systems.

[source, sh]
----
echo "cerbosAdmin" | htpasswd -niBC 10 cerbos | cut -d ':' -f 2
----


== Enable Playground

The Cerbos playground API is disabled by default. To enable it, set `playgroundEnabled` to `true`.
Expand Down
23 changes: 23 additions & 0 deletions docs/modules/configuration/pages/storage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,26 @@ storage:
user: git
privateKeyFile: ${HOME}/.ssh/id_rsa
----

[#sqlite3]
== Sqlite3 Driver

Cerbos has experimental support for using sqlite3 as a policy repository. Currently this is the only storage driver that can be used in conjunction with the xref:server.adoc#admin-api[Admin API] to add or update policies via an API call.

.In-memory ephemeral database
[source,yaml,linenums]
----
storage:
driver: "sqlite3"
sqlite3:
dsn: ":memory:"
----

.On-disk persistent database
[source,yaml,linenums]
----
storage:
driver: "sqlite3"
sqlite3:
dsn: "file:/tmp/cerbos.sqlite?mode=rwc&cache=shared&_fk=true"
----
2 changes: 2 additions & 0 deletions docs/modules/policies/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ NOTE: View the latest documentation and example requests by accessing a running
** `apiVersion`: Required. Must be `api.cerbos.dev/v1`.
** `description`: Optional. Description of the policy.
** `disabled`: Optional. Set to `true` to make the Cerbos engine ignore this policy file.
** `metadata.sourceFile`: Optional. Set to the source of the policy data for auditing purposes.
** `metadata.annotations`: Optional. Key-value pairs of strings holding free-form data for auditing purposes.
* Resource names, actions, and principal names can be hierarchical. Use `:` as the delimiter. E.g. `app:component:resource`.
* Wildcard matches are allowed on certain fields. Wildcards respect the hierarchy delimiter `:`.
* See xref:conditions.adoc[Conditions] to learn how to write conditions in policy rules.

0 comments on commit 1370261

Please sign in to comment.