Compare commits
4 Commits
0bf26d2019
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e77a67a3de | |||
| d815b12719 | |||
| 7660cc57fd | |||
| 25526ac993 |
19
README.md
19
README.md
@@ -8,7 +8,7 @@ I had some trouble during TLS communication between both of my gRPC server and c
|
||||
## TODO:
|
||||
- [ ] Create intermediate authority to sign certificates on behalf CA to add more security. If intermediate is hacked then you can revoke from CA and generate new intermediates keeping CA isolated from beeing hacked.
|
||||
|
||||
- [ ] Complete tests
|
||||
- ~~[x] Complete tests~~
|
||||
|
||||
## Configuration
|
||||
If you are on `dev` environment, like I've been doing, you must create `.env` file similar as `.env.example` in this repo:
|
||||
@@ -59,6 +59,23 @@ Then you can just run
|
||||
go run main.go
|
||||
```
|
||||
|
||||
## tests
|
||||
Just simply run make command and watch coverage results on `cover.html` within `coverage`
|
||||
```shell
|
||||
make test-coverage
|
||||
rm -rf coverage
|
||||
mkdir coverage
|
||||
go test -v -coverprofile coverage/cover.out ./...
|
||||
=== RUN TestCredentialsFromKeyWithPasswd
|
||||
--- PASS: TestCredentialsFromKeyWithPasswd (0.37s)
|
||||
=== RUN TestCredentialsFromKeyWithPasswdError
|
||||
--- PASS: TestCredentialsFromKeyWithPasswdError (0.46s)
|
||||
PASS
|
||||
coverage: 90.9% of statements
|
||||
ok gitea.urkob.com/urko/go-grpc-certificate/pkg/credentials 0.839s coverage: 90.9% of statements
|
||||
go tool cover -html coverage/cover.out -o coverage/cover.html
|
||||
```
|
||||
|
||||
## goreportcard
|
||||
```bash
|
||||
make goreportcard
|
||||
|
||||
51
cmd/main.go
51
cmd/main.go
@@ -27,9 +27,9 @@ var envConfig struct {
|
||||
|
||||
var writer pkgio.WriterIface
|
||||
|
||||
func intEnvConfig(isProd bool) {
|
||||
if !isProd {
|
||||
err := godotenv.Load(util.RootDir() + "/.env")
|
||||
func intEnvConfig(envFilePath string) {
|
||||
if envFilePath != "" {
|
||||
err := godotenv.Load(envFilePath)
|
||||
if err != nil {
|
||||
log.Fatalf("environment variable ENV is empty and an error occurred while loading the .env file: %s\n", err)
|
||||
}
|
||||
@@ -87,32 +87,59 @@ var rootCmd = &cobra.Command{
|
||||
log.Fatalf("rootCA.WithClientCert: %s", err)
|
||||
}
|
||||
|
||||
exportPem("root-ca.pem", rootCA.PEM())
|
||||
exportPem("root-key.pem", rootCA.Key())
|
||||
outputPath, err := exportPem("root-ca.pem", rootCA.PEM())
|
||||
if err != nil {
|
||||
log.Fatalf("exportPem: %s\n", err)
|
||||
}
|
||||
log.Printf("file created successfully: %s\n", outputPath)
|
||||
|
||||
exportPem("client-cert.pem", clientCert.PEM())
|
||||
exportPem("client-key.pem", clientCert.Key())
|
||||
outputPath, err = exportPem("root-key.pem", rootCA.Key())
|
||||
if err != nil {
|
||||
log.Fatalf("exportPem: %s\n", err)
|
||||
}
|
||||
log.Printf("file created successfully: %s\n", outputPath)
|
||||
|
||||
outputPath, err = exportPem("client-cert.pem", clientCert.PEM())
|
||||
if err != nil {
|
||||
log.Fatalf("exportPem: %s\n", err)
|
||||
}
|
||||
log.Printf("file created successfully: %s\n", outputPath)
|
||||
|
||||
outputPath, err = exportPem("client-key.pem", clientCert.Key())
|
||||
if err != nil {
|
||||
log.Fatalf("exportPem: %s\n", err)
|
||||
}
|
||||
log.Printf("file created successfully: %s\n", outputPath)
|
||||
},
|
||||
}
|
||||
|
||||
func getExtKeyUsage(intKeyUsageSlice []int) []x509.ExtKeyUsage {
|
||||
extKeyUsage := make([]x509.ExtKeyUsage, len(intKeyUsageSlice))
|
||||
if intKeyUsageSlice == nil || len(intKeyUsageSlice) <= 0 {
|
||||
return []x509.ExtKeyUsage{}
|
||||
}
|
||||
|
||||
extKeyUsage := make([]x509.ExtKeyUsage, 0, len(intKeyUsageSlice))
|
||||
for _, v := range intKeyUsageSlice {
|
||||
extKeyUsage = append(extKeyUsage, x509.ExtKeyUsage(v))
|
||||
}
|
||||
return extKeyUsage
|
||||
}
|
||||
|
||||
func exportPem(filename string, data []byte) {
|
||||
func exportPem(filename string, data []byte) (string, error) {
|
||||
outputPath, err := writer.WriteFile(filename, data)
|
||||
if err != nil {
|
||||
log.Fatalf("rootCA.WithClientCert: %s", err)
|
||||
return "", fmt.Errorf("rootCA.WithClientCert: %s", err)
|
||||
}
|
||||
log.Printf("file created successfully: %s\n", outputPath)
|
||||
return outputPath, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
intEnvConfig(false)
|
||||
envFile := ""
|
||||
if os.Getenv("ENV") != "prod" {
|
||||
envFile = "./.env"
|
||||
}
|
||||
|
||||
intEnvConfig(envFile)
|
||||
cobra.OnInitialize(initConfig)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,62 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"crypto/x509"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.com/urkob/go-cert-gen/internal/io"
|
||||
)
|
||||
|
||||
func TestExecute(t *testing.T) {
|
||||
Execute()
|
||||
}
|
||||
|
||||
func Test_getExtKeyUsage(t *testing.T) {
|
||||
intKeyUsageSlice := make([]int, 0, 1)
|
||||
intKeyUsageSlice = append(intKeyUsageSlice, int(x509.ExtKeyUsageClientAuth))
|
||||
|
||||
keyUsage := getExtKeyUsage(intKeyUsageSlice)
|
||||
assert.Len(t, keyUsage, len(intKeyUsageSlice))
|
||||
assert.Equal(t, keyUsage[0], x509.ExtKeyUsageClientAuth)
|
||||
|
||||
intKeyUsageSlice = make([]int, 0)
|
||||
keyUsage = getExtKeyUsage(intKeyUsageSlice)
|
||||
assert.Len(t, keyUsage, 0)
|
||||
|
||||
keyUsage = getExtKeyUsage(nil)
|
||||
assert.Len(t, keyUsage, 0)
|
||||
}
|
||||
|
||||
var testFile = "test-file.txt"
|
||||
|
||||
func init() {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalf("os.Getwd: %s\n", err)
|
||||
}
|
||||
writer = io.NewWriter(wd)
|
||||
}
|
||||
|
||||
func Test_exportPem(t *testing.T) {
|
||||
defer func() {
|
||||
os.Remove(testFile)
|
||||
err := os.Remove(testFile)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
data := []byte("test data")
|
||||
outputPath, err := exportPem(testFile, data)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, outputPath)
|
||||
}
|
||||
|
||||
func Test_exportPemError(t *testing.T) {
|
||||
data := []byte("test data")
|
||||
outputPath, err := exportPem("", data)
|
||||
require.Error(t, err)
|
||||
require.Empty(t, outputPath)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gitlab.com/urkob/go-cert-gen/pkg/io"
|
||||
@@ -17,18 +18,19 @@ func (w writer) WriteFile(filename string, data []byte) (string, error) {
|
||||
if filename == "" {
|
||||
return "", fmt.Errorf("filename cannot be empty")
|
||||
}
|
||||
|
||||
if w.dirPath == "" {
|
||||
return "", fmt.Errorf("export directory cannot be empty")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(w.dirPath, 0o755); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Println("to write file")
|
||||
outputPath := w.dirPath + "/" + filename
|
||||
if err := os.WriteFile(outputPath, data, 0o600); err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Println("file written")
|
||||
return outputPath, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
var (
|
||||
testWriterPath = "testPath"
|
||||
testWriterPathError = "test Path, @:ººººº\\/.Ç*⁺´+"
|
||||
testFileContent = "test data"
|
||||
testFileContent = []byte("test data")
|
||||
testFileName = "test-file.txt"
|
||||
workingDir = ""
|
||||
)
|
||||
@@ -53,13 +53,13 @@ func Test_writer_WriteFile(t *testing.T) {
|
||||
}(t)
|
||||
|
||||
w := newWriter(testWriterPath)
|
||||
wgot, err := w.WriteFile(testFileName, []byte(testFileContent))
|
||||
wgot, err := w.WriteFile(testFileName, testFileContent)
|
||||
require.NoError(t, err)
|
||||
|
||||
btsReaded, err := os.ReadFile(wgot)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, btsReaded)
|
||||
require.Equal(t, string(btsReaded), testFileContent)
|
||||
require.Equal(t, string(btsReaded), string(testFileContent))
|
||||
}
|
||||
|
||||
func Test_writer_WriteFileError(t *testing.T) {
|
||||
@@ -72,39 +72,23 @@ func Test_writer_WriteFileError(t *testing.T) {
|
||||
}(t)
|
||||
|
||||
w := newWriter("")
|
||||
_, err = w.WriteFile(testFileName, []byte(testFileContent))
|
||||
_, err = w.WriteFile(testFileName, testFileContent)
|
||||
assert.Error(t, err)
|
||||
|
||||
w = newWriter(testWriterPath)
|
||||
_, err = w.WriteFile("", []byte(testFileContent))
|
||||
_, err = w.WriteFile("", testFileContent)
|
||||
require.Error(t, err)
|
||||
|
||||
go func(t *testing.T) {
|
||||
err := deleteAllDirs()
|
||||
go func(err error) {
|
||||
require.NoError(t, err)
|
||||
}(err)
|
||||
err = os.MkdirAll(testWriterPath, fs.ModeDir)
|
||||
require.NoError(t, err, "mkdir should not throw error")
|
||||
|
||||
for {
|
||||
f, err := os.Stat(testWriterPath)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no such file or directory") {
|
||||
continue
|
||||
}
|
||||
t.Errorf("os.Stat error: %s", err)
|
||||
}
|
||||
err = os.RemoveAll(testWriterPath)
|
||||
require.NotNil(t, f)
|
||||
log.Println("exists deleting dir")
|
||||
require.NoError(t, err, "should not throw error because dir exists")
|
||||
return
|
||||
}
|
||||
}(t)
|
||||
err = os.MkdirAll(testWriterPath+"/"+testFileName, fs.ModeDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = w.WriteFile(testFileName, nil)
|
||||
assert.Error(t, err)
|
||||
|
||||
w = newWriter(testWriterPathError)
|
||||
_, err = w.WriteFile(testFileContent, []byte(testFileContent))
|
||||
_, err = w.WriteFile(testFileName, testFileContent)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user