This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package agentprotocol
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const Version = "v1"
|
||||
|
||||
type Capability struct {
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
ReadOnly bool `json:"readOnly"`
|
||||
}
|
||||
type Hello struct {
|
||||
Protocol string `json:"protocol"`
|
||||
AgentID string `json:"agentId"`
|
||||
ObservedAt time.Time `json:"observedAt"`
|
||||
Capabilities []Capability `json:"capabilities"`
|
||||
}
|
||||
|
||||
func (h Hello) Validate(now time.Time) error {
|
||||
if h.Protocol != Version {
|
||||
return errors.New("unsupported agent protocol")
|
||||
}
|
||||
if strings.TrimSpace(h.AgentID) == "" || len(h.AgentID) > 120 {
|
||||
return errors.New("invalid agent id")
|
||||
}
|
||||
if h.ObservedAt.IsZero() || h.ObservedAt.After(now.Add(time.Minute)) {
|
||||
return errors.New("invalid agent observation time")
|
||||
}
|
||||
if len(h.Capabilities) > 50 {
|
||||
return errors.New("too many agent capabilities")
|
||||
}
|
||||
for _, capability := range h.Capabilities {
|
||||
if strings.TrimSpace(capability.ID) == "" || capability.Version == "" || !capability.ReadOnly {
|
||||
return errors.New("agent capability must be explicit and read-only")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package agentprotocol
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHelloRejectsMutationCapability(t *testing.T) {
|
||||
now := time.Now().UTC()
|
||||
hello := Hello{Protocol: Version, AgentID: "agent-1", ObservedAt: now, Capabilities: []Capability{{ID: "containers.read", Version: Version, ReadOnly: false}}}
|
||||
if err := hello.Validate(now); err == nil {
|
||||
t.Fatal("expected mutation capability rejection")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user