Merge pull request #410 from ameihm0912/mig-pkg-style

style related code cleanup in mig top-level package
This commit is contained in:
Aaron Meihm 2017-10-26 16:19:34 -05:00 коммит произвёл GitHub
Родитель d4edb097d7 034de6f3da
Коммит 910338e57d
17 изменённых файлов: 207 добавлений и 182 удалений

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

Просмотреть файл

@ -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, "", " ")

Просмотреть файл

@ -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"`

Просмотреть файл

@ -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
} }

Просмотреть файл

@ -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"

Просмотреть файл

@ -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()

Просмотреть файл

@ -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