Skip to content

Commit

Permalink
Add ca template functions to dependency graph
Browse files Browse the repository at this point in the history
  • Loading branch information
emosbaugh committed Aug 6, 2020
1 parent 7574b10 commit 521b2f8
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 27 deletions.
101 changes: 85 additions & 16 deletions pkg/template/depgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ import (
)

type depGraph struct {
Dependencies map[string]map[string]struct{}
CertItems map[string]map[string]struct{} // items that use the TLSCert template function. map of certnames to configoptions that provide the certname
KeyItems map[string]map[string]struct{} // items that use the TLSKey template function. map of configoptions to the certnames they use
Dependencies map[string]map[string]struct{}
CertItems map[string]map[string]struct{} // items that use the TLSCert template function. map of certnames to configoptions that provide the certname
KeyItems map[string]map[string]struct{} // items that use the TLSKey template function. map of TLSKey configoptions to the certnames they use
CAItems map[string]map[string]struct{} // items that use the TLSCACert template function. map of canames to configoptions that provide the caname
CAFromCertItems map[string]map[string]struct{} // items that use the TLSCertFromCA template function. map of TLSCertFromCA configoptions to the canames they use
CertFromCACertItems map[string]map[string]struct{} // items that use the TLSCertFromCA template function. map of canames and certnames to configoptions that provide the certname
CAItemsFromKey map[string]map[string]struct{} // items that use the TLSKeyFromCA template function. map of TLSKeyFromCA configoptions to the canames they use
CACertItemsFromKey map[string]map[string]struct{} // items that use the TLSKeyFromCA template function. map of TLSKeyFromCA configoptions to the canames and certnames they use
}

// these config functions are used to add their dependencies to the depGraph
Expand All @@ -33,14 +38,32 @@ func (d *depGraph) funcMap(parent string) template.FuncMap {
return certName
}

addCAFunc := func(caName string, _ ...string) string {
d.AddCA(parent, caName)
return caName
}

addCertFromCAFunc := func(caName, certName string, _ ...string) string {
d.AddCertFromCA(parent, caName, certName)
return certName
}

addKeyFromCAFunc := func(caName, certName string, _ ...string) string {
d.AddKeyFromCA(parent, caName, certName)
return certName
}

return template.FuncMap{
"ConfigOption": addDepFunc,
"ConfigOptionIndex": addDepFunc,
"ConfigOptionData": addDepFunc,
"ConfigOptionEquals": addDepFunc,
"ConfigOptionNotEquals": addDepFunc,
"TLSCACert": addCAFunc,
"TLSCert": addCertFunc,
"TLSCertFromCA": addCertFromCAFunc,
"TLSKey": addKeyFunc,
"TLSKeyFromCA": addKeyFromCAFunc,
}
}

Expand All @@ -61,25 +84,37 @@ func (d *depGraph) AddDep(source, newDependency string) {
}

func (d *depGraph) AddCert(source, certName string) {
if d.CertItems == nil {
d.CertItems = make(map[string]map[string]struct{})
}
if _, ok := d.CertItems[certName]; !ok {
d.CertItems[certName] = make(map[string]struct{})
}

d.CertItems[certName][source] = struct{}{}
d.CertItems = addDepGraphItem(d.CertItems, certName, source)
}

func (d *depGraph) AddKey(source, certName string) {
if d.KeyItems == nil {
d.KeyItems = make(map[string]map[string]struct{})
d.KeyItems = addDepGraphItem(d.KeyItems, source, certName)
}

func (d *depGraph) AddCA(source, caName string) {
d.CAItems = addDepGraphItem(d.CAItems, caName, source)
}

func (d *depGraph) AddCertFromCA(source, caName, certName string) {
d.CAFromCertItems = addDepGraphItem(d.CAFromCertItems, source, caName)
d.CertFromCACertItems = addDepGraphItem(d.CertFromCACertItems, caName+certName, source)
}

func (d *depGraph) AddKeyFromCA(source, caName, certName string) {
d.CAItemsFromKey = addDepGraphItem(d.CAItemsFromKey, source, caName)
d.CACertItemsFromKey = addDepGraphItem(d.CACertItemsFromKey, source, caName+certName)
}

func addDepGraphItem(m map[string]map[string]struct{}, key, value string) map[string]map[string]struct{} {
if m == nil {
m = make(map[string]map[string]struct{})
}
if _, ok := d.KeyItems[source]; !ok {
d.KeyItems[source] = make(map[string]struct{})
if _, ok := m[key]; !ok {
m[key] = make(map[string]struct{})
}

d.KeyItems[source][certName] = struct{}{}
m[key][value] = struct{}{}
return m
}

func (d *depGraph) resolveCertKeys() {
Expand All @@ -94,6 +129,39 @@ func (d *depGraph) resolveCertKeys() {
}
}

func (d *depGraph) resolveCACerts() {
for source, caNameMap := range d.CAFromCertItems {
for caName := range caNameMap {
for caProvider := range d.CAItems[caName] {
if caProvider != source {
d.AddDep(source, caProvider)
}
}
}
}
}

func (d *depGraph) resolveCACertKeys() {
for source, caNameMap := range d.CAItemsFromKey {
for caName := range caNameMap {
for caProvider := range d.CAItems[caName] {
if caProvider != source {
d.AddDep(source, caProvider)
}
}
}
}
for source, caCertNameMap := range d.CACertItemsFromKey {
for caCertName := range caCertNameMap {
for certProvider := range d.CertFromCACertItems[caCertName] {
if certProvider != source {
d.AddDep(source, certProvider)
}
}
}
}
}

func (d *depGraph) ResolveDep(resolvedDependency string) {
for _, depMap := range d.Dependencies {
delete(depMap, resolvedDependency)
Expand Down Expand Up @@ -168,6 +236,7 @@ func (d *depGraph) ParseConfigGroup(configGroups []kotsv1beta1.ConfigGroup) erro
}

d.resolveCertKeys()
d.resolveCACertKeys()

return nil
}
114 changes: 103 additions & 11 deletions pkg/template/depgraph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ import (
)

type depGraphTestCase struct {
dependencies map[string][]string
testCerts map[string][]string
testKeys map[string][]string
resolveOrder []string
expectError bool //expect an error fetching head nodes
expectNotFound string //expect this dependency not to be part of the head nodes
dependencies map[string][]string
testCerts map[string][]string
testKeys map[string][]string
testCAs map[string][]string
testCAFromCerts map[string][][2]string
testCAFromKeys map[string][][2]string
resolveOrder []string
expectError bool //expect an error fetching head nodes
expectNotFound []string //expect these dependencies not to be part of the head nodes

name string
}
Expand Down Expand Up @@ -64,7 +67,7 @@ func TestDepGraph(t *testing.T) {
"foxtrot": {},
},
resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot"},
expectNotFound: "delta",
expectNotFound: []string{"delta"},
name: "unresolved_dependency",
},
{
Expand Down Expand Up @@ -148,7 +151,48 @@ func TestDepGraph(t *testing.T) {
},
resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo"},
name: "basic_certs_original_order",
expectNotFound: "delta",
expectNotFound: []string{"delta"},
},
{
dependencies: map[string][]string{
"alpha": {},
"bravo": {"alpha"},
"charlie": {"alpha", "bravo"},
"delta": {},
"echo": {},
},
testCAs: map[string][]string{
"echo": {"caA"},
},
testCAFromCerts: map[string][][2]string{
"delta": {{"caA", "certA"}},
},
testCAFromKeys: map[string][][2]string{
"charlie": {{"caA", "certA"}},
},
resolveOrder: []string{"alpha", "bravo", "echo", "delta", "charlie"},
name: "basic_cacerts",
},
{
dependencies: map[string][]string{
"alpha": {},
"bravo": {"alpha"},
"charlie": {"alpha", "bravo"},
"delta": {},
"echo": {},
},
testCAs: map[string][]string{
"echo": {"caA"},
},
testCAFromCerts: map[string][][2]string{
"delta": {{"caA", "certA"}},
},
testCAFromKeys: map[string][][2]string{
"charlie": {{"caA", "certA"}},
},
resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo"},
name: "basic_cacerts_original_order",
expectNotFound: []string{"delta", "charlie"},
},
}
for _, test := range tests {
Expand All @@ -173,7 +217,24 @@ func TestDepGraph(t *testing.T) {
graph.AddKey(source, key)
}
}
for source, caNames := range test.testCAs {
for _, caName := range caNames {
graph.AddCA(source, caName)
}
}
for source, caCertNames := range test.testCAFromCerts {
for _, caCertName := range caCertNames {
graph.AddCertFromCA(source, caCertName[0], caCertName[1])
}
}
for source, caCertNames := range test.testCAFromKeys {
for _, caCertName := range caCertNames {
graph.AddKeyFromCA(source, caCertName[0], caCertName[1])
}
}
graph.resolveCertKeys()
graph.resolveCACerts()
graph.resolveCACertKeys()

runGraphTests(t, test, graph)
})
Expand All @@ -184,7 +245,11 @@ func TestDepGraph(t *testing.T) {

graph := depGraph{}

groups := buildTestConfigGroups(test.dependencies, test.testCerts, test.testKeys, "templateStringStart", "templateStringEnd", true)
groups := buildTestConfigGroups(
test.dependencies, test.testCerts, test.testKeys,
test.testCAs, test.testCAFromCerts, test.testCAFromKeys,
"templateStringStart", "templateStringEnd", true,
)

err := graph.ParseConfigGroup(groups)
require.NoError(t, err)
Expand All @@ -195,7 +260,7 @@ func TestDepGraph(t *testing.T) {
}

// this makes sure that we test with each of the configOption types, in both Value and Default
func buildTestConfigGroups(dependencies, certs, keys map[string][]string, prefix string, suffix string, rotate bool) []kotsv1beta1.ConfigGroup {
func buildTestConfigGroups(dependencies, certs, keys, cas map[string][]string, caFromCerts, caFromKeys map[string][][2]string, prefix string, suffix string, rotate bool) []kotsv1beta1.ConfigGroup {
group := kotsv1beta1.ConfigGroup{}
group.Items = make([]kotsv1beta1.ConfigItem, 0)
counter := 0
Expand Down Expand Up @@ -237,6 +302,24 @@ func buildTestConfigGroups(dependencies, certs, keys map[string][]string, prefix
}
}

if caNames, ok := cas[source]; ok {
for _, caName := range caNames {
depString += fmt.Sprintf("{{repl TLSCACert \"%s\" }}", caName)
}
}

if caCertNames, ok := caFromCerts[source]; ok {
for _, caCertName := range caCertNames {
depString += fmt.Sprintf("{{repl TLSCertFromCA \"%s\" \"%s\" }}", caCertName[0], caCertName[1])
}
}

if caCertNames, ok := caFromKeys[source]; ok {
for _, caCertName := range caCertNames {
depString += fmt.Sprintf("{{repl TLSKeyFromCA \"%s\" \"%s\" }}", caCertName[0], caCertName[1])
}
}

depString += suffix

if counter%2 == 0 {
Expand Down Expand Up @@ -268,7 +351,7 @@ func runGraphTests(t *testing.T, test depGraphTestCase, graph depGraph) {

require.NoError(t, err, "toResolve: %s", toResolve)

if test.expectNotFound != "" && toResolve == test.expectNotFound {
if stringInSlice(toResolve, test.expectNotFound) {
require.NotContains(t, available, toResolve)
return
}
Expand All @@ -286,3 +369,12 @@ func runGraphTests(t *testing.T, test depGraphTestCase, graph depGraph) {

require.Equal(t, depLen, len(graphCopy.Dependencies))
}

func stringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}

0 comments on commit 521b2f8

Please sign in to comment.