Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rule: Add migration capabilities #268

Merged
merged 2 commits into from
Sep 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ builds:
flags:
- -a
ldflags:
- -s -w -X github.com/ory/oathkeeper/cmd.Version={{.Env.RELEASE_NAME}} -X github.com/ory/oathkeeper/cmd.Commit={{.FullCommit}} -X github.com/ory/oathkeeper/cmd.Date={{.Date}}
- -s -w -X github.com/ory/oathkeeper/x.Version={{.Env.RELEASE_NAME}} -X github.com/ory/oathkeeper/x.Commit={{.FullCommit}} -X github.com/ory/oathkeeper/x.Date={{.Date}}
binary: oathkeeper
env:
- CGO_ENABLED=0
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ install-stable:
git checkout $$OATHKEEPER_LATEST
packr2
GO111MODULE=on go install \
-ldflags "-X github.com/ory/oathkeeper/cmd.Version=$$OATHKEEPER_LATEST -X github.com/ory/oathkeeper/cmd.Date=`TZ=UTC date -u '+%Y-%m-%dT%H:%M:%SZ'` -X github.com/ory/oathkeeper/cmd.Commit=`git rev-parse HEAD`" \
-ldflags "-X github.com/ory/oathkeeper/x.Version=$$OATHKEEPER_LATEST -X github.com/ory/oathkeeper/x.Date=`TZ=UTC date -u '+%Y-%m-%dT%H:%M:%SZ'` -X github.com/ory/oathkeeper/x.Commit=`git rev-parse HEAD`" \
.
packr2 clean
git checkout master
Expand Down
8 changes: 4 additions & 4 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ Previously, this value was only configurable in the global config. Now, it can
be set on a per rule basis as well as globally. The global config will always be
used as a fallback when no access rule specific configuration is set.

For this to work, the ORY Oathkeeper global configuration file (`~/.oathkeeper.yaml`) has changed when it
comes to mutators, authenticaotrs, and authorizers. Instead of defining the
config at the same level as the `enabled` flag, it is now nested in a subkey
"config":
For this to work, the ORY Oathkeeper global configuration file
(`~/.oathkeeper.yaml`) has changed when it comes to mutators, authenticaotrs,
and authorizers. Instead of defining the config at the same level as the
`enabled` flag, it is now nested in a subkey "config":

```
authorizers:
Expand Down
6 changes: 0 additions & 6 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ import (
"github.com/ory/x/logrusx"
)

var (
Version = "master"
Date = "undefined"
Commit = "undefined"
)

var schemas = packr.New("schemas", "../.schemas")

// RootCmd represents the base command when called without any subcommands
Expand Down
3 changes: 2 additions & 1 deletion cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package cmd

import (
"github.com/ory/oathkeeper/cmd/server"
"github.com/ory/oathkeeper/x"

"github.com/ory/x/logrusx"
"github.com/ory/x/viperx"
Expand All @@ -41,7 +42,7 @@ on configuration options, open the configuration documentation:

>> https://www.ory.sh/docs/oathkeeper/configuration <<
`,
Run: server.RunServe(Version, Commit, Date),
Run: server.RunServe(x.Version, x.Commit, x.Date),
}

func init() {
Expand Down
8 changes: 5 additions & 3 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@ import (
"fmt"

"github.com/spf13/cobra"

"github.com/ory/oathkeeper/x"
)

// versionCmd represents the version command
var versionCmd = &cobra.Command{
Use: "version",
Short: "Display this binary's version, build time and git hash of this build",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Version: %s\n", Version)
fmt.Printf("Git Hash: %s\n", Commit)
fmt.Printf("Build Time: %s\n", Date)
fmt.Printf("Version: %s\n", x.Version)
fmt.Printf("Git Hash: %s\n", x.Commit)
fmt.Printf("Build Time: %s\n", x.Date)
},
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/Microsoft/go-winio v0.4.12 // indirect
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf
github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7
github.com/blang/semver v3.5.1+incompatible
github.com/bxcodec/faker v2.0.1+incompatible
github.com/cenkalti/backoff v2.1.1+incompatible
github.com/dgrijalva/jwt-go v3.2.0+incompatible
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7 h1:irR1cO6
github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA=
Expand Down
31 changes: 31 additions & 0 deletions rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ type Rule struct {
// You will need this ID later on to update or delete the rule.
ID string `json:"id"`

// Version represents the access rule version. Should match one of ORY Oathkeepers release versions. Supported since
// v0.20.0-beta.1+oryOS.14.
Version string `json:"version"`

// Description is a human readable description of this rule.
Description string `json:"description"`

Expand Down Expand Up @@ -110,6 +114,8 @@ type Upstream struct {
URL string `json:"url"`
}

var _ json.Unmarshaler = new(Rule)

func NewRule() *Rule {
return &Rule{
Match: RuleMatch{},
Expand All @@ -118,6 +124,31 @@ func NewRule() *Rule {
}
}

func (r *Rule) UnmarshalJSON(raw []byte) error {
var rr struct {
ID string `json:"id"`
Version string `json:"version"`
Description string `json:"description"`
Match RuleMatch `json:"match"`
Authenticators []RuleHandler `json:"authenticators"`
Authorizer RuleHandler `json:"authorizer"`
Mutators []RuleHandler `json:"mutators"`
Upstream Upstream `json:"upstream"`
}

transformed, err := migrateRuleJSON(raw)
if err != nil {
return err
}

if err := errors.WithStack(json.Unmarshal(transformed, &rr)); err != nil {
return err
}

*r = rr
return nil
}

// GetID returns the rule's ID.
func (r *Rule) GetID() string {
return r.ID
Expand Down
46 changes: 46 additions & 0 deletions rule/rule_migrator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package rule

import (
"strings"

"github.com/blang/semver"
"github.com/pkg/errors"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"

"github.com/ory/herodot"
"github.com/ory/x/stringsx"

"github.com/ory/oathkeeper/x"
)

func migrateRuleJSON(raw []byte) ([]byte, error) {
rv := strings.TrimPrefix(
stringsx.Coalesce(
gjson.GetBytes(raw, "version").String(),
x.Version,
x.UnknownVersion,
),
"v",
)

if rv == x.UnknownVersion {
return raw, nil
}

version, err := semver.Make(rv)
if err != nil {
return nil, errors.WithStack(err)
}

raw, err = sjson.SetBytes(raw, "version", strings.Split(x.Version, "+")[0])
if err != nil {
return nil, errors.WithStack(err)
}

if semver.MustParseRange(">=0.19.0-alpha.0")(version) {
return raw, nil
}

return nil, errors.WithStack(herodot.ErrBadRequest.WithReasonf("Unknown access rule version %s, unable to migrate.", version.String()))
}
67 changes: 67 additions & 0 deletions rule/rule_migrator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package rule

import (
"bytes"
"encoding/json"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ory/oathkeeper/x"
)

func TestRuleMigration(t *testing.T) {
for k, tc := range []struct {
d string
in string
out string
expectErr bool
version string
}{
{
d: "should work with v0.19.0-beta.1",
in: `{}`,
out: `{"id":"","version":"v0.19.0-beta.1","description":"","match":{"methods":null,"url":""},"authenticators":null,"authorizer":{"handler":"","config":null},"mutators":null,"upstream":{"preserve_host":false,"strip_path":"","url":""}}`,
version: "v0.19.0-beta.1",
},
{
d: "should work with v0.19.0-beta.1+oryOS.12",
in: `{}`,
out: `{"id":"","version":"v0.19.0-beta.1","description":"","match":{"methods":null,"url":""},"authenticators":null,"authorizer":{"handler":"","config":null},"mutators":null,"upstream":{"preserve_host":false,"strip_path":"","url":""}}`,
version: "v0.19.0-beta.1+oryOS.12",
},
{
d: "should work with v0.19.0-beta.1",
in: `{"version":"v0.19.0-beta.1"}`,
out: `{"id":"","version":"v0.19.0-beta.1","description":"","match":{"methods":null,"url":""},"authenticators":null,"authorizer":{"handler":"","config":null},"mutators":null,"upstream":{"preserve_host":false,"strip_path":"","url":""}}`,
version: "v0.19.0-beta.1",
},
{
d: "should work with 0.19.0-beta.1",
in: `{"version":"0.19.0-beta.1"}`,
out: `{"id":"","version":"v0.19.0-beta.1","description":"","match":{"methods":null,"url":""},"authenticators":null,"authorizer":{"handler":"","config":null},"mutators":null,"upstream":{"preserve_host":false,"strip_path":"","url":""}}`,
version: "v0.19.0-beta.1+oryOS.12",
},
} {
t.Run(fmt.Sprintf("case=%d/description=%s", k, tc.d), func(t *testing.T) {
var r Rule

x.Version = tc.version
err := json.NewDecoder(bytes.NewBufferString(tc.in)).Decode(&r)
x.Version = x.UnknownVersion

if tc.expectErr {
require.Error(t, err)
return
}

require.NoError(t, err, "%+v", err)

var out bytes.Buffer
require.NoError(t, json.NewEncoder(&out).Encode(&r))
assert.JSONEq(t, tc.out, out.String(), "%s", out.String())
})
}
}
9 changes: 9 additions & 0 deletions x/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package x

const UnknownVersion = "master"

var (
Version = "master"
Date = "undefined"
Commit = "undefined"
)