mirror of
https://github.com/cloudflare/redoctober.git
synced 2025-12-23 06:15:45 +00:00
Add a status endpoint to the server.
This pull request adds a status endpoint to the Red October server; as of this pull request, the status endpoint only returns the current delegation persistence state. The HTTP UI has not been updated, as this is scoped out for a future request; however, the CLI utility now features a status command to fetch this information.
This commit is contained in:
@@ -372,3 +372,18 @@ func (c *RemoteServer) OrderCancel(req core.OrderInfoRequest) (*core.ResponseDat
|
|||||||
|
|
||||||
return unmarshalResponseData(respBytes)
|
return unmarshalResponseData(respBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status returns the current delegation persistence state from the remote server.
|
||||||
|
func (c *RemoteServer) Status(req core.StatusRequest) (*core.ResponseData, error) {
|
||||||
|
reqBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
respBytes, err := c.doAction("status", reqBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmarshalResponseData(respBytes)
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ var commandSet = map[string]command{
|
|||||||
"re-encrypt": command{Run: runReEncrypt, Desc: "re-encrypt a file"},
|
"re-encrypt": command{Run: runReEncrypt, Desc: "re-encrypt a file"},
|
||||||
"order": command{Run: runOrder, Desc: "place an order for delegations"},
|
"order": command{Run: runOrder, Desc: "place an order for delegations"},
|
||||||
"owners": command{Run: runOwner, Desc: "show owners list"},
|
"owners": command{Run: runOwner, Desc: "show owners list"},
|
||||||
|
"status": command{Run: runStatus, Desc: "show Red October persistent delegation state"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerFlags() {
|
func registerFlags() {
|
||||||
@@ -260,6 +261,19 @@ func runOwner() {
|
|||||||
fmt.Println(resp)
|
fmt.Println(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runStatus() {
|
||||||
|
req := core.StatusRequest{
|
||||||
|
Name: user,
|
||||||
|
Password: pswd,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := roServer.Status(req)
|
||||||
|
processError(err)
|
||||||
|
|
||||||
|
fmt.Println(resp.Status)
|
||||||
|
fmt.Println(resp)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Println("Usage: ro [options] subcommand")
|
fmt.Println("Usage: ro [options] subcommand")
|
||||||
|
|||||||
@@ -84,6 +84,24 @@ func (hc *HipChat) Merge(other *HipChat) {
|
|||||||
setIfNotEmpty(&hc.APIKey, other.APIKey)
|
setIfNotEmpty(&hc.APIKey, other.APIKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Valid returns true if the HipChat config is ready to be used for
|
||||||
|
// HipChat notifications.
|
||||||
|
func (hc *HipChat) Valid() bool {
|
||||||
|
if hc.APIKey == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if hc.Room == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if hc.Host == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Metrics contains the configuration for the Prometheus metrics
|
// Metrics contains the configuration for the Prometheus metrics
|
||||||
// collector.
|
// collector.
|
||||||
type Metrics struct {
|
type Metrics struct {
|
||||||
|
|||||||
@@ -247,3 +247,25 @@ func TestValid(t *testing.T) {
|
|||||||
t.Fatal("config should be valid")
|
t.Fatal("config should be valid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHipChatValid(t *testing.T) {
|
||||||
|
hc := &HipChat{}
|
||||||
|
if hc.Valid() {
|
||||||
|
t.Fatal("empty hipchat config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
hc.APIKey = "test"
|
||||||
|
if hc.Valid() {
|
||||||
|
t.Fatal("invalid hipchat config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
hc.Room = "test"
|
||||||
|
if hc.Valid() {
|
||||||
|
t.Fatal("invalid hipchat config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
hc.Host = "test"
|
||||||
|
if !hc.Valid() {
|
||||||
|
t.Fatal("valid hipchat config marked as invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
71
core/core.go
71
core/core.go
@@ -12,6 +12,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/cloudflare/redoctober/config"
|
||||||
"github.com/cloudflare/redoctober/cryptor"
|
"github.com/cloudflare/redoctober/cryptor"
|
||||||
"github.com/cloudflare/redoctober/hipchat"
|
"github.com/cloudflare/redoctober/hipchat"
|
||||||
"github.com/cloudflare/redoctober/keycache"
|
"github.com/cloudflare/redoctober/keycache"
|
||||||
@@ -129,6 +130,7 @@ type OrderInfoRequest struct {
|
|||||||
|
|
||||||
OrderNum string
|
OrderNum string
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrderOutstandingRequest struct {
|
type OrderOutstandingRequest struct {
|
||||||
Name string
|
Name string
|
||||||
Password string
|
Password string
|
||||||
@@ -141,6 +143,11 @@ type OrderCancelRequest struct {
|
|||||||
OrderNum string
|
OrderNum string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StatusRequest struct {
|
||||||
|
Name string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
// These structures map the JSON responses that will be sent from the API
|
// These structures map the JSON responses that will be sent from the API
|
||||||
|
|
||||||
type ResponseData struct {
|
type ResponseData struct {
|
||||||
@@ -166,6 +173,23 @@ type OwnersData struct {
|
|||||||
Predicate string
|
Predicate string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StatusData struct {
|
||||||
|
Status string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegation restoration and persistance configuration follows.
|
||||||
|
|
||||||
|
const (
|
||||||
|
PDStateNeverPersist = "disabled"
|
||||||
|
PDStateNotPersisting = "inactive"
|
||||||
|
PDStateNowPersisting = "active"
|
||||||
|
)
|
||||||
|
|
||||||
|
var restore struct {
|
||||||
|
Config *config.Delegations
|
||||||
|
State string
|
||||||
|
}
|
||||||
|
|
||||||
// Helper functions that create JSON responses sent by core
|
// Helper functions that create JSON responses sent by core
|
||||||
|
|
||||||
func jsonStatusOk() ([]byte, error) {
|
func jsonStatusOk() ([]byte, error) {
|
||||||
@@ -217,7 +241,7 @@ func validateName(name, password string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init reads the records from disk from a given path
|
// Init reads the records from disk from a given path
|
||||||
func Init(path, hcKey, hcRoom, hcHost, roHost string) error {
|
func Init(path string, config *config.Config) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -233,18 +257,24 @@ func Init(path, hcKey, hcRoom, hcHost, roHost string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var hipchatClient hipchat.HipchatClient
|
var hipchatClient hipchat.HipchatClient
|
||||||
if hcKey != "" && hcRoom != "" && hcHost != "" {
|
hc := config.HipChat
|
||||||
roomId, err := strconv.Atoi(hcRoom)
|
if hc.Valid() {
|
||||||
|
roomId, err := strconv.Atoi(hc.Room)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("core.init unable to use hipchat roomId provided")
|
return errors.New("core.init unable to use hipchat roomId provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
hipchatClient = hipchat.HipchatClient{
|
hipchatClient = hipchat.HipchatClient{
|
||||||
ApiKey: hcKey,
|
ApiKey: hc.APIKey,
|
||||||
RoomId: roomId,
|
RoomId: roomId,
|
||||||
HcHost: hcHost,
|
HcHost: hc.Host,
|
||||||
RoHost: roHost,
|
RoHost: config.UI.Root,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restore.Config = config.Delegations
|
||||||
|
restore.State = PDStateNeverPersist
|
||||||
|
|
||||||
orders = order.NewOrderer(hipchatClient)
|
orders = order.NewOrderer(hipchatClient)
|
||||||
cache = keycache.Cache{UserKeys: make(map[keycache.DelegateIndex]keycache.ActiveUser)}
|
cache = keycache.Cache{UserKeys: make(map[keycache.DelegateIndex]keycache.ActiveUser)}
|
||||||
crypt = cryptor.New(&records, &cache)
|
crypt = cryptor.New(&records, &cache)
|
||||||
@@ -903,3 +933,32 @@ func OrderCancel(jsonIn []byte) (out []byte, err error) {
|
|||||||
err = errors.New("Invalid Order Number")
|
err = errors.New("Invalid Order Number")
|
||||||
return jsonStatusError(err)
|
return jsonStatusError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status returns the current delegation persistence state. In the
|
||||||
|
// future, this may return more data.
|
||||||
|
func Status(jsonIn []byte) (out []byte, err error) {
|
||||||
|
var req StatusRequest
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("core.status failed: user=%s %v", req.Name, err)
|
||||||
|
} else {
|
||||||
|
log.Printf("core.status success: user=%s", req.Name)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = json.Unmarshal(jsonIn, &req); err != nil {
|
||||||
|
return jsonStatusError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateUser(req.Name, req.Password, false); err != nil {
|
||||||
|
return jsonStatusError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := StatusData{Status: restore.State}
|
||||||
|
if out, err = json.Marshal(resp); err != nil {
|
||||||
|
return jsonStatusError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -45,6 +45,7 @@ var functions = map[string]func([]byte) ([]byte, error){
|
|||||||
"/orderout": core.OrdersOutstanding,
|
"/orderout": core.OrdersOutstanding,
|
||||||
"/orderinfo": core.OrderInfo,
|
"/orderinfo": core.OrderInfo,
|
||||||
"/ordercancel": core.OrderCancel,
|
"/ordercancel": core.OrderCancel,
|
||||||
|
"/status": core.Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
type userRequest struct {
|
type userRequest struct {
|
||||||
@@ -290,7 +291,7 @@ func main() {
|
|||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := core.Init(vaultPath, cfg.HipChat.APIKey, cfg.HipChat.Room, cfg.HipChat.Room, cfg.UI.Root); err != nil {
|
if err := core.Init(vaultPath, cfg); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user