forked from TrueCloudLab/certificates
commit
02fd0e7170
9 changed files with 543 additions and 257 deletions
67
cas/vaultcas/auth/approle/approle.go
Normal file
67
cas/vaultcas/auth/approle/approle.go
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package approle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api/auth/approle"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthOptions defines the configuration options added using the
|
||||||
|
// VaultOptions.AuthOptions field when AuthType is approle
|
||||||
|
type AuthOptions struct {
|
||||||
|
RoleID string `json:"roleID,omitempty"`
|
||||||
|
SecretID string `json:"secretID,omitempty"`
|
||||||
|
SecretIDFile string `json:"secretIDFile,omitempty"`
|
||||||
|
SecretIDEnv string `json:"secretIDEnv,omitempty"`
|
||||||
|
IsWrappingToken bool `json:"isWrappingToken,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApproleAuthMethod(mountPath string, options json.RawMessage) (*approle.AppRoleAuth, error) {
|
||||||
|
var opts *AuthOptions
|
||||||
|
|
||||||
|
err := json.Unmarshal(options, &opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding AppRole auth options: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var approleAuth *approle.AppRoleAuth
|
||||||
|
|
||||||
|
var loginOptions []approle.LoginOption
|
||||||
|
if mountPath != "" {
|
||||||
|
loginOptions = append(loginOptions, approle.WithMountPath(mountPath))
|
||||||
|
}
|
||||||
|
if opts.IsWrappingToken {
|
||||||
|
loginOptions = append(loginOptions, approle.WithWrappingToken())
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.RoleID == "" {
|
||||||
|
return nil, errors.New("you must set roleID")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sid approle.SecretID
|
||||||
|
switch {
|
||||||
|
case opts.SecretID != "" && opts.SecretIDFile == "" && opts.SecretIDEnv == "":
|
||||||
|
sid = approle.SecretID{
|
||||||
|
FromString: opts.SecretID,
|
||||||
|
}
|
||||||
|
case opts.SecretIDFile != "" && opts.SecretID == "" && opts.SecretIDEnv == "":
|
||||||
|
sid = approle.SecretID{
|
||||||
|
FromFile: opts.SecretIDFile,
|
||||||
|
}
|
||||||
|
case opts.SecretIDEnv != "" && opts.SecretIDFile == "" && opts.SecretID == "":
|
||||||
|
sid = approle.SecretID{
|
||||||
|
FromEnv: opts.SecretIDEnv,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("you must set one of secretID, secretIDFile or secretIDEnv")
|
||||||
|
}
|
||||||
|
|
||||||
|
approleAuth, err = approle.NewAppRoleAuth(opts.RoleID, &sid, loginOptions...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to initialize Kubernetes auth method: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return approleAuth, nil
|
||||||
|
}
|
195
cas/vaultcas/auth/approle/approle_test.go
Normal file
195
cas/vaultcas/auth/approle/approle_test.go
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
package approle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
vault "github.com/hashicorp/vault/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testCAHelper(t *testing.T) (*url.URL, *vault.Client) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch {
|
||||||
|
case r.RequestURI == "/v1/auth/approle/login":
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintf(w, `{
|
||||||
|
"auth": {
|
||||||
|
"client_token": "hvs.0000"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
case r.RequestURI == "/v1/auth/custom-approle/login":
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintf(w, `{
|
||||||
|
"auth": {
|
||||||
|
"client_token": "hvs.9999"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
fmt.Fprintf(w, `{"error":"not found"}`)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
srv.Close()
|
||||||
|
})
|
||||||
|
u, err := url.Parse(srv.URL)
|
||||||
|
if err != nil {
|
||||||
|
srv.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := vault.DefaultConfig()
|
||||||
|
config.Address = srv.URL
|
||||||
|
|
||||||
|
client, err := vault.NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
srv.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, client
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApprole_LoginMountPaths(t *testing.T) {
|
||||||
|
caURL, _ := testCAHelper(t)
|
||||||
|
|
||||||
|
config := vault.DefaultConfig()
|
||||||
|
config.Address = caURL.String()
|
||||||
|
client, _ := vault.NewClient(config)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mountPath string
|
||||||
|
token string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "ok default mount path",
|
||||||
|
mountPath: "",
|
||||||
|
token: "hvs.0000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok explicit mount path",
|
||||||
|
mountPath: "approle",
|
||||||
|
token: "hvs.0000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok custom mount path",
|
||||||
|
mountPath: "custom-approle",
|
||||||
|
token: "hvs.9999",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
method, err := NewApproleAuthMethod(tt.mountPath, json.RawMessage(`{"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false}`))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewApproleAuthMethod() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, err := client.Auth().Login(context.Background(), method)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Login() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, _ := secret.TokenID()
|
||||||
|
if token != tt.token {
|
||||||
|
t.Errorf("Token error got %v, expected %v", token, tt.token)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApprole_NewApproleAuthMethod(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mountPath string
|
||||||
|
raw string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"ok secret-id string",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretID": "0000-0000-0000-0000"}`,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ok secret-id string and wrapped",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretID": "0000-0000-0000-0000", "isWrappedToken": true}`,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ok secret-id string and wrapped with custom mountPath",
|
||||||
|
"approle2",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretID": "0000-0000-0000-0000", "isWrappedToken": true}`,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ok secret-id file",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretIDFile": "./secret-id"}`,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ok secret-id env",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretIDEnv": "VAULT_APPROLE_SECRETID"}`,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail mandatory role-id",
|
||||||
|
"",
|
||||||
|
`{}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail mandatory secret-id any",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000"}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail multiple secret-id types id and env",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretID": "0000-0000-0000-0000", "SecretIDEnv": "VAULT_APPROLE_SECRETID"}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail multiple secret-id types id and file",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretID": "0000-0000-0000-0000", "SecretIDFile": "./secret-id"}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail multiple secret-id types env and file",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretIDFile": "./secret-id", "SecretIDEnv": "VAULT_APPROLE_SECRETID"}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail multiple secret-id types all",
|
||||||
|
"",
|
||||||
|
`{"RoleID": "0000-0000-0000-0000", "SecretID": "0000-0000-0000-0000", "SecretIDFile": "./secret-id", "SecretIDEnv": "VAULT_APPROLE_SECRETID"}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
_, err := NewApproleAuthMethod(tt.mountPath, json.RawMessage(tt.raw))
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Approle.NewApproleAuthMethod() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
49
cas/vaultcas/auth/kubernetes/kubernetes.go
Normal file
49
cas/vaultcas/auth/kubernetes/kubernetes.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api/auth/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthOptions defines the configuration options added using the
|
||||||
|
// VaultOptions.AuthOptions field when AuthType is kubernetes
|
||||||
|
type AuthOptions struct {
|
||||||
|
Role string `json:"role,omitempty"`
|
||||||
|
TokenPath string `json:"tokenPath,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKubernetesAuthMethod(mountPath string, options json.RawMessage) (*kubernetes.KubernetesAuth, error) {
|
||||||
|
var opts *AuthOptions
|
||||||
|
|
||||||
|
err := json.Unmarshal(options, &opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding Kubernetes auth options: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubernetesAuth *kubernetes.KubernetesAuth
|
||||||
|
|
||||||
|
var loginOptions []kubernetes.LoginOption
|
||||||
|
if mountPath != "" {
|
||||||
|
loginOptions = append(loginOptions, kubernetes.WithMountPath(mountPath))
|
||||||
|
}
|
||||||
|
if opts.TokenPath != "" {
|
||||||
|
loginOptions = append(loginOptions, kubernetes.WithServiceAccountTokenPath(opts.TokenPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Role == "" {
|
||||||
|
return nil, errors.New("you must set role")
|
||||||
|
}
|
||||||
|
|
||||||
|
kubernetesAuth, err = kubernetes.NewKubernetesAuth(
|
||||||
|
opts.Role,
|
||||||
|
loginOptions...,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to initialize Kubernetes auth method: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return kubernetesAuth, nil
|
||||||
|
}
|
149
cas/vaultcas/auth/kubernetes/kubernetes_test.go
Normal file
149
cas/vaultcas/auth/kubernetes/kubernetes_test.go
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
vault "github.com/hashicorp/vault/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testCAHelper(t *testing.T) (*url.URL, *vault.Client) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch {
|
||||||
|
case r.RequestURI == "/v1/auth/kubernetes/login":
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintf(w, `{
|
||||||
|
"auth": {
|
||||||
|
"client_token": "hvs.0000"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
case r.RequestURI == "/v1/auth/custom-kubernetes/login":
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintf(w, `{
|
||||||
|
"auth": {
|
||||||
|
"client_token": "hvs.9999"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
fmt.Fprintf(w, `{"error":"not found"}`)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
srv.Close()
|
||||||
|
})
|
||||||
|
u, err := url.Parse(srv.URL)
|
||||||
|
if err != nil {
|
||||||
|
srv.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := vault.DefaultConfig()
|
||||||
|
config.Address = srv.URL
|
||||||
|
|
||||||
|
client, err := vault.NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
srv.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, client
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApprole_LoginMountPaths(t *testing.T) {
|
||||||
|
caURL, _ := testCAHelper(t)
|
||||||
|
_, filename, _, _ := runtime.Caller(0)
|
||||||
|
tokenPath := filepath.Join(path.Dir(filename), "token")
|
||||||
|
|
||||||
|
config := vault.DefaultConfig()
|
||||||
|
config.Address = caURL.String()
|
||||||
|
client, _ := vault.NewClient(config)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mountPath string
|
||||||
|
token string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "ok default mount path",
|
||||||
|
mountPath: "",
|
||||||
|
token: "hvs.0000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok explicit mount path",
|
||||||
|
mountPath: "kubernetes",
|
||||||
|
token: "hvs.0000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok custom mount path",
|
||||||
|
mountPath: "custom-kubernetes",
|
||||||
|
token: "hvs.9999",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
method, err := NewKubernetesAuthMethod(tt.mountPath, json.RawMessage(`{"role": "SomeRoleName", "tokenPath": "`+tokenPath+`"}`))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewApproleAuthMethod() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, err := client.Auth().Login(context.Background(), method)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Login() error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, _ := secret.TokenID()
|
||||||
|
if token != tt.token {
|
||||||
|
t.Errorf("Token error got %v, expected %v", token, tt.token)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApprole_NewApproleAuthMethod(t *testing.T) {
|
||||||
|
_, filename, _, _ := runtime.Caller(0)
|
||||||
|
tokenPath := filepath.Join(path.Dir(filename), "token")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mountPath string
|
||||||
|
raw string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"ok secret-id string",
|
||||||
|
"",
|
||||||
|
`{"role": "SomeRoleName", "tokenPath": "` + tokenPath + `"}`,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail mandatory role",
|
||||||
|
"",
|
||||||
|
`{}`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
_, err := NewKubernetesAuthMethod(tt.mountPath, json.RawMessage(tt.raw))
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Kubernetes.NewKubernetesAuthMethod() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
1
cas/vaultcas/auth/kubernetes/token
Normal file
1
cas/vaultcas/auth/kubernetes/token
Normal file
|
@ -0,0 +1 @@
|
||||||
|
token
|
|
@ -15,9 +15,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/smallstep/certificates/cas/apiv1"
|
"github.com/smallstep/certificates/cas/apiv1"
|
||||||
|
"github.com/smallstep/certificates/cas/vaultcas/auth/approle"
|
||||||
|
"github.com/smallstep/certificates/cas/vaultcas/auth/kubernetes"
|
||||||
|
|
||||||
vault "github.com/hashicorp/vault/api"
|
vault "github.com/hashicorp/vault/api"
|
||||||
auth "github.com/hashicorp/vault/api/auth/approle"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -29,15 +30,14 @@ func init() {
|
||||||
// VaultOptions defines the configuration options added using the
|
// VaultOptions defines the configuration options added using the
|
||||||
// apiv1.Options.Config field.
|
// apiv1.Options.Config field.
|
||||||
type VaultOptions struct {
|
type VaultOptions struct {
|
||||||
PKI string `json:"pki,omitempty"`
|
PKIMountPath string `json:"pkiMountPath,omitempty"`
|
||||||
PKIRoleDefault string `json:"pkiRoleDefault,omitempty"`
|
PKIRoleDefault string `json:"pkiRoleDefault,omitempty"`
|
||||||
PKIRoleRSA string `json:"pkiRoleRSA,omitempty"`
|
PKIRoleRSA string `json:"pkiRoleRSA,omitempty"`
|
||||||
PKIRoleEC string `json:"pkiRoleEC,omitempty"`
|
PKIRoleEC string `json:"pkiRoleEC,omitempty"`
|
||||||
PKIRoleEd25519 string `json:"pkiRoleEd25519,omitempty"`
|
PKIRoleEd25519 string `json:"pkiRoleEd25519,omitempty"`
|
||||||
RoleID string `json:"roleID,omitempty"`
|
AuthType string `json:"authType,omitempty"`
|
||||||
SecretID auth.SecretID `json:"secretID,omitempty"`
|
AuthMountPath string `json:"authMountPath,omitempty"`
|
||||||
AppRole string `json:"appRole,omitempty"`
|
AuthOptions json.RawMessage `json:"authOptions,omitempty"`
|
||||||
IsWrappingToken bool `json:"isWrappingToken,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VaultCAS implements a Certificate Authority Service using Hashicorp Vault.
|
// VaultCAS implements a Certificate Authority Service using Hashicorp Vault.
|
||||||
|
@ -77,28 +77,22 @@ func New(ctx context.Context, opts apiv1.Options) (*VaultCAS, error) {
|
||||||
return nil, fmt.Errorf("unable to initialize vault client: %w", err)
|
return nil, fmt.Errorf("unable to initialize vault client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var appRoleAuth *auth.AppRoleAuth
|
var method vault.AuthMethod
|
||||||
if vc.IsWrappingToken {
|
switch vc.AuthType {
|
||||||
appRoleAuth, err = auth.NewAppRoleAuth(
|
case "kubernetes":
|
||||||
vc.RoleID,
|
method, err = kubernetes.NewKubernetesAuthMethod(vc.AuthMountPath, vc.AuthOptions)
|
||||||
&vc.SecretID,
|
case "approle":
|
||||||
auth.WithWrappingToken(),
|
method, err = approle.NewApproleAuthMethod(vc.AuthMountPath, vc.AuthOptions)
|
||||||
auth.WithMountPath(vc.AppRole),
|
default:
|
||||||
)
|
return nil, fmt.Errorf("unknown auth type: %s, only 'kubernetes' and 'approle' currently supported", vc.AuthType)
|
||||||
} else {
|
|
||||||
appRoleAuth, err = auth.NewAppRoleAuth(
|
|
||||||
vc.RoleID,
|
|
||||||
&vc.SecretID,
|
|
||||||
auth.WithMountPath(vc.AppRole),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to initialize AppRole auth method: %w", err)
|
return nil, fmt.Errorf("unable to configure %s auth method: %w", vc.AuthType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authInfo, err := client.Auth().Login(ctx, appRoleAuth)
|
authInfo, err := client.Auth().Login(ctx, method)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to login to AppRole auth method: %w", err)
|
return nil, fmt.Errorf("unable to login to %s auth method: %w", vc.AuthType, err)
|
||||||
}
|
}
|
||||||
if authInfo == nil {
|
if authInfo == nil {
|
||||||
return nil, errors.New("no auth info was returned after login")
|
return nil, errors.New("no auth info was returned after login")
|
||||||
|
@ -134,7 +128,7 @@ func (v *VaultCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv
|
||||||
// GetCertificateAuthority returns the root certificate of the certificate
|
// GetCertificateAuthority returns the root certificate of the certificate
|
||||||
// authority using the configured fingerprint.
|
// authority using the configured fingerprint.
|
||||||
func (v *VaultCAS) GetCertificateAuthority(req *apiv1.GetCertificateAuthorityRequest) (*apiv1.GetCertificateAuthorityResponse, error) {
|
func (v *VaultCAS) GetCertificateAuthority(req *apiv1.GetCertificateAuthorityRequest) (*apiv1.GetCertificateAuthorityResponse, error) {
|
||||||
secret, err := v.client.Logical().Read(v.config.PKI + "/cert/ca_chain")
|
secret, err := v.client.Logical().Read(v.config.PKIMountPath + "/cert/ca_chain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading ca chain: %w", err)
|
return nil, fmt.Errorf("error reading ca chain: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -190,7 +184,7 @@ func (v *VaultCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv
|
||||||
vaultReq := map[string]interface{}{
|
vaultReq := map[string]interface{}{
|
||||||
"serial_number": formatSerialNumber(sn),
|
"serial_number": formatSerialNumber(sn),
|
||||||
}
|
}
|
||||||
_, err := v.client.Logical().Write(v.config.PKI+"/revoke/", vaultReq)
|
_, err := v.client.Logical().Write(v.config.PKIMountPath+"/revoke/", vaultReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error revoking certificate: %w", err)
|
return nil, fmt.Errorf("error revoking certificate: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -224,7 +218,7 @@ func (v *VaultCAS) createCertificate(cr *x509.CertificateRequest, lifetime time.
|
||||||
"ttl": lifetime.Seconds(),
|
"ttl": lifetime.Seconds(),
|
||||||
}
|
}
|
||||||
|
|
||||||
secret, err := v.client.Logical().Write(v.config.PKI+"/sign/"+vaultPKIRole, vaultReq)
|
secret, err := v.client.Logical().Write(v.config.PKIMountPath+"/sign/"+vaultPKIRole, vaultReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("error signing certificate: %w", err)
|
return nil, nil, fmt.Errorf("error signing certificate: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -247,21 +241,17 @@ func (v *VaultCAS) createCertificate(cr *x509.CertificateRequest, lifetime time.
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadOptions(config json.RawMessage) (*VaultOptions, error) {
|
func loadOptions(config json.RawMessage) (*VaultOptions, error) {
|
||||||
var vc *VaultOptions
|
// setup default values
|
||||||
|
vc := VaultOptions{
|
||||||
|
PKIMountPath: "pki",
|
||||||
|
PKIRoleDefault: "default",
|
||||||
|
}
|
||||||
|
|
||||||
err := json.Unmarshal(config, &vc)
|
err := json.Unmarshal(config, &vc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error decoding vaultCAS config: %w", err)
|
return nil, fmt.Errorf("error decoding vaultCAS config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vc.PKI == "" {
|
|
||||||
vc.PKI = "pki" // use default pki vault name
|
|
||||||
}
|
|
||||||
|
|
||||||
if vc.PKIRoleDefault == "" {
|
|
||||||
vc.PKIRoleDefault = "default" // use default pki role name
|
|
||||||
}
|
|
||||||
|
|
||||||
if vc.PKIRoleRSA == "" {
|
if vc.PKIRoleRSA == "" {
|
||||||
vc.PKIRoleRSA = vc.PKIRoleDefault
|
vc.PKIRoleRSA = vc.PKIRoleDefault
|
||||||
}
|
}
|
||||||
|
@ -272,23 +262,7 @@ func loadOptions(config json.RawMessage) (*VaultOptions, error) {
|
||||||
vc.PKIRoleEd25519 = vc.PKIRoleDefault
|
vc.PKIRoleEd25519 = vc.PKIRoleDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
if vc.RoleID == "" {
|
return &vc, nil
|
||||||
return nil, errors.New("vaultCAS config options must define `roleID`")
|
|
||||||
}
|
|
||||||
|
|
||||||
if vc.SecretID.FromEnv == "" && vc.SecretID.FromFile == "" && vc.SecretID.FromString == "" {
|
|
||||||
return nil, errors.New("vaultCAS config options must define `secretID` object with one of `FromEnv`, `FromFile` or `FromString`")
|
|
||||||
}
|
|
||||||
|
|
||||||
if vc.PKI == "" {
|
|
||||||
vc.PKI = "pki" // use default pki vault name
|
|
||||||
}
|
|
||||||
|
|
||||||
if vc.AppRole == "" {
|
|
||||||
vc.AppRole = "auth/approle"
|
|
||||||
}
|
|
||||||
|
|
||||||
return vc, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCertificates(pemCert string) []*x509.Certificate {
|
func parseCertificates(pemCert string) []*x509.Certificate {
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
vault "github.com/hashicorp/vault/api"
|
vault "github.com/hashicorp/vault/api"
|
||||||
auth "github.com/hashicorp/vault/api/auth/approle"
|
|
||||||
"github.com/smallstep/certificates/cas/apiv1"
|
"github.com/smallstep/certificates/cas/apiv1"
|
||||||
"go.step.sm/crypto/pemutil"
|
"go.step.sm/crypto/pemutil"
|
||||||
)
|
)
|
||||||
|
@ -99,7 +98,7 @@ func testCAHelper(t *testing.T) (*url.URL, *vault.Client) {
|
||||||
|
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
switch {
|
switch {
|
||||||
case r.RequestURI == "/v1/auth/auth/approle/login":
|
case r.RequestURI == "/v1/auth/approle/login":
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
fmt.Fprintf(w, `{
|
fmt.Fprintf(w, `{
|
||||||
"auth": {
|
"auth": {
|
||||||
|
@ -183,11 +182,8 @@ func TestNew_register(t *testing.T) {
|
||||||
CertificateAuthority: caURL.String(),
|
CertificateAuthority: caURL.String(),
|
||||||
CertificateAuthorityFingerprint: testRootFingerprint,
|
CertificateAuthorityFingerprint: testRootFingerprint,
|
||||||
Config: json.RawMessage(`{
|
Config: json.RawMessage(`{
|
||||||
"PKI": "pki",
|
"AuthType": "approle",
|
||||||
"PKIRoleDefault": "pki-role",
|
"AuthOptions": {"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false}
|
||||||
"RoleID": "roleID",
|
|
||||||
"SecretID": {"FromString": "secretID"},
|
|
||||||
"IsWrappingToken": false
|
|
||||||
}`),
|
}`),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -201,15 +197,11 @@ func TestVaultCAS_CreateCertificate(t *testing.T) {
|
||||||
_, client := testCAHelper(t)
|
_, client := testCAHelper(t)
|
||||||
|
|
||||||
options := VaultOptions{
|
options := VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "rsa",
|
PKIRoleRSA: "rsa",
|
||||||
PKIRoleEC: "ec",
|
PKIRoleEC: "ec",
|
||||||
PKIRoleEd25519: "ed25519",
|
PKIRoleEd25519: "ed25519",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromString: "secretID"},
|
|
||||||
AppRole: "approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fields struct {
|
type fields struct {
|
||||||
|
@ -291,7 +283,7 @@ func TestVaultCAS_GetCertificateAuthority(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
options := VaultOptions{
|
options := VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
}
|
}
|
||||||
|
|
||||||
rootCert := parseCertificates(testRootCertificate)[0]
|
rootCert := parseCertificates(testRootCertificate)[0]
|
||||||
|
@ -335,15 +327,11 @@ func TestVaultCAS_RevokeCertificate(t *testing.T) {
|
||||||
_, client := testCAHelper(t)
|
_, client := testCAHelper(t)
|
||||||
|
|
||||||
options := VaultOptions{
|
options := VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "rsa",
|
PKIRoleRSA: "rsa",
|
||||||
PKIRoleEC: "ec",
|
PKIRoleEC: "ec",
|
||||||
PKIRoleEd25519: "ed25519",
|
PKIRoleEd25519: "ed25519",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromString: "secretID"},
|
|
||||||
AppRole: "approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fields struct {
|
type fields struct {
|
||||||
|
@ -407,15 +395,11 @@ func TestVaultCAS_RenewCertificate(t *testing.T) {
|
||||||
_, client := testCAHelper(t)
|
_, client := testCAHelper(t)
|
||||||
|
|
||||||
options := VaultOptions{
|
options := VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "rsa",
|
PKIRoleRSA: "rsa",
|
||||||
PKIRoleEC: "ec",
|
PKIRoleEC: "ec",
|
||||||
PKIRoleEd25519: "ed25519",
|
PKIRoleEd25519: "ed25519",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromString: "secretID"},
|
|
||||||
AppRole: "approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fields struct {
|
type fields struct {
|
||||||
|
@ -464,202 +448,66 @@ func TestVaultCAS_loadOptions(t *testing.T) {
|
||||||
want *VaultOptions
|
want *VaultOptions
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
"ok mandatory with SecretID FromString",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromString": "secretID"}}`,
|
|
||||||
&VaultOptions{
|
|
||||||
PKI: "pki",
|
|
||||||
PKIRoleDefault: "default",
|
|
||||||
PKIRoleRSA: "default",
|
|
||||||
PKIRoleEC: "default",
|
|
||||||
PKIRoleEd25519: "default",
|
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromString: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ok mandatory with SecretID FromFile",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromFile": "secretID"}}`,
|
|
||||||
&VaultOptions{
|
|
||||||
PKI: "pki",
|
|
||||||
PKIRoleDefault: "default",
|
|
||||||
PKIRoleRSA: "default",
|
|
||||||
PKIRoleEC: "default",
|
|
||||||
PKIRoleEd25519: "default",
|
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromFile: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ok mandatory with SecretID FromEnv",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromEnv": "secretID"}}`,
|
|
||||||
&VaultOptions{
|
|
||||||
PKI: "pki",
|
|
||||||
PKIRoleDefault: "default",
|
|
||||||
PKIRoleRSA: "default",
|
|
||||||
PKIRoleEC: "default",
|
|
||||||
PKIRoleEd25519: "default",
|
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromEnv: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ok mandatory PKIRole PKIRoleEd25519",
|
"ok mandatory PKIRole PKIRoleEd25519",
|
||||||
`{"PKIRoleDefault": "role", "PKIRoleEd25519": "ed25519" , "RoleID": "roleID", "SecretID": {"FromEnv": "secretID"}}`,
|
`{"PKIRoleDefault": "role", "PKIRoleEd25519": "ed25519"}`,
|
||||||
&VaultOptions{
|
&VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "role",
|
PKIRoleRSA: "role",
|
||||||
PKIRoleEC: "role",
|
PKIRoleEC: "role",
|
||||||
PKIRoleEd25519: "ed25519",
|
PKIRoleEd25519: "ed25519",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromEnv: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ok mandatory PKIRole PKIRoleEC",
|
"ok mandatory PKIRole PKIRoleEC",
|
||||||
`{"PKIRoleDefault": "role", "PKIRoleEC": "ec" , "RoleID": "roleID", "SecretID": {"FromEnv": "secretID"}}`,
|
`{"PKIRoleDefault": "role", "PKIRoleEC": "ec"}`,
|
||||||
&VaultOptions{
|
&VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "role",
|
PKIRoleRSA: "role",
|
||||||
PKIRoleEC: "ec",
|
PKIRoleEC: "ec",
|
||||||
PKIRoleEd25519: "role",
|
PKIRoleEd25519: "role",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromEnv: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ok mandatory PKIRole PKIRoleRSA",
|
"ok mandatory PKIRole PKIRoleRSA",
|
||||||
`{"PKIRoleDefault": "role", "PKIRoleRSA": "rsa" , "RoleID": "roleID", "SecretID": {"FromEnv": "secretID"}}`,
|
`{"PKIRoleDefault": "role", "PKIRoleRSA": "rsa"}`,
|
||||||
&VaultOptions{
|
&VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "rsa",
|
PKIRoleRSA: "rsa",
|
||||||
PKIRoleEC: "role",
|
PKIRoleEC: "role",
|
||||||
PKIRoleEd25519: "role",
|
PKIRoleEd25519: "role",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromEnv: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ok mandatory PKIRoleRSA PKIRoleEC PKIRoleEd25519",
|
"ok mandatory PKIRoleRSA PKIRoleEC PKIRoleEd25519",
|
||||||
`{"PKIRoleRSA": "rsa", "PKIRoleEC": "ec", "PKIRoleEd25519": "ed25519", "RoleID": "roleID", "SecretID": {"FromEnv": "secretID"}}`,
|
`{"PKIRoleRSA": "rsa", "PKIRoleEC": "ec", "PKIRoleEd25519": "ed25519"}`,
|
||||||
&VaultOptions{
|
&VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "default",
|
PKIRoleDefault: "default",
|
||||||
PKIRoleRSA: "rsa",
|
PKIRoleRSA: "rsa",
|
||||||
PKIRoleEC: "ec",
|
PKIRoleEC: "ec",
|
||||||
PKIRoleEd25519: "ed25519",
|
PKIRoleEd25519: "ed25519",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromEnv: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ok mandatory PKIRoleRSA PKIRoleEC PKIRoleEd25519 with useless PKIRoleDefault",
|
"ok mandatory PKIRoleRSA PKIRoleEC PKIRoleEd25519 with useless PKIRoleDefault",
|
||||||
`{"PKIRoleDefault": "role", "PKIRoleRSA": "rsa", "PKIRoleEC": "ec", "PKIRoleEd25519": "ed25519", "RoleID": "roleID", "SecretID": {"FromEnv": "secretID"}}`,
|
`{"PKIRoleDefault": "role", "PKIRoleRSA": "rsa", "PKIRoleEC": "ec", "PKIRoleEd25519": "ed25519"}`,
|
||||||
&VaultOptions{
|
&VaultOptions{
|
||||||
PKI: "pki",
|
PKIMountPath: "pki",
|
||||||
PKIRoleDefault: "role",
|
PKIRoleDefault: "role",
|
||||||
PKIRoleRSA: "rsa",
|
PKIRoleRSA: "rsa",
|
||||||
PKIRoleEC: "ec",
|
PKIRoleEC: "ec",
|
||||||
PKIRoleEd25519: "ed25519",
|
PKIRoleEd25519: "ed25519",
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromEnv: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ok mandatory with AppRole",
|
|
||||||
`{"AppRole": "test", "RoleID": "roleID", "SecretID": {"FromString": "secretID"}}`,
|
|
||||||
&VaultOptions{
|
|
||||||
PKI: "pki",
|
|
||||||
PKIRoleDefault: "default",
|
|
||||||
PKIRoleRSA: "default",
|
|
||||||
PKIRoleEC: "default",
|
|
||||||
PKIRoleEd25519: "default",
|
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromString: "secretID"},
|
|
||||||
AppRole: "test",
|
|
||||||
IsWrappingToken: false,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ok mandatory with IsWrappingToken",
|
|
||||||
`{"IsWrappingToken": true, "RoleID": "roleID", "SecretID": {"FromString": "secretID"}}`,
|
|
||||||
&VaultOptions{
|
|
||||||
PKI: "pki",
|
|
||||||
PKIRoleDefault: "default",
|
|
||||||
PKIRoleRSA: "default",
|
|
||||||
PKIRoleEC: "default",
|
|
||||||
PKIRoleEd25519: "default",
|
|
||||||
RoleID: "roleID",
|
|
||||||
SecretID: auth.SecretID{FromString: "secretID"},
|
|
||||||
AppRole: "auth/approle",
|
|
||||||
IsWrappingToken: true,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fail with SecretID FromFail",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromFail": "secretID"}}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fail with SecretID empty FromEnv",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromEnv": ""}}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fail with SecretID empty FromFile",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromFile": ""}}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fail with SecretID empty FromString",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromString": ""}}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fail mandatory with SecretID FromFail",
|
|
||||||
`{"RoleID": "roleID", "SecretID": {"FromFail": "secretID"}}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fail missing RoleID",
|
|
||||||
`{"SecretID": {"FromString": "secretID"}}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -29,6 +29,7 @@ require (
|
||||||
github.com/googleapis/gax-go/v2 v2.1.1
|
github.com/googleapis/gax-go/v2 v2.1.1
|
||||||
github.com/hashicorp/vault/api v1.3.1
|
github.com/hashicorp/vault/api v1.3.1
|
||||||
github.com/hashicorp/vault/api/auth/approle v0.1.1
|
github.com/hashicorp/vault/api/auth/approle v0.1.1
|
||||||
|
github.com/hashicorp/vault/api/auth/kubernetes v0.1.0
|
||||||
github.com/jhump/protoreflect v1.9.0 // indirect
|
github.com/jhump/protoreflect v1.9.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -449,6 +449,8 @@ github.com/hashicorp/vault/api v1.3.1 h1:pkDkcgTh47PRjY1NEFeofqR4W/HkNUi9qIakESO
|
||||||
github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw=
|
github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw=
|
||||||
github.com/hashicorp/vault/api/auth/approle v0.1.1 h1:R5yA+xcNvw1ix6bDuWOaLOq2L4L77zDCVsethNw97xQ=
|
github.com/hashicorp/vault/api/auth/approle v0.1.1 h1:R5yA+xcNvw1ix6bDuWOaLOq2L4L77zDCVsethNw97xQ=
|
||||||
github.com/hashicorp/vault/api/auth/approle v0.1.1/go.mod h1:mHOLgh//xDx4dpqXoq6tS8Ob0FoCFWLU2ibJ26Lfmag=
|
github.com/hashicorp/vault/api/auth/approle v0.1.1/go.mod h1:mHOLgh//xDx4dpqXoq6tS8Ob0FoCFWLU2ibJ26Lfmag=
|
||||||
|
github.com/hashicorp/vault/api/auth/kubernetes v0.1.0 h1:6BtyahbF4aQp8gg3ww0A/oIoqzbhpNP1spXU3nHE0n0=
|
||||||
|
github.com/hashicorp/vault/api/auth/kubernetes v0.1.0/go.mod h1:Pdgk78uIs0mgDOLvc3a+h/vYIT9rznw2sz+ucuH9024=
|
||||||
github.com/hashicorp/vault/sdk v0.3.0 h1:kR3dpxNkhh/wr6ycaJYqp6AFT/i2xaftbfnwZduTKEY=
|
github.com/hashicorp/vault/sdk v0.3.0 h1:kR3dpxNkhh/wr6ycaJYqp6AFT/i2xaftbfnwZduTKEY=
|
||||||
github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
|
github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||||
|
|
Loading…
Reference in a new issue