Skip to content

Commit

Permalink
Add a flag to enable external data client auth
Browse files Browse the repository at this point in the history
Signed-off-by: GitHub <noreply@github.com>
  • Loading branch information
Ernest Wong committed Jun 6, 2022
1 parent 6e71d90 commit 42a8425
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 17 deletions.
8 changes: 8 additions & 0 deletions constraint/pkg/client/drivers/local/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ func AddClientTLSKeyPair(certFile, keyFile string) Arg {
}
}

func EnableExternalDataClientAuth() Arg {
return func(d *Driver) error {
d.enableExternalDataClientAuth = true

return nil
}
}

// Externs sets the fields under `data` that Rego in ConstraintTemplates
// can access. If unset, all fields can be accessed. Only fields recognized by
// the system can be enabled.
Expand Down
15 changes: 2 additions & 13 deletions constraint/pkg/client/drivers/local/builtin.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package local

import (
"crypto/tls"
"net/http"

"github.com/open-policy-agent/frameworks/constraint/pkg/externaldata"
Expand All @@ -21,22 +20,12 @@ func externalDataBuiltin(d *Driver) func(bctx rego.BuiltinContext, regorequest *
return externaldata.HandleError(http.StatusBadRequest, err)
}

certPEM, err := d.readFile(d.clientCertFile)
clientCert, err := d.getTLSCertificate()
if err != nil {
return externaldata.HandleError(http.StatusBadRequest, err)
}

keyPEM, err := d.readFile(d.clientKeyFile)
if err != nil {
return externaldata.HandleError(http.StatusBadRequest, err)
}

clientCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
return externaldata.HandleError(http.StatusBadRequest, err)
}

externaldataResponse, statusCode, err := d.sendRequestToProvider(bctx.Context, &provider, regoReq.Keys, &clientCert)
externaldataResponse, statusCode, err := d.sendRequestToProvider(bctx.Context, &provider, regoReq.Keys, clientCert)
if err != nil {
return externaldata.HandleError(statusCode, err)
}
Expand Down
28 changes: 28 additions & 0 deletions constraint/pkg/client/drivers/local/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package local
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"fmt"
"io/fs"
Expand Down Expand Up @@ -64,6 +65,10 @@ type Driver struct {
// sendRequestToProvider allows Rego to send requests to the provider specified in external_data.
sendRequestToProvider externaldata.SendRequestToProvider

// enableExternalDataClientAuth enables the injection of a TLS certificate into an HTTP client
// that is used to communicate with providers.
enableExternalDataClientAuth bool

// fs is the filesystem to use for reading files.
fs fs.FS

Expand Down Expand Up @@ -343,6 +348,29 @@ func (d *Driver) readFile(name string) ([]byte, error) {
return ioutil.ReadAll(file)
}

func (d *Driver) getTLSCertificate() (*tls.Certificate, error) {
if !d.enableExternalDataClientAuth {
return nil, nil
}

certPEM, err := d.readFile(d.clientCertFile)
if err != nil {
return nil, err
}

keyPEM, err := d.readFile(d.clientKeyFile)
if err != nil {
return nil, err
}

clientCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
return nil, err
}

return &clientCert, nil
}

// rewriteModulePackage rewrites the module's package path to path.
func rewriteModulePackage(module *ast.Module) error {
pathParts := ast.Ref([]*ast.Term{ast.VarTerm(templatePath)})
Expand Down
5 changes: 4 additions & 1 deletion constraint/pkg/client/drivers/local/driver_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,10 @@ func TestDriver_ExternalData(t *testing.T) {
},
} {
t.Run(tt.name, func(t *testing.T) {
d, err := New(AddExternalDataProviderCache(externaldata.NewCache()))
d, err := New(
AddExternalDataProviderCache(externaldata.NewCache()),
EnableExternalDataClientAuth(),
)
if err != nil {
t.Fatal(err)
}
Expand Down
10 changes: 7 additions & 3 deletions constraint/pkg/externaldata/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,18 @@ func getClient(provider *v1alpha1.Provider, clientCert *tls.Certificate) (*http.
client := &http.Client{
Timeout: time.Duration(provider.Spec.Timeout) * time.Second,
}

tlsConfig := &tls.Config{
// present our client cert to the server
// in case provider wants to verify it
Certificates: []tls.Certificate{*clientCert},
//nolint:gosec
InsecureSkipVerify: provider.Spec.InsecureTLSSkipVerify,
}

// present our client cert to the server
// in case provider wants to verify it
if clientCert != nil {
tlsConfig.Certificates = []tls.Certificate{*clientCert}
}

if u.Scheme == HTTPSScheme && !provider.Spec.InsecureTLSSkipVerify {
// if the provider presents its own CA bundle,
// we will use it to verify the server's certificate
Expand Down

0 comments on commit 42a8425

Please sign in to comment.