-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from madflojo/ip-support
Adding IP Address support
- Loading branch information
Showing
6 changed files
with
693 additions
and
273 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package testcerts | ||
|
||
// GenerateCerts generates a x509 certificate and key. | ||
// It returns the certificate and key as byte slices, and any error that occurred. | ||
// | ||
// cert, key, err := GenerateCerts() | ||
// if err != nil { | ||
// // handle error | ||
// } | ||
func GenerateCerts(domains ...string) ([]byte, []byte, error) { | ||
ca := NewCA() | ||
|
||
// Returning CA for backwards compatibility | ||
if len(domains) == 0 { | ||
return ca.PublicKey(), ca.PrivateKey(), nil | ||
} | ||
|
||
// If domains exist return a regular cert | ||
kp, err := ca.NewKeyPair(domains...) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
return kp.PublicKey(), kp.PrivateKey(), nil | ||
} | ||
|
||
// GenerateCertsToFile creates a x509 certificate and key and writes it to the specified file paths. | ||
// | ||
// err := GenerateCertsToFile("/path/to/cert", "/path/to/key") | ||
// if err != nil { | ||
// // handle error | ||
// } | ||
// | ||
// If the specified file paths already exist, it will overwrite the existing files. | ||
func GenerateCertsToFile(certFile, keyFile string) error { | ||
// Create Certs using CA for backwards compatibility | ||
return NewCA().ToFile(certFile, keyFile) | ||
} | ||
|
||
// GenerateCertsToTempFile will create a temporary x509 certificate and key in a randomly generated file using the | ||
// directory path provided. If no directory is specified, the default directory for temporary files as returned by | ||
// os.TempDir will be used. | ||
// | ||
// cert, key, err := GenerateCertsToTempFile("/tmp/") | ||
// if err != nil { | ||
// // handle error | ||
// } | ||
func GenerateCertsToTempFile(dir string) (string, string, error) { | ||
// Create Certs using CA for backwards compatibility | ||
cert, key, err := NewCA().ToTempFile(dir) | ||
if err != nil { | ||
return "", "", err | ||
} | ||
|
||
return cert.Name(), key.Name(), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package testcerts | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
) | ||
|
||
func TestGeneratingCerts(t *testing.T) { | ||
_, _, err := GenerateCerts() | ||
if err != nil { | ||
t.Errorf("Error while generating certificates - %s", err) | ||
} | ||
} | ||
|
||
func TestGeneratingCertsToFile(t *testing.T) { | ||
t.Run("Test the happy path", func(t *testing.T) { | ||
tempDir, err := os.MkdirTemp("", "") | ||
if err != nil { | ||
t.Errorf("Error creating temporary directory: %s", err) | ||
} | ||
defer os.RemoveAll(tempDir) | ||
|
||
certPath := filepath.Join(tempDir, "cert") | ||
keyPath := filepath.Join(tempDir, "key") | ||
|
||
err = GenerateCertsToFile(certPath, keyPath) | ||
if err != nil { | ||
t.Errorf("Error while generating certificates to files - %s", err) | ||
} | ||
|
||
// Check if Cert file exists | ||
_, err = os.Stat(certPath) | ||
if err != nil { | ||
t.Errorf("Error while generating certificates to files file error - %s", err) | ||
} | ||
|
||
// Check if Key file exists | ||
_, err = os.Stat(keyPath) | ||
if err != nil { | ||
t.Errorf("Error while generating certificates to files file error - %s", err) | ||
} | ||
}) | ||
|
||
t.Run("Testing the unhappy path for cert files", func(t *testing.T) { | ||
tempDir, err := os.MkdirTemp("", "") | ||
if err != nil { | ||
t.Errorf("Error creating temporary directory: %s", err) | ||
} | ||
defer os.RemoveAll(tempDir) | ||
|
||
certPath := filepath.Join(tempDir, "doesntexist", "cert") | ||
keyPath := filepath.Join(tempDir, "key") | ||
|
||
err = GenerateCertsToFile(certPath, keyPath) | ||
if err == nil { | ||
t.Errorf("Expected error when generating a certificate with a bad path got nil") | ||
} | ||
}) | ||
|
||
t.Run("Testing the unhappy path for key files", func(t *testing.T) { | ||
tempDir, err := os.MkdirTemp("", "") | ||
if err != nil { | ||
t.Errorf("Error creating temporary directory: %s", err) | ||
} | ||
defer os.RemoveAll(tempDir) | ||
|
||
certPath := filepath.Join(tempDir, "cert") | ||
keyPath := filepath.Join(tempDir, "doesntexist", "key") | ||
|
||
err = GenerateCertsToFile(certPath, keyPath) | ||
if err == nil { | ||
t.Errorf("Expected error when generating a key with a bad path got nil") | ||
} | ||
}) | ||
|
||
t.Run("Testing the unhappy path for insufficient permissions", func(t *testing.T) { | ||
dir, err := os.MkdirTemp("", "permission-test") | ||
if err != nil { | ||
t.Errorf("Error creating temp directory - %s", err) | ||
} | ||
defer os.RemoveAll(dir) | ||
|
||
// Change permissions of the temp directory so that it can't be written to | ||
err = os.Chmod(dir, 0444) | ||
if err != nil { | ||
t.Errorf("Error changing permissions of temp directory - %s", err) | ||
} | ||
|
||
certPath := filepath.Join(dir, "cert") | ||
keyPath := filepath.Join(dir, "key") | ||
|
||
err = GenerateCertsToFile(certPath, keyPath) | ||
if err == nil { | ||
t.Errorf("Expected error when generating certificate with insufficient permissions, got nil") | ||
} | ||
}) | ||
} | ||
|
||
func TestGenerateCertsToTempFile(t *testing.T) { | ||
t.Run("Test the happy path", func(t *testing.T) { | ||
certFile, keyFile, err := GenerateCertsToTempFile("/tmp") | ||
if err != nil { | ||
t.Errorf("Error while generating certificates to temp files - %s", err) | ||
} | ||
|
||
// Check if Cert file exists | ||
_, err = os.Stat(certFile) | ||
if err != nil { | ||
t.Errorf("Error while generating certificates to temp files file error - %s", err) | ||
} | ||
_ = os.Remove(certFile) | ||
|
||
// Check if Key file exists | ||
_, err = os.Stat(keyFile) | ||
if err != nil { | ||
t.Errorf("Error while generating certificates to temp files file error - %s", err) | ||
} | ||
_ = os.Remove(keyFile) | ||
}) | ||
|
||
t.Run("Testing the unhappy path when creating cert temp file", func(t *testing.T) { | ||
_, _, err := GenerateCertsToTempFile("/doesnotexist") | ||
if err == nil { | ||
t.Errorf("Expected error when generating a certificate with a bad directory path got nil") | ||
} | ||
}) | ||
|
||
t.Run("Testing the unhappy path for insufficient permissions when creating temp file", func(t *testing.T) { | ||
dir, err := os.MkdirTemp("", "permission-test") | ||
if err != nil { | ||
t.Errorf("Error creating temp directory - %s", err) | ||
} | ||
defer os.RemoveAll(dir) | ||
|
||
// Change permissions of the temp directory so that it can't be written to | ||
err = os.Chmod(dir, 0444) | ||
if err != nil { | ||
t.Errorf("Error changing permissions of temp directory - %s", err) | ||
} | ||
|
||
_, _, err = GenerateCertsToTempFile(dir) | ||
if err == nil { | ||
t.Errorf("Expected error when generating a key with a bad directory path got nil") | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package testcerts | ||
|
||
import ( | ||
"errors" | ||
"net" | ||
) | ||
|
||
var ( | ||
// ErrEmptyConfig is returned when a KeyPairConfig is empty. | ||
ErrEmptyConfig = errors.New("empty KeyPairConfig") | ||
|
||
// ErrInvalidIP is returned when an IP address is invalid. | ||
ErrInvalidIP = errors.New("invalid IP address") | ||
) | ||
|
||
// KeyPairConfig is a configuration for generating an X.509 key pair. | ||
type KeyPairConfig struct { | ||
// Domains is a list of domains to include in the certificate as Subject | ||
// Alternative Names. | ||
Domains []string | ||
|
||
// IPAddresses is a list of IP addresses to include in the certificate | ||
// as Subject Alternative Names. | ||
IPAddresses []string | ||
} | ||
|
||
// Validate validates the KeyPairConfig ensuring that it is not empty and that | ||
// provided values are valid. | ||
func (c *KeyPairConfig) Validate() error { | ||
// Check if the config is empty. | ||
if len(c.Domains) == 0 && len(c.IPAddresses) == 0 { | ||
return ErrEmptyConfig | ||
} | ||
|
||
// Validate IP addresses. | ||
for _, ip := range c.IPAddresses { | ||
if net.ParseIP(ip) == nil { | ||
return ErrInvalidIP | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// IPAddresses returns a list of IP addresses in Net.IP format. | ||
func (c *KeyPairConfig) IPNetAddresses() ([]net.IP, error) { | ||
var ips []net.IP | ||
for _, ip := range c.IPAddresses { | ||
parsed := net.ParseIP(ip) | ||
if parsed == nil { | ||
return nil, ErrInvalidIP | ||
} | ||
ips = append(ips, parsed) | ||
} | ||
return ips, nil | ||
} |
Oops, something went wrong.