Skip to content

Commit

Permalink
feat: adds sigstore/sigstore for kms and adds hashivault support.
Browse files Browse the repository at this point in the history
Signed-off-by: ianhundere <[email protected]>
  • Loading branch information
ianhundere committed Dec 19, 2024
1 parent 11afd00 commit 867602c
Show file tree
Hide file tree
Showing 8 changed files with 1,600 additions and 1,623 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 @@ -98,6 +100,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 @@ -131,6 +135,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
98 changes: 53 additions & 45 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,19 @@ 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.Error("logger should not be nil")
}
require.NotNil(t, logger)
}

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

rootTemplate := `{
Expand Down Expand Up @@ -136,13 +131,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.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)
err = os.WriteFile(leafTmplPath, []byte(leafTemplate), 0600)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)

tests := []struct {
name string
Expand Down Expand Up @@ -181,26 +172,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: "no such file or directory",
},
{
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: "no such file or directory",
},
{
name: "GCP KMS with credentials file",
Expand Down Expand Up @@ -232,13 +223,39 @@ 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", 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: "operation error KMS",
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",
},
}

Expand All @@ -254,11 +271,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 @@ -273,13 +292,10 @@ func TestRunCreate(t *testing.T) {
err := cmd.Execute()

if tt.wantError {
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.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)
}
})
}
Expand All @@ -299,22 +315,18 @@ func TestCreateCommand(t *testing.T) {
cmd.Flags().StringVar(&leafKeyID, "leaf-key-id", "", "Leaf key ID")

err := cmd.Execute()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)

err = cmd.ParseFlags([]string{
"--kms-type", "awskms",
"--aws-region", "us-west-2",
"--root-key-id", "arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab",
"--leaf-key-id", "arn:aws:kms:us-west-2:123456789012:key/9876fedc-ba98-7654-3210-fedcba987654",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)

if kmsType != "awskms" {
t.Errorf("got kmsType %v, want awskms", kmsType)
assert.Equal(t, "awskms", kmsType)
}
if kmsRegion != "us-west-2" {
t.Errorf("got kmsRegion %v, want us-west-2", kmsRegion)
Expand All @@ -330,13 +342,9 @@ func TestCreateCommand(t *testing.T) {
func TestRootCommand(t *testing.T) {
rootCmd.SetArgs([]string{"--help"})
err := rootCmd.Execute()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)

rootCmd.SetArgs([]string{"unknown"})
err = rootCmd.Execute()
if err == nil {
t.Error("expected error for unknown command, got nil")
}
require.Error(t, err)
}
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.19.0
github.com/spiffe/go-spiffe/v2 v2.4.0
github.com/stretchr/testify v1.10.0
github.com/tink-crypto/tink-go-awskms/v2 v2.1.0
github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0
github.com/tink-crypto/tink-go/v2 v2.2.0
Expand All @@ -59,8 +60,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 Down Expand Up @@ -88,6 +87,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chainguard-dev/clog v1.5.1 // 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/felixge/httpsnoop v1.0.4 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-logr/logr v1.4.2 // indirect
Expand Down Expand Up @@ -126,6 +126,7 @@ require (
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
Expand Down
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,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 @@ -408,8 +404,6 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
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.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
Expand Down
Loading

0 comments on commit 867602c

Please sign in to comment.