зеркало из https://github.com/mozilla/mig.git
Merge pull request #410 from ameihm0912/mig-pkg-style
style related code cleanup in mig top-level package
This commit is contained in:
Коммит
910338e57d
8
acl.go
8
acl.go
|
@ -35,12 +35,12 @@ func verifyPermission(moduleName string, acl ACL, fingerprints []string) error {
|
||||||
// No ACL entry found for this module name, see if we can find a default
|
// No ACL entry found for this module name, see if we can find a default
|
||||||
aclent, ok = acl["default"]
|
aclent, ok = acl["default"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("No ACL entry found for %v, and no default present", moduleName)
|
return fmt.Errorf("no ACL entry found for %v, and no default present", moduleName)
|
||||||
}
|
}
|
||||||
aclname = "default"
|
aclname = "default"
|
||||||
}
|
}
|
||||||
if aclent.MinimumWeight < 1 {
|
if aclent.MinimumWeight < 1 {
|
||||||
return fmt.Errorf("Invalid ACL %v, weight must be > 0", aclname)
|
return fmt.Errorf("invalid ACL %v, weight must be > 0", aclname)
|
||||||
}
|
}
|
||||||
var seenFp []string
|
var seenFp []string
|
||||||
signaturesWeight := 0
|
signaturesWeight := 0
|
||||||
|
@ -48,7 +48,7 @@ func verifyPermission(moduleName string, acl ACL, fingerprints []string) error {
|
||||||
// if the same key is used to sign multiple times, return an error
|
// if the same key is used to sign multiple times, return an error
|
||||||
for _, seen := range seenFp {
|
for _, seen := range seenFp {
|
||||||
if seen == fp {
|
if seen == fp {
|
||||||
return fmt.Errorf("Permission violation: key %v used to sign multiple times", fp)
|
return fmt.Errorf("permission violation: key %v used to sign multiple times", fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, signer := range aclent.Investigators {
|
for _, signer := range aclent.Investigators {
|
||||||
|
@ -59,7 +59,7 @@ func verifyPermission(moduleName string, acl ACL, fingerprints []string) error {
|
||||||
seenFp = append(seenFp, fp)
|
seenFp = append(seenFp, fp)
|
||||||
}
|
}
|
||||||
if signaturesWeight < aclent.MinimumWeight {
|
if signaturesWeight < aclent.MinimumWeight {
|
||||||
return fmt.Errorf("Permission denied for operation %v, insufficient signatures weight"+
|
return fmt.Errorf("permission denied for operation %v, insufficient signatures weight"+
|
||||||
" (need %v, got %v)", moduleName, aclent.MinimumWeight, signaturesWeight)
|
" (need %v, got %v)", moduleName, aclent.MinimumWeight, signaturesWeight)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
70
action.go
70
action.go
|
@ -16,7 +16,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ import (
|
||||||
// ActionVersion is the version of the syntax that is expected
|
// ActionVersion is the version of the syntax that is expected
|
||||||
const ActionVersion uint16 = 2
|
const ActionVersion uint16 = 2
|
||||||
|
|
||||||
// an Action is the json object that is created by an investigator
|
// Action is the json object that is created by an investigator
|
||||||
// and provided to the MIG platform. It must be PGP signed.
|
// and provided to the MIG platform. It must be PGP signed.
|
||||||
type Action struct {
|
type Action struct {
|
||||||
ID float64 `json:"id"`
|
ID float64 `json:"id"`
|
||||||
|
@ -47,7 +46,7 @@ type Action struct {
|
||||||
SyntaxVersion uint16 `json:"syntaxversion,omitempty"`
|
SyntaxVersion uint16 `json:"syntaxversion,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some counters used to track the completion of an action
|
// ActionCounters are counters used to track the completion of an action
|
||||||
type ActionCounters struct {
|
type ActionCounters struct {
|
||||||
Sent int `json:"sent,omitempty"`
|
Sent int `json:"sent,omitempty"`
|
||||||
Done int `json:"done,omitempty"`
|
Done int `json:"done,omitempty"`
|
||||||
|
@ -59,7 +58,7 @@ type ActionCounters struct {
|
||||||
TimeOut int `json:"timeout,omitempty"`
|
TimeOut int `json:"timeout,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// a description is a simple object that contains detail about the
|
// Description is a simple object that contains detail about the
|
||||||
// action's author, and it's revision.
|
// action's author, and it's revision.
|
||||||
type Description struct {
|
type Description struct {
|
||||||
Author string `json:"author,omitempty"`
|
Author string `json:"author,omitempty"`
|
||||||
|
@ -68,8 +67,8 @@ type Description struct {
|
||||||
Revision float64 `json:"revision,omitempty"`
|
Revision float64 `json:"revision,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// a threat provides the investigator with an idea of how dangerous
|
// Threat provides the investigator with details on a threat indicator
|
||||||
// a the compromission might be, if the indicators return positive
|
// if included in an action
|
||||||
type Threat struct {
|
type Threat struct {
|
||||||
Ref string `json:"ref,omitempty"`
|
Ref string `json:"ref,omitempty"`
|
||||||
Level string `json:"level,omitempty"`
|
Level string `json:"level,omitempty"`
|
||||||
|
@ -77,8 +76,8 @@ type Threat struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// an operation is an object that maps to an agent module.
|
// Operation is an object that maps to an agent module.
|
||||||
// the parameters of the operation are passed to the module as an argument,
|
// The parameters of the operation are passed to the module as an argument,
|
||||||
// and thus their format depends on the module itself.
|
// and thus their format depends on the module itself.
|
||||||
type Operation struct {
|
type Operation struct {
|
||||||
Module string `json:"module"`
|
Module string `json:"module"`
|
||||||
|
@ -93,7 +92,7 @@ type Operation struct {
|
||||||
WantCompressed bool `json:"want_compressed,omitempty"`
|
WantCompressed bool `json:"want_compressed,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress the parameters stored within an operation
|
// CompressOperationParam compresses the parameters stored within an operation
|
||||||
func (op *Operation) CompressOperationParam() (err error) {
|
func (op *Operation) CompressOperationParam() (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
|
@ -118,7 +117,7 @@ func (op *Operation) CompressOperationParam() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress the parameters stored within an operation
|
// DecompressOperationParam decompresses the parameters stored within an operation
|
||||||
func (op *Operation) DecompressOperationParam() (err error) {
|
func (op *Operation) DecompressOperationParam() (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
|
@ -150,14 +149,14 @@ func (op *Operation) DecompressOperationParam() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActionFromFile() reads an action from a local file on the file system
|
// ActionFromFile reads an action from a local file on the file system
|
||||||
// and returns a mig.Action structure
|
// and returns a mig.Action structure
|
||||||
func ActionFromFile(path string) (Action, error) {
|
func ActionFromFile(path string) (Action, error) {
|
||||||
var err error
|
var err error
|
||||||
var a Action
|
var a Action
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.ActionFromFile(): %v", e)
|
err = fmt.Errorf("ActionFromFile() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// parse the json of the action into a mig.Action
|
// parse the json of the action into a mig.Action
|
||||||
|
@ -208,7 +207,7 @@ type id struct {
|
||||||
|
|
||||||
var globalID id
|
var globalID id
|
||||||
|
|
||||||
// GenID() returns a float64 ID number that is unique to this process. The ID is initialized
|
// GenID returns a float64 ID number that is unique to this process. The ID is initialized
|
||||||
// at the number of seconds since MIG's creation date, shifted 16 bits to the right and incremented
|
// at the number of seconds since MIG's creation date, shifted 16 bits to the right and incremented
|
||||||
// by one every time a new ID is requested. The resulting value must fit in 53 bits of precision
|
// by one every time a new ID is requested. The resulting value must fit in 53 bits of precision
|
||||||
// provided by the float64 type.
|
// provided by the float64 type.
|
||||||
|
@ -222,47 +221,40 @@ func GenID() float64 {
|
||||||
tmpid = tmpid << 16
|
tmpid = tmpid << 16
|
||||||
globalID.value = float64(tmpid)
|
globalID.value = float64(tmpid)
|
||||||
return globalID.value
|
return globalID.value
|
||||||
} else {
|
|
||||||
globalID.value++
|
|
||||||
return globalID.value
|
|
||||||
}
|
}
|
||||||
}
|
globalID.value++
|
||||||
|
return globalID.value
|
||||||
// GenHexID returns a string with an hexadecimal encoded ID
|
|
||||||
func GenB32ID() string {
|
|
||||||
id := GenID()
|
|
||||||
return strconv.FormatUint(uint64(id), 36)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate verifies that the Action received contained all the
|
// Validate verifies that the Action received contained all the
|
||||||
// necessary fields, and returns an error when it doesn't.
|
// necessary fields, and returns an error when it doesn't.
|
||||||
func (a Action) Validate() (err error) {
|
func (a Action) Validate() (err error) {
|
||||||
if a.Name == "" {
|
if a.Name == "" {
|
||||||
return errors.New("Action.Name is empty. Expecting string.")
|
return errors.New("action name is empty")
|
||||||
}
|
}
|
||||||
if a.Target == "" {
|
if a.Target == "" {
|
||||||
return errors.New("Action.Target is empty. Expecting string.")
|
return errors.New("action target is empty")
|
||||||
}
|
}
|
||||||
if a.SyntaxVersion != ActionVersion {
|
if a.SyntaxVersion != ActionVersion {
|
||||||
return fmt.Errorf("Wrong Syntax Version integer. Expection version %d", ActionVersion)
|
return fmt.Errorf("wring syntax version, expected %v", ActionVersion)
|
||||||
}
|
}
|
||||||
if a.ValidFrom.String() == "" {
|
if a.ValidFrom.String() == "" {
|
||||||
return errors.New("Action.ValidFrom is empty. Expecting string.")
|
return errors.New("action validfrom is empty")
|
||||||
}
|
}
|
||||||
if a.ExpireAfter.String() == "" {
|
if a.ExpireAfter.String() == "" {
|
||||||
return errors.New("Action.ExpireAfter is empty. Expecting string.")
|
return errors.New("action expireafter is empty")
|
||||||
}
|
}
|
||||||
if a.ValidFrom.After(a.ExpireAfter) {
|
if a.ValidFrom.After(a.ExpireAfter) {
|
||||||
return errors.New("Action.ExpireAfter is set before Action.ValidFrom.")
|
return errors.New("action expireafter is set before action validfrom")
|
||||||
}
|
}
|
||||||
if time.Now().After(a.ExpireAfter) {
|
if time.Now().After(a.ExpireAfter) {
|
||||||
return errors.New("Action.ExpireAfter is passed. Action has expired.")
|
return errors.New("action expireafter is in the past")
|
||||||
}
|
}
|
||||||
if a.Operations == nil {
|
if a.Operations == nil {
|
||||||
return errors.New("Action.Operations is nil. Expecting string.")
|
return errors.New("action operations is empty")
|
||||||
}
|
}
|
||||||
if len(a.PGPSignatures) < 1 {
|
if len(a.PGPSignatures) < 1 {
|
||||||
return errors.New("Action.PGPSignatures is empty. Expecting array of strings.")
|
return errors.New("action pgpsignatures is empty")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -307,11 +299,11 @@ func (a Action) VerifySignatures(keyring io.Reader) (err error) {
|
||||||
}()
|
}()
|
||||||
astr, err := a.String()
|
astr, err := a.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Failed to stringify action")
|
return errors.New("failed to stringify action")
|
||||||
}
|
}
|
||||||
// If the action does not contain any signatures, treat this as an error condition
|
// If the action does not contain any signatures, treat this as an error condition
|
||||||
if a.PGPSignatures == nil || len(a.PGPSignatures) == 0 {
|
if a.PGPSignatures == nil || len(a.PGPSignatures) == 0 {
|
||||||
return errors.New("Action contained no valid signatures")
|
return errors.New("action contained no valid signatures")
|
||||||
}
|
}
|
||||||
// Create a copy of the keyring we can use during validation of each
|
// Create a copy of the keyring we can use during validation of each
|
||||||
// signature. We don't want to use the keyring reader directly as it is
|
// signature. We don't want to use the keyring reader directly as it is
|
||||||
|
@ -325,10 +317,10 @@ func (a Action) VerifySignatures(keyring io.Reader) (err error) {
|
||||||
keyrdr := bytes.NewBuffer(keycopy)
|
keyrdr := bytes.NewBuffer(keycopy)
|
||||||
valid, _, err := pgp.Verify(astr, sig, keyrdr)
|
valid, _, err := pgp.Verify(astr, sig, keyrdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Failed to verify PGP Signature")
|
return errors.New("failed to verify PGP Signature")
|
||||||
}
|
}
|
||||||
if !valid {
|
if !valid {
|
||||||
return errors.New("Invalid PGP Signature")
|
return errors.New("invalid PGP Signature")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -354,7 +346,7 @@ func (a Action) VerifyACL(acl ACL, keyring io.Reader, onlyVerifyPubKey bool) (er
|
||||||
var fingerprints []string
|
var fingerprints []string
|
||||||
astr, err := a.String()
|
astr, err := a.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Failed to stringify action")
|
return errors.New("failed to stringify action")
|
||||||
}
|
}
|
||||||
// Create a copy of the keyring we can use during validation of each
|
// Create a copy of the keyring we can use during validation of each
|
||||||
// signature. We don't want to use the keyring reader directly as it is
|
// signature. We don't want to use the keyring reader directly as it is
|
||||||
|
@ -368,13 +360,13 @@ func (a Action) VerifyACL(acl ACL, keyring io.Reader, onlyVerifyPubKey bool) (er
|
||||||
keyrdr := bytes.NewBuffer(keycopy)
|
keyrdr := bytes.NewBuffer(keycopy)
|
||||||
fp, err := pgp.GetFingerprintFromSignature(astr, sig, keyrdr)
|
fp, err := pgp.GetFingerprintFromSignature(astr, sig, keyrdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to retrieve fingerprint from signatures: %v", err)
|
return fmt.Errorf("failed to retrieve fingerprint from signatures: %v", err)
|
||||||
}
|
}
|
||||||
fingerprints = append(fingerprints, fp)
|
fingerprints = append(fingerprints, fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(fingerprints) == 0 {
|
if len(fingerprints) == 0 {
|
||||||
return errors.New("No valid fingerprints found.")
|
return errors.New("no valid fingerprints found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if onlyVerifyPubKey {
|
if onlyVerifyPubKey {
|
||||||
|
@ -416,7 +408,7 @@ func (a Action) PrintCounters() {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", out)
|
fmt.Fprintf(os.Stderr, "%s\n", out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the an indented JSON string representing the action suitable for
|
// IndentedString returns an indented JSON string representing the action suitable for
|
||||||
// display
|
// display
|
||||||
func (a Action) IndentedString() (string, error) {
|
func (a Action) IndentedString() (string, error) {
|
||||||
buf, err := json.MarshalIndent(a, "", " ")
|
buf, err := json.MarshalIndent(a, "", " ")
|
||||||
|
|
7
agent.go
7
agent.go
|
@ -8,6 +8,7 @@ package mig /* import "mig.ninja/mig" */
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// Various agent status values
|
||||||
const (
|
const (
|
||||||
AgtStatusOnline string = "online"
|
AgtStatusOnline string = "online"
|
||||||
AgtStatusDestroyed string = "destroyed"
|
AgtStatusDestroyed string = "destroyed"
|
||||||
|
@ -49,7 +50,7 @@ type AgentEnv struct {
|
||||||
Modules []string `json:"modules,omitempty"`
|
Modules []string `json:"modules,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores AWS specific agent environment values
|
// AgentEnvAWS stores AWS specific agent environment values
|
||||||
type AgentEnvAWS struct {
|
type AgentEnvAWS struct {
|
||||||
InstanceID string `json:"instanceid,omitempty"`
|
InstanceID string `json:"instanceid,omitempty"`
|
||||||
LocalIPV4 string `json:"localipv4,omitempty"`
|
LocalIPV4 string `json:"localipv4,omitempty"`
|
||||||
|
@ -57,6 +58,8 @@ type AgentEnvAWS struct {
|
||||||
InstanceType string `json:"instancetype,omitempty"`
|
InstanceType string `json:"instancetype,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AgentsStats stores information about the global MIG environment, primarily used
|
||||||
|
// in command line tools and the API/scheduler
|
||||||
type AgentsStats struct {
|
type AgentsStats struct {
|
||||||
Timestamp time.Time `json:"timestamp"`
|
Timestamp time.Time `json:"timestamp"`
|
||||||
OnlineAgents float64 `json:"onlineagents"`
|
OnlineAgents float64 `json:"onlineagents"`
|
||||||
|
@ -71,6 +74,8 @@ type AgentsStats struct {
|
||||||
FlappingEndpoints float64 `json:"flappingendpoints"`
|
FlappingEndpoints float64 `json:"flappingendpoints"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AgentsVersionsSum stores information on the count of agents at a specific version
|
||||||
|
// level, primarily used in command line tools and the API/scheduler
|
||||||
type AgentsVersionsSum struct {
|
type AgentsVersionsSum struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Count float64 `json:"count"`
|
Count float64 `json:"count"`
|
||||||
|
|
13
command.go
13
command.go
|
@ -15,6 +15,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Command describes an action as applied to a single agent, and will include
|
||||||
|
// results
|
||||||
type Command struct {
|
type Command struct {
|
||||||
ID float64 `json:"id"`
|
ID float64 `json:"id"`
|
||||||
Action Action `json:"action"`
|
Action Action `json:"action"`
|
||||||
|
@ -34,6 +36,7 @@ type Command struct {
|
||||||
FinishTime time.Time `json:"finishtime"`
|
FinishTime time.Time `json:"finishtime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Various command status values
|
||||||
const (
|
const (
|
||||||
StatusSent string = "sent"
|
StatusSent string = "sent"
|
||||||
StatusSuccess string = "success"
|
StatusSuccess string = "success"
|
||||||
|
@ -43,12 +46,12 @@ const (
|
||||||
StatusTimeout string = "timeout"
|
StatusTimeout string = "timeout"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FromFile reads a command from a local file on the file system
|
// CmdFromFile reads a command from a local file on the file system
|
||||||
// and return the mig.Command structure
|
// and return the mig.Command structure
|
||||||
func CmdFromFile(path string) (cmd Command, err error) {
|
func CmdFromFile(path string) (cmd Command, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.CmdFromFile()-> %v", e)
|
err = fmt.Errorf("CmdFromFile() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
jsonCmd, err := ioutil.ReadFile(path)
|
jsonCmd, err := ioutil.ReadFile(path)
|
||||||
|
@ -71,13 +74,13 @@ func CmdFromFile(path string) (cmd Command, err error) {
|
||||||
// necessary fields, and returns an error when it doesn't.
|
// necessary fields, and returns an error when it doesn't.
|
||||||
func checkCmd(cmd Command) error {
|
func checkCmd(cmd Command) error {
|
||||||
if cmd.Agent.Name == "" {
|
if cmd.Agent.Name == "" {
|
||||||
return errors.New("cmd.Agent.Name is empty. Expecting string.")
|
return errors.New("command agent name is empty")
|
||||||
}
|
}
|
||||||
if cmd.Agent.QueueLoc == "" {
|
if cmd.Agent.QueueLoc == "" {
|
||||||
return errors.New("cmd.Agent.QueueLoc is empty. Expecting string.")
|
return errors.New("command queue location is empty")
|
||||||
}
|
}
|
||||||
if cmd.Status == "" {
|
if cmd.Status == "" {
|
||||||
return errors.New("cmd.Status is empty. Expecting string.")
|
return errors.New("command status is empty")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
18
constants.go
18
constants.go
|
@ -6,18 +6,10 @@
|
||||||
|
|
||||||
package mig /* import "mig.ninja/mig" */
|
package mig /* import "mig.ninja/mig" */
|
||||||
|
|
||||||
|
// Various constants that indicate exchange and queue names used in RabbitMQ
|
||||||
const (
|
const (
|
||||||
// rabbitmq exchanges and common queues
|
ExchangeToAgents = "toagents"
|
||||||
Mq_Ex_ToAgents = "toagents"
|
ExchangeToSchedulers = "toschedulers"
|
||||||
Mq_Ex_ToSchedulers = "toschedulers"
|
QueueAgentHeartbeat = "mig.agt.heartbeats"
|
||||||
Mq_Q_Heartbeat = "mig.agt.heartbeats"
|
QueueAgentResults = "mig.agt.results"
|
||||||
Mq_Q_Results = "mig.agt.results"
|
|
||||||
|
|
||||||
// event queues
|
|
||||||
Ev_Q_Agt_Auth_Fail = "agent.authentication.failure"
|
|
||||||
Ev_Q_Agt_New = "agent.new"
|
|
||||||
Ev_Q_Cmd_Res = "command.results"
|
|
||||||
|
|
||||||
// dummy queue for scheduler heartbeats to the relays
|
|
||||||
Ev_Q_Sched_Hb = "scheduler.heartbeat"
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Investigator describes a single MIG investigator
|
||||||
type Investigator struct {
|
type Investigator struct {
|
||||||
ID float64 `json:"id,omitempty"`
|
ID float64 `json:"id,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
@ -25,7 +26,7 @@ type Investigator struct {
|
||||||
Permissions InvestigatorPerms `json:"permissions"`
|
Permissions InvestigatorPerms `json:"permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check an investigator has given permission pv
|
// CheckPermission validates if an investigator has given permission pv
|
||||||
func (i *Investigator) CheckPermission(pv int64) bool {
|
func (i *Investigator) CheckPermission(pv int64) bool {
|
||||||
switch pv {
|
switch pv {
|
||||||
case PermSearch:
|
case PermSearch:
|
||||||
|
@ -68,7 +69,7 @@ func (i *Investigator) CheckPermission(pv int64) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describes permissions assigned to an investigator
|
// InvestigatorPerms describes permissions assigned to an investigator
|
||||||
type InvestigatorPerms struct {
|
type InvestigatorPerms struct {
|
||||||
Search bool `json:"search"`
|
Search bool `json:"search"`
|
||||||
Action bool `json:"action"`
|
Action bool `json:"action"`
|
||||||
|
@ -91,7 +92,7 @@ type InvestigatorPerms struct {
|
||||||
InvestigatorUpdate bool `json:"investigator_update"`
|
InvestigatorUpdate bool `json:"investigator_update"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a permission bit mask into a boolean permission set
|
// FromMask converts a permission bit mask into a boolean permission set
|
||||||
func (ip *InvestigatorPerms) FromMask(mask int64) {
|
func (ip *InvestigatorPerms) FromMask(mask int64) {
|
||||||
if (mask & PermSearch) != 0 {
|
if (mask & PermSearch) != 0 {
|
||||||
ip.Search = true
|
ip.Search = true
|
||||||
|
@ -152,7 +153,7 @@ func (ip *InvestigatorPerms) FromMask(mask int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a boolean permission set to a permission bit mask
|
// ToMask converts a boolean permission set to a permission bit mask
|
||||||
func (ip *InvestigatorPerms) ToMask() (ret int64) {
|
func (ip *InvestigatorPerms) ToMask() (ret int64) {
|
||||||
if ip.Search {
|
if ip.Search {
|
||||||
ret |= PermSearch
|
ret |= PermSearch
|
||||||
|
@ -214,9 +215,8 @@ func (ip *InvestigatorPerms) ToMask() (ret int64) {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert an existing boolean permission set to a descriptive string, used
|
// ToDescriptive converts an existing boolean permission set to a descriptive string, used
|
||||||
// primarily in mig-console for summarizing permissions assigned to an
|
// primarily in mig-console for summarizing permissions assigned to an investigator
|
||||||
// investigator
|
|
||||||
func (ip *InvestigatorPerms) ToDescriptive() string {
|
func (ip *InvestigatorPerms) ToDescriptive() string {
|
||||||
cf := func(want int64, have int64) (bool, int64) {
|
cf := func(want int64, have int64) (bool, int64) {
|
||||||
var (
|
var (
|
||||||
|
@ -289,11 +289,11 @@ func (ip *InvestigatorPerms) ToDescriptive() string {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe permission sets that can be applied; note default is omitted as this
|
// PermSets describes permission sets that can be applied; note default is omitted as this
|
||||||
// is currently always applied
|
// is currently always applied
|
||||||
var PermSets = []string{"PermManifest", "PermLoader", "PermAdmin"}
|
var PermSets = []string{"PermManifest", "PermLoader", "PermAdmin"}
|
||||||
|
|
||||||
// Apply permission sets in slice sl to the investigator
|
// FromSetList applies permission sets in slice sl to the investigator
|
||||||
func (ip *InvestigatorPerms) FromSetList(sl []string) error {
|
func (ip *InvestigatorPerms) FromSetList(sl []string) error {
|
||||||
for _, x := range sl {
|
for _, x := range sl {
|
||||||
switch x {
|
switch x {
|
||||||
|
@ -310,7 +310,7 @@ func (ip *InvestigatorPerms) FromSetList(sl []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a default set of permissions on the investigator
|
// DefaultSet sets a default set of permissions on the investigator
|
||||||
func (ip *InvestigatorPerms) DefaultSet() {
|
func (ip *InvestigatorPerms) DefaultSet() {
|
||||||
ip.Search = true
|
ip.Search = true
|
||||||
ip.Action = true
|
ip.Action = true
|
||||||
|
@ -320,7 +320,7 @@ func (ip *InvestigatorPerms) DefaultSet() {
|
||||||
ip.Dashboard = true
|
ip.Dashboard = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set manifest related permissions on the investigator
|
// ManifestSet sets manifest related permissions on the investigator
|
||||||
func (ip *InvestigatorPerms) ManifestSet() {
|
func (ip *InvestigatorPerms) ManifestSet() {
|
||||||
ip.Manifest = true
|
ip.Manifest = true
|
||||||
ip.ManifestSign = true
|
ip.ManifestSign = true
|
||||||
|
@ -329,7 +329,7 @@ func (ip *InvestigatorPerms) ManifestSet() {
|
||||||
ip.ManifestLoaders = true
|
ip.ManifestLoaders = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set loader related permissions on the investigator
|
// LoaderSet sets loader related permissions on the investigator
|
||||||
func (ip *InvestigatorPerms) LoaderSet() {
|
func (ip *InvestigatorPerms) LoaderSet() {
|
||||||
ip.Loader = true
|
ip.Loader = true
|
||||||
ip.LoaderStatus = true
|
ip.LoaderStatus = true
|
||||||
|
@ -338,7 +338,7 @@ func (ip *InvestigatorPerms) LoaderSet() {
|
||||||
ip.LoaderNew = true
|
ip.LoaderNew = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set administrative permissions on the investigator
|
// AdminSet sets administrative permissions on the investigator
|
||||||
func (ip *InvestigatorPerms) AdminSet() {
|
func (ip *InvestigatorPerms) AdminSet() {
|
||||||
ip.Investigator = true
|
ip.Investigator = true
|
||||||
ip.InvestigatorCreate = true
|
ip.InvestigatorCreate = true
|
||||||
|
@ -368,6 +368,7 @@ const (
|
||||||
PermInvestigatorUpdate
|
PermInvestigatorUpdate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Possible status values for an investigator
|
||||||
const (
|
const (
|
||||||
StatusActiveInvestigator string = "active"
|
StatusActiveInvestigator string = "active"
|
||||||
StatusDisabledInvestigator string = "disabled"
|
StatusDisabledInvestigator string = "disabled"
|
||||||
|
|
38
loader.go
38
loader.go
|
@ -13,7 +13,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Describes a loader entry stored in the database
|
// LoaderEntry describes a loader entry stored in the database
|
||||||
type LoaderEntry struct {
|
type LoaderEntry struct {
|
||||||
ID float64 `json:"id"` // Loader ID
|
ID float64 `json:"id"` // Loader ID
|
||||||
Name string `json:"name"` // Loader name
|
Name string `json:"name"` // Loader name
|
||||||
|
@ -25,6 +25,7 @@ type LoaderEntry struct {
|
||||||
ExpectEnv string `json:"expectenv"` // Expected environment
|
ExpectEnv string `json:"expectenv"` // Expected environment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate validates a loader entry
|
||||||
func (le *LoaderEntry) Validate() (err error) {
|
func (le *LoaderEntry) Validate() (err error) {
|
||||||
if le.Key != "" {
|
if le.Key != "" {
|
||||||
err = ValidateLoaderPrefixAndKey(le.Prefix + le.Key)
|
err = ValidateLoaderPrefixAndKey(le.Prefix + le.Key)
|
||||||
|
@ -32,8 +33,8 @@ func (le *LoaderEntry) Validate() (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Small helper type used primarily during the loader authentication
|
// LoaderAuthDetails is a small helper type used primarily during the loader
|
||||||
// process between the API and database code, temporarily stores
|
// authentication process between the API and database code, temporarily stores
|
||||||
// authentication information
|
// authentication information
|
||||||
type LoaderAuthDetails struct {
|
type LoaderAuthDetails struct {
|
||||||
ID float64
|
ID float64
|
||||||
|
@ -41,6 +42,7 @@ type LoaderAuthDetails struct {
|
||||||
Salt []byte
|
Salt []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate validates a LoaderAuthDetails type
|
||||||
func (lad *LoaderAuthDetails) Validate() error {
|
func (lad *LoaderAuthDetails) Validate() error {
|
||||||
if len(lad.Hash) != LoaderHashedKeyLength ||
|
if len(lad.Hash) != LoaderHashedKeyLength ||
|
||||||
len(lad.Salt) != LoaderSaltLength {
|
len(lad.Salt) != LoaderSaltLength {
|
||||||
|
@ -49,24 +51,32 @@ func (lad *LoaderAuthDetails) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a new loader prefix value
|
// GenerateLoaderPrefix will generate a new loader prefix value
|
||||||
func GenerateLoaderPrefix() string {
|
func GenerateLoaderPrefix() string {
|
||||||
return RandAPIKeyString(LoaderPrefixLength)
|
return RandAPIKeyString(LoaderPrefixLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a new loader key value
|
// GenerateLoaderKey will generate a new loader key value
|
||||||
func GenerateLoaderKey() string {
|
func GenerateLoaderKey() string {
|
||||||
return RandAPIKeyString(LoaderKeyLength)
|
return RandAPIKeyString(LoaderKeyLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Various constants related to properties of the loader keys
|
// LoaderPrefixAndKeyLength is the key length for a loader key including the prefix
|
||||||
const LoaderPrefixAndKeyLength = 40 // Key length including prefix
|
const LoaderPrefixAndKeyLength = 40
|
||||||
const LoaderPrefixLength = 8 // Prefix length
|
|
||||||
const LoaderKeyLength = 32 // Length excluding prefix
|
|
||||||
const LoaderHashedKeyLength = 32 // Length of hashed key in the database
|
|
||||||
const LoaderSaltLength = 16 // Length of salt
|
|
||||||
|
|
||||||
// Validate a loader key, returns nil if it is valid
|
// LoaderPrefixLength is the length of the loader prefix
|
||||||
|
const LoaderPrefixLength = 8
|
||||||
|
|
||||||
|
// LoaderKeyLength is the length of the loader key
|
||||||
|
const LoaderKeyLength = 32
|
||||||
|
|
||||||
|
// LoaderHashedKeyLength is the length of the hashed loader key in the database
|
||||||
|
const LoaderHashedKeyLength = 32
|
||||||
|
|
||||||
|
// LoaderSaltLength is the length of the salt applied to loader keys
|
||||||
|
const LoaderSaltLength = 16
|
||||||
|
|
||||||
|
// ValidateLoaderKey validates a loader key, returns nil if it is valid
|
||||||
func ValidateLoaderKey(key string) error {
|
func ValidateLoaderKey(key string) error {
|
||||||
repstr := fmt.Sprintf("^[A-Za-z0-9]{%v}$", LoaderKeyLength)
|
repstr := fmt.Sprintf("^[A-Za-z0-9]{%v}$", LoaderKeyLength)
|
||||||
ok, err := regexp.MatchString(repstr, key)
|
ok, err := regexp.MatchString(repstr, key)
|
||||||
|
@ -76,7 +86,7 @@ func ValidateLoaderKey(key string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate a loader prefix value, returns nil if it is valid
|
// ValidateLoaderPrefix validates a loader prefix value, returns nil if it is valid
|
||||||
func ValidateLoaderPrefix(prefix string) error {
|
func ValidateLoaderPrefix(prefix string) error {
|
||||||
repstr := fmt.Sprintf("^[A-Za-z0-9]{%v}$", LoaderPrefixLength)
|
repstr := fmt.Sprintf("^[A-Za-z0-9]{%v}$", LoaderPrefixLength)
|
||||||
ok, err := regexp.MatchString(repstr, prefix)
|
ok, err := regexp.MatchString(repstr, prefix)
|
||||||
|
@ -86,7 +96,7 @@ func ValidateLoaderPrefix(prefix string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate a loader key that includes the prefix
|
// ValidateLoaderPrefixAndKey validates a loader key that includes the prefix
|
||||||
func ValidateLoaderPrefixAndKey(pk string) error {
|
func ValidateLoaderPrefixAndKey(pk string) error {
|
||||||
if len(pk) != LoaderPrefixAndKeyLength {
|
if len(pk) != LoaderPrefixAndKeyLength {
|
||||||
return fmt.Errorf("loader key is incorrect length")
|
return fmt.Errorf("loader key is incorrect length")
|
||||||
|
|
|
@ -17,9 +17,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MODE_STDOUT = 1 << iota
|
logModeStdout = 1 << iota
|
||||||
MODE_FILE
|
logModeFile
|
||||||
MODE_SYSLOG
|
logModeSyslog
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logging stores the attributes needed to perform the logging
|
// Logging stores the attributes needed to perform the logging
|
||||||
|
@ -42,6 +42,7 @@ type Log struct {
|
||||||
Priority syslog.Priority
|
Priority syslog.Priority
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg sets Log entry level to emergency
|
||||||
func (l Log) Emerg() (mlog Log) {
|
func (l Log) Emerg() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_EMERG
|
mlog.Priority = syslog.LOG_EMERG
|
||||||
|
@ -49,6 +50,7 @@ func (l Log) Emerg() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alert sets Log entry level to alert
|
||||||
func (l Log) Alert() (mlog Log) {
|
func (l Log) Alert() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_ALERT
|
mlog.Priority = syslog.LOG_ALERT
|
||||||
|
@ -56,6 +58,7 @@ func (l Log) Alert() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit sets Log entry level to critical
|
||||||
func (l Log) Crit() (mlog Log) {
|
func (l Log) Crit() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_CRIT
|
mlog.Priority = syslog.LOG_CRIT
|
||||||
|
@ -63,6 +66,7 @@ func (l Log) Crit() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err sets Log entry level to error
|
||||||
func (l Log) Err() (mlog Log) {
|
func (l Log) Err() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_ERR
|
mlog.Priority = syslog.LOG_ERR
|
||||||
|
@ -70,6 +74,7 @@ func (l Log) Err() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning sets Log entry level to warning
|
||||||
func (l Log) Warning() (mlog Log) {
|
func (l Log) Warning() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_WARNING
|
mlog.Priority = syslog.LOG_WARNING
|
||||||
|
@ -77,6 +82,7 @@ func (l Log) Warning() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice sets Log entry level to notice
|
||||||
func (l Log) Notice() (mlog Log) {
|
func (l Log) Notice() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_NOTICE
|
mlog.Priority = syslog.LOG_NOTICE
|
||||||
|
@ -84,6 +90,7 @@ func (l Log) Notice() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info sets Log entry level to info
|
||||||
func (l Log) Info() (mlog Log) {
|
func (l Log) Info() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_INFO
|
mlog.Priority = syslog.LOG_INFO
|
||||||
|
@ -91,6 +98,7 @@ func (l Log) Info() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug sets log entry level to debug
|
||||||
func (l Log) Debug() (mlog Log) {
|
func (l Log) Debug() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = syslog.LOG_DEBUG
|
mlog.Priority = syslog.LOG_DEBUG
|
||||||
|
@ -98,7 +106,7 @@ func (l Log) Debug() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom type to satisfy io.Writer to use as file logging output, handles
|
// rotateLogWriter is a custom type to satisfy io.Writer to use as file logging output, handles
|
||||||
// log file rotation
|
// log file rotation
|
||||||
type rotateLogWriter struct {
|
type rotateLogWriter struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
@ -177,29 +185,29 @@ func (r *rotateLogWriter) initAndCheck() (err error) {
|
||||||
|
|
||||||
// InitLogger prepares the context for logging based on the configuration
|
// InitLogger prepares the context for logging based on the configuration
|
||||||
// in Logging
|
// in Logging
|
||||||
func InitLogger(orig_logctx Logging, progname string) (logctx Logging, err error) {
|
func InitLogger(origLogctx Logging, progname string) (logctx Logging, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.InitLogger() -> %v", e)
|
err = fmt.Errorf("InitLogger() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
switch logctx.Mode {
|
switch logctx.Mode {
|
||||||
case "stdout":
|
case "stdout":
|
||||||
logctx.logmode = MODE_STDOUT
|
logctx.logmode = logModeStdout
|
||||||
logctx, err = initLogStdOut(logctx)
|
logctx, err = initLogStdOut(logctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
case "file":
|
case "file":
|
||||||
logctx.logmode = MODE_FILE
|
logctx.logmode = logModeFile
|
||||||
logctx, err = initLogFile(logctx)
|
logctx, err = initLogFile(logctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
case "syslog":
|
case "syslog":
|
||||||
logctx.logmode = MODE_SYSLOG
|
logctx.logmode = logModeSyslog
|
||||||
logctx, err = initSyslog(logctx, progname)
|
logctx, err = initSyslog(logctx, progname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -207,7 +215,7 @@ func InitLogger(orig_logctx Logging, progname string) (logctx Logging, err error
|
||||||
default:
|
default:
|
||||||
log.Println("Logging mode is missing. Assuming stdout.")
|
log.Println("Logging mode is missing. Assuming stdout.")
|
||||||
logctx.Mode = "stdout"
|
logctx.Mode = "stdout"
|
||||||
logctx.logmode = MODE_STDOUT
|
logctx.logmode = logModeStdout
|
||||||
logctx, err = initLogStdOut(logctx)
|
logctx, err = initLogStdOut(logctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -237,14 +245,14 @@ func InitLogger(orig_logctx Logging, progname string) (logctx Logging, err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// initSyslog creates a connection to syslog and stores the handler in ctx
|
// initSyslog creates a connection to syslog and stores the handler in ctx
|
||||||
func initSyslog(orig_logctx Logging, progname string) (logctx Logging, err error) {
|
func initSyslog(origLogctx Logging, progname string) (logctx Logging, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.initSyslog() -> %v", e)
|
err = fmt.Errorf("initSyslog() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
if logctx.Host == "" {
|
if logctx.Host == "" {
|
||||||
panic("Syslog host is missing")
|
panic("Syslog host is missing")
|
||||||
}
|
}
|
||||||
|
@ -266,14 +274,14 @@ func initSyslog(orig_logctx Logging, progname string) (logctx Logging, err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// initLogFile creates a logfile and stores the descriptor in ctx
|
// initLogFile creates a logfile and stores the descriptor in ctx
|
||||||
func initLogFile(orig_logctx Logging) (logctx Logging, err error) {
|
func initLogFile(origLogctx Logging) (logctx Logging, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.InitLogFile() -> %v", e)
|
err = fmt.Errorf("initLogFile() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
err = logctx.rotateWriter.new(logctx.File, logctx.MaxFileSize)
|
err = logctx.rotateWriter.new(logctx.File, logctx.MaxFileSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -284,18 +292,18 @@ func initLogFile(orig_logctx Logging) (logctx Logging, err error) {
|
||||||
|
|
||||||
// initLogStdOut does nothing except storing in ctx that logs should be
|
// initLogStdOut does nothing except storing in ctx that logs should be
|
||||||
// sent to stdout directly
|
// sent to stdout directly
|
||||||
func initLogStdOut(orig_logctx Logging) (logctx Logging, err error) {
|
func initLogStdOut(origLogctx Logging) (logctx Logging, err error) {
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// processLog receives events and perform logging and evaluationg of the log
|
// ProcessLog receives events and performs logging and evaluation of the log
|
||||||
// if the log is too critical, Analyze will trigger a scheduler shutdown
|
// severity level, in the event of an emergency level entry stop will be true
|
||||||
func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
stop = false
|
stop = false
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.ProcessLog() -> %v", e)
|
err = fmt.Errorf("ProcessLog() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -339,12 +347,12 @@ func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
if l.Desc != "" {
|
if l.Desc != "" {
|
||||||
logline += l.Desc
|
logline += l.Desc
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("Missing mandatory description in logent")
|
err = fmt.Errorf("missing mandatory description in logent")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch logctx.logmode {
|
switch logctx.logmode {
|
||||||
case MODE_SYSLOG:
|
case logModeSyslog:
|
||||||
switch l.Priority {
|
switch l.Priority {
|
||||||
// emergency logging causes the scheduler to shut down
|
// emergency logging causes the scheduler to shut down
|
||||||
case syslog.LOG_EMERG:
|
case syslog.LOG_EMERG:
|
||||||
|
@ -376,10 +384,10 @@ func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
err = logctx.syslogfd.Info(logline)
|
err = logctx.syslogfd.Info(logline)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case MODE_STDOUT:
|
case logModeStdout:
|
||||||
log.Println(logline)
|
log.Println(logline)
|
||||||
return
|
return
|
||||||
case MODE_FILE:
|
case logModeFile:
|
||||||
log.Println(logline)
|
log.Println(logline)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
@ -388,6 +396,8 @@ func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy can be used to indicate no further logging with the given logging context
|
||||||
|
// will take place
|
||||||
func (logctx Logging) Destroy() {
|
func (logctx Logging) Destroy() {
|
||||||
if logctx.Mode == "syslog" {
|
if logctx.Mode == "syslog" {
|
||||||
logctx.syslogfd.Close()
|
logctx.syslogfd.Close()
|
||||||
|
|
|
@ -17,9 +17,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MODE_STDOUT = 1 << iota
|
logModeStdout = 1 << iota
|
||||||
MODE_FILE
|
logModeFile
|
||||||
MODE_EVENTLOG
|
logModeEventlog
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logging stores the attributes needed to perform the logging
|
// Logging stores the attributes needed to perform the logging
|
||||||
|
@ -42,6 +42,7 @@ type Log struct {
|
||||||
Priority int
|
Priority int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg sets Log entry level to emergency
|
||||||
func (l Log) Emerg() (mlog Log) {
|
func (l Log) Emerg() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Error
|
mlog.Priority = eventlog.Error
|
||||||
|
@ -49,6 +50,7 @@ func (l Log) Emerg() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alert sets Log entry level to alert
|
||||||
func (l Log) Alert() (mlog Log) {
|
func (l Log) Alert() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Error
|
mlog.Priority = eventlog.Error
|
||||||
|
@ -56,6 +58,7 @@ func (l Log) Alert() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit sets Log entry level to critical
|
||||||
func (l Log) Crit() (mlog Log) {
|
func (l Log) Crit() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Error
|
mlog.Priority = eventlog.Error
|
||||||
|
@ -63,6 +66,7 @@ func (l Log) Crit() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err sets Log entry level to error
|
||||||
func (l Log) Err() (mlog Log) {
|
func (l Log) Err() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Error
|
mlog.Priority = eventlog.Error
|
||||||
|
@ -70,6 +74,7 @@ func (l Log) Err() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning sets Log entry level to warning
|
||||||
func (l Log) Warning() (mlog Log) {
|
func (l Log) Warning() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Warning
|
mlog.Priority = eventlog.Warning
|
||||||
|
@ -77,6 +82,7 @@ func (l Log) Warning() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice sets Log entry level to notice
|
||||||
func (l Log) Notice() (mlog Log) {
|
func (l Log) Notice() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Warning
|
mlog.Priority = eventlog.Warning
|
||||||
|
@ -84,6 +90,7 @@ func (l Log) Notice() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info sets Log entry level to info
|
||||||
func (l Log) Info() (mlog Log) {
|
func (l Log) Info() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = eventlog.Info
|
mlog.Priority = eventlog.Info
|
||||||
|
@ -91,7 +98,8 @@ func (l Log) Info() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't log debug messages on windows
|
// Debug sets log entry level to debug, we don't log debug
|
||||||
|
// messages on Windows
|
||||||
func (l Log) Debug() (mlog Log) {
|
func (l Log) Debug() (mlog Log) {
|
||||||
mlog = l
|
mlog = l
|
||||||
mlog.Priority = 999
|
mlog.Priority = 999
|
||||||
|
@ -99,7 +107,7 @@ func (l Log) Debug() (mlog Log) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom type to satisfy io.Writer to use as file logging output, handles
|
// rotateLogWriter is a custom type to satisfy io.Writer to use as file logging output, handles
|
||||||
// log file rotation
|
// log file rotation
|
||||||
type rotateLogWriter struct {
|
type rotateLogWriter struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
@ -181,29 +189,29 @@ func (r *rotateLogWriter) initAndCheck() (err error) {
|
||||||
|
|
||||||
// InitLogger prepares the context for logging based on the configuration
|
// InitLogger prepares the context for logging based on the configuration
|
||||||
// in Logging
|
// in Logging
|
||||||
func InitLogger(orig_logctx Logging, progname string) (logctx Logging, err error) {
|
func InitLogger(origLogctx Logging, progname string) (logctx Logging, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.InitLogger() -> %v", e)
|
err = fmt.Errorf("InitLogger() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
switch logctx.Mode {
|
switch logctx.Mode {
|
||||||
case "stdout":
|
case "stdout":
|
||||||
logctx.logmode = MODE_STDOUT
|
logctx.logmode = logModeStdout
|
||||||
logctx, err = initLogStdOut(logctx)
|
logctx, err = initLogStdOut(logctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
case "file":
|
case "file":
|
||||||
logctx.logmode = MODE_FILE
|
logctx.logmode = logModeFile
|
||||||
logctx, err = initLogFile(logctx)
|
logctx, err = initLogFile(logctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
case "syslog":
|
case "syslog":
|
||||||
logctx.logmode = MODE_EVENTLOG
|
logctx.logmode = logModeEventlog
|
||||||
logctx, err = initEventlog(logctx, progname)
|
logctx, err = initEventlog(logctx, progname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -211,7 +219,7 @@ func InitLogger(orig_logctx Logging, progname string) (logctx Logging, err error
|
||||||
default:
|
default:
|
||||||
log.Println("Logging mode is missing. Assuming stdout.")
|
log.Println("Logging mode is missing. Assuming stdout.")
|
||||||
logctx.Mode = "stdout"
|
logctx.Mode = "stdout"
|
||||||
logctx.logmode = MODE_STDOUT
|
logctx.logmode = logModeStdout
|
||||||
logctx, err = initLogStdOut(logctx)
|
logctx, err = initLogStdOut(logctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -242,11 +250,11 @@ func InitLogger(orig_logctx Logging, progname string) (logctx Logging, err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// initEventlog creates a connection to event logs and stores the handler in ctx
|
// initEventlog creates a connection to event logs and stores the handler in ctx
|
||||||
func initEventlog(orig_logctx Logging, progname string) (logctx Logging, err error) {
|
func initEventlog(origLogctx Logging, progname string) (logctx Logging, err error) {
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.initEventlog() -> %v", e)
|
err = fmt.Errorf("initEventlog() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
const name = "mylog"
|
const name = "mylog"
|
||||||
|
@ -263,14 +271,14 @@ func initEventlog(orig_logctx Logging, progname string) (logctx Logging, err err
|
||||||
}
|
}
|
||||||
|
|
||||||
// initLogFile creates a logfile and stores the descriptor in ctx
|
// initLogFile creates a logfile and stores the descriptor in ctx
|
||||||
func initLogFile(orig_logctx Logging) (logctx Logging, err error) {
|
func initLogFile(origLogctx Logging) (logctx Logging, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.InitLogFile() -> %v", e)
|
err = fmt.Errorf("initLogFile() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
err = logctx.rotateWriter.new(logctx.File, logctx.MaxFileSize)
|
err = logctx.rotateWriter.new(logctx.File, logctx.MaxFileSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -281,18 +289,18 @@ func initLogFile(orig_logctx Logging) (logctx Logging, err error) {
|
||||||
|
|
||||||
// initLogStdOut does nothing except storing in ctx that logs should be
|
// initLogStdOut does nothing except storing in ctx that logs should be
|
||||||
// sent to stdout directly
|
// sent to stdout directly
|
||||||
func initLogStdOut(orig_logctx Logging) (logctx Logging, err error) {
|
func initLogStdOut(origLogctx Logging) (logctx Logging, err error) {
|
||||||
logctx = orig_logctx
|
logctx = origLogctx
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// processLog receives events and perform logging and evaluationg of the log
|
// ProcessLog receives events and performs logging and evaluation of the log
|
||||||
// if the log is too critical, Analyze will trigger a scheduler shutdown
|
// severity level, in the event of an emergency level entry stop will be true
|
||||||
func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
stop = false
|
stop = false
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("mig.ProcessLog() -> %v", e)
|
err = fmt.Errorf("ProcessLog() -> %v", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -336,12 +344,12 @@ func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
if l.Desc != "" {
|
if l.Desc != "" {
|
||||||
logline += l.Desc
|
logline += l.Desc
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("Missing mandatory description in logent")
|
err = fmt.Errorf("missing mandatory description in logent")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch logctx.logmode {
|
switch logctx.logmode {
|
||||||
case MODE_EVENTLOG:
|
case logModeEventlog:
|
||||||
switch l.Priority {
|
switch l.Priority {
|
||||||
case eventlog.Error:
|
case eventlog.Error:
|
||||||
err = logctx.fd.Error(1, logline)
|
err = logctx.fd.Error(1, logline)
|
||||||
|
@ -360,10 +368,10 @@ func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
err = logctx.fd.Info(3, logline)
|
err = logctx.fd.Info(3, logline)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case MODE_STDOUT:
|
case logModeStdout:
|
||||||
log.Println(logline)
|
log.Println(logline)
|
||||||
return
|
return
|
||||||
case MODE_FILE:
|
case logModeFile:
|
||||||
log.Println(logline)
|
log.Println(logline)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
@ -373,6 +381,8 @@ func ProcessLog(logctx Logging, l Log) (stop bool, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy can be used to indicate no further logging with the given logging context
|
||||||
|
// will take place
|
||||||
func (logctx Logging) Destroy() {
|
func (logctx Logging) Destroy() {
|
||||||
if logctx.Mode == "syslog" {
|
if logctx.Mode == "syslog" {
|
||||||
_ = logctx.fd.Close()
|
_ = logctx.fd.Close()
|
||||||
|
|
47
manifest.go
47
manifest.go
|
@ -27,7 +27,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Describes a manifest record stored within the MIG database
|
// ManifestRecord describes a manifest record stored within the MIG database
|
||||||
type ManifestRecord struct {
|
type ManifestRecord struct {
|
||||||
ID float64 `json:"id"` // Manifest record ID
|
ID float64 `json:"id"` // Manifest record ID
|
||||||
Name string `json:"name"` // The name of the manifest record
|
Name string `json:"name"` // The name of the manifest record
|
||||||
|
@ -38,7 +38,7 @@ type ManifestRecord struct {
|
||||||
Signatures []string `json:"signatures"` // Signatures applied to the record
|
Signatures []string `json:"signatures"` // Signatures applied to the record
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate an existing manifest record
|
// Validate validates an existing manifest record
|
||||||
func (m *ManifestRecord) Validate() (err error) {
|
func (m *ManifestRecord) Validate() (err error) {
|
||||||
if m.Name == "" {
|
if m.Name == "" {
|
||||||
return fmt.Errorf("manifest has invalid name")
|
return fmt.Errorf("manifest has invalid name")
|
||||||
|
@ -57,7 +57,7 @@ func (m *ManifestRecord) Validate() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign a manifest record
|
// Sign will sign a manifest record using the indicated key ID
|
||||||
func (m *ManifestRecord) Sign(keyid string, secring io.Reader) (sig string, err error) {
|
func (m *ManifestRecord) Sign(keyid string, secring io.Reader) (sig string, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
|
@ -83,7 +83,7 @@ func (m *ManifestRecord) Sign(keyid string, secring io.Reader) (sig string, err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a manifest record into a manifest response
|
// ManifestResponse converts a manifest record into a manifest response
|
||||||
func (m *ManifestRecord) ManifestResponse() (ManifestResponse, error) {
|
func (m *ManifestRecord) ManifestResponse() (ManifestResponse, error) {
|
||||||
ret := ManifestResponse{}
|
ret := ManifestResponse{}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ func (m *ManifestRecord) ManifestResponse() (ManifestResponse, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the requested file object as a gzip compressed byte slice
|
// ManifestObject returns the requested file object as a gzip compressed byte slice
|
||||||
// from the manifest record
|
// from the manifest record
|
||||||
func (m *ManifestRecord) ManifestObject(obj string) ([]byte, error) {
|
func (m *ManifestRecord) ManifestObject(obj string) ([]byte, error) {
|
||||||
var bufw bytes.Buffer
|
var bufw bytes.Buffer
|
||||||
|
@ -195,8 +195,8 @@ func (m *ManifestRecord) ManifestObject(obj string) ([]byte, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load manifest content from a file on the file system (a gzip'd tar file),
|
// ContentFromFile loads manifest content from a file on the file system (a gzip'd tar file),
|
||||||
// primarily utilized by mig-console during manifest creation operations.
|
// primarily utilized by mig-console during manifest creation operations
|
||||||
func (m *ManifestRecord) ContentFromFile(path string) (err error) {
|
func (m *ManifestRecord) ContentFromFile(path string) (err error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
fd, err := os.Open(path)
|
fd, err := os.Open(path)
|
||||||
|
@ -218,7 +218,7 @@ func (m *ManifestRecord) ContentFromFile(path string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write manifest content to a file on the file system
|
// FileFromContent writes manifest content to a file on the file system
|
||||||
func (m *ManifestRecord) FileFromContent(path string) (err error) {
|
func (m *ManifestRecord) FileFromContent(path string) (err error) {
|
||||||
fd, err := os.Create(path)
|
fd, err := os.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -238,20 +238,20 @@ func (m *ManifestRecord) FileFromContent(path string) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest parameters are sent from the loader to the API as part of
|
// ManifestParameters are sent from the loader to the API as part of
|
||||||
// a manifest request.
|
// a manifest request.
|
||||||
type ManifestParameters struct {
|
type ManifestParameters struct {
|
||||||
AgentIdentifier Agent `json:"agent"` // Agent context information
|
AgentIdentifier Agent `json:"agent"` // Agent context information
|
||||||
Object string `json:"object"` // Object being requested
|
Object string `json:"object"` // Object being requested
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate parameters included in a manifest request
|
// Validate validetes a ManifestParameters type for correct formatting
|
||||||
func (m *ManifestParameters) Validate() error {
|
func (m *ManifestParameters) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate parameters included in a manifest request with an object fetch
|
// ValidateFetch validates the parameters included in a manifest request with an
|
||||||
// component
|
// object fetch component
|
||||||
func (m *ManifestParameters) ValidateFetch() error {
|
func (m *ManifestParameters) ValidateFetch() error {
|
||||||
err := m.Validate()
|
err := m.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -263,19 +263,19 @@ func (m *ManifestParameters) ValidateFetch() error {
|
||||||
return m.Validate()
|
return m.Validate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The response to a manifest object fetch
|
// ManifestFetchResponse is the response to a manifest object fetch
|
||||||
type ManifestFetchResponse struct {
|
type ManifestFetchResponse struct {
|
||||||
Data []byte `json:"data"`
|
Data []byte `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// The response to a standard manifest request
|
// ManifestResponse is the response to a standard manifest request
|
||||||
type ManifestResponse struct {
|
type ManifestResponse struct {
|
||||||
LoaderName string `json:"loader_name"`
|
LoaderName string `json:"loader_name"`
|
||||||
Entries []ManifestEntry `json:"entries"`
|
Entries []ManifestEntry `json:"entries"`
|
||||||
Signatures []string `json:"signatures"`
|
Signatures []string `json:"signatures"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate a manifest response
|
// Validate validates a ManifestResponse type ensuring required content is present
|
||||||
func (m *ManifestResponse) Validate() error {
|
func (m *ManifestResponse) Validate() error {
|
||||||
if m.LoaderName == "" {
|
if m.LoaderName == "" {
|
||||||
return fmt.Errorf("manifest response has no loader name")
|
return fmt.Errorf("manifest response has no loader name")
|
||||||
|
@ -283,8 +283,9 @@ func (m *ManifestResponse) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates signatures stored in the manifest against keys in keyring, returns
|
// VerifySignatures verifies the signatures present in a manifest response against the keys
|
||||||
// the number of valid signature matches
|
// present in keyring. It returns the number of valid unique signatures identified in the
|
||||||
|
// ManifestResponse.
|
||||||
func (m *ManifestResponse) VerifySignatures(keyring io.Reader) (validcnt int, err error) {
|
func (m *ManifestResponse) VerifySignatures(keyring io.Reader) (validcnt int, err error) {
|
||||||
var sigs []string
|
var sigs []string
|
||||||
|
|
||||||
|
@ -335,20 +336,17 @@ func (m *ManifestResponse) VerifySignatures(keyring io.Reader) (validcnt int, er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describes individual file elements within a manifest
|
// ManifestEntry describes an individual file element within a manifest
|
||||||
type ManifestEntry struct {
|
type ManifestEntry struct {
|
||||||
Name string `json:"name"` // Corresponds to a bundle name
|
Name string `json:"name"` // Corresponds to a bundle name
|
||||||
SHA256 string `json:"sha256"` // SHA256 of entry
|
SHA256 string `json:"sha256"` // SHA256 of entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// The bundle dictionary is used to map tokens within the loader manifest to
|
// BundleDictionaryEntry is used to map tokens within the loader manifest to
|
||||||
// objects on the file system. We don't allow specification of an exact path
|
// objects on the file system. We don't allow specification of an exact path
|
||||||
// for interrogation or manipulation in the manifest. This results in some
|
// for interrogation or manipulation in the manifest. This results in some
|
||||||
// restrictions but hardens the loader against making unauthorized changes
|
// restrictions but hardens the loader against making unauthorized changes
|
||||||
// to the file system.
|
// to the file system.
|
||||||
//
|
|
||||||
// If a Transform function is set on the entry, this is used to transform
|
|
||||||
// bytes into the data set prior to hash calculation
|
|
||||||
type BundleDictionaryEntry struct {
|
type BundleDictionaryEntry struct {
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
|
@ -393,12 +391,15 @@ var bundleEntryWindows = []BundleDictionaryEntry{
|
||||||
{"loaderconfig", "C:\\mig\\mig-loader.cfg", "", 0600},
|
{"loaderconfig", "C:\\mig\\mig-loader.cfg", "", 0600},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BundleDictionary maps GOOS platform names to specific bundle entry values
|
||||||
var BundleDictionary = map[string][]BundleDictionaryEntry{
|
var BundleDictionary = map[string][]BundleDictionaryEntry{
|
||||||
"linux": bundleEntryLinux,
|
"linux": bundleEntryLinux,
|
||||||
"darwin": bundleEntryDarwin,
|
"darwin": bundleEntryDarwin,
|
||||||
"windows": bundleEntryWindows,
|
"windows": bundleEntryWindows,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHostBundle returns the correct BundleDictionaryEntry given the platform the
|
||||||
|
// code is executing on
|
||||||
func GetHostBundle() ([]BundleDictionaryEntry, error) {
|
func GetHostBundle() ([]BundleDictionaryEntry, error) {
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
|
@ -411,7 +412,7 @@ func GetHostBundle() ([]BundleDictionaryEntry, error) {
|
||||||
return nil, fmt.Errorf("no entry for %v in bundle dictionary", runtime.GOOS)
|
return nil, fmt.Errorf("no entry for %v in bundle dictionary", runtime.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populates a slice of BundleDictionaryEntrys, adding the SHA256 checksums
|
// HashBundle populates a slice of BundleDictionaryEntrys, adding the SHA256 checksums
|
||||||
// from the file system
|
// from the file system
|
||||||
func HashBundle(b []BundleDictionaryEntry) ([]BundleDictionaryEntry, error) {
|
func HashBundle(b []BundleDictionaryEntry) ([]BundleDictionaryEntry, error) {
|
||||||
ret := b
|
ret := b
|
||||||
|
|
|
@ -889,7 +889,7 @@ func sendResults(ctx *Context, result mig.Command) (err error) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = publish(ctx, mig.Mq_Ex_ToSchedulers, mig.Mq_Q_Results, body)
|
err = publish(ctx, mig.ExchangeToSchedulers, mig.QueueAgentResults, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -930,7 +930,7 @@ func heartbeat(ctx *Context) (err error) {
|
||||||
}
|
}
|
||||||
desc := fmt.Sprintf("heartbeat %q", body)
|
desc := fmt.Sprintf("heartbeat %q", body)
|
||||||
ctx.Channels.Log <- mig.Log{Desc: desc}.Debug()
|
ctx.Channels.Log <- mig.Log{Desc: desc}.Debug()
|
||||||
publish(ctx, mig.Mq_Ex_ToSchedulers, mig.Mq_Q_Heartbeat, body)
|
publish(ctx, mig.ExchangeToSchedulers, mig.QueueAgentHeartbeat, body)
|
||||||
// update the local heartbeat file
|
// update the local heartbeat file
|
||||||
err = ioutil.WriteFile(path.Join(ctx.Agent.RunDir, "mig-agent.ok"), []byte(time.Now().String()), 0644)
|
err = ioutil.WriteFile(path.Join(ctx.Agent.RunDir, "mig-agent.ok"), []byte(time.Now().String()), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -498,10 +498,10 @@ func initMQ(orig_ctx Context, try_proxy bool, proxy string) (ctx Context, err er
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.MQ.Chan.QueueBind(ctx.MQ.Bind.Queue, // Queue name
|
err = ctx.MQ.Chan.QueueBind(ctx.MQ.Bind.Queue, // Queue name
|
||||||
ctx.MQ.Bind.Key, // Routing key name
|
ctx.MQ.Bind.Key, // Routing key name
|
||||||
mig.Mq_Ex_ToAgents, // Exchange name
|
mig.ExchangeToAgents, // Exchange name
|
||||||
false, // is noWait
|
false, // is noWait
|
||||||
nil) // AMQP args
|
nil) // AMQP args
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,12 @@ func startHeartbeatsListener(ctx Context) (heartbeatChan <-chan amqp.Delivery, e
|
||||||
ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: "leaving startHeartbeatsListener()"}.Debug()
|
ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: "leaving startHeartbeatsListener()"}.Debug()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
_, err = ctx.MQ.Chan.QueueDeclare(mig.Mq_Q_Heartbeat, true, false, false, false, nil)
|
_, err = ctx.MQ.Chan.QueueDeclare(mig.QueueAgentHeartbeat, true, false, false, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.MQ.Chan.QueueBind(mig.Mq_Q_Heartbeat, mig.Mq_Q_Heartbeat, mig.Mq_Ex_ToSchedulers, false, nil)
|
err = ctx.MQ.Chan.QueueBind(mig.QueueAgentHeartbeat, mig.QueueAgentHeartbeat, mig.ExchangeToSchedulers, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func startHeartbeatsListener(ctx Context) (heartbeatChan <-chan amqp.Delivery, e
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
heartbeatChan, err = ctx.MQ.Chan.Consume(mig.Mq_Q_Heartbeat, "", true, false, false, false, nil)
|
heartbeatChan, err = ctx.MQ.Chan.Consume(mig.QueueAgentHeartbeat, "", true, false, false, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -176,12 +176,12 @@ func startResultsListener(ctx Context) (resultsChan <-chan amqp.Delivery, err er
|
||||||
ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: "leaving startResultsListener()"}.Debug()
|
ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: "leaving startResultsListener()"}.Debug()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
_, err = ctx.MQ.Chan.QueueDeclare(mig.Mq_Q_Results, true, false, false, false, nil)
|
_, err = ctx.MQ.Chan.QueueDeclare(mig.QueueAgentResults, true, false, false, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.MQ.Chan.QueueBind(mig.Mq_Q_Results, mig.Mq_Q_Results, mig.Mq_Ex_ToSchedulers, false, nil)
|
err = ctx.MQ.Chan.QueueBind(mig.QueueAgentResults, mig.QueueAgentResults, mig.ExchangeToSchedulers, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ func startResultsListener(ctx Context) (resultsChan <-chan amqp.Delivery, err er
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resultsChan, err = ctx.MQ.Chan.Consume(mig.Mq_Q_Results, "", true, false, false, false, nil)
|
resultsChan, err = ctx.MQ.Chan.Consume(mig.QueueAgentResults, "", true, false, false, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,12 +290,12 @@ func initRelay(orig_ctx Context) (ctx Context, err error) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// declare the "toagents" exchange used for communication from schedulers to agents
|
// declare the "toagents" exchange used for communication from schedulers to agents
|
||||||
err = ctx.MQ.Chan.ExchangeDeclare(mig.Mq_Ex_ToAgents, "direct", true, false, false, false, nil)
|
err = ctx.MQ.Chan.ExchangeDeclare(mig.ExchangeToAgents, "direct", true, false, false, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// declare the "toschedulers" exchange used for communication from agents to schedulers
|
// declare the "toschedulers" exchange used for communication from agents to schedulers
|
||||||
err = ctx.MQ.Chan.ExchangeDeclare(mig.Mq_Ex_ToSchedulers, "direct", true, false, false, false, nil)
|
err = ctx.MQ.Chan.ExchangeDeclare(mig.ExchangeToSchedulers, "direct", true, false, false, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ func sendCommands(cmds []mig.Command, ctx Context) (err error) {
|
||||||
}
|
}
|
||||||
agtQueue := fmt.Sprintf("mig.agt.%s", cmd.Agent.QueueLoc)
|
agtQueue := fmt.Sprintf("mig.agt.%s", cmd.Agent.QueueLoc)
|
||||||
go func() {
|
go func() {
|
||||||
err = ctx.MQ.Chan.Publish(mig.Mq_Ex_ToAgents, agtQueue, true, false, msg)
|
err = ctx.MQ.Chan.Publish(mig.ExchangeToAgents, agtQueue, true, false, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, ActionID: cmd.Action.ID, CommandID: cmd.ID, Desc: "publishing failed to queue" + agtQueue}.Err()
|
ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, ActionID: cmd.Action.ID, CommandID: cmd.ID, Desc: "publishing failed to queue" + agtQueue}.Err()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
package mig /* import "mig.ninja/mig" */
|
package mig /* import "mig.ninja/mig" */
|
||||||
|
|
||||||
// Describes results that are produced by mig-runner
|
// RunnerResult describes results that are produced by mig-runner. This data
|
||||||
|
// would be consumed by mig-runner plugins.
|
||||||
type RunnerResult struct {
|
type RunnerResult struct {
|
||||||
Action Action `json:"action"`
|
Action Action `json:"action"`
|
||||||
Commands []Command `json:"commands"`
|
Commands []Command `json:"commands"`
|
||||||
|
|
|
@ -10,7 +10,7 @@ package mig /* import "mig.ninja/mig" */
|
||||||
// components. You'd typically want to set this during install using flags
|
// components. You'd typically want to set this during install using flags
|
||||||
// such as -ldflags "-X mig.ninja/mig.Version=20170913-0.06824ce0.dev" when
|
// such as -ldflags "-X mig.ninja/mig.Version=20170913-0.06824ce0.dev" when
|
||||||
// calling the go build tools.
|
// calling the go build tools.
|
||||||
var Version string = ""
|
var Version = ""
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// If the default value of Version is not being specified using the build
|
// If the default value of Version is not being specified using the build
|
||||||
|
|
Загрузка…
Ссылка в новой задаче