Skip to content

Commit

Permalink
chore(comments): Write function comments and update license header
Browse files Browse the repository at this point in the history
  • Loading branch information
m8rmclaren committed Dec 14, 2023
1 parent e2fcce9 commit a7fe383
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 10 deletions.
8 changes: 7 additions & 1 deletion internal/controllers/certificatesigningrequest_controller.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,6 +43,8 @@ type CertificateSigningRequestReconciler struct {
CredsSecret, ConfigMap, CaCertConfigmap types.NamespacedName
}

// Reconcile attempts to sign a CertificateSigningRequest given the configuration provided and a configured
// EJBCA certificate signer.
func (c *CertificateSigningRequestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, err error) {
reconcileLog := ctrl.LoggerFrom(ctx)

Expand Down Expand Up @@ -145,12 +147,16 @@ func (c *CertificateSigningRequestReconciler) Reconcile(ctx context.Context, req
return ctrl.Result{}, nil
}

// SetupWithManager registers the CertificateSigningRequestReconciler with the controller manager.
// It configures controller-runtime to reconcile CertificateSigningRequests in the cluster.
func (c *CertificateSigningRequestReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&certificates.CertificateSigningRequest{}).
Complete(c)
}

// IsIssuerInScope checks if the given issuer name is in scope of the controller's service account using
// the SelfSubjectAccessReview API.
func (c *CertificateSigningRequestReconciler) IsIssuerInScope(ctx context.Context, issuerName string) (v1.SubjectAccessReviewStatus, error) {
scopeLog := ctrl.LoggerFrom(ctx)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion internal/controllers/fake_configclient_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion internal/controllers/fake_signer_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
30 changes: 29 additions & 1 deletion internal/signer/signer.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -81,22 +81,28 @@ type ejbcaSigner struct {
restClient *ejbca.APIClient
}

// NewEjbcaSignerBuilder returns a new Builder for the EJBCA signer
func NewEjbcaSignerBuilder() Builder {
return &ejbcaSigner{}
}

// Reset resets the Builder to its initial state for reuse
func (s *ejbcaSigner) Reset() Builder {
s.errs = make([]error, 0)
s.enrollWithEst = false
return s
}

// WithContext sets the context for the Builder
func (s *ejbcaSigner) WithContext(ctx context.Context) Builder {
s.ctx = ctx
s.logger = log.FromContext(ctx)
return s
}

// WithCredsSecret sets the credentials secret for the Builder. If the secret is of type TLS, the signer will
// authenticate to the EJBCA API using a client certificate. If the secret is of type BasicAuth, the signer will
// authenticate to the EJBCA EST API using HTTP Basic Auth.
func (s *ejbcaSigner) WithCredsSecret(secret corev1.Secret) Builder {
if secret.Type == corev1.SecretTypeTLS {
// If we have a TLS secret, we will assume that we are not enrolling with EST and will authenticate to
Expand Down Expand Up @@ -136,6 +142,7 @@ func (s *ejbcaSigner) WithCredsSecret(secret corev1.Secret) Builder {
return s
}

// WithConfigMap sets the configuration config map for the Builder.
func (s *ejbcaSigner) WithConfigMap(config corev1.ConfigMap) Builder {
if host, ok := config.Data["ejbcaHostname"]; ok && host != "" {
s.hostname = config.Data["ejbcaHostname"]
Expand Down Expand Up @@ -174,6 +181,7 @@ func (s *ejbcaSigner) WithConfigMap(config corev1.ConfigMap) Builder {
return s
}

// WithCACertConfigMap sets the CA certificate config map for the Builder. The CA certificate config map is optional.
func (s *ejbcaSigner) WithCACertConfigMap(config corev1.ConfigMap) Builder {
if len(config.Data) == 0 {
return s
Expand Down Expand Up @@ -208,6 +216,9 @@ func (s *ejbcaSigner) WithCACertConfigMap(config corev1.ConfigMap) Builder {
return s
}

// PreFlight performs preflight checks to ensure that the signer is ready to sign CSRs.
// If the builder is configured to sign certificates with the EJBCA EST API, this method will create an EJBCA EST client.
// If the builder is configured to sign certificates with the EJBCA REST API, this method will create an EJBCA REST client.
func (s *ejbcaSigner) PreFlight() error {
var err error

Expand All @@ -229,6 +240,9 @@ func (s *ejbcaSigner) PreFlight() error {
return utilerrors.NewAggregate(s.errs)
}

// newRestClient creates a new EJBCA REST API client using the EJBCA Go Client SDK.
// It sets up the client to use the client certificate from the credentials secret
// and the CA certificate from the CA certificate config map.
func (s *ejbcaSigner) newRestClient() (*ejbca.APIClient, error) {
// Create EJBCA API Client
ejbcaConfig := ejbca.NewConfiguration()
Expand Down Expand Up @@ -310,6 +324,8 @@ func (s *ejbcaSigner) newRestClient() (*ejbca.APIClient, error) {
return client, nil
}

// newEstClient creates a new EJBCA EST API client using the EJBCA Go Client.
// It sets up the client to use HTTP Basic Auth with the username and password from the credentials secret
func (s *ejbcaSigner) newEstClient() (*ejbcaest.Client, error) {
// Get username and password from secret
username, ok := s.creds.Data["username"]
Expand Down Expand Up @@ -358,6 +374,8 @@ func (s *ejbcaSigner) newEstClient() (*ejbcaest.Client, error) {
return ejbcaClient, nil
}

// Build builds the Signer from the Builder, but secretly returns the Builder since it implements
// the Signer interface as well.
func (s *ejbcaSigner) Build() Signer {
if !s.preflightComplete {
s.logger.Error(fmt.Errorf("preflight not complete"), "preflight must be completed before building signer")
Expand All @@ -367,6 +385,7 @@ func (s *ejbcaSigner) Build() Signer {
return s
}

// Sign signs the given CSR using the configured EJBCA API client.
func (s *ejbcaSigner) Sign(csr certificates.CertificateSigningRequest) ([]byte, error) {
if s.enrollWithEst {
return s.signWithEst(&csr)
Expand All @@ -375,6 +394,7 @@ func (s *ejbcaSigner) Sign(csr certificates.CertificateSigningRequest) ([]byte,
}
}

// getEndEntityName determines the EJBCA end entity name based on the CSR and the defaultEndEntityName option.
func (s *ejbcaSigner) getEndEntityName(csr *x509.CertificateRequest) string {
eeName := ""
// 1. If the endEntityName option is set, determine the end entity name based on the option
Expand Down Expand Up @@ -429,6 +449,8 @@ func (s *ejbcaSigner) getEndEntityName(csr *x509.CertificateRequest) string {
return eeName
}

// deprecatedAnnotationGetter is a helper function to get annotations that were
// specified without the ejbca-k8s-csr-signer.keyfactor.com/ prefix.
func (s *ejbcaSigner) deprecatedAnnotationGetter(annotations map[string]string, annotation string) string {
annotationValue, ok := annotations[annotation]
if ok {
Expand All @@ -439,6 +461,7 @@ func (s *ejbcaSigner) deprecatedAnnotationGetter(annotations map[string]string,
return ""
}

// signWithRest sets up a request to the EJBCA REST API and enrolls the certificate.
func (s *ejbcaSigner) signWithRest(csr *certificates.CertificateSigningRequest) ([]byte, error) {
annotations := csr.GetAnnotations()

Expand Down Expand Up @@ -573,6 +596,7 @@ func (s *ejbcaSigner) signWithRest(csr *certificates.CertificateSigningRequest)
return pemChain, nil
}

// parseCSR parses a PEM encoded PKCS#10 CSR to an x509.CertificateRequest object
func parseCSR(pemBytes []byte) (*x509.CertificateRequest, error) {
// extract PEM from request object
block, _ := pem.Decode(pemBytes)
Expand All @@ -582,6 +606,7 @@ func parseCSR(pemBytes []byte) (*x509.CertificateRequest, error) {
return x509.ParseCertificateRequest(block.Bytes)
}

// getCertificatesFromEjbcaObject is a helper function to get the certificates from an EJBCA API response.
func getCertificatesFromEjbcaObject(ejbcaCert ejbca.CertificateRestResponse) ([]*x509.Certificate, bool, error) {
var certBytes []byte
var err error
Expand Down Expand Up @@ -640,6 +665,7 @@ func getCertificatesFromEjbcaObject(ejbcaCert ejbca.CertificateRestResponse) ([]
return certs, certChainFound, nil
}

// signWithEst sets up a request to the EJBCA EST API and enrolls the certificate.
func (s *ejbcaSigner) signWithEst(csr *certificates.CertificateSigningRequest) ([]byte, error) {
annotations := csr.GetAnnotations()
alias := "" // Default is already set in the EST client
Expand Down Expand Up @@ -711,11 +737,13 @@ func (s *ejbcaSigner) signWithEst(csr *certificates.CertificateSigningRequest) (
return pemChain, nil
}

// ptr is a helper function to return a pointer to a value
func ptr[T any](v T) *T {
return &v
}

// From https://github.com/hashicorp/terraform-plugin-sdk/blob/v2.10.0/helper/acctest/random.go#L51
// randStringFromCharSet generates a random string of a given length from a given character set.
func randStringFromCharSet(strlen int) string {
charSet := "abcdefghijklmnopqrstuvwxyz012346789"
result := make([]byte, strlen)
Expand Down
2 changes: 1 addition & 1 deletion internal/signer/signer_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
9 changes: 8 additions & 1 deletion pkg/util/configclient.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,6 +28,7 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
)

// ConfigClient is an interface for a K8s REST client.
type ConfigClient interface {
SetContext(ctx context.Context)
GetConfigMap(name types.NamespacedName, out *corev1.ConfigMap) error
Expand All @@ -43,6 +44,7 @@ type configClient struct {
verifyAccessFunc func(apiResource string, resource types.NamespacedName) error
}

// NewConfigClient creates a new K8s REST client using the configuration from the controller-runtime.
func NewConfigClient(ctx context.Context) (ConfigClient, error) {
config := ctrl.GetConfigOrDie()

Expand All @@ -64,11 +66,14 @@ func NewConfigClient(ctx context.Context) (ConfigClient, error) {
return client, nil
}

// SetContext sets the context for the client.
func (c *configClient) SetContext(ctx context.Context) {
c.ctx = ctx
c.logger = klog.FromContext(ctx)
}

// verifyAccessToResource verifies that the client has access to the given resource using the K8s
// SelfSubjectAccessReview API.
func (c *configClient) verifyAccessToResource(apiResource string, resource types.NamespacedName) error {
verbs := []string{"get", "list", "watch"}

Expand Down Expand Up @@ -101,6 +106,7 @@ func (c *configClient) verifyAccessToResource(apiResource string, resource types
return nil
}

// GetConfigMap gets the configmap with the given name and namespace and copies it into the out parameter.
func (c *configClient) GetConfigMap(name types.NamespacedName, out *corev1.ConfigMap) error {
if c == nil {
return fmt.Errorf("config client is nil")
Expand All @@ -126,6 +132,7 @@ func (c *configClient) GetConfigMap(name types.NamespacedName, out *corev1.Confi
return nil
}

// GetSecret gets the secret with the given name and namespace and copies it into the out parameter.
func (c *configClient) GetSecret(name types.NamespacedName, out *corev1.Secret) error {
if c == nil {
return fmt.Errorf("config client is nil")
Expand Down
2 changes: 1 addition & 1 deletion pkg/util/configclient_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 5 additions & 1 deletion pkg/util/util.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2023 The Keyfactor Command Authors.
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -54,6 +54,8 @@ func IsCertificateRequestApproved(csr certificates.CertificateSigningRequest) bo
return approved && !denied
}

// getCertApprovalCondition returns true if a certificate request has the
// "Approved" condition and no "Denied" conditions; false otherwise.
func getCertApprovalCondition(status certificates.CertificateSigningRequestStatus) (approved bool, denied bool) {
for _, c := range status.Conditions {
if c.Type == certificates.CertificateApproved {
Expand Down Expand Up @@ -84,6 +86,8 @@ func CompileCertificatesToPemBytes(certificates []*x509.Certificate) ([]byte, er
return []byte(leafAndChain.String()), nil
}

// DecodePEMBytes takes a byte array and returns a slice of PEM blocks containing
// certificates and a PEM block containing a private key if one exists.
func DecodePEMBytes(buf []byte) ([]*pem.Block, *pem.Block) {
var privKey *pem.Block
var certs []*pem.Block
Expand Down
16 changes: 16 additions & 0 deletions pkg/util/util_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
Copyright © 2023 Keyfactor
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package util

import (
Expand Down

0 comments on commit a7fe383

Please sign in to comment.