diff --git a/client/client.go b/client/client.go index 92ebac2..e8031f1 100644 --- a/client/client.go +++ b/client/client.go @@ -372,3 +372,18 @@ func (c *RemoteServer) OrderCancel(req core.OrderInfoRequest) (*core.ResponseDat 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) +} diff --git a/cmd/ro/main.go b/cmd/ro/main.go index a9055ab..efb271e 100644 --- a/cmd/ro/main.go +++ b/cmd/ro/main.go @@ -43,6 +43,7 @@ var commandSet = map[string]command{ "re-encrypt": command{Run: runReEncrypt, Desc: "re-encrypt a file"}, "order": command{Run: runOrder, Desc: "place an order for delegations"}, "owners": command{Run: runOwner, Desc: "show owners list"}, + "status": command{Run: runStatus, Desc: "show Red October persistent delegation state"}, } func registerFlags() { @@ -260,6 +261,19 @@ func runOwner() { 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() { flag.Usage = func() { fmt.Println("Usage: ro [options] subcommand") diff --git a/config/config.go b/config/config.go index ef11d77..92457f6 100644 --- a/config/config.go +++ b/config/config.go @@ -84,6 +84,24 @@ func (hc *HipChat) Merge(other *HipChat) { 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 // collector. type Metrics struct { diff --git a/config/config_test.go b/config/config_test.go index eed4ad8..817a8b9 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -247,3 +247,25 @@ func TestValid(t *testing.T) { 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") + } +} diff --git a/core/core.go b/core/core.go index 855475a..7e71c4e 100644 --- a/core/core.go +++ b/core/core.go @@ -12,6 +12,7 @@ import ( "strconv" "time" + "github.com/cloudflare/redoctober/config" "github.com/cloudflare/redoctober/cryptor" "github.com/cloudflare/redoctober/hipchat" "github.com/cloudflare/redoctober/keycache" @@ -129,6 +130,7 @@ type OrderInfoRequest struct { OrderNum string } + type OrderOutstandingRequest struct { Name string Password string @@ -141,6 +143,11 @@ type OrderCancelRequest struct { OrderNum string } +type StatusRequest struct { + Name string + Password string +} + // These structures map the JSON responses that will be sent from the API type ResponseData struct { @@ -166,6 +173,23 @@ type OwnersData struct { 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 func jsonStatusOk() ([]byte, error) { @@ -217,7 +241,7 @@ func validateName(name, password string) error { } // 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 defer func() { @@ -233,18 +257,24 @@ func Init(path, hcKey, hcRoom, hcHost, roHost string) error { } var hipchatClient hipchat.HipchatClient - if hcKey != "" && hcRoom != "" && hcHost != "" { - roomId, err := strconv.Atoi(hcRoom) + hc := config.HipChat + if hc.Valid() { + roomId, err := strconv.Atoi(hc.Room) if err != nil { return errors.New("core.init unable to use hipchat roomId provided") } + hipchatClient = hipchat.HipchatClient{ - ApiKey: hcKey, + ApiKey: hc.APIKey, RoomId: roomId, - HcHost: hcHost, - RoHost: roHost, + HcHost: hc.Host, + RoHost: config.UI.Root, } } + + restore.Config = config.Delegations + restore.State = PDStateNeverPersist + orders = order.NewOrderer(hipchatClient) cache = keycache.Cache{UserKeys: make(map[keycache.DelegateIndex]keycache.ActiveUser)} crypt = cryptor.New(&records, &cache) @@ -903,3 +933,32 @@ func OrderCancel(jsonIn []byte) (out []byte, err error) { err = errors.New("Invalid Order Number") 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 +} diff --git a/core/core_test.go b/core/core_test.go index 6b00f05..1af8b99 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -12,13 +12,15 @@ import ( "sort" "testing" + "github.com/cloudflare/redoctober/config" "github.com/cloudflare/redoctober/passvault" ) func TestCreate(t *testing.T) { createJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\"}") + cfg := config.New() - Init("memory", "", "", "", "") + Init("memory", cfg) respJson, err := Create(createJson) if err != nil { @@ -66,13 +68,15 @@ func TestSummary(t *testing.T) { t.Fatalf("Error in summary of account with no vault, %v", s.Status) } - Init("memory", "", "", "", "") + cfg := config.New() + Init("memory", cfg) // check for summary of initialized vault respJson, err = Create(createJson) if err != nil { t.Fatalf("Error in creating account, %v", err) } + err = json.Unmarshal(respJson, &s) if err != nil { t.Fatalf("Error in creating account, %v", err) @@ -81,6 +85,23 @@ func TestSummary(t *testing.T) { t.Fatalf("Error in creating account, %v", s.Status) } + // redoctober should be in a non-persisting state at this + // time. + respJson, err = Status(createJson) + if err != nil { + t.Fatalf("Error in creating account, %v", err) + } + + var st StatusData + err = json.Unmarshal(respJson, &st) + if err != nil { + t.Fatalf("Error getting status, %v", err) + } + if st.Status != PDStateNeverPersist { + t.Fatalf("Persistent delegations should be '%s' but are '%s'", + PDStateNeverPersist, st.Status) + } + respJson, err = Summary(createJson) if err != nil { t.Fatalf("Error in summary of account, %v", err) @@ -219,8 +240,9 @@ func TestCreateUser(t *testing.T) { createUserJson := []byte("{\"Name\":\"Bill\",\"Password\":\"Lizard\"}") createUserECCJson := []byte("{\"Name\":\"Cat\",\"Password\":\"Cheshire\",\"UserType\":\"ECC\"}") createVaultJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\"}") + cfg := config.New() - Init("memory", "", "", "", "") + Init("memory", cfg) // Check that users cannot be created before a vault is respJson, err := CreateUser(createUserJson) @@ -291,8 +313,9 @@ func TestPassword(t *testing.T) { passwordJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"NewPassword\":\"Olleh\"}") delegateJson2 := []byte("{\"Name\":\"Alice\",\"Password\":\"Olleh\",\"Time\":\"2h\",\"Uses\":1}") passwordJson2 := []byte("{\"Name\":\"Alice\",\"Password\":\"Olleh\",\"NewPassword\":\"Hello\"}") + cfg := config.New() - Init("memory", "", "", "", "") + Init("memory", cfg) // check for summary of initialized vault with new member var s ResponseData @@ -404,8 +427,9 @@ func TestEncryptDecrypt(t *testing.T) { encryptJson := []byte("{\"Name\":\"Carol\",\"Password\":\"Hello\",\"Minimum\":2,\"Owners\":[\"Alice\",\"Bob\",\"Carol\"],\"Data\":\"SGVsbG8gSmVsbG8=\"}") encryptJson2 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Minimum\":2,\"Owners\":[\"Alice\",\"Bob\",\"Carol\"],\"Data\":\"SGVsbG8gSmVsbG8=\",\"Labels\":[\"blue\",\"red\"]}") encryptJson3 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Minimum\":1,\"Owners\":[\"Alice\"],\"Data\":\"SGVsbG8gSmVsbG8=\"}") + cfg := config.New() - Init("memory", "", "", "", "") + Init("memory", cfg) // check for summary of initialized vault with new member var s ResponseData @@ -631,8 +655,9 @@ func TestReEncrypt(t *testing.T) { delegateJson6 := []byte(`{"Name":"Bob","Password":"Hello","Time":"10s","Uses":2,"Users":["Alice"],"Labels":["red"]}`) delegateJson7 := []byte(`{"Name":"Carol","Password":"Hello","Time":"10s","Uses":2,"Users":["Alice"],"Labels":["red"]}`) encryptJson := []byte(`{"Name":"Carol","Password":"Hello","Minimum":2,"Owners":["Alice","Bob","Carol"],"Data":"SGVsbG8gSmVsbG8=","Labels":["blue"]}`) + cfg := config.New() - Init("memory", "", "", "", "") + Init("memory", cfg) // check for summary of initialized vault with new member var s ResponseData @@ -808,11 +833,12 @@ func TestOwners(t *testing.T) { delegateJson2 := []byte("{\"Name\":\"Bob\",\"Password\":\"Hello\",\"Time\":\"0s\",\"Uses\":0}") delegateJson3 := []byte("{\"Name\":\"Carol\",\"Password\":\"Hello\",\"Time\":\"0s\",\"Uses\":0}") encryptJson := []byte("{\"Name\":\"Carol\",\"Password\":\"Hello\",\"Minimum\":2,\"Owners\":[\"Alice\",\"Bob\",\"Carol\"],\"Data\":\"SGVsbG8gSmVsbG8=\"}") + cfg := config.New() var s ResponseData var l OwnersData - Init("memory", "", "", "", "") + Init("memory", cfg) Create(delegateJson) Delegate(delegateJson2) @@ -867,8 +893,9 @@ func TestModify(t *testing.T) { modifyJson3 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"ToModify\":\"Carol\",\"Command\":\"admin\"}") modifyJson4 := []byte("{\"Name\":\"Carol\",\"Password\":\"Hello\",\"ToModify\":\"Alice\",\"Command\":\"revoke\"}") modifyJson5 := []byte("{\"Name\":\"Carol\",\"Password\":\"Hello\",\"ToModify\":\"Alice\",\"Command\":\"delete\"}") + cfg := config.New() - Init("memory", "", "", "", "") + Init("memory", cfg) // check for summary of initialized vault with new member var s ResponseData @@ -1044,7 +1071,9 @@ func TestStatic(t *testing.T) { delegateJson3 := []byte("{\"Name\":\"Carol\",\"Password\":\"~~~222\",\"Time\":\"1h\",\"Uses\":30}") decryptJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Data\":\"eyJWZXJzaW9uIjoxLCJWYXVsdElkIjo1Mjk4NTM4OTU3NzU0NTQwODEwLCJLZXlTZXQiOlt7Ik5hbWUiOlsiQm9iIiwiQWxpY2UiXSwiS2V5IjoiMmozdEkyUEJGQmJ3RlgwQmxRZFV1QT09In0seyJOYW1lIjpbIkJvYiIsIkNhcm9sIl0sIktleSI6InlMU1NCL1U2KzVyYzFFK2dqR1hUNHc9PSJ9LHsiTmFtZSI6WyJBbGljZSIsIkJvYiJdLCJLZXkiOiJERGxXSEY3c3p6SVN1WFdhRXo4bGxRPT0ifSx7Ik5hbWUiOlsiQWxpY2UiLCJDYXJvbCJdLCJLZXkiOiJUa0ExM2FQcllGTmJ2ZUlibDBxZHd3PT0ifSx7Ik5hbWUiOlsiQ2Fyb2wiLCJCb2IiXSwiS2V5IjoiS1htMHVPYm1SSjJadlNZRVdQd2syQT09In0seyJOYW1lIjpbIkNhcm9sIiwiQWxpY2UiXSwiS2V5IjoiTDljK1BxdHhQaDl5NmFwUnZ0YkNRdz09In1dLCJLZXlTZXRSU0EiOnsiQWxpY2UiOnsiS2V5IjoiZmo1bXFucTd5NUtDYWZDR1QxSTUxeEk1SnNYNzQ2KzlUVFNzcC84eWJmM2laamhGelNsd1AzYU5tc094M1NVS1RtWmxmcytiK01lRDRlS0oydUtCRnpRSEFJUE8wZndvaUNES0hoS0g2S3NvbE5xNCtqZ3BrTEFNT0xzUUdzOGc2QmhKeTZiQ0ZSalpWYzNJZGxRQUJQTTZQa1RidVN2S2huOWF0REZ3WlFENVRKQklTaTdkMmh3NExyYWR0TElUYk5xd2lGTVRRUTkrcHNYenlhdlk4SDNMTkhLR2dmNU9kN0lwdGhFUVBDSGk0bnc3WC9ZVlJURU1mb0lWY01jS093WWpsQzQ1L1ZKRUhLOVp5M0RTaUxCemptcjU3WU5JVmp3OFlaWTVER0JXcWJndTUxUlViSWNycXlMcGhCaFhvQlJ1NFIreXJoeWdCTldidmtraWZBPT0ifSwiQm9iIjp7IktleSI6IkhUWWlaMThzZjcyMWNBTjFMUk5rSi8rTDRBS1dpbE1ya015TmlCaldjbDlIUlRWUE5YSVRxUUJYZDBmQmdnR05QaVpyNlZRVHlTSzRaRnZKS0dER2l6MTdUZS9Ub0RuOFlrL0I5Y3FNc041ZkhvUXRYdmw4SVpvMndpb0E2N2NjQUoxZ0hNTU5wUHlMZEY0M1NRcWdJK1hhUTJsTVNZTE1meHhEbUJCT1ExU1dBdG8wQkRSZG5zcXB3VXdJUEtROVkzLzFvc21yakxtSm9BQzNNUHBsZXhZV2hleE53SnRTZCttRmRWWjNRZTR4OVJzUkhjTi9teWloT3QvNjdWNjBxenMxM0YwUlprTVNEemo1RGRnKzFLVk5KWlk5ZG1vbFBOa0Faajh6MjBMOXV6cGF0clRZVFI2QThxL3NSbitpbk83WlFWUTAwWE82cTZsWVlRenhudz09In0sIkNhcm9sIjp7IktleSI6Ikl0cnZTMDJuU2ZiY0EyZmwxTDFpNjF4cVBFREtSZHNyWWUzK1VDYmtUK2lwaGVpUVJQU3Vpa2J6ZVYya3NobjR5SkRla3U1Ym1UTnFXOEhTR3RVN0dUZ0NvSVdWOFdtRWY0dzZvdnpTaFBidStWckladlJ6M3dqaDJvWUhUL2d0UFZBUW5CYS83MUZlb0JOeHk1bC9oQmNVbUJreTQzajgzTWx0Mis4UVp4NlBFVURtcGFQUWVtVmg5OStDMjBuUXRrQVVGZU1jMkdlNHk3UmxIU3h0ZkFCdndsWHgxTnpDRDQwbnlKZkYxU2pWL2ZaaC9FMkFsNFRhdng2RE9Ka1lHb0oybXA3WEJ2WDBJRjJ0cDhUM1U1VnBuVGVrL1d1TnJMTDl6Ny9qcXpXaDg3bFo1S2hlV1hoR2tVMUJOSDRsZklqNDNwRGtTeTUwYUR2UzB6WWZIUT09In19LCJJViI6IjU4cjlNejhlMDZtSXRCRzluU1YvMFE9PSIsIkRhdGEiOiJRRTlaaGNHWE5YYXVVZE1rMDRiaVVHeTFTb1A1SDJuRi9qMkpqaWlWRktQZElkUnAvR2MrQVp2VUk5bjIyWk00cSt6RGlKejdxdks0YkthUHBYaFRtR1AwWGhlYUZVdWtlVk5TOVNUTW9UYk5jWS9adFZPejZoaXpVUEY3Z1NxMzg4UVBVc1QrQXhtbDNyRVVUV09obnc9PSIsIlNpZ25hdHVyZSI6IlZWaVJvYUN4cUtBdk54eU14RGhydFlvMENaQT0ifQ==\"}") diskVault := []byte("{\"Version\":1,\"VaultId\":5298538957754540810,\"HmacKey\":\"Qugc5ZQ0vC7KQSgmDHTVgQ==\",\"Passwords\":{\"Alice\":{\"Type\":\"RSA\",\"PasswordSalt\":\"HrVbQ4JvEdORxWN6FrSy4w==\",\"HashedPassword\":\"nanadB0t/EmVuHyRUNtfyQ==\",\"KeySalt\":\"u0cwMmHikadpxm9wClrf3g==\",\"AESKey\":\"pOcxCYMk0l+kaEM5IHolfA==\",\"RSAKey\":{\"RSAExp\":\"yDBotK0XkaDk6rt35ciBnlyPGSXjp9ypdTH2j89CybXe2ReF6xLVZ10CCoz91UUFpbiQi2tVWFS8V7lxUehx7C6HI30Zr0iwJMXk8sgRKs2Ee3rAGCrM9vvQMO8ApKwe4kvB+PrFgnhIEgZI7zyPJPcdZnxbcVFyUC3uIivFS4Bv3jVBnrkAx71keQqrkKzu3jTquCIS3rTEm2hrgsZ3n1t/4BADvUpcMpII2Phv2Senonp1EMz9sRFsR4w9HVep8AgfUGuPTcQ/uv9R16xiHvlN80rOtWzVLpEruzGw/JTvlsshFBU5SY/zthGl9TwxWz1yZpVHYhIWhbxw34CXYczB6q19bdEPkJJldi/1coI=\",\"RSAExpIV\":\"RI9B8nzwW/CXiIU4lSYRWg==\",\"RSAPrimeP\":\"yB3TMdRhWLiZ/ayPlu/iLDHxWsuMi9pA8Ctps7WZFxVsxYEzy/s0Otzsbtgay8of72xVkO64MaudXXRjj26kVSQhS8WhPmv7xDO5ba3SsTffCA99aSr3MH+JmUoL+EDjYviUf5F1DSZniv+Ae+6x9AMbbRQqRvmdH/INW76rFbLX4VtsMpgVkAhADwCUSfNS\",\"RSAPrimePIV\":\"ZE8xe7zVqz4fTN1XWvD1Tg==\",\"RSAPrimeQ\":\"pq7rEAmXoiMWhuEpTy2pQiheLHuzcGeGm1IsgtP7TRIpHaumBAjasxhMY95ODspzehfHp8RPb3pz550g+EXpRP5bfmZkiPMGWKsFUWY7h51hm2Yg6t7yOSXxQvzseWDUjJqBXIG56su0ItD/7NT9YPnhOWAcLaV+L/D3dLdUOP3sgrfp2fcz5IWgcAHUKwLj\",\"RSAPrimeQIV\":\"po4GB9LNDJEFwVo7pd7M+w==\",\"RSAPublic\":{\"N\":23149224936745228096494487629641309516714939646787578848987096719230079441991920927625328021835418605829165905957281054739040782220661415211495551591590967025905842090248342119030961900558364831442589592519977574953153506098793781379522492850670706181134690851176026007414311463584686376540335844073069224992659463459793269384975134553539299820716318523937519020382533972574258510063896159690996712751336541794097684994088922002126390397554509324964165816682788604802958437629743951677011277308533675371215221012180522157452368867794857042597831942805118364469257052754518983480732149823871291876054393236400292711237,\"E\":65537}},\"Admin\":true},\"Bob\":{\"Type\":\"RSA\",\"PasswordSalt\":\"yqWZFNuuCRMw+snL83FcWQ==\",\"HashedPassword\":\"jYLSUIdvw8UVXhxVSS5uKQ==\",\"KeySalt\":\"ZJDOGSv9yUlJ5+83+FV6Nw==\",\"AESKey\":\"9bj4qQDJKglD9eIm7MNeag==\",\"RSAKey\":{\"RSAExp\":\"rnmHX1FgAN0KFm89Uj+O4L7/njDlQPwGHSYjGKB7qMyNPGF4jKn9ez1LI9e9jI8uE475KBhoXRmIuHdap6HtD+sH+nHugDzD3np6Dbq1MM+19PW41n9xblwx6tsNwvufCYgb2qtZd0bLXemeKBszJg2UXlTeSHkXGmjY/VAbZYbUFUNKIykiJWnQ+3HlAo7UHjjKSDI6HtiMnODwYucKH9uYdmroM3DqRUP+j+AhMctyeyOt68q6RuVyubzG0PM1/T9QqPgTIzFvg9dxk+LmPYmlv4b7Euea7KQHww4kTUlpNYondRisuA436G7EfWIJFeRShFuSVk0GvmrgN5vK+/FkdqMuikPaPV1dITFzaCU=\",\"RSAExpIV\":\"eoIov2XYwK19tpFkZyTL+Q==\",\"RSAPrimeP\":\"x9VqeHfHZBMksWNz3Bq90KyLYO0+y9tbfH17uAxQHIZbhn6RUHMXJFs4/H+TnL9s7D05HdxKNCD3ilISkhLZ/DQVD+VMvSFQ/2DL/OoKNg4UyxeGpKefJxCU9LOeXGTfN+UpGHN4Myal3PL2yi0yWCVZvX+zPks05Nqmzkmtx1Yz0IqeUaR+I1jw2y0xy+nc\",\"RSAPrimePIV\":\"h+J0h35kSaNFjBFyejmqSQ==\",\"RSAPrimeQ\":\"CUGaukdC8slcy1Qm6kBw8QYhVenJWFylPqJTvf03ATkkaxQJ8ZSK/RodXFiKCztRSx/HVw0LoGGx9RiavSxl1I+NPIiGEBXiYnLCwWjIbohEIviX0XrKEegECKZtEPxlkDGI8C5ScmUiUOoCUFODqPi1ymEPPIpqj6NZu0Q3lOXseZ7vHbCwiO7Nxznoed2V\",\"RSAPrimeQIV\":\"fglAccK/JKbbP6FKd3MoPA==\",\"RSAPublic\":{\"N\":28335031342838743289078885439639803673108967200362163631216970159249785951860249148476503896024171065194110189927394386737974335124568755441420594193064949823336810514078294805084876384362160530316962043860952904024334641317905429962254720146672817625880231384279651687169091903559644110839987019710966818515746956556387614880164417442090115347521394174077031531398826388780347541493782387177778507223791525305993050791342196579264299166530031123364885677134064847664024722422373550942639559346558112737229502294633354781474882714474174085566901518771722057743396746938093859383451665388899451851738694979184054459471,\"E\":65537}},\"Admin\":false},\"Carol\":{\"Type\":\"RSA\",\"PasswordSalt\":\"kPCA68PNIi3qODVfBHonMA==\",\"HashedPassword\":\"L05ueGkNhqRI7xo7OaG5fQ==\",\"KeySalt\":\"bUXHAjmdtpcYMNN/YzHvhA==\",\"AESKey\":\"34sh2HYt11JMd63CTC2g3Q==\",\"RSAKey\":{\"RSAExp\":\"blJ6FvmAC6ZegcR6ITdg8WDSMljcikrUp3dRGbRDgKIfK0sx7b9i/kDtp4uD7/3IuTpD/qq09k07PO10T5R9NI2OdaEUGsoKJ4wqyzP6XzC9l/KeQmU7cMTh5OHO5UcqXWBn+g1INWaWI6DNAPFKK+4jcTyy6gTQQZQKSYRvRmgN6GkjOhbsdH0eM29eZScShJy2cGemZwbx8g2x7+cebALJmnJxycq29uBZaNBq4gV2/oNXxUhAogJY8SVhgPzCgig2MAJBLK/PzzxJ2LgnBLosZkUXo4vLPKSELX0qXSkSOoC/qPXvcQGawsknqUkSaaDwB1T1MYHmcJS/wpiIRM89Qru0Oy8sy8NRApk3ef0=\",\"RSAExpIV\":\"pQnJ6tvdJkPmMkqFjwJg5g==\",\"RSAPrimeP\":\"xTwgxhDvEvMCn8W6Mqv4ogRnBXFTLbuLP8YC2exQ+RwKmUbNsjB1eBlHyYRtKwc7qoDLf/zqpMZk3yPPcQDP+szAS5mmhCgpd+ePee8vvwVR5DImDuCquMGrPNEgpg3LL1aBHMF66pfnYGob+P6GZYzJP3mhlewUlh86NDzP8YkoVlrNRZrarB1/ZmA+w2Y2\",\"RSAPrimePIV\":\"BYynxyFw7WxrpSKJ3ogwOw==\",\"RSAPrimeQ\":\"wrSXyN/gpDTvK/BMeH+04uhzGUFVbBrfo47L3i+E1QsQndJDy2yyyE1D26mFcvyiefObaD097M3ruR9Wz7WfjxmyawG8N2W/BgtHZz/Ds2ThN/T9t1XqskxnIV8l2eq9LL7SqjAyp8jUGMNVS4WODDtDngLIR6OeehfyHpgwVZRuqQMxIT3wA78SwDcWo41s\",\"RSAPrimeQIV\":\"nh42rsJHRpRyrT7DUHCSGQ==\",\"RSAPublic\":{\"N\":21157349824302424474586534982259249211803834319040688464355493234801787797103302507532796077498450217821871970018694577875997137564403612290101696297388762661598985028358214691463545987525906601624475015641369758738594698734277968689933610815708041386873182005594893971935327515126641632178583839753604241275307504709356922001828087700047657269629468786192584360390570302228520684623917906322926285597325969441240603594319235541820769758760147548185811818605055779607442920451051925838835969679126714958513824527149123555098280031335447316080110515987423541389176918537439220114191601986031091845506241054078769049741,\"E\":65537}},\"Admin\":false}}}") + cfg := config.New() + // TODO: create a proper temp file for this. file, err := os.Create("/tmp/db1.json") if err != nil { t.Fatalf("Error opening file, %v", err) @@ -1059,7 +1088,7 @@ func TestStatic(t *testing.T) { t.Fatalf("Error closing file, %v", err) } - Init("/tmp/db1.json", "", "", "", "") + Init("/tmp/db1.json", cfg) // check for summary of initialized vault with new member var s ResponseData diff --git a/redoctober.go b/redoctober.go index 01bb944..b9256b2 100644 --- a/redoctober.go +++ b/redoctober.go @@ -45,6 +45,7 @@ var functions = map[string]func([]byte) ([]byte, error){ "/orderout": core.OrdersOutstanding, "/orderinfo": core.OrderInfo, "/ordercancel": core.OrderCancel, + "/status": core.Status, } type userRequest struct { @@ -290,7 +291,7 @@ func main() { 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) }