vault/helper/testhelpers/mssql/mssqlhelper.go
Steven Clark c3d5c1b3ec
Update to Go 1.23.3 (#28920)
* Update to Go 1.23.3

 - Update to latest major version of Go 1.23.3 from 1.22.8.
 - Update github.com/sasha-s/go-deadlock to address deadlock timer
   issue we were seeing.
 - Fix one of our tests to only reset the member variable we change
   instead of the entire Opts parameter to avoid a data race during
   testing.

* Add workaround for MSSQL TLS certificate container issue
2024-11-15 13:32:09 -05:00

129 lines
3.6 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package mssqlhelper
import (
"context"
"database/sql"
"fmt"
"net/url"
"os"
"runtime"
"strings"
"testing"
"time"
"github.com/hashicorp/vault/helper/testhelpers"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/sdk/helper/docker"
)
const mssqlPassword = "yourStrong(!)Password"
// This constant is used in retrying the mssql container restart, since
// intermittently the container starts but mssql within the container
// is unreachable.
const numRetries = 3
func PrepareMSSQLTestContainer(t *testing.T) (cleanup func(), retURL string) {
if strings.Contains(runtime.GOARCH, "arm") {
t.Skip("Skipping, as this image is not supported on ARM architectures")
}
if os.Getenv("MSSQL_URL") != "" {
return func() {}, os.Getenv("MSSQL_URL")
}
logger := corehelpers.NewTestLogger(t)
// Workaround for https://github.com/microsoft/mssql-docker/issues/895 and us temporary seeing
// tls: failed to parse certificate from server: x509: negative serial number in test case failures.
containerfile := `
FROM mcr.microsoft.com/mssql/server:2022-latest
USER root
ENV MSDIR=/var/opt/mssql
RUN mkdir -p $MSDIR \
&& openssl req -x509 -nodes -newkey rsa:2048 -subj '/CN=mssql' -addext "subjectAltName = DNS:mssql" -keyout $MSDIR/mssql.key -out $MSDIR/mssql.pem -days 1 \
&& chmod 400 $MSDIR/mssql.key \
&& chmod 400 $MSDIR/mssql.pem \
&& chown -R mssql $MSDIR
RUN echo "[network]" > $MSDIR/mssql.conf \
&& echo "tlscert = $MSDIR/mssql.pem" >> $MSDIR/mssql.conf \
&& echo "tlskey = $MSDIR/mssql.key" >> $MSDIR/mssql.conf \
&& echo "tlsprotocols = 1.2" >> $MSDIR/mssql.conf \
&& echo "forceencryption = 1" >> $MSDIR/mssql.conf
USER mssql
`
bCtx := docker.NewBuildContext()
imageName := "mssql-workaround-895"
imageTag := "latest"
runner, err := docker.NewServiceRunner(docker.RunOptions{
ContainerName: "sqlserver",
ImageRepo: imageName,
ImageTag: imageTag,
Env: []string{"ACCEPT_EULA=Y", "SA_PASSWORD=" + mssqlPassword},
Ports: []string{"1433/tcp"},
LogConsumer: func(s string) {
logger.Info(s)
},
})
if err != nil {
t.Fatalf("Could not provision docker service runner: %s", err)
}
// Sometimes we see timeouts and issues pulling the zlint code from GitHub
testhelpers.RetryUntil(t, 30*time.Second, func() error {
output, err := runner.BuildImage(context.Background(), containerfile, bCtx,
docker.BuildRemove(true),
docker.BuildForceRemove(true),
docker.BuildPullParent(true),
docker.BuildTags([]string{imageName + ":" + imageTag}))
if err != nil {
return fmt.Errorf("could not build new mssql image: %w", err)
}
t.Logf("Image build output: %v", string(output))
return nil
})
for i := 0; i < numRetries; i++ {
var svc *docker.Service
svc, err = runner.StartService(context.Background(), connectMSSQL)
if err == nil {
return svc.Cleanup, svc.Config.URL().String()
}
logger.Error("failed starting service", "error", err.Error())
}
t.Fatalf("Could not start docker MSSQL last error: %v", err)
return nil, ""
}
func connectMSSQL(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
u := url.URL{
Scheme: "sqlserver",
User: url.UserPassword("sa", mssqlPassword),
Host: fmt.Sprintf("%s:%d", host, port),
}
// Attempt to address connection flakiness within tests such as "Failed to initialize: error verifying connection ..."
u.Query().Add("Connection Timeout", "30")
db, err := sql.Open("mssql", u.String())
if err != nil {
return nil, err
}
defer db.Close()
err = db.Ping()
if err != nil {
return nil, err
}
return docker.NewServiceURL(u), nil
}