From e5cfab22c46f1be8a182861b5a3a52dad2dd8358 Mon Sep 17 00:00:00 2001 From: Lukas Zapletal Date: Tue, 19 Nov 2024 13:01:10 +0100 Subject: [PATCH] otk: add mtls into resolve ostree command --- cmd/otk/osbuild-resolve-ostree-commit/main.go | 16 +++++ .../main_test.go | 66 +++++++++++++++++-- .../test_mtls_server/http_mtls_server.go | 4 ++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/cmd/otk/osbuild-resolve-ostree-commit/main.go b/cmd/otk/osbuild-resolve-ostree-commit/main.go index 54086240b1..b2e140f63d 100644 --- a/cmd/otk/osbuild-resolve-ostree-commit/main.go +++ b/cmd/otk/osbuild-resolve-ostree-commit/main.go @@ -27,6 +27,16 @@ type Input struct { // Whether to use RHSM secrets when resolving and fetching the commit. RHSM bool `json:"rhsm,omitempty"` + + // MTLS information. Will be ignored if RHSM is set. + MTLS *struct { + CA string `json:"ca"` + ClientCert string `json:"client_cert"` + ClientKey string `json:"client_key"` + } `json:"mtls,omitempty"` + + // HTTP proxy to use when fetching the ref. + Proxy string `json:"proxy,omitempty"` } // Output contains everything needed to write a manifest that requires pulling @@ -53,6 +63,12 @@ func run(r io.Reader, w io.Writer) error { URL: inputTree.Tree.URL, Ref: inputTree.Tree.Ref, RHSM: inputTree.Tree.RHSM, + MTLS: &ostree.MTLS{ + CA: inputTree.Tree.MTLS.CA, + ClientCert: inputTree.Tree.MTLS.ClientCert, + ClientKey: inputTree.Tree.MTLS.ClientKey, + }, + Proxy: inputTree.Tree.Proxy, } var commitSpec ostree.CommitSpec diff --git a/cmd/otk/osbuild-resolve-ostree-commit/main_test.go b/cmd/otk/osbuild-resolve-ostree-commit/main_test.go index 7091329ffc..11395309f1 100644 --- a/cmd/otk/osbuild-resolve-ostree-commit/main_test.go +++ b/cmd/otk/osbuild-resolve-ostree-commit/main_test.go @@ -10,6 +10,7 @@ import ( "testing" resolver "github.com/osbuild/images/cmd/otk/osbuild-resolve-ostree-commit" + "github.com/osbuild/images/pkg/ostree/test_mtls_server" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -22,9 +23,11 @@ var commitMap = map[string]string{ "test/ref/one": "7433e1b49fb136d61dcca49ebe34e713fdbb8e29bf328fe90819628f71b86105", } +const TestCertDir = "../../../pkg/ostree/test_mtls_server" + // Create a test server that responds with the commit ID that corresponds to // the ref. -func createTestServer(refIDs map[string]string) *httptest.Server { +func createTestServer(refIDs map[string]string, mtls bool) *httptest.Server { handler := http.NewServeMux() handler.HandleFunc("/refs/heads/", func(w http.ResponseWriter, r *http.Request) { reqRef := strings.TrimPrefix(r.URL.Path, "/refs/heads/") @@ -36,14 +39,25 @@ func createTestServer(refIDs map[string]string) *httptest.Server { fmt.Fprint(w, id) }) - return httptest.NewServer(handler) + var server *httptest.Server + if mtls { + mtlss, err := test_mtls_server.NewMTLSServerInPath(handler, TestCertDir) + if err != nil { + panic(err) + } + + server = mtlss.Server + } else { + server = httptest.NewServer(handler) + } + return server } func TestResolver(t *testing.T) { require := require.New(t) assert := assert.New(t) - repoServer := createTestServer(commitMap) + repoServer := createTestServer(commitMap, false) defer repoServer.Close() url := repoServer.URL @@ -77,6 +91,50 @@ func TestResolver(t *testing.T) { } } +func TestResolverMTLS(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + + repoServer := createTestServer(commitMap, true) + defer repoServer.Close() + + url := repoServer.URL + for ref, id := range commitMap { + inputReq, err := json.Marshal(map[string]interface{}{ + "tree": map[string]interface{}{ + "url": url, + "ref": ref, + "mtls": map[string]string{ + "ca": fmt.Sprintf("%s/ca.crt", TestCertDir), + "client_cert": fmt.Sprintf("%s/client.crt", TestCertDir), + "client_key": fmt.Sprintf("%s/client.key", TestCertDir), + }, + }, + }) + require.NoError(err) + + inpBuf := bytes.NewBuffer(inputReq) + outBuf := &bytes.Buffer{} + + assert.NoError(resolver.Run(inpBuf, outBuf)) + + var output map[string]map[string]map[string]string + require.NoError(json.Unmarshal(outBuf.Bytes(), &output)) + + expOutput := map[string]map[string]map[string]string{ + "tree": { + "const": { + "url": url, + "ref": ref, + "checksum": id, + "secrets": "org.osbuild.mtls", + }, + }, + } + assert.Equal(expOutput, output) + } +} + func TestResolverByID(t *testing.T) { require := require.New(t) assert := assert.New(t) @@ -148,7 +206,7 @@ func TestResolverIDwithURL(t *testing.T) { func TestResolverErrors(t *testing.T) { - repoServer := createTestServer(commitMap) + repoServer := createTestServer(commitMap, false) defer repoServer.Close() type testCase struct { diff --git a/pkg/ostree/test_mtls_server/http_mtls_server.go b/pkg/ostree/test_mtls_server/http_mtls_server.go index 0a745734fe..3c31f40c49 100644 --- a/pkg/ostree/test_mtls_server/http_mtls_server.go +++ b/pkg/ostree/test_mtls_server/http_mtls_server.go @@ -24,6 +24,10 @@ func NewMTLSServer(handler http.Handler) (*MTLSServer, error) { return nil, err } + return NewMTLSServerInPath(handler, certsPath) +} + +func NewMTLSServerInPath(handler http.Handler, certsPath string) (*MTLSServer, error) { caPath := filepath.Join(certsPath, "ca.crt") serverKeyPath := filepath.Join(certsPath, "server.key") serverCrtPath := filepath.Join(certsPath, "server.crt")