mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-26 17:11:13 +02:00
* enos(artifactory): unify dev and test scenario artifactory metadata into new module There was previously a lot of shared logic between `build_artifactory_artifact` and `build_artifactory_package` as it regards to building an artifact name. When it comes down to it, both modules are very similar and their only major difference is searching for any artifact (released or not) by either a combination of `revision`, `edition`, `version`, and `type` vs. searching for a released artifact with a combination of `version`, `edition`, and `type`. Rather than bolt on new `s390x` and `fips1403` artifact metadata to both, I factored their metadata for package names and such into a unified and shared `artifact/metadata` module that is now called by both. This was tricky as dev and test scenarios currently differ in what we pass in as the `vault_version`, but we hope to remove that difference soon. We also add metadata support for the forthcoming FIPS 140-3. This commit was tested extensively, along with other test scenarios in support for `s390x but will be useful immediately for FIPS 140-3 so I've extracted it out. Signed-off-by: Ryan Cragun <me@ryan.ec> * Fix artifactory metadata before merge The initial pass of the artifactory metadata was largely untested and extracted from a different branch. After testing, this commit fixes a few issues with the metadata module. In order to test this I also had to fix an issue where AWS secrets engine testing became a requirement but is impossible unless you exectue against a blessed AWS account that has required roles. Instead, we now make those verification opt-in via a new variable. We also make some improvements to the pki-verify-certificates script so that it works reliably against all our supported distros. We also update our dynamic configuration to use the updated versions in samples. Signed-off-by: Ryan Cragun <me@ryan.ec>
209 lines
6.3 KiB
Go
209 lines
6.3 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package generate
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
|
|
"github.com/Masterminds/semver"
|
|
"github.com/hashicorp/hcl/v2/gohcl"
|
|
"github.com/hashicorp/hcl/v2/hclwrite"
|
|
"github.com/hashicorp/vault/tools/pipeline/internal/pkg/metadata"
|
|
"github.com/hashicorp/vault/tools/pipeline/internal/pkg/releases"
|
|
slogctx "github.com/veqryn/slog-context"
|
|
)
|
|
|
|
// EnosDynamicConfigReq is a request to generate dynamic enos configuration
|
|
type EnosDynamicConfigReq struct {
|
|
VaultEdition string
|
|
VaultVersion string
|
|
EnosDir string
|
|
FileName string
|
|
Skip []string
|
|
NMinus uint
|
|
releases.VersionLister
|
|
}
|
|
|
|
// EnosDynamicConfigRes is a response from a request to generate dynamic enos configuration
|
|
type EnosDynamicConfigRes struct {
|
|
Globals *Globals `json:"globals,omitempty" hcl:"globals,block" cty:"globals"`
|
|
}
|
|
|
|
// Globals are our dynamic globals
|
|
type Globals struct {
|
|
SampleAttributes *SampleAttrs `json:"sample_attributes,omitempty" hcl:"sample_attributes" cty:"sample_attributes"`
|
|
}
|
|
|
|
// SampleAttrs are the dynamic sample attributes that we'll write as globals
|
|
type SampleAttrs struct {
|
|
AWSRegion []string `json:"aws_region,omitempty" hcl:"aws_region" cty:"aws_region"`
|
|
DistroVersionAmzn []string `json:"distro_version_amzn,omitempty" hcl:"distro_version_amzn" cty:"distro_version_amzn"`
|
|
DistroVersionLeap []string `json:"distro_version_leap,omitempty" hcl:"distro_version_leap" cty:"distro_version_leap"`
|
|
DistroVersionRhel []string `json:"distro_version_rhel,omitempty" hcl:"distro_version_rhel" cty:"distro_version_rhel"`
|
|
DistroVersionSles []string `json:"distro_version_sles,omitempty" hcl:"distro_version_sles" cty:"distro_version_sles"`
|
|
DistroVersionUbuntu []string `json:"distro_version_ubuntu,omitempty" hcl:"distro_version_ubuntu" cty:"distro_version_ubuntu"`
|
|
UpgradeInitialVersion []string `json:"upgrade_initial_version,omitempty" hcl:"upgrade_initial_version" cty:"upgrade_initial_version"`
|
|
}
|
|
|
|
// Validate validates the request parameters
|
|
func (e *EnosDynamicConfigReq) Validate(ctx context.Context) error {
|
|
if e == nil {
|
|
return errors.New("enos dynamic config req: validate: uninitialized")
|
|
}
|
|
|
|
slog.Default().DebugContext(ctx, "validating enos dynamic config request")
|
|
|
|
if e.FileName == "" {
|
|
return errors.New("no destination file name set")
|
|
}
|
|
|
|
if e.VersionLister == nil {
|
|
return errors.New("no version lister set")
|
|
}
|
|
|
|
if !slices.Contains(metadata.Editions, e.VaultEdition) {
|
|
return fmt.Errorf("unknown edition: %s", e.VaultEdition)
|
|
}
|
|
|
|
_, err := semver.NewVersion(e.VaultVersion)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid version: %s: %w", e.VaultVersion, err)
|
|
}
|
|
|
|
s, err := os.Stat(e.EnosDir)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid enos dir: %s: %w", e.EnosDir, err)
|
|
}
|
|
|
|
if !s.IsDir() {
|
|
return fmt.Errorf("invalid enos dir: %s is not a directory", e.EnosDir)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Run runs the dynamic configuration request
|
|
func (e *EnosDynamicConfigReq) Run(ctx context.Context) (*EnosDynamicConfigRes, error) {
|
|
if e == nil {
|
|
return nil, fmt.Errorf("enos-dynamic-config-req uninitialized")
|
|
}
|
|
|
|
ctx = slogctx.Append(ctx,
|
|
slog.String("vault-edition", e.VaultEdition),
|
|
slog.String("vault-version", e.VaultVersion),
|
|
slog.String("file-name", e.FileName),
|
|
slog.String("dir", e.EnosDir),
|
|
slog.Uint64("n-minnux", uint64(e.NMinus)),
|
|
"skip", e.Skip,
|
|
)
|
|
slog.Default().DebugContext(ctx, "running enos dynamic config request")
|
|
|
|
err := e.Validate(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
res := &EnosDynamicConfigRes{}
|
|
res.Globals, err = e.getGlobals(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return res, e.writeFile(ctx, res)
|
|
}
|
|
|
|
func (e *EnosDynamicConfigReq) getGlobals(ctx context.Context) (*Globals, error) {
|
|
var err error
|
|
res := &Globals{}
|
|
res.SampleAttributes, err = e.getSampleAttrs(ctx)
|
|
|
|
return res, err
|
|
}
|
|
|
|
func (e *EnosDynamicConfigReq) getSampleAttrs(ctx context.Context) (*SampleAttrs, error) {
|
|
// Create our HCL body
|
|
attrs := &SampleAttrs{
|
|
// Use the cheapest regions
|
|
AWSRegion: []string{"us-east-1", "us-west-2"},
|
|
// Current distro defaults
|
|
DistroVersionAmzn: []string{"2023"},
|
|
DistroVersionLeap: []string{"15.6"},
|
|
DistroVersionRhel: []string{"8.10", "9.5"},
|
|
DistroVersionSles: []string{"15.6"},
|
|
DistroVersionUbuntu: []string{"20.04", "24.04"},
|
|
}
|
|
|
|
// Create our initial upgrade version list. We'll find all released versions between N-3 -> Current
|
|
// version, minus any explicitly skipped versions that have been set. Since CE and Ent do not share
|
|
// the same version lineage now we'll also have to figure that in as well.
|
|
versionReq := &releases.ListVersionsReq{
|
|
VersionLister: e.VersionLister,
|
|
LicenseClass: e.VaultEdition,
|
|
UpperBound: e.VaultVersion,
|
|
NMinus: e.NMinus,
|
|
Skip: e.Skip,
|
|
}
|
|
|
|
versionRes, err := versionReq.Run(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
attrs.UpgradeInitialVersion = versionRes.Versions
|
|
|
|
return attrs, nil
|
|
}
|
|
|
|
// writeFile creates the dynamic config file and writes the dynamic data into it
|
|
func (e *EnosDynamicConfigReq) writeFile(ctx context.Context, res *EnosDynamicConfigRes) error {
|
|
select {
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
default:
|
|
}
|
|
|
|
slog.Default().DebugContext(ctx, "writing enos dynamic config request")
|
|
|
|
// Make sure our path is valid
|
|
path, err := filepath.Abs(filepath.Join(e.EnosDir, e.FileName))
|
|
if err != nil {
|
|
return fmt.Errorf("expanding path dynamic config request path: %w", err)
|
|
}
|
|
|
|
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
|
|
if err != nil {
|
|
return fmt.Errorf("opening dynamic config request destination file: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
if _, err = f.WriteString(`# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
# Code generated by pipeline generate enos-dynamic-config DO NOT EDIT.
|
|
|
|
# This file is overwritten in CI as it contains branch specific and sometimes ever-changing values.
|
|
# It's checked in here so that enos samples and scenarios can be performed, just be aware that this
|
|
# might change out from under you.
|
|
`); err != nil {
|
|
return err
|
|
}
|
|
|
|
hf := hclwrite.NewEmptyFile()
|
|
gohcl.EncodeIntoBody(res, hf.Body())
|
|
bytes := hclwrite.Format(hf.Bytes())
|
|
|
|
slog.Default().InfoContext(ctx, "writing enos dynamic config request",
|
|
"path", path,
|
|
"hcl", string(bytes),
|
|
)
|
|
_, err = f.Write(bytes)
|
|
|
|
return err
|
|
}
|