Skip to content

Commit

Permalink
feat(core): Allow for passing CA certs to config.
Browse files Browse the repository at this point in the history
feat(core): Allow to skip TLS verification
  • Loading branch information
spbsoluble committed May 13, 2024
1 parent fa93edb commit 61bc391
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 20 deletions.
10 changes: 0 additions & 10 deletions .github/config/environments.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ module "keyfactor_github_test_environment_ad_10_5_0" {
keyfactor_password = var.keyfactor_password_10_5_0
}

# module "keyfactor_github_test_environment_11_5_0_ad" {
# source = "git::ssh://[email protected]/Keyfactor/terraform-module-keyfactor-github-test-environment-ad.git?ref=v1.0.0"
#
# gh_environment_name = "KFC_11_5_0_AD"
# gh_repo_name = data.github_repository.repo.name
# keyfactor_hostname = var.keyfactor_hostname_11_5_0_AD
# keyfactor_username = var.keyfactor_username_11_5_0_AD
# keyfactor_password = var.keyfactor_password_11_5_0_AD
# }

module "keyfactor_github_test_environment_11_5_0_kc" {
source = "git::ssh://[email protected]/Keyfactor/terraform-module-keyfactor-github-test-environment-kc.git?ref=main"

Expand Down
82 changes: 72 additions & 10 deletions auth_providers/auth_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package auth_providers

import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io"
Expand All @@ -24,14 +26,15 @@ import (
)

const (
DefaultCommandPort = "443"
DefaultCommandAPIPath = "KeyfactorAPI"
DefaultAPIVersion = "1"
DefaultAPIClientName = "APIClient"
DefaultProductVersion = "10.5.0.0"
EnvKeyfactorHostName = "KEYFACTOR_HOSTNAME"
EnvKeyfactorPort = "KEYFACTOR_PORT"
EnvKeyfactorAPIPath = "KEYFACTOR_API_PATH"
DefaultCommandPort = "443"
DefaultCommandAPIPath = "KeyfactorAPI"
DefaultAPIVersion = "1"
DefaultAPIClientName = "APIClient"
DefaultProductVersion = "10.5.0.0"
EnvKeyfactorHostName = "KEYFACTOR_HOSTNAME"
EnvKeyfactorPort = "KEYFACTOR_PORT"
EnvKeyfactorAPIPath = "KEYFACTOR_API_PATH"
EnvKeyfactorSkipVerify = "KEYFACTOR_SKIP_VERIFY"
)

// CommandAuthConfig represents the base configuration needed for authentication to Keyfactor Command API.
Expand All @@ -54,8 +57,11 @@ type CommandAuthConfig struct {
// CommandAPIVersion is the version of the Keyfactor Command API, default is "1"
CommandVersion string `json:"command_version"`

// CommandCACert is the CA certificate to be used for authentication to Keyfactor Command API for use with not widely trusted certificates
CommandCACert string `json:"command_ca_cert;omitempty"`
// CommandCACert is the CA certificate to be used for authentication to Keyfactor Command API for use with not widely trusted certificates. This can be a filepath or a string of the certificate in PEM format.
CommandCACert string `json:"command_ca_cert"`

// SkipVerify is a flag to skip verification of the server's certificate chain and host name. Default is false.
SkipVerify bool `json:"skip_verify"`

// HttpClient is the http client to be used for authentication to Keyfactor Command API
HttpClient *http.Client
Expand Down Expand Up @@ -87,6 +93,18 @@ func (c *CommandAuthConfig) ValidateAuthConfig() error {

c.setClient()

if c.SkipVerify {
c.HttpClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
return nil
}

caErr := c.updateCACerts()
if caErr != nil {
return caErr
}

return nil
}

Expand All @@ -97,6 +115,50 @@ func (c *CommandAuthConfig) setClient() {
}
}

// updateCACerts updates the CA certs for the http client.
func (c *CommandAuthConfig) updateCACerts() error {
// check if CommandCACert is set
if c.CommandCACert == "" {
return nil
}

c.setClient()
// Load the system certs
rootCAs, pErr := x509.SystemCertPool()
if pErr != nil {
return pErr
}
if rootCAs == nil {
rootCAs = x509.NewCertPool()
}

// check if CommandCACert is a file
if _, err := os.Stat(c.CommandCACert); err == nil {
cert, ioErr := os.ReadFile(c.CommandCACert)
if ioErr != nil {
return ioErr
}
// Append your custom cert to the pool
if ok := rootCAs.AppendCertsFromPEM(cert); !ok {
return fmt.Errorf("failed to append custom CA cert to pool")
}
} else {
// Append your custom cert to the pool
if ok := rootCAs.AppendCertsFromPEM([]byte(c.CommandCACert)); !ok {
return fmt.Errorf("failed to append custom CA cert to pool")
}
}

// Trust the augmented cert pool in our client
c.HttpClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: rootCAs,
},
}

return nil
}

// Authenticate performs the authentication test to Keyfactor Command API and sets Command product version.
func (c *CommandAuthConfig) Authenticate() error {
// call /Status/Endpoints API to validate credentials
Expand Down
62 changes: 62 additions & 0 deletions auth_providers/keycloak/keycloak_auth_client_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
package keycloak

import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"

"keyfactor_auth_client/auth_providers"
Expand All @@ -37,6 +41,9 @@ type CommandAuthConfigKeyCloak struct {

// AuthType is the type of Keycloak auth to use such as client_credentials, password, etc.
AuthType string `json:"auth_type"`

// Auth CA Cert is the CA certificate to be used for authentication to Keycloak for use with not widely trusted certificates. This can be a filepath or a string of the certificate in PEM format.
AuthCACert string `json:"auth_ca_cert"`
}

// ValidateAuthConfig validates the authentication configuration for Keycloak.
Expand All @@ -60,5 +67,60 @@ func (c *CommandAuthConfigKeyCloak) ValidateAuthConfig() error {
c.AuthPort = DefaultKeyfactorAuthPort
}
}

caErr := c.updateCACerts()
if caErr != nil {
return caErr
}
return nil
}

func (c *CommandAuthConfigKeyCloak) updateCACerts() error {
// check if CommandCACert is set
if c.AuthCACert == "" {
return nil
}

// Load the system certs
rootCAs, pErr := x509.SystemCertPool()
if pErr != nil {
return pErr
}
if rootCAs == nil {
rootCAs = x509.NewCertPool()
}

// check if CommandCACert is a file
if _, err := os.Stat(c.AuthCACert); err == nil {
cert, ioErr := os.ReadFile(c.AuthCACert)
if ioErr != nil {
return ioErr
}
// Append your custom cert to the pool
if ok := rootCAs.AppendCertsFromPEM(cert); !ok {
return fmt.Errorf("failed to append custom CA cert to pool")
}
} else {
// Append your custom cert to the pool
if ok := rootCAs.AppendCertsFromPEM([]byte(c.AuthCACert)); !ok {
return fmt.Errorf("failed to append custom CA cert to pool")
}
}

// check if client already has a tls config
if c.HttpClient.Transport == nil {
// Trust the augmented cert pool in our client
c.HttpClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: rootCAs,
},
}
} else {
// Trust the augmented cert pool in our client
c.HttpClient.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
RootCAs: rootCAs,
}
}

return nil
}

0 comments on commit 61bc391

Please sign in to comment.