1
0
mirror of https://github.com/strongdm/comply synced 2025-12-16 03:04:24 +00:00

Compare commits

...

5 Commits

27 changed files with 498 additions and 213 deletions

View File

@@ -0,0 +1,33 @@
# Controls
Controls explicitly state a specific action that the organization will take to enforce a Policy goal.
## Format
```
name: Access Control Procedures
family: Access Control
identifier: AC-2
governingPolicy:
- policyName: Access Onboarding and Termination
policyID: SDM-AOTP
policyClause: 1.1
owner: Director, Security & Compliance
published: 2020-01-01
targets:
TSC 2017:
- CC6.1
- CC6.2
- CC6.3
NIST 800-53:
- AC-1
revisions:
- date: Sep 1 2020
comment: Initial documentation of control
---
1. Develop, document, and disseminate to all employees:
1. Organizational access control policy that:
1. Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and
```

View File

@@ -66,7 +66,7 @@ html lang=en
a onclick="javascript:show('procedures')" Procedures a onclick="javascript:show('procedures')" Procedures
li.top-nav.standards li.top-nav.standards
strong strong
a onclick="javascript:show('standards')" Standards a onclick="javascript:show('frameworks')" Frameworks
/ li.top-nav.evidence / li.top-nav.evidence
/ a onclick="javascript:show('evidence')" Evidence Vault / a onclick="javascript:show('evidence')" Evidence Vault
#overview.section.top-nav.container.content #overview.section.top-nav.container.content
@@ -76,17 +76,17 @@ html lang=en
.columns.is-vcentered .columns.is-vcentered
.column.is-one-third .column.is-one-third
div div
p.subtitle.is-3.has-text-centered Control Tracking p.subtitle.is-3.has-text-centered CriterionTracking
.column.has-text-centered .column.has-text-centered
div div
p.heading Satisfied Controls p.heading Satisfied Criteria
p.title p.title
{{.Stats.ControlsSatisfied}} {{.Stats.CriteriaSatisfied}}
.column.has-text-centered .column.has-text-centered
div div
p.heading Total Controls p.heading Total Controls
p.title p.title
{{.Stats.ControlsTotal}} {{.Stats.CriteriaTotal}}
.columns.is-vcentered .columns.is-vcentered
.column.is-one-third .column.is-one-third
div div
@@ -191,19 +191,19 @@ html lang=en
blockquote blockquote
h3 h3
p p
strong Standards strong Frameworks
| specify the controls satisfied by the compliance program. | specify the Framework Criteria satisfied by the compliance program.
table.table.is-size-4.is-fullwidth table.table.is-size-4.is-fullwidth
thead thead
tr tr
th Control Key th CriterionKey
th Name th Name
th Satisfied? th Satisfied?
th Satisfied By th Satisfied By
tbody tbody
{{range .Controls }} {{range .Criteria}}
tr tr
td {{.ControlKey}} td {{.criteriaKey}}
td td
strong {{.Name}} strong {{.Name}}
.subtitle {{.Description}} .subtitle {{.Description}}
@@ -234,4 +234,4 @@ html lang=en
show(destination) show(destination)
} }
} }
} }

1
go.mod
View File

@@ -33,6 +33,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/robfig/cron v1.2.0 github.com/robfig/cron v1.2.0
github.com/russross/blackfriday/v2 v2.0.1
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
github.com/trivago/tgo v1.0.7 // indirect github.com/trivago/tgo v1.0.7 // indirect

1
go.sum
View File

@@ -430,6 +430,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.5.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.5.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6 h1:tlXG832s5pa9x9Gs3Rp2rTvEqjiDEuETUOSfBEiTcns= github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6 h1:tlXG832s5pa9x9Gs3Rp2rTvEqjiDEuETUOSfBEiTcns=
github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=

View File

@@ -12,7 +12,7 @@ import (
var todoCommand = cli.Command{ var todoCommand = cli.Command{
Name: "todo", Name: "todo",
Usage: "list declared vs satisfied compliance controls", Usage: "list declared vs satisfied compliance criteria",
Action: todoAction, Action: todoAction,
Before: projectMustExist, Before: projectMustExist,
} }
@@ -24,42 +24,42 @@ func todoAction(c *cli.Context) error {
} }
w := tablewriter.NewWriter(os.Stdout) w := tablewriter.NewWriter(os.Stdout)
w.SetHeader([]string{"Standard", "Control", "Satisfied?", "Name"}) w.SetHeader([]string{"Framework", "Criterion", "Satisfied?", "Name"})
type row struct { type row struct {
standard string framework string
controlKey string criterionKey string
satisfied string satisfied string
controlName string criterionName string
} }
satisfied := model.ControlsSatisfied(d) satisfied := model.CriteriaSatisfied(d)
var rows []row var rows []row
for _, std := range d.Standards { for _, std := range d.Frameworks {
for id, c := range std.Controls { for id, c := range std.Criteria{
sat := "NO" sat := "NO"
if _, ok := satisfied[id]; ok { if _, ok := satisfied[id]; ok {
sat = color.GreenString("YES") sat = color.GreenString("YES")
} }
rows = append(rows, row{ rows = append(rows, row{
standard: std.Name, framework: std.Name,
controlKey: id, criterionKey: id,
satisfied: sat, satisfied: sat,
controlName: c.Name, criterionName: c.Name,
}) })
} }
} }
sort.Slice(rows, func(i, j int) bool { sort.Slice(rows, func(i, j int) bool {
return rows[i].controlKey < rows[j].controlKey return rows[i].criterionKey < rows[j].criterionKey
}) })
w.SetAutoWrapText(false) w.SetAutoWrapText(false)
for _, r := range rows { for _, r := range rows {
w.Append([]string{r.standard, r.controlKey, r.satisfied, r.controlName}) w.Append([]string{r.framework, r.criterionKey, r.satisfied, r.criterionName})
} }
w.Render() w.Render()

24
internal/model/control.go Normal file
View 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
}

View File

@@ -8,6 +8,7 @@ type Document struct {
Revisions []Revision `yaml:"majorRevisions"` Revisions []Revision `yaml:"majorRevisions"`
Satisfies Satisfaction `yaml:"satisfies"` Satisfies Satisfaction `yaml:"satisfies"`
Targets Target `yaml:"targets"`
FullPath string FullPath string
OutputFilename string OutputFilename string
ModifiedAt time.Time ModifiedAt time.Time

View File

@@ -1,18 +1,23 @@
package model package model
type Control struct { type Criterion struct {
Family string `yaml:"family"` Family string `yaml:"family"`
Name string `yaml:"name"` Name string `yaml:"name"`
Description string `yaml:"description"` Description string `yaml:"description"`
Satisfied bool
SatisfiedBy []string
} }
type Standard struct { type Framework struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Controls map[string]Control `yaml:",inline"` Criteria map[string]Criterion `yaml:",inline"`
} }
// ControlsSatisfied determines the unique controls currently satisfied by all Narratives, Policies, and Procedures type Target map[string][]string
func ControlsSatisfied(data *Data) 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) satisfied := make(map[string][]string)
appendSatisfaction := func(in map[string][]string, k string, v string) []string { appendSatisfaction := func(in map[string][]string, k string, v string) []string {
@@ -25,22 +30,29 @@ func ControlsSatisfied(data *Data) map[string][]string {
} }
for _, n := range data.Narratives { for _, n := range data.Narratives {
for _, controlKeys := range n.Satisfies { for _, criteriaKeys := range n.Satisfies {
for _, key := range controlKeys { for _, key := range criteriaKeys {
satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename) satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename)
} }
} }
} }
for _, n := range data.Policies { for _, n := range data.Policies {
for _, controlKeys := range n.Satisfies { for _, criteriaKeys := range n.Satisfies {
for _, key := range controlKeys { for _, key := range criteriaKeys {
satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename)
}
}
}
for _, n := range data.Controls {
for _, criteriaKeys := range n.Targets {
for _, key := range criteriaKeys {
satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename) satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename)
} }
} }
} }
for _, n := range data.Procedures { for _, n := range data.Procedures {
for _, controlKeys := range n.Satisfies { for _, criteriaKeys := range n.Satisfies {
for _, key := range controlKeys { for _, key := range criteriaKeys {
satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename) satisfied[key] = appendSatisfaction(satisfied, key, n.OutputFilename)
} }
} }

View File

@@ -26,11 +26,15 @@ func ReadData() (*Data, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
controls, err := ReadControls()
if err != nil {
return nil, err
}
procedures, err := ReadProcedures() procedures, err := ReadProcedures()
if err != nil { if err != nil {
return nil, err return nil, err
} }
standards, err := ReadStandards() frameworks, err := ReadFrameworks()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -39,8 +43,9 @@ func ReadData() (*Data, error) {
Tickets: tickets, Tickets: tickets,
Narratives: narratives, Narratives: narratives,
Policies: policies, Policies: policies,
Controls: controls,
Procedures: procedures, Procedures: procedures,
Standards: standards, Frameworks: frameworks,
}, nil }, nil
} }
@@ -67,27 +72,27 @@ func tickets(rawTickets []string) ([]*Ticket, error) {
return tickets, nil return tickets, nil
} }
// ReadStandards loads standard definitions from the filesystem. // ReadFrameworks loads standard definitions from the filesystem.
func ReadStandards() ([]*Standard, error) { func ReadFrameworks() ([]*Framework, error) {
var standards []*Standard var frameworks []*Framework
files, err := path.Standards() files, err := path.Frameworks()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "unable to enumerate paths") return nil, errors.Wrap(err, "unable to enumerate paths")
} }
for _, f := range files { for _, f := range files {
s := &Standard{} s := &Framework{}
sBytes, err := ioutil.ReadFile(f.FullPath) sBytes, err := ioutil.ReadFile(f.FullPath)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "unable to read "+f.FullPath) return nil, errors.Wrap(err, "unable to read "+f.FullPath)
} }
yaml.Unmarshal(sBytes, &s) yaml.Unmarshal(sBytes, &s)
standards = append(standards, s) frameworks = append(frameworks, s)
} }
return standards, nil return frameworks, nil
} }
// ReadNarratives loads narrative descriptions from the filesystem. // ReadNarratives loads narrative descriptions from the filesystem.
@@ -166,6 +171,31 @@ func ReadPolicies() ([]*Document, error) {
return policies, nil 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 { type metadataMarkdown struct {
yaml string yaml string
body string body string

View File

@@ -1,12 +1,13 @@
package model package model
type Data struct { type Data struct {
Standards []*Standard Frameworks []*Framework
Narratives []*Document Narratives []*Document
Policies []*Document Policies []*Document
Procedures []*Procedure Controls []*Control
Tickets []*Ticket Procedures []*Procedure
Audits []*Audit Tickets []*Ticket
Audits []*Audit
} }
type Revision struct { type Revision struct {

7
internal/model/policy.go Normal file
View File

@@ -0,0 +1,7 @@
package model
type Policy struct {
Name string `yaml:"policyName"`
ID string `yaml:"policyID"`
Clause string `yaml:"policyClause"`
}

View File

@@ -9,6 +9,7 @@ type Procedure struct {
Revisions []Revision `yaml:"majorRevisions"` Revisions []Revision `yaml:"majorRevisions"`
Satisfies Satisfaction `yaml:"satisfies"` Satisfies Satisfaction `yaml:"satisfies"`
Targets Target `yaml:"targets"`
FullPath string FullPath string
OutputFilename string OutputFilename string
ModifiedAt time.Time ModifiedAt time.Time

View File

@@ -15,9 +15,9 @@ type File struct {
Info os.FileInfo Info os.FileInfo
} }
// Standards lists all standard files. // Frameworks lists all standard files.
func Standards() ([]File, error) { func Frameworks() ([]File, error) {
return filesFor("standards", "yml") return filesFor("frameworks", "yaml")
} }
// Narratives lists all narrative files. // Narratives lists all narrative files.
@@ -30,6 +30,11 @@ func Policies() ([]File, error) {
return filesFor("policies", "md") return filesFor("policies", "md")
} }
// Controls lists all control files.
func Controls() ([]File, error) {
return filesFor("controls", "md")
}
// Procedures lists all procedure files. // Procedures lists all procedure files.
func Procedures() ([]File, error) { func Procedures() ([]File, error) {
return filesFor("procedures", "md") return filesFor("procedures", "md")

View File

@@ -2,12 +2,14 @@ package render
import ( import (
"fmt" "fmt"
"sort"
"time" "time"
"html/template"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/strongdm/comply/internal/config" "github.com/strongdm/comply/internal/config"
"github.com/strongdm/comply/internal/model" "github.com/strongdm/comply/internal/model"
"github.com/russross/blackfriday/v2"
) )
type project struct { type project struct {
@@ -16,8 +18,10 @@ type project struct {
} }
type stats struct { type stats struct {
ControlsTotal int ControlsTotal int
ControlsSatisfied int
CriteriaTotal int
CriteriaSatisfied int
ProcedureTotal int ProcedureTotal int
ProcedureOpen int ProcedureOpen int
@@ -30,21 +34,21 @@ type stats struct {
type renderData struct { type renderData struct {
// duplicates Project.OrganizationName // duplicates Project.OrganizationName
Name string Name string
Project *project Project *project
Stats *stats Stats *stats
Narratives []*model.Document Narratives []*model.Document
Policies []*model.Document Policies []*model.Document
Procedures []*model.Procedure Controls []*model.Control
Standards []*model.Standard Procedures []*model.Procedure
Tickets []*model.Ticket Frameworks []*model.Framework
Controls []*control Tickets []*model.Ticket
Links *model.TicketLinks Links *model.TicketLinks
} }
type control struct { type criterion struct {
Standard string Framework string
ControlKey string CriteriaKey string
Name string Name string
Description string Description string
Satisfied bool Satisfied bool
@@ -63,36 +67,27 @@ func load() (*model.Data, *renderData, error) {
Name: fmt.Sprintf("%s Compliance Program", cfg.Name), Name: fmt.Sprintf("%s Compliance Program", cfg.Name),
} }
satisfied := model.ControlsSatisfied(modelData) satisfied := model.CriteriaSatisfied(modelData)
controls := make([]*control, 0) for _, framework := range modelData.Frameworks {
for _, standard := range modelData.Standards { for key, c := range framework.Criteria{
for key, c := range standard.Controls {
satisfactions, ok := satisfied[key] satisfactions, ok := satisfied[key]
satisfied := ok && len(satisfactions) > 0 satisfied := ok && len(satisfactions) > 0
controls = append(controls, &control{ c.Satisfied = satisfied
Standard: standard.Name, c.SatisfiedBy = satisfactions
ControlKey: key, framework.Criteria[key] = c
Name: c.Name,
Description: c.Description,
Satisfied: satisfied,
SatisfiedBy: satisfactions,
})
} }
} }
sort.Slice(controls, func(i, j int) bool {
return controls[i].ControlKey < controls[j].ControlKey
})
rd := &renderData{} rd := &renderData{}
rd.Narratives = modelData.Narratives rd.Narratives = modelData.Narratives
rd.Policies = modelData.Policies rd.Policies = modelData.Policies
rd.Controls = modelData.Controls
rd.Procedures = modelData.Procedures rd.Procedures = modelData.Procedures
rd.Standards = modelData.Standards rd.Frameworks = modelData.Frameworks
rd.Tickets = modelData.Tickets rd.Tickets = modelData.Tickets
rd.Links = &model.TicketLinks{} rd.Links = &model.TicketLinks{}
rd.Project = project rd.Project = project
rd.Name = project.OrganizationName rd.Name = project.OrganizationName
rd.Controls = controls
ts, err := config.Config().TicketSystem() ts, err := config.Config().TicketSystem()
if err != nil { if err != nil {
@@ -114,6 +109,12 @@ func loadWithStats() (*model.Data, *renderData, error) {
return nil, nil, err return nil, nil, err
} }
// Convert the markdown body of each control to HTML
for _, n := range modelData.Controls {
b := []byte(n.Body)
n.BodyHTML = template.HTML(blackfriday.Run(b))
}
addStats(modelData, renderData) addStats(modelData, renderData)
return modelData, renderData, nil return modelData, renderData, nil
} }
@@ -121,13 +122,14 @@ func loadWithStats() (*model.Data, *renderData, error) {
func addStats(modelData *model.Data, renderData *renderData) { func addStats(modelData *model.Data, renderData *renderData) {
stats := &stats{} stats := &stats{}
satisfied := model.ControlsSatisfied(modelData) satisfied := model.CriteriaSatisfied(modelData)
stats.ControlsTotal += len(renderData.Controls)
for _, std := range renderData.Standards { for _, std := range renderData.Frameworks {
stats.ControlsTotal += len(std.Controls) stats.CriteriaTotal += len(std.Criteria)
for controlKey := range std.Controls { for criteriaKey := range std.Criteria{
if _, ok := satisfied[controlKey]; ok { if _, ok := satisfied[criteriaKey]; ok {
stats.ControlsSatisfied++ stats.CriteriaSatisfied++
} }
} }
} }

View File

@@ -114,7 +114,7 @@ func preprocessDoc(data *renderData, pol *model.Document, fullPath string) error
for standard, keys := range pol.Satisfies { for standard, keys := range pol.Satisfies {
rows += fmt.Sprintf("| %s | %s |\n", standard, strings.Join(keys, ", ")) rows += fmt.Sprintf("| %s | %s |\n", standard, strings.Join(keys, ", "))
} }
satisfiesTable = fmt.Sprintf("|Standard|Controls Satisfied|\n|-------+--------------------------------------------|\n%s\nTable: Control satisfaction\n", rows) satisfiesTable = fmt.Sprintf("|Framework|Criteria Satisfied|\n|-------+--------------------------------------------|\n%s\nTable: Criterion satisfaction\n", rows)
} }
if len(pol.Revisions) > 0 { if len(pol.Revisions) > 0 {

View File

@@ -16,6 +16,7 @@ func watch(errCh chan error) {
b.Add("./templates/") b.Add("./templates/")
b.Add("./narratives/") b.Add("./narratives/")
b.Add("./policies/") b.Add("./policies/")
b.Add("./controls/")
b.Add("./procedures/") b.Add("./procedures/")
b.Add("./.comply/") b.Add("./.comply/")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
# Controls
Controls explicitly state a specific action that the organization will take to enforce a Policy goal.
## Format
```
name: Access Control Procedures
family: Access Control
identifier: AC-2
governingPolicy:
- policyName: Access Onboarding and Termination
policyID: SDM-AOTP
policyClause: 1.1
owner: Director, Security & Compliance
published: 2020-01-01
targets:
TSC 2017:
- CC6.1
- CC6.2
- CC6.3
NIST 800-53:
- AC-1
revisions:
- date: Sep 1 2020
comment: Initial documentation of control
---
1. Develop, document, and disseminate to all employees:
1. Organizational access control policy that:
1. Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and
```

View File

View File

@@ -66,7 +66,7 @@ html lang=en
a onclick="javascript:show('procedures')" Procedures a onclick="javascript:show('procedures')" Procedures
li.top-nav.standards li.top-nav.standards
strong strong
a onclick="javascript:show('standards')" Standards a onclick="javascript:show('frameworks')" Frameworks
/ li.top-nav.evidence / li.top-nav.evidence
/ a onclick="javascript:show('evidence')" Evidence Vault / a onclick="javascript:show('evidence')" Evidence Vault
#overview.section.top-nav.container.content #overview.section.top-nav.container.content
@@ -76,17 +76,17 @@ html lang=en
.columns.is-vcentered .columns.is-vcentered
.column.is-one-third .column.is-one-third
div div
p.subtitle.is-3.has-text-centered Control Tracking p.subtitle.is-3.has-text-centered CriterionTracking
.column.has-text-centered .column.has-text-centered
div div
p.heading Satisfied Controls p.heading Satisfied Criteria
p.title p.title
{{.Stats.ControlsSatisfied}} {{.Stats.CriteriaSatisfied}}
.column.has-text-centered .column.has-text-centered
div div
p.heading Total Controls p.heading Total Controls
p.title p.title
{{.Stats.ControlsTotal}} {{.Stats.CriteriaTotal}}
.columns.is-vcentered .columns.is-vcentered
.column.is-one-third .column.is-one-third
div div
@@ -187,23 +187,23 @@ html lang=en
td On demand td On demand
{{end}} {{end}}
{{end}} {{end}}
#standards.section.top-nav.container.content #frameworks.section.top-nav.container.content
blockquote blockquote
h3 h3
p p
strong Standards strong Framework Targets
| specify the controls satisfied by the compliance program. | specify the Frameworks and Framework Criteria targeted by the compliance program.
table.table.is-size-4.is-fullwidth table.table.is-size-4.is-fullwidth
thead thead
tr tr
th Control Key th CriterionKey
th Name th Name
th Satisfied? th Satisfied?
th Satisfied By th Satisfied By
tbody tbody
{{range .Controls }} {{range .Criteria}}
tr tr
td {{.ControlKey}} td {{.criteriaKey}}
td td
strong {{.Name}} strong {{.Name}}
.subtitle {{.Description}} .subtitle {{.Description}}
@@ -234,4 +234,4 @@ html lang=en
show(destination) show(destination)
} }
} }
} }

View File

@@ -10,7 +10,7 @@ Compliance documents are organized as follows:
narratives/ Narratives provide an overview of the organization and the compliance environment. narratives/ Narratives provide an overview of the organization and the compliance environment.
policies/ Policies govern the behavior of employees and contractors. policies/ Policies govern the behavior of employees and contractors.
procedures/ Procedures prescribe specific steps that are taken in response to key events. procedures/ Procedures prescribe specific steps that are taken in response to key events.
standards/ Standards specify the controls satisfied by the compliance program. frameworks/ Frameworks specify the control criteria targeted by the compliance program.
templates/ Templates control the output format of the HTML Dashboard and PDF assets. templates/ Templates control the output format of the HTML Dashboard and PDF assets.
``` ```
@@ -57,4 +57,4 @@ comply build
# publish static site from output/ directory # publish static site from output/ directory
upload.sh output/ upload.sh output/
``` ```

View File

@@ -0,0 +1,33 @@
# Controls
Controls explicitly state a specific action that the organization will take to enforce a Policy goal.
## Format
```
name: Access Control Procedures
family: Access Control
identifier: AC-2
governingPolicy:
- policyName: Access Onboarding and Termination
policyID: SDM-AOTP
policyClause: 1.1
owner: Director, Security & Compliance
published: 2020-01-01
targets:
TSC 2017:
- CC6.1
- CC6.2
- CC6.3
NIST 800-53:
- AC-1
revisions:
- date: Sep 1 2020
comment: Initial documentation of control
---
1. Develop, document, and disseminate to all employees:
1. Organizational access control policy that:
1. Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and
```

View File

@@ -1,5 +1,5 @@
# Standards # Frameworks
All `yaml` files in this directory are assumed to conform to https://github.com/opencontrol/schemas/tree/master/kwalify/standard All `yaml` files in this directory are assumed to conform to https://github.com/opencontrol/schemas/tree/master/kwalify/standard
Adjust the target standard for this project by adding or removing line-items within each file, or adding/removing a standard file entirely. Adjust the target standard for this project by adding or removing line-items within each file, or adding/removing a standard file entirely.

View File

@@ -1,4 +1,4 @@
name: Control Environment Narrative name: CriterionEnvironment Narrative
acronym: CEN acronym: CEN
satisfies: satisfies:
TSC: TSC:
@@ -15,7 +15,7 @@ majorRevisions:
comment: Initial document comment: Initial document
--- ---
# Control Environment Narrative # CriterionEnvironment Narrative
The following provides a description of the control structure of {{.Name}}. The following provides a description of the control structure of {{.Name}}.
@@ -34,7 +34,7 @@ The intent of this description is to enumerate the logical, policy, and procedur
{{.Name}} employs several policy controls to protect confidential data and ensure normal operation of its core product. These policies include, but are not limited to: {{.Name}} employs several policy controls to protect confidential data and ensure normal operation of its core product. These policies include, but are not limited to:
- Access Control Policy - Access CriterionPolicy
- Encryption Policy - Encryption Policy
- Office Security Policy - Office Security Policy
- Password Policy - Password Policy

View File

View File

@@ -66,7 +66,7 @@ html lang=en
a onclick="javascript:show('procedures')" Procedures a onclick="javascript:show('procedures')" Procedures
li.top-nav.standards li.top-nav.standards
strong strong
a onclick="javascript:show('standards')" Standards a onclick="javascript:show('frameworks')" Frameworks
/ li.top-nav.evidence / li.top-nav.evidence
/ a onclick="javascript:show('evidence')" Evidence Vault / a onclick="javascript:show('evidence')" Evidence Vault
#overview.section.top-nav.container.content #overview.section.top-nav.container.content
@@ -76,17 +76,17 @@ html lang=en
.columns.is-vcentered .columns.is-vcentered
.column.is-one-third .column.is-one-third
div div
p.subtitle.is-3.has-text-centered Control Tracking p.subtitle.is-3.has-text-centered CriterionTracking
.column.has-text-centered .column.has-text-centered
div div
p.heading Satisfied Controls p.heading Satisfied Criteria
p.title p.title
{{.Stats.ControlsSatisfied}} {{.Stats.CriteriaSatisfied}}
.column.has-text-centered .column.has-text-centered
div div
p.heading Total Controls p.heading Total Controls
p.title p.title
{{.Stats.ControlsTotal}} {{.Stats.CriteriaTotal}}
.columns.is-vcentered .columns.is-vcentered
.column.is-one-third .column.is-one-third
div div
@@ -187,23 +187,23 @@ html lang=en
td On demand td On demand
{{end}} {{end}}
{{end}} {{end}}
#standards.section.top-nav.container.content #frameworks.section.top-nav.container.content
blockquote blockquote
h3 h3
p p
strong Standards strong Framework Targets
| specify the controls satisfied by the compliance program. | specify the Frameworks and Framework Criteria targeted by the compliance program.
table.table.is-size-4.is-fullwidth table.table.is-size-4.is-fullwidth
thead thead
tr tr
th Control Key th CriterionKey
th Name th Name
th Satisfied? th Satisfied?
th Satisfied By th Satisfied By
tbody tbody
{{range .Controls }} {{range .Criteria}}
tr tr
td {{.ControlKey}} td {{.criteriaKey}}
td td
strong {{.Name}} strong {{.Name}}
.subtitle {{.Description}} .subtitle {{.Description}}
@@ -234,4 +234,4 @@ html lang=en
show(destination) show(destination)
} }
} }
} }