Skip to content

Commit

Permalink
Add load certificate test and support non-standard Go versions in make (
Browse files Browse the repository at this point in the history
  • Loading branch information
thom-at-redhat authored Apr 2, 2024
1 parent 5bc3119 commit 97685d2
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 29 deletions.
22 changes: 12 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ else
DEBUGFLAGS=
endif

GO ?= go

receptor: $(shell find pkg -type f -name '*.go') ./cmd/receptor-cl/receptor.go
CGO_ENABLED=0 GOFLAGS="-buildvcs=false" go build -o receptor $(DEBUGFLAGS) -ldflags "-X 'github.com/ansible/receptor/internal/version.Version=$(VERSION)'" $(TAGPARAM) ./cmd/receptor-cl
CGO_ENABLED=0 GOFLAGS="-buildvcs=false" $(GO) build -o receptor $(DEBUGFLAGS) -ldflags "-X 'github.com/ansible/receptor/internal/version.Version=$(VERSION)'" $(TAGPARAM) ./cmd/receptor-cl

clean:
@rm -fv .container-flag*
Expand Down Expand Up @@ -90,7 +92,7 @@ receptorctl-lint: receptorctl/.VERSION
@cd receptorctl && tox -e lint

format:
@find cmd/ pkg/ -type f -name '*.go' -exec go fmt {} \;
@find cmd/ pkg/ -type f -name '*.go' -exec $(GO) fmt {} \;

fmt: format

Expand All @@ -99,17 +101,17 @@ pre-commit:

build-all:
@echo "Running Go builds..." && \
GOOS=windows go build -o receptor.exe ./cmd/receptor-cl && \
GOOS=darwin go build -o receptor.app ./cmd/receptor-cl && \
go build example/*.go && \
go build -o receptor --tags no_backends,no_services,no_tls_config ./cmd/receptor-cl && \
go build -o receptor ./cmd/receptor-cl
GOOS=windows $(GO) build -o receptor.exe ./cmd/receptor-cl && \
GOOS=darwin $(GO) build -o receptor.app ./cmd/receptor-cl && \
$(GO) build example/*.go && \
$(GO) build -o receptor --tags no_backends,no_services,no_tls_config ./cmd/receptor-cl && \
$(GO) build -o receptor ./cmd/receptor-cl

DIST := receptor_$(shell echo '$(VERSION)' | sed 's/^v//')_$(GOOS)_$(GOARCH)
build-package:
@echo "Building and packaging binary for $(GOOS)/$(GOARCH) as dist/$(DIST).tar.gz" && \
mkdir -p dist/$(DIST) && \
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 go build -o dist/$(DIST)/$(BINNAME) $(DEBUGFLAGS) -ldflags "-X 'github.com/ansible/receptor/internal/version.Version=$(VERSION)'" $(TAGPARAM) ./cmd/receptor-cl && \
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 $(GO) build -o dist/$(DIST)/$(BINNAME) $(DEBUGFLAGS) -ldflags "-X 'github.com/ansible/receptor/internal/version.Version=$(VERSION)'" $(TAGPARAM) ./cmd/receptor-cl && \
tar -C dist/$(DIST) -zcf dist/$(DIST).tar.gz $(BINNAME) && \
cd dist/ && sha256sum $(DIST).tar.gz >> checksums.txt

Expand All @@ -124,7 +126,7 @@ BLOCKLIST='/tests/|mock_|example'
COVERAGE_FILE='coverage.txt'

coverage: build-all
PATH="${PWD}:${PATH}" go test $$(go list ./... | grep -vE $(BLOCKLIST)) \
PATH="${PWD}:${PATH}" $(GO) test $$($(GO) list ./... | grep -vE $(BLOCKLIST)) \
$(TESTCMD) \
-count=1 \
-cover \
Expand All @@ -135,7 +137,7 @@ coverage: build-all

test: receptor
PATH="${PWD}:${PATH}" \
go test ./... $(TESTCMD) -count=1 -race -timeout 5m
$(GO) test ./... $(TESTCMD) -count=1 -race -timeout 5m

receptorctl-test: receptorctl/.VERSION
@cd receptorctl && tox -e py3
Expand Down
24 changes: 17 additions & 7 deletions pkg/certificates/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ import (
"github.com/ansible/receptor/pkg/utils"
)

type Oser interface {
ReadFile(name string) ([]byte, error)
}

type OsWrapper struct{}

func (ow *OsWrapper) ReadFile(name string) ([]byte, error) {
return os.ReadFile(name)
}

type Rsaer interface {
GenerateKey(random io.Reader, bits int) (*rsa.PrivateKey, error)
}
Expand Down Expand Up @@ -48,8 +58,8 @@ type CertOptions struct {
}

// LoadFromPEMFile loads certificate data from a PEM file.
func LoadFromPEMFile(filename string) ([]interface{}, error) {
content, err := os.ReadFile(filename)
func LoadFromPEMFile(filename string, osWrapper Oser) ([]interface{}, error) {
content, err := Oser.ReadFile(osWrapper, filename)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -178,8 +188,8 @@ func SaveToPEMFile(filename string, data []interface{}) error {
}

// LoadCertificate loads a single certificate from a file.
func LoadCertificate(filename string) (*x509.Certificate, error) {
data, err := LoadFromPEMFile(filename)
func LoadCertificate(filename string, osWrapper Oser) (*x509.Certificate, error) {
data, err := LoadFromPEMFile(filename, osWrapper)
if err != nil {
return nil, err
}
Expand All @@ -196,7 +206,7 @@ func LoadCertificate(filename string) (*x509.Certificate, error) {

// LoadRequest loads a single certificate request from a file.
func LoadRequest(filename string) (*x509.CertificateRequest, error) {
data, err := LoadFromPEMFile(filename)
data, err := LoadFromPEMFile(filename, &OsWrapper{})
if err != nil {
return nil, err
}
Expand All @@ -213,7 +223,7 @@ func LoadRequest(filename string) (*x509.CertificateRequest, error) {

// LoadPrivateKey loads a single RSA private key from a file.
func LoadPrivateKey(filename string) (*rsa.PrivateKey, error) {
data, err := LoadFromPEMFile(filename)
data, err := LoadFromPEMFile(filename, &OsWrapper{})
if err != nil {
return nil, err
}
Expand All @@ -230,7 +240,7 @@ func LoadPrivateKey(filename string) (*rsa.PrivateKey, error) {

// LoadPublicKey loads a single RSA public key from a file.
func LoadPublicKey(filename string) (*rsa.PublicKey, error) {
data, err := LoadFromPEMFile(filename)
data, err := LoadFromPEMFile(filename, &OsWrapper{})
if err != nil {
return nil, err
}
Expand Down
182 changes: 173 additions & 9 deletions pkg/certificates/ca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,27 @@ import (
"go.uber.org/mock/gomock"
)

func TestCreateCAValid(t *testing.T) {
type args struct {
opts *certificates.CertOptions
func setupGoodCertificate() (*x509.Certificate, error) {
goodPEMData := setupGoodCertificatePEMData()
goodCertificateBlock, rest := pem.Decode(goodPEMData)
if len(rest) != 0 {
return &x509.Certificate{}, fmt.Errorf("Excess PEM Data: %v", rest)
}

if goodCertificateBlock.Type != "CERTIFICATE" {
return &x509.Certificate{}, fmt.Errorf("PEM Block is not a certificate: %v", goodCertificateBlock.Type)
}

goodCertificate, err := x509.ParseCertificate(goodCertificateBlock.Bytes)
if err != nil {
return &x509.Certificate{}, err
}
goodCaBlock, _ := pem.Decode([]byte(`
-----BEGIN CERTIFICATE-----

return goodCertificate, nil
}

func setupGoodCertificatePEMData() []byte {
return []byte(`-----BEGIN CERTIFICATE-----
MIIFVTCCAz2gAwIBAgIEYdeDaTANBgkqhkiG9w0BAQsFADA7MTkwNwYDVQQDEzBB
bnNpYmxlIEF1dG9tYXRpb24gQ29udHJvbGxlciBOb2RlcyBNZXNoIFJPT1QgQ0Ew
HhcNMjIwMTA3MDAwMzUxWhcNMzIwMTA3MDAwMzUxWjA7MTkwNwYDVQQDEzBBbnNp
Expand Down Expand Up @@ -56,12 +71,21 @@ rKshMt4IOKQf1ScE+EJe1njpREHV+fa+kYvQB6cRuxW9a8sOSeQNaSL73Zv54elZ
xffYhMv6yXvVxVnJHEsG3kM/CsvsU364BBd9kDcZbHpjNcDHMu+XxECJjD2atVtu
FdaOLykGKfMCYVBP+xs97IJO8En/5N9QQwc+N4cfCg9/BWoZKHPbRx/V+57VEj0m
69EpJXbL15ZQLCPsaIcqJqpK23VyJKc8fA==
-----END CERTIFICATE-----
`))
-----END CERTIFICATE-----`)
}

goodCaCertificate, err := x509.ParseCertificate(goodCaBlock.Bytes)
func TestCreateCAValid(t *testing.T) {
type args struct {
opts *certificates.CertOptions
}
goodCaCertificate, err := setupGoodCertificate()
if err != nil {
t.Errorf("Error parsing certificate: %v", err)
t.Errorf("Error setting up certificate: %v", err)
}

goodCaCertificate.ExtKeyUsage = []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
}

goodCaTimeAfterString := "2032-01-07T00:03:51Z"
Expand Down Expand Up @@ -671,3 +695,143 @@ func TestGetReqNamesNegative(t *testing.T) {
})
}
}

func TestLoadCertificate(t *testing.T) {
type args struct {
filename string
}

goodCertificate, err := setupGoodCertificate()
if err != nil {
t.Fatal(err)
}

positiveTestFilename := "positive_test_filename"
tests := []struct {
name string
args args
want *x509.Certificate
wantErr bool
}{
{
name: "Positive test",
args: args{
filename: positiveTestFilename,
},
want: goodCertificate,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

o := mock_certificates.NewMockOser(ctrl)

o.
EXPECT().
ReadFile(gomock.Eq(positiveTestFilename)).
Return(setupGoodCertificatePEMData(), nil).
Times(1)
got, err := certificates.LoadCertificate(tt.args.filename, o)
if (err != nil) != tt.wantErr {
t.Errorf("LoadCertificate() error = %v, wantErr %v", err, tt.wantErr)

return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("LoadCertificate() = %v, want %v", got, tt.want)
}
})
}
}

func TestLoadCertificatesNegative(t *testing.T) {
type args struct {
filename string
}

_, goodCertificateRequest, err := setupGoodCertRequest()
if err != nil {
t.Fatal(err)
}

goodCertificateRequest.Extensions = []pkix.Extension{
{
Id: utils.OIDSubjectAltName,
Critical: true,
Value: nil,
},
}

negativeMultipleItemTest := "negative_multiple_item_test"

multipleCertificates := setupGoodCertificatePEMData()
multipleCertificates = append(multipleCertificates, multipleCertificates[0])

negativeNoCertificateTest := "negative_no_certificate_test"
noCertificates := []byte{
0, 0, 0, 0,
}

tests := []struct {
name string
args args
want *x509.Certificate
wantErr bool
}{
{
name: "Negative multiple item test",
args: args{
filename: negativeMultipleItemTest,
},
want: nil,
wantErr: true,
},
{
name: "Negative no certificate test",
args: args{
filename: negativeNoCertificateTest,
},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

o := mock_certificates.NewMockOser(ctrl)

switch tt.args.filename {
case negativeMultipleItemTest:
o.
EXPECT().
ReadFile(gomock.Eq(negativeMultipleItemTest)).
Return(multipleCertificates, nil).
Times(1)

case negativeNoCertificateTest:
o.
EXPECT().
ReadFile(gomock.Eq(negativeNoCertificateTest)).
Return(noCertificates, nil).
Times(1)

default:
t.Errorf("Unexpected filename: %s", tt.args.filename)
}
got, err := certificates.LoadCertificate(tt.args.filename, o)
if (err != nil) != tt.wantErr {
t.Errorf("LoadCertificate() error = %v, wantErr %v", err, tt.wantErr)

return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetReqNames() = %v, want %v", got, tt.want)
}
})
}
}
4 changes: 2 additions & 2 deletions pkg/certificates/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func MakeReq(opts *CertOptions, keyIn, keyOut, reqOut string) error {
var req *x509.CertificateRequest
var key *rsa.PrivateKey
if keyIn != "" {
data, err := LoadFromPEMFile(keyIn)
data, err := LoadFromPEMFile(keyIn, &OsWrapper{})
if err != nil {
return err
}
Expand Down Expand Up @@ -154,7 +154,7 @@ func (mr makeReq) Run() error {
func SignReq(opts *CertOptions, caCrtPath, caKeyPath, reqPath, certOut string, verify bool) error {
ca := &CA{}
var err error
ca.Certificate, err = LoadCertificate(caCrtPath)
ca.Certificate, err = LoadCertificate(caCrtPath, &OsWrapper{})
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 97685d2

Please sign in to comment.