Implement monorepo layout
Implemented the nexantic monorepo.
Smalltown code was moved to `core`. From now on all code will live in top level directories named after the projects with the exception for general purpose libraries which should go to `<lang>libs`.
General build and utility folders are underscore prefixed.
The repo name will from now on be rNXT (nexantic). I think this change makes sense since components in this repo will not all be part of Smalltown, the Smalltown brand has been claimed by Signon GmbH so we need to change it anyway and the longer we wait the harder it will be to change/move it.
Test Plan: Launched Smalltown using `./scripts/bin/bazel run //core/scripts:launch`
X-Origin-Diff: phab/D210
GitOrigin-RevId: fa5a7f08143d2ead2cb7206b4c63ab641794162c
diff --git a/core/internal/iam/BUILD.bazel b/core/internal/iam/BUILD.bazel
new file mode 100644
index 0000000..f737d5c
--- /dev/null
+++ b/core/internal/iam/BUILD.bazel
@@ -0,0 +1,22 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
+
+go_library(
+ name = "go_default_library",
+ srcs = [
+ "capabilities.go",
+ "policies.go",
+ ],
+ importpath = "git.monogon.dev/source/nexantic.git/core/internal/iam",
+ visibility = ["//visibility:private"],
+ deps = [
+ "@com_github_open_policy_agent_opa//ast:go_default_library",
+ "@com_github_open_policy_agent_opa//rego:go_default_library",
+ "@com_github_open_policy_agent_opa//util:go_default_library",
+ ],
+)
+
+go_binary(
+ name = "iam",
+ embed = [":go_default_library"],
+ visibility = ["//:__subpackages__"],
+)
diff --git a/core/internal/iam/README.md b/core/internal/iam/README.md
new file mode 100644
index 0000000..07635ad
--- /dev/null
+++ b/core/internal/iam/README.md
@@ -0,0 +1,102 @@
+## Smalltown IAM
+
+There are 4 kinds of elements in Smalltown's Authorization system
+* Identities
+ * User
+ * Key
+ * Module
+* Objects
+ * Key
+ * Secret
+ * Module
+* Policies
+* Permissions
+
+### Identity
+Identities represent an actor that can execute **actions** like editing or interacting with an object.
+
+Identities possess **permissions** and **properties** which can be accessed by policies.
+
+### Objects
+Objects are things that can be interacted with like keys, secrets or modules.
+
+Each object has a **policy** that handles authorization of **actions** performed on it.
+
+When an object is created a default policy is attached which forwards all decisions to the global policy.
+For the first iteration of the system this policy will not be modifiable.
+
+**WARNING**: by modifying a policy, an object could become inaccessible!
+
+### Permissions
+
+Permissions can be assigned to an identity.
+
+| Property | Description | Example |
+|----------|-------------|---------|
+| Allowed Action | Regex specifying the allowed actions | key:meta:edit |
+| Object | Regex specifying the objects this affects | keys:* |
+| Multisig | Number of approvals required | 2 |
+
+Optionally a permission can have a multisig flag that requires N approvals from identities with the same permission.
+
+### Policies
+
+Policies guard actions that are performed on an object.
+
+By default a global policy governs all objects and global actions using an AWS IAM like model.
+
+Potentially a dynamic model using attachable policies could be implemented in the future to allow
+for highly custom models.
+
+A potential graphical representation of a future policy:
+
+
+
+### Global Default Ruleset
+
+This default global policy defines an AWS IAM like permission system.
+
+The following actions are implemented on objects:
+
+| Category | Action | Description | Note |
+|----------|-------------|---------|---------|
+| Object | object:view | Allow to view the object | Cannot be scripted using the policy builder |
+| Object | object:delete | Allow to delete the object |
+| Object | object:attach:normal | Allow to attach the object to a module slot |
+| Object | object:attach:exclusive | Allow to attach the object to an exclusive module slot |
+| Object | object:policy:view | Allow to view the object's attached policy |
+| Object | object:policy:edit | Allow to edit the object's attached policy |
+| Object | object:audit:view | Allow to view the object's audit log |
+| Object:Key | key:sign:eddsa | Allow to sign using the key |
+| Object:Key | key:sign:ecdsa | Allow to sign using the key |
+| Object:Key | key:sign:rsa | Allow to sign using the key |
+| Object:Key | key:encrypt:rsa | Allow to encrypt using the key |
+| Object:Key | key:encrypt:des | Allow to encrypt using the key |
+| Object:Key | key:encrypt:3des| Allow to encrypt using the key |
+| Object:Key | key:encrypt:aes | Allow to encrypt using the key |
+| Object:Key | key:decrypt:rsa | Allow to decrypt using the key |
+| Object:Key | key:decrypt:des | Allow to decrypt using the key |
+| Object:Key | key:decrypt:3des| Allow to decrypt using the key |
+| Object:Key | key:decrypt:aes | Allow to decrypt using the key |
+| Object:Key | key:auth:hmac | Allow to auth messages using the key |
+| Object:Secret | secret:reveal | Allow to reveal a secret to the identity |
+| Object:Module | module:update | Allow to update a module's bytecode | Updates verify the module signature
+| Object:Module | module:config | Allow to configure a module | Assigning objects to slots requires additional permissions on that object
+| Object:Module | module:call:* | Allow to call a function of the module | Function names are defined in the module and vary between modules
+
+The following actions are implemented globally:
+
+| Category | Action | Description | Note |
+|----------|-------------|---------|---------|
+| Object | g:key:generate | Allow to generate a key |
+| Object | g:key:import | Allow to import a key |
+| Object | g:secret:import | Allow to import a secret |
+| Object | g:module:install | Allow to install a module |
+| Object | g:user:create | Allow to create a user |
+| Object | g:user:permission_remove | Allow to create a user | **Privilege Escalation Risk**: Recommend Multisig
+| Object | g:user:permission_add | Allow to create a user | **Privilege Escalation Risk**: Recommend Multisig
+| Object | g:cluster:view | Allow to view cluster nodes
+| Object | g:cluster:add | Allow to add a node to the cluster | **Dangerous**: Recommend Multisig
+| Object | g:cluster:remove | Allow to remove a node from the cluster | **Dangerous**: Recommend Multisig
+| Object | g:config:edit | Allow to edit the global config
+
diff --git a/core/internal/iam/capabilities.go b/core/internal/iam/capabilities.go
new file mode 100644
index 0000000..1c692a3
--- /dev/null
+++ b/core/internal/iam/capabilities.go
@@ -0,0 +1,23 @@
+// Copyright 2020 The Monogon Project Authors.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+type (
+ Capability struct {
+ Name string
+ }
+)
diff --git a/core/internal/iam/policies.go b/core/internal/iam/policies.go
new file mode 100644
index 0000000..b17b623
--- /dev/null
+++ b/core/internal/iam/policies.go
@@ -0,0 +1,69 @@
+// Copyright 2020 The Monogon Project Authors.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "context"
+ "fmt"
+ "github.com/open-policy-agent/opa/ast"
+ "github.com/open-policy-agent/opa/rego"
+ "github.com/open-policy-agent/opa/util"
+)
+
+type dataSetProfile struct {
+ numTokens int
+ numPaths int
+}
+
+func main() {
+ ctx := context.Background()
+ compiler := ast.NewCompiler()
+ module := ast.MustParseModule(policy)
+
+ compiler.Compile(map[string]*ast.Module{"": module})
+ if compiler.Failed() {
+ }
+
+ r := rego.New(
+ rego.Compiler(compiler),
+ rego.Input(util.MustUnmarshalJSON([]byte(`{
+ "token_id": "deadbeef",
+ "path": "mna",
+ "method": "GET"
+ }`))),
+ rego.Query("data.restauthz"),
+ )
+
+ rs, err := r.Eval(ctx)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Printf("%v", rs)
+}
+
+const policy = `package restauthz
+
+default allow = false
+
+allow {
+ input.method == "GET"
+}
+
+allow {
+ not input.method == "GET"
+}
+`