Skip to content

Commit

Permalink
feat: adds sigstore/sigstore for kms and hashivault support.
Browse files Browse the repository at this point in the history
Signed-off-by: ianhundere <138915+ianhundere@users.noreply.github.com>
  • Loading branch information
ianhundere committed Dec 19, 2024
1 parent ae6c735 commit 90ac751
Show file tree
Hide file tree
Showing 7 changed files with 2,010 additions and 823 deletions.
13 changes: 12 additions & 1 deletion cmd/certificate_maker/certificate_maker.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ var (
intermediateKeyID string
intermediateTemplate string
intermediateCert string
kmsVaultToken string
kmsVaultAddr string

rawJSON = []byte(`{
"level": "debug",
Expand All @@ -84,7 +86,7 @@ func init() {

rootCmd.AddCommand(createCmd)

createCmd.Flags().StringVar(&kmsType, "kms-type", "", "KMS provider type (awskms, gcpkms, azurekms)")
createCmd.Flags().StringVar(&kmsType, "kms-type", "", "KMS provider type (awskms, gcpkms, azurekms, hashivault)")
createCmd.Flags().StringVar(&kmsRegion, "aws-region", "", "AWS KMS region")
createCmd.Flags().StringVar(&kmsKeyID, "kms-key-id", "", "KMS key identifier")
createCmd.Flags().StringVar(&kmsTenantID, "azure-tenant-id", "", "Azure KMS tenant ID")
Expand All @@ -100,6 +102,8 @@ func init() {
createCmd.Flags().StringVar(&intermediateKeyID, "intermediate-key-id", "", "KMS key identifier for intermediate certificate")
createCmd.Flags().StringVar(&intermediateTemplate, "intermediate-template", "pkg/certmaker/templates/intermediate-template.json", "Path to intermediate certificate template")
createCmd.Flags().StringVar(&intermediateCert, "intermediate-cert", "intermediate.pem", "Output path for intermediate certificate")
createCmd.Flags().StringVar(&kmsVaultToken, "vault-token", "", "HashiVault token")
createCmd.Flags().StringVar(&kmsVaultAddr, "vault-address", "", "HashiVault server address")
}

func runCreate(_ *cobra.Command, _ []string) error {
Expand Down Expand Up @@ -133,6 +137,13 @@ func runCreate(_ *cobra.Command, _ []string) error {
if tenantID := getConfigValue(kmsTenantID, "AZURE_TENANT_ID"); tenantID != "" {
config.Options["tenant-id"] = tenantID
}
case "hashivault":
if token := getConfigValue(kmsVaultToken, "VAULT_TOKEN"); token != "" {
config.Options["token"] = token
}
if addr := getConfigValue(kmsVaultAddr, "VAULT_ADDR"); addr != "" {
config.Options["address"] = addr
}
}

km, err := certmaker.InitKMS(ctx, config)
Expand Down
108 changes: 77 additions & 31 deletions cmd/certificate_maker/certificate_maker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ package main
import (
"os"
"path/filepath"
"strings"
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGetConfigValue(t *testing.T) {
Expand Down Expand Up @@ -83,25 +84,38 @@ func TestGetConfigValue(t *testing.T) {
defer os.Unsetenv(tt.envVar)
}
got := getConfigValue(tt.flagValue, tt.envVar)
if got != tt.want {
t.Errorf("got %v, want %v", got, tt.want)
}
assert.Equal(t, tt.want, got)
})
}
}

func TestInitLogger(t *testing.T) {
logger := initLogger()
if logger == nil {
t.Errorf("logger is nil")
}
require.NotNil(t, logger)
}

func TestInitLoggerWithDebug(t *testing.T) {
os.Setenv("DEBUG", "true")
defer os.Unsetenv("DEBUG")
logger := initLogger()
require.NotNil(t, logger)
}

func TestInitLoggerWithInvalidLevel(t *testing.T) {
os.Setenv("DEBUG", "invalid")
defer os.Unsetenv("DEBUG")

logger := initLogger()
require.NotNil(t, logger)

os.Setenv("DEBUG", "")
logger = initLogger()
require.NotNil(t, logger)
}

func TestRunCreate(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "cert-test-*")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
require.NoError(t, err)
defer os.RemoveAll(tmpDir)

rootTemplate := `{
Expand Down Expand Up @@ -136,13 +150,9 @@ func TestRunCreate(t *testing.T) {
rootTmplPath := filepath.Join(tmpDir, "root-template.json")
leafTmplPath := filepath.Join(tmpDir, "leaf-template.json")
err = os.WriteFile(rootTmplPath, []byte(rootTemplate), 0600)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
require.NoError(t, err)
err = os.WriteFile(leafTmplPath, []byte(leafTemplate), 0600)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
require.NoError(t, err)

tests := []struct {
name string
Expand Down Expand Up @@ -181,26 +191,26 @@ func TestRunCreate(t *testing.T) {
args: []string{
"--kms-type", "awskms",
"--aws-region", "us-west-2",
"--root-key-id", "arn:aws:kms:us-west-2:123456789012:key/test-key",
"--leaf-key-id", "arn:aws:kms:us-west-2:123456789012:key/test-key",
"--root-key-id", "alias/test-key",
"--leaf-key-id", "alias/test-key",
"--root-template", "nonexistent.json",
"--leaf-template", leafTmplPath,
},
wantError: true,
errMsg: "template not found",
errMsg: "root template error: template not found at nonexistent.json",
},
{
name: "missing leaf template",
args: []string{
"--kms-type", "awskms",
"--aws-region", "us-west-2",
"--root-key-id", "arn:aws:kms:us-west-2:123456789012:key/test-key",
"--leaf-key-id", "arn:aws:kms:us-west-2:123456789012:key/test-key",
"--root-key-id", "alias/test-key",
"--leaf-key-id", "alias/test-key",
"--root-template", rootTmplPath,
"--leaf-template", "nonexistent.json",
},
wantError: true,
errMsg: "template not found",
errMsg: "leaf template error: template not found at nonexistent.json",
},
{
name: "GCP KMS with credentials file",
Expand All @@ -227,6 +237,45 @@ func TestRunCreate(t *testing.T) {
wantError: true,
errMsg: "tenant-id is required",
},
{
name: "AWS KMS test",
args: []string{
"--kms-type", "awskms",
"--aws-region", "us-west-2",
"--root-key-id", "alias/test-key",
"--leaf-key-id", "alias/test-key",
"--root-template", rootTmplPath,
"--leaf-template", leafTmplPath,
},
wantError: true,
errMsg: "NotFoundException: Alias arn:aws:kms:us-west-2",
},
{
name: "HashiVault KMS without token",
args: []string{
"--kms-type", "hashivault",
"--root-key-id", "transit/keys/test-key",
"--leaf-key-id", "transit/keys/leaf-key",
"--vault-address", "http://vault:8200",
"--root-template", rootTmplPath,
"--leaf-template", leafTmplPath,
},
wantError: true,
errMsg: "token is required for HashiVault KMS",
},
{
name: "HashiVault KMS without address",
args: []string{
"--kms-type", "hashivault",
"--root-key-id", "transit/keys/test-key",
"--leaf-key-id", "transit/keys/leaf-key",
"--vault-token", "test-token",
"--root-template", rootTmplPath,
"--leaf-template", leafTmplPath,
},
wantError: true,
errMsg: "address is required for HashiVault KMS",
},
}

for _, tt := range tests {
Expand All @@ -241,11 +290,13 @@ func TestRunCreate(t *testing.T) {
RunE: runCreate,
}

cmd.Flags().StringVar(&kmsType, "kms-type", "", "KMS provider type (awskms, gcpkms, azurekms)")
cmd.Flags().StringVar(&kmsType, "kms-type", "", "KMS provider type (awskms, gcpkms, azurekms, hashivault)")
cmd.Flags().StringVar(&kmsRegion, "aws-region", "", "AWS KMS region")
cmd.Flags().StringVar(&kmsKeyID, "kms-key-id", "", "KMS key identifier")
cmd.Flags().StringVar(&kmsTenantID, "azure-tenant-id", "", "Azure KMS tenant ID")
cmd.Flags().StringVar(&kmsCredsFile, "gcp-credentials-file", "", "Path to credentials file for GCP KMS")
cmd.Flags().StringVar(&kmsVaultToken, "vault-token", "", "HashiVault token")
cmd.Flags().StringVar(&kmsVaultAddr, "vault-address", "", "HashiVault server address")
cmd.Flags().StringVar(&rootKeyID, "root-key-id", "", "KMS key identifier for root certificate")
cmd.Flags().StringVar(&leafKeyID, "leaf-key-id", "", "KMS key identifier for leaf certificate")
cmd.Flags().StringVar(&rootTemplatePath, "root-template", "", "Path to root certificate template")
Expand All @@ -260,15 +311,10 @@ func TestRunCreate(t *testing.T) {
err := cmd.Execute()

if tt.wantError {
if err == nil {
t.Errorf("expected error, but got nil")
} else if !strings.Contains(err.Error(), tt.errMsg) {
t.Errorf("error %q should contain %q", err.Error(), tt.errMsg)
}
require.Error(t, err)
assert.Contains(t, err.Error(), tt.errMsg)
} else {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
require.NoError(t, err)
}
})
}
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
github.com/urfave/negroni v1.0.0
go.step.sm/crypto v0.55.0
go.uber.org/zap v1.27.0
Expand All @@ -53,8 +54,6 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.1 // indirect
Expand All @@ -81,6 +80,7 @@ require (
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
Expand Down Expand Up @@ -131,6 +131,7 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
Expand Down
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvUL
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0 h1:7rKG7UmnrxX4N53TFhkYqjc+kVUZuw0fL8I3Fh+Ld9E=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0/go.mod h1:Wjo+24QJVhhl/L7jy6w9yzFF2yDOf3cKECAa8ecf9vE=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 h1:eXnN9kaS8TiDwXjoie3hMRLuwdUBUMW9KRgOqB3mCaw=
Expand Down Expand Up @@ -386,8 +382,6 @@ go.step.sm/crypto v0.55.0 h1:575Q7NahuM/ZRxUVN1GkO2e1aDYQJqIIg+nbfOajQJk=
go.step.sm/crypto v0.55.0/go.mod h1:MgEmD1lgwsuzZwTgI0GwKapHjKVEQLVggSvHuf3bYnU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
Expand Down
Loading

0 comments on commit 90ac751

Please sign in to comment.