mirror of
https://github.com/strongdm/comply
synced 2025-12-06 06:14:09 +00:00
Add a model for a Control, which ou can use to document control statements, owners, governing policies, etc.
This commit is contained in:
24
internal/model/control.go
Normal file
24
internal/model/control.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
type Control struct {
|
||||
Name string `yaml:"name"`
|
||||
ID string `yaml:"identifier"`
|
||||
Family string `yaml:"family"`
|
||||
Owner string `yaml:"owner"`
|
||||
GoverningPolicy []Policy `yaml:"governingPolicy"`
|
||||
Revisions []Revision `yaml:"revisions"`
|
||||
Targets Target `yaml:"targets"`
|
||||
Published string `yaml:"published"`
|
||||
|
||||
FullPath string
|
||||
OutputFilename string
|
||||
ModifiedAt time.Time
|
||||
|
||||
Body string
|
||||
BodyHTML template.HTML
|
||||
}
|
||||
@@ -11,6 +11,8 @@ type Framework struct {
|
||||
Criteria map[string]Criterion `yaml:",inline"`
|
||||
}
|
||||
|
||||
type Target map[string][]string
|
||||
|
||||
// CriteriaSatisfied determines the unique criteria currently satisfied by all Narratives, Policies, and Procedures
|
||||
func CriteriaSatisfied(data *Data) map[string][]string {
|
||||
satisfied := make(map[string][]string)
|
||||
@@ -38,6 +40,13 @@ func CriteriaSatisfied(data *Data) map[string][]string {
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, n := range data.Controls {
|
||||
for _, criteriaKeys := range n.Targets {
|
||||
for _, key := range criteriaKeys {
|
||||
satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, n := range data.Procedures {
|
||||
for _, criteriaKeys := range n.Satisfies {
|
||||
for _, key := range criteriaKeys {
|
||||
|
||||
@@ -26,6 +26,10 @@ func ReadData() (*Data, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
controls, err := ReadControls()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
procedures, err := ReadProcedures()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -39,6 +43,7 @@ func ReadData() (*Data, error) {
|
||||
Tickets: tickets,
|
||||
Narratives: narratives,
|
||||
Policies: policies,
|
||||
Controls: controls,
|
||||
Procedures: procedures,
|
||||
Frameworks: frameworks,
|
||||
}, nil
|
||||
@@ -166,6 +171,31 @@ func ReadPolicies() ([]*Document, error) {
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
// ReadControls loads control documents from the filesystem
|
||||
func ReadControls() ([]*Control, error) {
|
||||
var controls []*Control
|
||||
|
||||
files, err := path.Controls()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to enumerate paths")
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
c := &Control{}
|
||||
mdmd := loadMDMD(f.FullPath)
|
||||
err = yaml.Unmarshal([]byte(mdmd.yaml), &c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to parse "+f.FullPath)
|
||||
}
|
||||
c.Body = mdmd.body
|
||||
c.FullPath = f.FullPath
|
||||
c.ModifiedAt = f.Info.ModTime()
|
||||
c.OutputFilename = fmt.Sprintf("%s-%s.pdf", config.Config().FilePrefix, c.ID)
|
||||
controls = append(controls, c)
|
||||
}
|
||||
return controls, nil
|
||||
}
|
||||
|
||||
type metadataMarkdown struct {
|
||||
yaml string
|
||||
body string
|
||||
|
||||
@@ -4,6 +4,7 @@ type Data struct {
|
||||
Frameworks []*Framework
|
||||
Narratives []*Document
|
||||
Policies []*Document
|
||||
Controls []*Control
|
||||
Procedures []*Procedure
|
||||
Tickets []*Ticket
|
||||
Audits []*Audit
|
||||
|
||||
7
internal/model/policy.go
Normal file
7
internal/model/policy.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
type Policy struct {
|
||||
Name string `yaml:"policyName"`
|
||||
ID string `yaml:"policyID"`
|
||||
Clause string `yaml:"policyClause"`
|
||||
}
|
||||
Reference in New Issue
Block a user