mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-16 16:21:11 +01:00
* Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License. Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUS-1.1 * Fix test that expected exact offset on hcl file --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Sarah Thompson <sthompson@hashicorp.com> Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com>
193 lines
5.0 KiB
Go
193 lines
5.0 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package pkiext
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/vault/builtin/logical/pki"
|
|
"github.com/hashicorp/vault/sdk/helper/docker"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var (
|
|
zRunner *docker.Runner
|
|
buildZLintOnce sync.Once
|
|
)
|
|
|
|
func buildZLintContainer(t *testing.T) {
|
|
containerfile := `
|
|
FROM docker.mirror.hashicorp.services/library/golang:latest
|
|
|
|
RUN go install github.com/zmap/zlint/v3/cmd/zlint@latest
|
|
`
|
|
|
|
bCtx := docker.NewBuildContext()
|
|
|
|
imageName := "vault_pki_zlint_validator"
|
|
imageTag := "latest"
|
|
|
|
var err error
|
|
zRunner, err = docker.NewServiceRunner(docker.RunOptions{
|
|
ImageRepo: imageName,
|
|
ImageTag: imageTag,
|
|
ContainerName: "pki_zlint",
|
|
// We want to run sleep in the background so we're not stuck waiting
|
|
// for the default golang container's shell to prompt for input.
|
|
Entrypoint: []string{"sleep", "45"},
|
|
LogConsumer: func(s string) {
|
|
if t.Failed() {
|
|
t.Logf("container logs: %s", s)
|
|
}
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Could not provision docker service runner: %s", err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
output, err := zRunner.BuildImage(ctx, containerfile, bCtx,
|
|
docker.BuildRemove(true), docker.BuildForceRemove(true),
|
|
docker.BuildPullParent(true),
|
|
docker.BuildTags([]string{imageName + ":" + imageTag}))
|
|
if err != nil {
|
|
t.Fatalf("Could not build new image: %v", err)
|
|
}
|
|
|
|
t.Logf("Image build output: %v", string(output))
|
|
}
|
|
|
|
func RunZLintContainer(t *testing.T, certificate string) []byte {
|
|
buildZLintOnce.Do(func() {
|
|
buildZLintContainer(t)
|
|
})
|
|
|
|
ctx := context.Background()
|
|
// We don't actually care about the address, we just want to start the
|
|
// container so we can run commands in it. We'd ideally like to skip this
|
|
// step and only build a new image, but the zlint output would be
|
|
// intermingled with container build stages, so its not that useful.
|
|
result, err := zRunner.Start(ctx, true, false)
|
|
if err != nil {
|
|
t.Fatalf("Could not start golang container for zlint: %s", err)
|
|
}
|
|
|
|
// Copy the cert into the newly running container.
|
|
certCtx := docker.NewBuildContext()
|
|
certCtx["cert.pem"] = docker.PathContentsFromBytes([]byte(certificate))
|
|
if err := zRunner.CopyTo(result.Container.ID, "/go/", certCtx); err != nil {
|
|
t.Fatalf("Could not copy certificate into container: %v", err)
|
|
}
|
|
|
|
// Run the zlint command and save the output.
|
|
cmd := []string{"/go/bin/zlint", "/go/cert.pem"}
|
|
stdout, stderr, retcode, err := zRunner.RunCmdWithOutput(ctx, result.Container.ID, cmd)
|
|
if err != nil {
|
|
t.Fatalf("Could not run command in container: %v", err)
|
|
}
|
|
|
|
if len(stderr) != 0 {
|
|
t.Logf("Got stderr from command:\n%v\n", string(stderr))
|
|
}
|
|
|
|
if retcode != 0 {
|
|
t.Logf("Got stdout from command:\n%v\n", string(stdout))
|
|
t.Fatalf("Got unexpected non-zero retcode from zlint: %v\n", retcode)
|
|
}
|
|
|
|
// Clean up after ourselves.
|
|
if err := zRunner.Stop(context.Background(), result.Container.ID); err != nil {
|
|
t.Fatalf("failed to stop container: %v", err)
|
|
}
|
|
|
|
return stdout
|
|
}
|
|
|
|
func RunZLintRootTest(t *testing.T, keyType string, keyBits int, usePSS bool, ignored []string) {
|
|
b, s := pki.CreateBackendWithStorage(t)
|
|
|
|
resp, err := pki.CBWrite(b, s, "root/generate/internal", map[string]interface{}{
|
|
"common_name": "Root X1",
|
|
"country": "US",
|
|
"organization": "Dadgarcorp",
|
|
"ou": "QA",
|
|
"key_type": keyType,
|
|
"key_bits": keyBits,
|
|
"use_pss": usePSS,
|
|
})
|
|
require.NoError(t, err)
|
|
rootCert := resp.Data["certificate"].(string)
|
|
|
|
var parsed map[string]interface{}
|
|
output := RunZLintContainer(t, rootCert)
|
|
|
|
if err := json.Unmarshal(output, &parsed); err != nil {
|
|
t.Fatalf("failed to parse zlint output as JSON: %v\nOutput:\n%v\n\n", err, string(output))
|
|
}
|
|
|
|
for key, rawValue := range parsed {
|
|
value := rawValue.(map[string]interface{})
|
|
result, ok := value["result"]
|
|
if !ok || result == "NA" {
|
|
continue
|
|
}
|
|
|
|
if result == "error" {
|
|
skip := false
|
|
for _, allowedFailures := range ignored {
|
|
if allowedFailures == key {
|
|
skip = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !skip {
|
|
t.Fatalf("got unexpected error from test %v: %v", key, value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func Test_ZLintRSA2048(t *testing.T) {
|
|
t.Parallel()
|
|
RunZLintRootTest(t, "rsa", 2048, false, nil)
|
|
}
|
|
|
|
func Test_ZLintRSA2048PSS(t *testing.T) {
|
|
t.Parallel()
|
|
RunZLintRootTest(t, "rsa", 2048, true, nil)
|
|
}
|
|
|
|
func Test_ZLintRSA3072(t *testing.T) {
|
|
t.Parallel()
|
|
RunZLintRootTest(t, "rsa", 3072, false, nil)
|
|
}
|
|
|
|
func Test_ZLintRSA3072PSS(t *testing.T) {
|
|
t.Parallel()
|
|
RunZLintRootTest(t, "rsa", 3072, true, nil)
|
|
}
|
|
|
|
func Test_ZLintECDSA256(t *testing.T) {
|
|
t.Parallel()
|
|
RunZLintRootTest(t, "ec", 256, false, nil)
|
|
}
|
|
|
|
func Test_ZLintECDSA384(t *testing.T) {
|
|
t.Parallel()
|
|
RunZLintRootTest(t, "ec", 384, false, nil)
|
|
}
|
|
|
|
func Test_ZLintECDSA521(t *testing.T) {
|
|
t.Parallel()
|
|
// Mozilla doesn't allow P-521 ECDSA keys.
|
|
RunZLintRootTest(t, "ec", 521, false, []string{
|
|
"e_mp_ecdsa_pub_key_encoding_correct",
|
|
"e_mp_ecdsa_signature_encoding_correct",
|
|
})
|
|
}
|