vault auth unit tests

This commit is contained in:
Erik De Lamarter 2022-05-15 17:42:08 +02:00
parent 6c44291d8d
commit 6989c7f146
No known key found for this signature in database
GPG key ID: 1470FA5D23177A9B
5 changed files with 321 additions and 20 deletions

View file

@ -2,6 +2,7 @@ package approle
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"github.com/hashicorp/vault/api/auth/approle" "github.com/hashicorp/vault/api/auth/approle"
@ -12,6 +13,8 @@ import (
type AuthOptions struct { type AuthOptions struct {
RoleID string `json:"roleID,omitempty"` RoleID string `json:"roleID,omitempty"`
SecretID string `json:"secretID,omitempty"` SecretID string `json:"secretID,omitempty"`
SecretIDFile string `json:"secretIDFile,omitempty"`
SecretIDEnv string `json:"secretIDEnv,omitempty"`
IsWrappingToken bool `json:"isWrappingToken,omitempty"` IsWrappingToken bool `json:"isWrappingToken,omitempty"`
} }
@ -33,8 +36,25 @@ func NewApproleAuthMethod(mountPath string, options json.RawMessage) (*approle.A
loginOptions = append(loginOptions, approle.WithWrappingToken()) loginOptions = append(loginOptions, approle.WithWrappingToken())
} }
sid := approle.SecretID{ if opts.RoleID == "" {
FromString: opts.SecretID, return nil, errors.New("you must set roleID")
}
var sid approle.SecretID
if opts.SecretID != "" {
sid = approle.SecretID{
FromString: opts.SecretID,
}
} else if opts.SecretIDFile != "" {
sid = approle.SecretID{
FromFile: opts.SecretIDFile,
}
} else if opts.SecretIDEnv != "" {
sid = approle.SecretID{
FromEnv: opts.SecretIDEnv,
}
} else {
return nil, errors.New("you must set one of secretID, secretIDFile or secretIDEnv")
} }
approleAuth, err = approle.NewAppRoleAuth(opts.RoleID, &sid, loginOptions...) approleAuth, err = approle.NewAppRoleAuth(opts.RoleID, &sid, loginOptions...)

View file

@ -1,16 +1,171 @@
package approle package approle
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing" "testing"
vault "github.com/hashicorp/vault/api"
) )
func TestKubernetes_NewKubernetesAuthMethod(t *testing.T) { func testCAHelper(t *testing.T) (*url.URL, *vault.Client) {
mountPath := "approle" t.Helper()
raw := `{"roleID": "roleID", "secretID": "secretIDwrapped", "isWrappedToken": true}`
_, err := NewApproleAuthMethod(mountPath, json.RawMessage(raw)) 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 { if err != nil {
srv.Close()
t.Fatal(err) 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,
},
}
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
}
})
}
} }

View file

@ -2,6 +2,7 @@ package kubernetes
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"github.com/hashicorp/vault/api/auth/kubernetes" "github.com/hashicorp/vault/api/auth/kubernetes"
@ -31,6 +32,11 @@ func NewKubernetesAuthMethod(mountPath string, options json.RawMessage) (*kubern
if opts.TokenPath != "" { if opts.TokenPath != "" {
loginOptions = append(loginOptions, kubernetes.WithServiceAccountTokenPath(opts.TokenPath)) loginOptions = append(loginOptions, kubernetes.WithServiceAccountTokenPath(opts.TokenPath))
} }
if opts.Role == "" {
return nil, errors.New("you must set role")
}
kubernetesAuth, err = kubernetes.NewKubernetesAuth( kubernetesAuth, err = kubernetes.NewKubernetesAuth(
opts.Role, opts.Role,
loginOptions..., loginOptions...,

View file

@ -1,21 +1,149 @@
package kubernetes package kubernetes
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"path" "path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"testing" "testing"
vault "github.com/hashicorp/vault/api"
) )
func TestKubernetes_NewKubernetesAuthMethod(t *testing.T) { func testCAHelper(t *testing.T) (*url.URL, *vault.Client) {
_, filename, _, _ := runtime.Caller(0) t.Helper()
tokenPath := filepath.Join(path.Dir(filename), "token")
mountPath := "kubernetes"
raw := `{"role": "SomeRoleName", "tokenPath": "` + tokenPath + `"}`
_, err := NewKubernetesAuthMethod(mountPath, json.RawMessage(raw)) 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 { if err != nil {
srv.Close()
t.Fatal(err) 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
}
})
}
} }

View file

@ -182,8 +182,6 @@ func TestNew_register(t *testing.T) {
CertificateAuthority: caURL.String(), CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint, CertificateAuthorityFingerprint: testRootFingerprint,
Config: json.RawMessage(`{ Config: json.RawMessage(`{
"PKIMountPath": "pki",
"PKIRoleDefault": "pki-role",
"AuthType": "approle", "AuthType": "approle",
"AuthOptions": {"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false} "AuthOptions": {"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false}
}`), }`),
@ -204,8 +202,6 @@ func TestVaultCAS_CreateCertificate(t *testing.T) {
PKIRoleRSA: "rsa", PKIRoleRSA: "rsa",
PKIRoleEC: "ec", PKIRoleEC: "ec",
PKIRoleEd25519: "ed25519", PKIRoleEd25519: "ed25519",
AuthType: "approle",
AuthOptions: json.RawMessage(`{"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false}`),
} }
type fields struct { type fields struct {
@ -336,8 +332,6 @@ func TestVaultCAS_RevokeCertificate(t *testing.T) {
PKIRoleRSA: "rsa", PKIRoleRSA: "rsa",
PKIRoleEC: "ec", PKIRoleEC: "ec",
PKIRoleEd25519: "ed25519", PKIRoleEd25519: "ed25519",
AuthType: "approle",
AuthOptions: json.RawMessage(`{"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false}`),
} }
type fields struct { type fields struct {
@ -406,8 +400,6 @@ func TestVaultCAS_RenewCertificate(t *testing.T) {
PKIRoleRSA: "rsa", PKIRoleRSA: "rsa",
PKIRoleEC: "ec", PKIRoleEC: "ec",
PKIRoleEd25519: "ed25519", PKIRoleEd25519: "ed25519",
AuthType: "approle",
AuthOptions: json.RawMessage(`{"RoleID":"roleID","SecretID":"secretID","IsWrappingToken":false}`),
} }
type fields struct { type fields struct {