Skip to content

Commit

Permalink
ca: allow user-defined dns names in certs
Browse files Browse the repository at this point in the history
  • Loading branch information
3u13r committed Dec 20, 2023
1 parent aae7c58 commit 307d1e2
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 30 deletions.
65 changes: 46 additions & 19 deletions cli/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package main
import (
"fmt"
"os"
"slices"

"github.com/edgelesssys/nunki/internal/kubeapi"
"github.com/edgelesssys/nunki/internal/manifest"
)

func policiesFromKubeResources(yamlPaths []string) (map[string]manifest.Policy, error) {
func policiesFromKubeResources(yamlPaths []string) (map[string]deployment, error) {
var kubeObjs []any
for _, path := range yamlPaths {
data, err := os.ReadFile(path)
Expand All @@ -22,24 +23,29 @@ func policiesFromKubeResources(yamlPaths []string) (map[string]manifest.Policy,
kubeObjs = append(kubeObjs, objs...)
}

policies := make(map[string]manifest.Policy)
deployments := make(map[string]deployment)
for _, objAny := range kubeObjs {
var name, annotation string
var name, annotation, namespace string
switch obj := objAny.(type) {
case kubeapi.Pod:
name = obj.Name
namespace = obj.Namespace
annotation = obj.Annotations[kataPolicyAnnotationKey]
case kubeapi.Deployment:
name = obj.Name
namespace = obj.Namespace
annotation = obj.Spec.Template.Annotations[kataPolicyAnnotationKey]
case kubeapi.ReplicaSet:
name = obj.Name
namespace = obj.Namespace
annotation = obj.Spec.Template.Annotations[kataPolicyAnnotationKey]
case kubeapi.StatefulSet:
name = obj.Name
namespace = obj.Namespace
annotation = obj.Spec.Template.Annotations[kataPolicyAnnotationKey]
case kubeapi.DaemonSet:
name = obj.Name
namespace = obj.Namespace
annotation = obj.Spec.Template.Annotations[kataPolicyAnnotationKey]
}
if annotation == "" {
Expand All @@ -48,46 +54,67 @@ func policiesFromKubeResources(yamlPaths []string) (map[string]manifest.Policy,
if name == "" {
return nil, fmt.Errorf("name is required but empty")
}
if namespace == "" {
namespace = "default"
}
policy, err := manifest.NewPolicyFromAnnotation([]byte(annotation))
if err != nil {
return nil, fmt.Errorf("failed to parse policy %s: %w", name, err)
}
policies[name] = policy
deployments[name] = deployment{
name: name,
namespace: namespace,
policy: policy,
}
}

return policies, nil
return deployments, nil
}

func manifestPolicyMapFromPolicies(policies map[string]manifest.Policy) (map[manifest.HexString]string, error) {
policyHashes := make(map[manifest.HexString]string)
for name, policy := range policies {
if existingName, ok := policyHashes[policy.Hash()]; ok {
if existingName != name {
return nil, fmt.Errorf("policy hash collision: %s and %s have the same hash %s",
existingName, name, policy.Hash())
func manifestPolicyMapFromPolicies(policies map[string]deployment) (map[manifest.HexString][]string, error) {
policyHashes := make(map[manifest.HexString][]string)
for name, depl := range policies {
if existingNames, ok := policyHashes[depl.policy.Hash()]; ok {
if slices.Equal(existingNames, depl.DNSNames()) {
return nil, fmt.Errorf("policy hash collision: %s and %s have the same hash %v",
existingNames, name, depl.policy.Hash())
}
continue
}
policyHashes[policy.Hash()] = name
policyHashes[depl.policy.Hash()] = depl.DNSNames()
}
return policyHashes, nil
}

func checkPoliciesMatchManifest(policies map[string]manifest.Policy, policyHashes map[manifest.HexString]string) error {
func checkPoliciesMatchManifest(policies map[string]deployment, policyHashes map[manifest.HexString][]string) error {
if len(policies) != len(policyHashes) {
return fmt.Errorf("policy count mismatch: %d policies in deployment, but %d in manifest",
len(policies), len(policyHashes))
}
for name, policy := range policies {
existingName, ok := policyHashes[policy.Hash()]
for name, deployment := range policies {
existingNames, ok := policyHashes[deployment.policy.Hash()]
if !ok {
return fmt.Errorf("policy %s not found in manifest", name)
}
if existingName != name {
return fmt.Errorf("policy %s with hash %s exists in manifest, but with different name %s",
name, policy.Hash(), existingName,

if !slices.Equal(existingNames, deployment.DNSNames()) {
return fmt.Errorf("policy %s with hash %s exists in manifest, but with different names %v",
name, deployment.policy.Hash(), existingNames,
)
}
}
return nil
}

type deployment struct {
name string
namespace string
policy manifest.Policy
}

func (d deployment) DNSNames() []string {
return []string{
fmt.Sprintf("%s.%s", d.name, d.namespace),
fmt.Sprintf("*.%s", d.namespace),
}
}
6 changes: 3 additions & 3 deletions cli/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ func parseSetFlags(cmd *cobra.Command) (*setFlags, error) {
return flags, nil
}

func policyMapToBytesList(m map[string]manifest.Policy) [][]byte {
func policyMapToBytesList(m map[string]deployment) [][]byte {
var policies [][]byte
for _, policy := range m {
policies = append(policies, policy)
for _, depl := range m {
policies = append(policies, depl.policy)
}
return policies
}
4 changes: 2 additions & 2 deletions coordinator/mesh.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (m *meshAuthority) SNPValidateOpts(report *sevsnp.Report) (*validate.Option

func (m *meshAuthority) ValidateCallback(ctx context.Context, report *sevsnp.Report, nonce []byte, peerPubKeyBytes []byte) error {
hostData := manifest.NewHexString(report.HostData)
commonName, ok := m.manifest.Policies[hostData]
dnsNames, ok := m.manifest.Policies[hostData]
if !ok {
return fmt.Errorf("report data %s not found in manifest", hostData)
}
Expand All @@ -81,7 +81,7 @@ func (m *meshAuthority) ValidateCallback(ctx context.Context, report *sevsnp.Rep
}

var extensions []pkix.Extension // TODO
cert, err := m.ca.NewAttestedMeshCert(commonName, extensions, peerPubKey)
cert, err := m.ca.NewAttestedMeshCert(dnsNames, extensions, peerPubKey)
if err != nil {
return fmt.Errorf("failed to issue new attested mesh cert: %w", err)
}
Expand Down
10 changes: 8 additions & 2 deletions data/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
{
"Policies": {
"2b3422e2e44c933f5a2bea3d25fc36502951cfac3bd07ea2033936b4b72b5c65": "workload",
"3638d61e7c8701e19e819751eb61e2e353f25f68374443d03428c8acc39ed3e9": "coordinator-kbs"
"2b3422e2e44c933f5a2bea3d25fc36502951cfac3bd07ea2033936b4b72b5c65": [
"workload.edg-coco",
"*.edg-coco"
],
"3638d61e7c8701e19e819751eb61e2e353f25f68374443d03428c8acc39ed3e9": [
"coordinator-kbs.edg-coco",
"*.edg-coco"
]
},
"ReferenceValues": {
"SNP": {
Expand Down
6 changes: 3 additions & 3 deletions internal/ca/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func New(namespace string) (*CA, error) {
}, nil
}

func (c *CA) NewAttestedMeshCert(commonName string, extensions []pkix.Extension, subjectPublicKey any) ([]byte, error) {
func (c *CA) NewAttestedMeshCert(dnsNames []string, extensions []pkix.Extension, subjectPublicKey any) ([]byte, error) {
serialNumber, err := crypto.GenerateCertificateSerialNumber()
if err != nil {
return nil, err
Expand All @@ -100,15 +100,15 @@ func (c *CA) NewAttestedMeshCert(commonName string, extensions []pkix.Extension,
now := time.Now()
certTemplate := &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{CommonName: commonName},
Subject: pkix.Name{CommonName: dnsNames[0]},
Issuer: pkix.Name{CommonName: "system:coordinator-kbs:intermediate"},
NotBefore: now.Add(-2 * time.Hour),
NotAfter: now.Add(354 * 24 * time.Hour),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
ExtraExtensions: extensions,
DNSNames: []string{fmt.Sprintf("*.%s", c.namespace)},
DNSNames: dnsNames,
}

certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, c.intermCert, subjectPublicKey, c.intermPrivKey)
Expand Down
2 changes: 1 addition & 1 deletion internal/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

type Manifest struct {
// policyHash/HOSTDATA -> commonName
Policies map[HexString]string
Policies map[HexString][]string
ReferenceValues ReferenceValues
}

Expand Down

0 comments on commit 307d1e2

Please sign in to comment.