-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd: Add rules management capabilities to the cli
- Loading branch information
Showing
52 changed files
with
476 additions
and
198 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package cmd | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/ory/oathkeeper/sdk/go/oathkeepersdk/swagger" | ||
) | ||
|
||
func checkResponse(response *swagger.APIResponse, err error, expectedStatusCode int) { | ||
must(err, "Could not validate token: %s", err) | ||
|
||
if response.StatusCode != expectedStatusCode { | ||
fmt.Printf("Command failed because status code %d was expeceted but code %d was received.", expectedStatusCode, response.StatusCode) | ||
os.Exit(1) | ||
return | ||
} | ||
} | ||
|
||
func formatResponse(response interface{}) string { | ||
out, err := json.MarshalIndent(response, "", "\t") | ||
must(err, `Command failed because an error ("%s") occurred while prettifying output.`, err) | ||
return string(out) | ||
} | ||
|
||
func must(err error, message string, args ...interface{}) { | ||
if err == nil { | ||
return | ||
} | ||
|
||
fmt.Fprintf(os.Stderr, message+"\n", args...) | ||
os.Exit(1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCommandLineInterface(t *testing.T) { | ||
var osArgs = make([]string, len(os.Args)) | ||
os.Setenv("DATABASE_URL", "memory") | ||
os.Setenv("HYDRA_URL", "http://does-not-exist.com/") | ||
os.Setenv("HYDRA_CLIENT_ID", "does-not-exist") | ||
os.Setenv("HYDRA_CLIENT_SECRET", "does-not-exist") | ||
copy(osArgs, os.Args) | ||
|
||
for _, c := range []struct { | ||
args []string | ||
wait func() bool | ||
expectErr bool | ||
}{ | ||
{ | ||
args: []string{"serve", "all"}, | ||
wait: func() bool { | ||
res, err := http.Get("http://localhost:4455") | ||
if err != nil { | ||
t.Logf("Network error while polling for server: %s", err) | ||
} | ||
defer res.Body.Close() | ||
return err != nil | ||
}, | ||
}, | ||
{args: []string{"rules", "--endpoint=http://127.0.0.1:4456/", "import", "../stub/rules.json"}}, | ||
{args: []string{"rules", "--endpoint=http://127.0.0.1:4456/", "list"}}, | ||
{args: []string{"rules", "--endpoint=http://127.0.0.1:4456/", "get", "test-rule-1"}}, | ||
{args: []string{"rules", "--endpoint=http://127.0.0.1:4456/", "get", "test-rule-2"}}, | ||
{args: []string{"rules", "--endpoint=http://127.0.0.1:4456/", "delete", "test-rule-1"}}, | ||
} { | ||
RootCmd.SetArgs(c.args) | ||
|
||
t.Run(fmt.Sprintf("command=%v", c.args), func(t *testing.T) { | ||
if c.wait != nil { | ||
go func() { | ||
assert.Nil(t, RootCmd.Execute()) | ||
}() | ||
} | ||
|
||
if c.wait != nil { | ||
var count = 0 | ||
for c.wait() { | ||
t.Logf("Port is not yet open, retrying attempt #%d...", count) | ||
count++ | ||
if count > 5 { | ||
t.FailNow() | ||
} | ||
time.Sleep(time.Second) | ||
} | ||
} else { | ||
err := RootCmd.Execute() | ||
if c.expectErr { | ||
assert.Error(t, err) | ||
} else { | ||
assert.NoError(t, err) | ||
} | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
// rulesCmd represents the rules command | ||
var rulesCmd = &cobra.Command{ | ||
Use: "rules", | ||
Short: "Commands for managing rules", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
fmt.Println(cmd.UsageString()) | ||
}, | ||
} | ||
|
||
func init() { | ||
RootCmd.AddCommand(rulesCmd) | ||
rulesCmd.PersistentFlags().StringP("endpoint", "e", "", "The endpoint URL of ORY Oathkeeper's management API (required)") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"net/http" | ||
|
||
"github.com/ory/oathkeeper/sdk/go/oathkeepersdk" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// deleteCmd represents the delete command | ||
var deleteCmd = &cobra.Command{ | ||
Use: "delete <id>", | ||
Short: "Delete a rule", | ||
Long: `Usage example: | ||
oathkeeper rules --endpoint=http://localhost:4456/ delete rule-1 | ||
`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
endpoint, _ := cmd.Flags().GetString("endpoint") | ||
if endpoint == "" { | ||
fatalf("Please specify the endpoint url using the --endpoint flag, for more information use `oathkeeper help rules`") | ||
} else if len(args) != 1 { | ||
fatalf("Please specify the rule id, for more information use `oathkeeper help rules delete`") | ||
} | ||
|
||
client := oathkeepersdk.NewSDK(endpoint) | ||
response, err := client.DeleteRule(args[0]) | ||
checkResponse(response, err, http.StatusNoContent) | ||
fmt.Printf("Successfully deleted rule %s\n", args[0]) | ||
}, | ||
} | ||
|
||
func init() { | ||
rulesCmd.AddCommand(deleteCmd) | ||
|
||
// Here you will define your flags and configuration settings. | ||
|
||
// Cobra supports Persistent Flags which will work for this command | ||
// and all subcommands, e.g.: | ||
// deleteCmd.PersistentFlags().String("foo", "", "A help for foo") | ||
|
||
// Cobra supports local flags which will only run when this command | ||
// is called directly, e.g.: | ||
// deleteCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cmd | ||
|
||
import ( | ||
"net/http" | ||
|
||
"github.com/ory/oathkeeper/sdk/go/oathkeepersdk" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// getCmd represents the get command | ||
var getCmd = &cobra.Command{ | ||
Use: "get <id>", | ||
Short: "Fetch a rule", | ||
Long: `Usage example: | ||
oathkeeper rules --endpoint=http://localhost:4456/ get rule-1 | ||
`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
endpoint, _ := cmd.Flags().GetString("endpoint") | ||
if endpoint == "" { | ||
fatalf("Please specify the endpoint url using the --endpoint flag, for more information use `oathkeeper help rules`") | ||
} else if len(args) != 1 { | ||
fatalf("Please specify the rule id, for more information use `oathkeeper help rules get`") | ||
} | ||
|
||
client := oathkeepersdk.NewSDK(endpoint) | ||
rules, response, err := client.GetRule(args[0]) | ||
checkResponse(response, err, http.StatusOK) | ||
formatResponse(rules) | ||
}, | ||
} | ||
|
||
func init() { | ||
rulesCmd.AddCommand(getCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package cmd | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
|
||
"github.com/ory/oathkeeper/sdk/go/oathkeepersdk" | ||
"github.com/ory/oathkeeper/sdk/go/oathkeepersdk/swagger" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// importCmd represents the import command | ||
var importCmd = &cobra.Command{ | ||
Use: "import <file>", | ||
Short: "Import rules from a JSON file", | ||
Long: `The JSON file must be formatted as an array containing one or more rules: | ||
[ | ||
{ id: "rule-1", ... }, | ||
{ id: "rule-2", ... }, | ||
] | ||
Usage example: | ||
oathkeeper rules --endpoint=http://localhost:4456/ import rules.json | ||
`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
endpoint, _ := cmd.Flags().GetString("endpoint") | ||
if endpoint == "" { | ||
fatalf("Please specify the endpoint url using the --endpoint flag, for more information use `oathkeeper help rules`") | ||
} else if len(args) != 1 { | ||
fatalf("Please specify a JSON file to load the rule definitions from, for more information use `oathkeeper help rules import`") | ||
} | ||
|
||
file, err := ioutil.ReadFile(args[0]) | ||
must(err, "Reading file %s resulted in error %s", args[0], err) | ||
|
||
var rules []swagger.Rule | ||
err = json.Unmarshal(file, &rules) | ||
must(err, "Decoding file contents from JSON resulted in error %s", err) | ||
|
||
for _, r := range rules { | ||
fmt.Printf("Importing rule %s...\n", r.Id) | ||
client := oathkeepersdk.NewSDK(endpoint) | ||
out, response, err := client.CreateRule(r) | ||
checkResponse(response, err, http.StatusCreated) | ||
fmt.Printf("Successfully imported rule %s...\n", out.Id) | ||
} | ||
fmt.Printf("Successfully imported all rules from %s", args[0]) | ||
}, | ||
} | ||
|
||
func init() { | ||
rulesCmd.AddCommand(importCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package cmd | ||
|
||
import ( | ||
"net/http" | ||
|
||
"github.com/ory/oathkeeper/sdk/go/oathkeepersdk" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// listCmd represents the list command | ||
var listCmd = &cobra.Command{ | ||
Use: "list", | ||
Short: "List all available rules", | ||
Long: `Usage example: | ||
oathkeeper rules --endpoint=http://localhost:4456/ list | ||
`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
endpoint, _ := cmd.Flags().GetString("endpoint") | ||
if endpoint == "" { | ||
fatalf("Please specify the endpoint url using the --endpoint flag, for more information use `oathkeeper help rules`") | ||
} | ||
|
||
client := oathkeepersdk.NewSDK(endpoint) | ||
rules, response, err := client.ListRules() | ||
checkResponse(response, err, http.StatusOK) | ||
formatResponse(rules) | ||
}, | ||
} | ||
|
||
func init() { | ||
rulesCmd.AddCommand(listCmd) | ||
} |
Oops, something went wrong.