1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Conjur E2E Tests for K8s JWT Authentication (#3217)

Signed-off-by: Shlomo Heigh <shlomo.heigh@cyberark.com>
This commit is contained in:
Shlomo Zalman Heigh 2024-03-01 11:36:19 -05:00 committed by GitHub
parent 91139d07f4
commit 1d3209da59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 391 additions and 59 deletions

View file

@ -44,6 +44,11 @@ type ConjurJWT struct {
// The conjur authn jwt webservice id
ServiceID string `json:"serviceID"`
// Optional HostID for JWT authentication. This may be used depending
// on how the Conjur JWT authenticator policy is configured.
// +optional
HostID string `json:"hostId"`
// Optional SecretRef that refers to a key in a Secret resource containing JWT token to
// authenticate with Conjur using the JWT authentication method.
// +optional

View file

@ -2311,6 +2311,11 @@ spec:
properties:
account:
type: string
hostId:
description: |-
Optional HostID for JWT authentication. This may be used depending
on how the Conjur JWT authenticator policy is configured.
type: string
secretRef:
description: |-
Optional SecretRef that refers to a key in a Secret resource containing JWT token to

View file

@ -2311,6 +2311,11 @@ spec:
properties:
account:
type: string
hostId:
description: |-
Optional HostID for JWT authentication. This may be used depending
on how the Conjur JWT authenticator policy is configured.
type: string
secretRef:
description: |-
Optional SecretRef that refers to a key in a Secret resource containing JWT token to

View file

@ -2764,6 +2764,11 @@ spec:
properties:
account:
type: string
hostId:
description: |-
Optional HostID for JWT authentication. This may be used depending
on how the Conjur JWT authenticator policy is configured.
type: string
secretRef:
description: |-
Optional SecretRef that refers to a key in a Secret resource containing JWT token to
@ -7918,6 +7923,11 @@ spec:
properties:
account:
type: string
hostId:
description: |-
Optional HostID for JWT authentication. This may be used depending
on how the Conjur JWT authenticator policy is configured.
type: string
secretRef:
description: |-
Optional SecretRef that refers to a key in a Secret resource containing JWT token to

View file

@ -1943,6 +1943,19 @@ string
</tr>
<tr>
<td>
<code>hostId</code></br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Optional HostID for JWT authentication. This may be used depending
on how the Conjur JWT authenticator policy is configured.</p>
</td>
</tr>
<tr>
<td>
<code>secretRef</code></br>
<em>
<a href="https://pkg.go.dev/github.com/external-secrets/external-secrets/apis/meta/v1#SecretKeySelector">

View file

@ -14,8 +14,10 @@ limitations under the License.
package addon
import (
"context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
@ -51,7 +53,8 @@ func NewConjur(namespace string) *Conjur {
Namespace: namespace,
ReleaseName: fmt.Sprintf("conjur-%s", namespace), // avoid cluster role collision
Chart: fmt.Sprintf("%s/conjur-oss", repo),
ChartVersion: "2.0.7",
// Use latest version of Conjur OSS. To pin to a specific version, uncomment the following line.
// ChartVersion: "2.0.7",
Repo: ChartRepo{
Name: repo,
URL: "https://cyberark.github.io/helm-charts",
@ -148,10 +151,101 @@ func (l *Conjur) initConjur() error {
func (l *Conjur) configureConjur() error {
ginkgo.By("configuring conjur")
// TODO: This will be used for the JWT tests
// Construct Conjur policy for authn-jwt. This uses the token-app-property "sub" to
// authenticate the host. This means that Conjur will determine which host is authenticating
// based on the "sub" claim in the JWT token, which is provided by the Kubernetes service account.
policy := `- !policy
id: conjur/authn-jwt/eso-tests
body:
- !webservice
- !variable public-keys
- !variable issuer
- !variable token-app-property
- !variable audience`
_, err := l.ConjurClient.LoadPolicy(conjurapi.PolicyModePost, "root", strings.NewReader(policy))
if err != nil {
return fmt.Errorf("unable to load authn-jwt policy: %w", err)
}
// Construct Conjur policy for authn-jwt-hostid. This does not use the token-app-property variable
// and instead uses the HostID passed in the authentication URL to determine which host is authenticating.
// This is not the recommended way to authenticate, but it is needed for certain use cases where the
// JWT token does not contain the "sub" claim.
policy = `- !policy
id: conjur/authn-jwt/eso-tests-hostid
body:
- !webservice
- !variable public-keys
- !variable issuer
- !variable audience`
_, err = l.ConjurClient.LoadPolicy(conjurapi.PolicyModePost, "root", strings.NewReader(policy))
if err != nil {
return fmt.Errorf("unable to load authn-jwt policy: %w", err)
}
// Fetch the jwks info from the k8s cluster
pubKeysJson, issuer, err := l.fetchJWKSandIssuer()
if err != nil {
return fmt.Errorf("unable to fetch jwks and issuer: %w", err)
}
// Set the variables for the authn-jwt policies
secrets := map[string]string{
"conjur/authn-jwt/eso-tests/audience": l.ConjurURL,
"conjur/authn-jwt/eso-tests/issuer": issuer,
"conjur/authn-jwt/eso-tests/public-keys": string(pubKeysJson),
"conjur/authn-jwt/eso-tests/token-app-property": "sub",
"conjur/authn-jwt/eso-tests-hostid/audience": l.ConjurURL,
"conjur/authn-jwt/eso-tests-hostid/issuer": issuer,
"conjur/authn-jwt/eso-tests-hostid/public-keys": string(pubKeysJson),
}
for secretPath, secretValue := range secrets {
err := l.ConjurClient.AddSecret(secretPath, secretValue)
if err != nil {
return fmt.Errorf("unable to add secret %s: %w", secretPath, err)
}
}
return nil
}
func (l *Conjur) fetchJWKSandIssuer() (pubKeysJson string, issuer string, err error) {
kc := l.chart.config.KubeClientSet
// Fetch the openid-configuration
res, err := kc.CoreV1().RESTClient().Get().AbsPath("/.well-known/openid-configuration").DoRaw(context.Background())
if err != nil {
return "", "", fmt.Errorf("unable to fetch openid-configuration: %w", err)
}
var openidConfig map[string]interface{}
json.Unmarshal(res, &openidConfig)
issuer = openidConfig["issuer"].(string)
// Fetch the jwks
jwksJson, err := kc.CoreV1().RESTClient().Get().AbsPath("/openid/v1/jwks").DoRaw(context.Background())
if err != nil {
return "", "", fmt.Errorf("unable to fetch jwks: %w", err)
}
var jwks map[string]interface{}
json.Unmarshal(jwksJson, &jwks)
// Create a JSON object with the jwks that can be used by Conjur
pubKeysObj := map[string]interface{}{
"type": "jwks",
"value": jwks,
}
pubKeysJsonObj, err := json.Marshal(pubKeysObj)
if err != nil {
return "", "", fmt.Errorf("unable to marshal jwks: %w", err)
}
pubKeysJson = string(pubKeysJsonObj)
return pubKeysJson, issuer, nil
}
func (l *Conjur) Logs() error {
return l.chart.Logs()
}

View file

@ -1,4 +1,4 @@
authenticators: authn,authn-jwt/eso-tests
authenticators: authn,authn-jwt/eso-tests,authn-jwt/eso-tests-hostid
logLevel: "debug"
service:
external:

View file

@ -21,8 +21,9 @@ import (
)
const (
withTokenAuth = "with apikey auth"
withJWTK8s = "with jwt k8s provider"
withTokenAuth = "with apikey auth"
withJWTK8s = "with jwt k8s provider"
withJWTK8sHostID = "with jwt k8s hostid provider"
)
var _ = Describe("[conjur]", Label("conjur"), func() {
@ -38,9 +39,17 @@ var _ = Describe("[conjur]", Label("conjur"), func() {
framework.Compose(withTokenAuth, f, common.JSONDataFromRewrite, useApiKeyAuth),
framework.Compose(withTokenAuth, f, common.SyncV1Alpha1, useApiKeyAuth),
// // use jwt k8s provider
// framework.Compose(withJWTK8s, f, common.JSONDataFromSync, useJWTK8sProvider),
// framework.Compose(withJWTK8s, f, common.JSONDataFromRewrite, useJWTK8sProvider),
// use jwt k8s provider
framework.Compose(withJWTK8s, f, common.SimpleDataSync, useJWTK8sProvider),
framework.Compose(withJWTK8s, f, common.SyncWithoutTargetName, useJWTK8sProvider),
framework.Compose(withJWTK8s, f, common.JSONDataFromSync, useJWTK8sProvider),
framework.Compose(withJWTK8s, f, common.JSONDataFromRewrite, useJWTK8sProvider),
// use jwt k8s hostid provider
framework.Compose(withJWTK8sHostID, f, common.SimpleDataSync, useJWTK8sHostIDProvider),
framework.Compose(withJWTK8sHostID, f, common.SyncWithoutTargetName, useJWTK8sHostIDProvider),
framework.Compose(withJWTK8sHostID, f, common.JSONDataFromSync, useJWTK8sHostIDProvider),
framework.Compose(withJWTK8sHostID, f, common.JSONDataFromRewrite, useJWTK8sHostIDProvider),
)
})
@ -48,6 +57,10 @@ func useApiKeyAuth(tc *framework.TestCase) {
tc.ExternalSecret.Spec.SecretStoreRef.Name = tc.Framework.Namespace.Name
}
// func useJWTK8sProvider(tc *framework.TestCase) {
// tc.ExternalSecret.Spec.SecretStoreRef.Name = jwtK8sProviderName
// }
func useJWTK8sProvider(tc *framework.TestCase) {
tc.ExternalSecret.Spec.SecretStoreRef.Name = jwtK8sProviderName
}
func useJWTK8sHostIDProvider(tc *framework.TestCase) {
tc.ExternalSecret.Spec.SecretStoreRef.Name = jwtK8sHostIDProviderName
}

View file

@ -0,0 +1,81 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package conjur
import (
"bytes"
"text/template"
)
const createVariablePolicyTemplate = `- !variable
id: {{ .Key }}
- !permit
role: !host system:serviceaccount:{{ .Namespace }}:test-app-sa
privilege: [ read, execute ]
resource: !variable {{ .Key }}
- !permit
role: !host system:serviceaccount:{{ .Namespace }}:test-app-hostid-sa
privilege: [ read, execute ]
resource: !variable {{ .Key }}`
const deleteVariablePolicyTemplate = `- !delete
record: !variable {{ .Key }}`
const jwtHostPolicyTemplate = `- !host
id: {{ .HostID }}
annotations:
authn-jwt/{{ .ServiceID }}/sub: "{{ .HostID }}"
- !permit
role: !host {{ .HostID }}
privilege: [ read, authenticate ]
resource: !webservice conjur/authn-jwt/{{ .ServiceID }}`
func createVariablePolicy(key, namespace string) string {
return renderTemplate(createVariablePolicyTemplate, map[string]string{
"Key": key,
"Namespace": namespace,
})
}
func deleteVariablePolicy(key string) string {
return renderTemplate(deleteVariablePolicyTemplate, map[string]string{
"Key": key,
})
}
func createJwtHostPolicy(hostID, serviceID string) string {
return renderTemplate(jwtHostPolicyTemplate, map[string]string{
"HostID": hostID,
"ServiceID": serviceID,
})
}
func renderTemplate(templateText string, data map[string]string) string {
// Use golang templates to render the policy
tmpl, err := template.New("policy").Parse(templateText)
if err != nil {
// The templates are hardcoded, so this should never happen
panic(err)
}
output := new(bytes.Buffer)
err = tmpl.Execute(output, data)
if err != nil {
// The templates are hardcoded, so this should never happen
panic(err)
}
return output.String()
}

View file

@ -40,8 +40,8 @@ type conjurProvider struct {
}
const (
apiKeyAuthProviderName = "api-key-auth-provider"
jwtK8sProviderName = "jwt-k8s-provider"
jwtK8sProviderName = "jwt-k8s-provider"
jwtK8sHostIDProviderName = "jwt-k8s-hostid-provider"
)
func newConjurProvider(f *framework.Framework) *conjurProvider {
@ -49,12 +49,14 @@ func newConjurProvider(f *framework.Framework) *conjurProvider {
framework: f,
}
BeforeEach(prov.BeforeEach)
AfterEach(prov.AfterEach)
return prov
}
func (s *conjurProvider) CreateSecret(key string, val framework.SecretEntry) {
// Generate a policy file for the secret key
policy := "- !variable " + key
policy := createVariablePolicy(key, s.framework.Namespace.Name)
_, err := s.client.LoadPolicy(conjurapi.PolicyModePost, "root", strings.NewReader(policy))
Expect(err).ToNot(HaveOccurred())
@ -64,8 +66,7 @@ func (s *conjurProvider) CreateSecret(key string, val framework.SecretEntry) {
}
func (s *conjurProvider) DeleteSecret(key string) {
policy := `- !delete
record: !variable ` + key
policy := deleteVariablePolicy(key)
_, err := s.client.LoadPolicy(conjurapi.PolicyModePatch, "root", strings.NewReader(policy))
Expect(err).ToNot(HaveOccurred())
@ -79,7 +80,33 @@ func (s *conjurProvider) BeforeEach() {
s.url = c.ConjurURL
s.CreateApiKeyStore(c, ns)
// s.CreateJWTK8sStore(c, ns)
s.CreateJWTK8sStore(c, ns)
s.CreateJWTK8sHostIDStore(c, ns)
}
func (s *conjurProvider) AfterEach() {
// Print Conjur logs if the test failed
if !CurrentGinkgoTestDescription().Failed {
return
}
// Get logs from Conjur pod
ns := s.framework.Namespace.Name
pods, err := s.framework.KubeClientSet.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{})
if err != nil {
GinkgoWriter.Printf("Error getting pods: %s\n", err)
return
}
for _, pod := range pods.Items {
if strings.Contains(pod.Name, "conjur-oss") {
logs, err := s.framework.KubeClientSet.CoreV1().Pods(ns).GetLogs(pod.Name, &v1.PodLogOptions{Container: "conjur-oss"}).DoRaw(context.Background())
if err != nil {
GinkgoWriter.Printf("Error getting logs from Conjur pod: %s\n", err)
}
GinkgoWriter.Printf("Conjur logs:\n%s\n", logs)
}
}
}
func makeStore(name, ns string, c *addon.Conjur) *esv1beta1.SecretStore {
@ -103,7 +130,6 @@ func (s *conjurProvider) CreateApiKeyStore(c *addon.Conjur, ns string) {
By("creating a conjur secret")
conjurCreds := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
// Name: apiKeyAuthProviderName,
Name: ns,
Namespace: ns,
},
@ -116,18 +142,15 @@ func (s *conjurProvider) CreateApiKeyStore(c *addon.Conjur, ns string) {
Expect(err).ToNot(HaveOccurred())
By("creating an secret store for conjur")
// secretStore := makeStore(apiKeyAuthProviderName, ns, c)
secretStore := makeStore(ns, ns, c)
secretStore.Spec.Provider.Conjur.Auth = esv1beta1.ConjurAuth{
APIKey: &esv1beta1.ConjurAPIKey{
Account: "default",
UserRef: &esmeta.SecretKeySelector{
// Name: apiKeyAuthProviderName,
Name: ns,
Key: "username",
},
APIKeyRef: &esmeta.SecretKeySelector{
// Name: apiKeyAuthProviderName,
Name: ns,
Key: "apikey",
},
@ -137,20 +160,77 @@ func (s *conjurProvider) CreateApiKeyStore(c *addon.Conjur, ns string) {
Expect(err).ToNot(HaveOccurred())
}
// func (s conjurProvider) CreateJWTK8sStore(c *addon.Conjur, ns string) {
// secretStore := makeStore(jwtK8sProviderName, ns, c)
// secretStore.Spec.Provider.Conjur.Auth = esv1beta1.ConjurAuth{
// Jwt: &esv1beta1.ConjurJWT{
// Account: "default",
// ServiceID: "eso-tests",
// ServiceAccountRef: &esmeta.ServiceAccountSelector{
// Name: "default",
// Audiences: []string{
// c.ConjurURL,
// },
// },
// },
// }
// err := s.framework.CRClient.Create(context.Background(), secretStore)
// Expect(err).ToNot(HaveOccurred())
// }
func (s conjurProvider) CreateJWTK8sStore(c *addon.Conjur, ns string) {
// Create a service account
sa := &v1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "test-app-sa",
Namespace: ns,
},
}
err := s.framework.CRClient.Create(context.Background(), sa)
Expect(err).ToNot(HaveOccurred())
// Add the service account to the Conjur policy with permissions to
// authenticate with authn-jwt
saName := "system:serviceaccount:" + ns + ":test-app-sa"
policy := createJwtHostPolicy(saName, "eso-tests")
_, err = s.client.LoadPolicy(conjurapi.PolicyModePost, "root", strings.NewReader(policy))
Expect(err).ToNot(HaveOccurred())
// Now create a secret store that uses the service account to authenticate
secretStore := makeStore(jwtK8sProviderName, ns, c)
secretStore.Spec.Provider.Conjur.Auth = esv1beta1.ConjurAuth{
Jwt: &esv1beta1.ConjurJWT{
Account: "default",
ServiceID: "eso-tests",
ServiceAccountRef: &esmeta.ServiceAccountSelector{
Name: "test-app-sa",
Audiences: []string{
c.ConjurURL,
},
},
},
}
err = s.framework.CRClient.Create(context.Background(), secretStore)
Expect(err).ToNot(HaveOccurred())
}
func (s conjurProvider) CreateJWTK8sHostIDStore(c *addon.Conjur, ns string) {
// Create a service account
sa := &v1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "test-app-hostid-sa",
Namespace: ns,
},
}
err := s.framework.CRClient.Create(context.Background(), sa)
Expect(err).ToNot(HaveOccurred())
// Add the service account to the Conjur policy with permissions to
// authenticate with authn-jwt
saName := "system:serviceaccount:" + ns + ":test-app-hostid-sa"
policy := createJwtHostPolicy(saName, "eso-tests-hostid")
_, err = s.client.LoadPolicy(conjurapi.PolicyModePost, "root", strings.NewReader(policy))
Expect(err).ToNot(HaveOccurred())
// Now create a secret store that uses the service account to authenticate
secretStore := makeStore(jwtK8sHostIDProviderName, ns, c)
secretStore.Spec.Provider.Conjur.Auth = esv1beta1.ConjurAuth{
Jwt: &esv1beta1.ConjurJWT{
Account: "default",
HostID: "host/" + saName,
ServiceID: "eso-tests-hostid",
ServiceAccountRef: &esmeta.ServiceAccountSelector{
Name: "test-app-hostid-sa",
Audiences: []string{
c.ConjurURL,
},
},
},
}
err = s.framework.CRClient.Create(context.Background(), secretStore)
Expect(err).ToNot(HaveOccurred())
}

View file

@ -95,7 +95,7 @@ func (p *Client) newClientFromJwt(ctx context.Context, config conjurapi.Config,
return nil, getJWTError
}
client, clientError := p.clientAPI.NewClientFromJWT(config, jwtToken, jwtAuth.ServiceID)
client, clientError := p.clientAPI.NewClientFromJWT(config, jwtToken, jwtAuth.ServiceID, jwtAuth.HostID)
if clientError != nil {
return nil, clientError
}

View file

@ -17,6 +17,7 @@ package conjur
import (
"fmt"
"net/http"
"net/url"
"strings"
"time"
@ -33,7 +34,7 @@ type SecretsClient interface {
// SecretsClientFactory is an interface for creating a Conjur client.
type SecretsClientFactory interface {
NewClientFromKey(config conjurapi.Config, loginPair authn.LoginPair) (SecretsClient, error)
NewClientFromJWT(config conjurapi.Config, jwtToken string, jwtServiceID string) (SecretsClient, error)
NewClientFromJWT(config conjurapi.Config, jwtToken string, jwtServiceID, jwtHostID string) (SecretsClient, error)
}
// ClientAPIImpl is an implementation of the ClientAPI interface.
@ -46,7 +47,7 @@ func (c *ClientAPIImpl) NewClientFromKey(config conjurapi.Config, loginPair auth
// NewClientFromJWT creates a new Conjur client from a JWT token.
// cannot use the built-in function "conjurapi.NewClientFromJwt" because it requires environment variables
// see: https://github.com/cyberark/conjur-api-go/blob/b698692392a38e5d38b8440f32ab74206544848a/conjurapi/client.go#L130
func (c *ClientAPIImpl) NewClientFromJWT(config conjurapi.Config, jwtToken, jwtServiceID string) (SecretsClient, error) {
func (c *ClientAPIImpl) NewClientFromJWT(config conjurapi.Config, jwtToken, jwtServiceID, jwtHostID string) (SecretsClient, error) {
jwtTokenString := fmt.Sprintf("jwt=%s", jwtToken)
var httpClient *http.Client
@ -63,7 +64,13 @@ func (c *ClientAPIImpl) NewClientFromJWT(config conjurapi.Config, jwtToken, jwtS
httpClient = &http.Client{Timeout: time.Second * 10}
}
authnJwtURL := strings.Join([]string{config.ApplianceURL, "authn-jwt", jwtServiceID, config.Account, "authenticate"}, "/")
var authnJwtURL string
// If a hostID is provided, it must be included in the URL
if jwtHostID != "" {
authnJwtURL = strings.Join([]string{config.ApplianceURL, "authn-jwt", jwtServiceID, config.Account, url.PathEscape(jwtHostID), "authenticate"}, "/")
} else {
authnJwtURL = strings.Join([]string{config.ApplianceURL, "authn-jwt", jwtServiceID, config.Account, "authenticate"}, "/")
}
req, err := http.NewRequest("POST", authnJwtURL, strings.NewReader(jwtTokenString))
if err != nil {

View file

@ -39,10 +39,13 @@ import (
)
var (
svcURL = "https://example.com"
svcUser = "user"
svcApikey = "apikey"
svcAccount = "account1"
svcURL = "https://example.com"
svcUser = "user"
svcApikey = "apikey"
svcAccount = "account1"
jwtAuthenticator = "jwt-authenticator"
jwtAuthnService = "jwt-auth-service"
jwtSecretName = "jwt-secret"
)
func makeValidRef(k string) *esv1beta1.ExternalSecretDataRemoteRef {
@ -81,27 +84,27 @@ func TestValidateStore(t *testing.T) {
},
{
store: makeJWTSecretStore(svcURL, "conjur", "", "jwt-auth-service", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, "conjur", "", jwtAuthnService, "", "myconjuraccount"),
err: nil,
},
{
store: makeJWTSecretStore(svcURL, "", "jwt-secret", "jwt-auth-service", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, "", jwtSecretName, jwtAuthnService, "", "myconjuraccount"),
err: nil,
},
{
store: makeJWTSecretStore(svcURL, "conjur", "", "jwt-auth-service", ""),
store: makeJWTSecretStore(svcURL, "conjur", "", jwtAuthnService, "", ""),
err: fmt.Errorf("missing Auth.Jwt.Account"),
},
{
store: makeJWTSecretStore(svcURL, "conjur", "", "", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, "conjur", "", "", "", "myconjuraccount"),
err: fmt.Errorf("missing Auth.Jwt.ServiceID"),
},
{
store: makeJWTSecretStore("", "conjur", "", "jwt-auth-service", "myconjuraccount"),
store: makeJWTSecretStore("", "conjur", "", jwtAuthnService, "", "myconjuraccount"),
err: fmt.Errorf("conjur URL cannot be empty"),
},
{
store: makeJWTSecretStore(svcURL, "", "", "jwt-auth-service", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, "", "", jwtAuthnService, "", "myconjuraccount"),
err: fmt.Errorf("must specify Auth.Jwt.SecretRef or Auth.Jwt.ServiceAccountRef"),
},
@ -175,7 +178,22 @@ func TestGetSecret(t *testing.T) {
"JwtWithServiceAccountRefReadSecretSuccess": {
reason: "Should read a secret successfully using a JWT auth secret store that references a k8s service account.",
args: args{
store: makeJWTSecretStore(svcURL, "my-service-account", "", "jwt-authenticator", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, svcAccount, "", jwtAuthenticator, "", "myconjuraccount"),
kube: clientfake.NewClientBuilder().
WithObjects().Build(),
namespace: "default",
secretPath: "path/to/secret",
corev1: utilfake.NewCreateTokenMock().WithToken(createFakeJwtToken(true)),
},
want: want{
err: nil,
value: "secret",
},
},
"JwtWithServiceAccountRefWithHostIdReadSecretSuccess": {
reason: "Should read a secret successfully using a JWT auth secret store that references a k8s service account and uses a host ID.",
args: args{
store: makeJWTSecretStore(svcURL, svcAccount, "", jwtAuthenticator, "myhostid", "myconjuraccount"),
kube: clientfake.NewClientBuilder().
WithObjects().Build(),
namespace: "default",
@ -190,11 +208,11 @@ func TestGetSecret(t *testing.T) {
"JwtWithSecretRefReadSecretSuccess": {
reason: "Should read a secret successfully using an JWT auth secret store that references a k8s secret.",
args: args{
store: makeJWTSecretStore(svcURL, "", "jwt-secret", "jwt-authenticator", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, "", jwtSecretName, jwtAuthenticator, "", "myconjuraccount"),
kube: clientfake.NewClientBuilder().
WithObjects(&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "jwt-secret",
Name: jwtSecretName,
Namespace: "default",
},
Data: map[string][]byte{
@ -212,7 +230,7 @@ func TestGetSecret(t *testing.T) {
"JwtWithCABundleSuccess": {
reason: "Should read a secret successfully using a JWT auth secret store that references a k8s service account.",
args: args{
store: makeJWTSecretStore(svcURL, "my-service-account", "", "jwt-authenticator", "myconjuraccount"),
store: makeJWTSecretStore(svcURL, svcAccount, "", jwtAuthenticator, "", "myconjuraccount"),
kube: clientfake.NewClientBuilder().
WithObjects().Build(),
namespace: "default",
@ -364,7 +382,7 @@ func makeAPIKeySecretStore(svcURL, svcUser, svcApikey, svcAccount string) *esv1b
return store
}
func makeJWTSecretStore(svcURL, serviceAccountName, secretName, jwtServiceID, conjurAccount string) *esv1beta1.SecretStore {
func makeJWTSecretStore(svcURL, serviceAccountName, secretName, jwtServiceID, jwtHostID, conjurAccount string) *esv1beta1.SecretStore {
serviceAccountRef := &esmeta.ServiceAccountSelector{
Name: serviceAccountName,
Audiences: []string{"conjur"},
@ -392,6 +410,7 @@ func makeJWTSecretStore(svcURL, serviceAccountName, secretName, jwtServiceID, co
ServiceID: jwtServiceID,
ServiceAccountRef: serviceAccountRef,
SecretRef: secretRef,
HostID: jwtHostID,
},
},
},
@ -402,7 +421,7 @@ func makeJWTSecretStore(svcURL, serviceAccountName, secretName, jwtServiceID, co
}
func makeStoreWithCA(caSource, caData string) *esv1beta1.SecretStore {
store := makeJWTSecretStore(svcURL, "conjur", "", "jwt-auth-service", "myconjuraccount")
store := makeJWTSecretStore(svcURL, "conjur", "", jwtAuthnService, "", "myconjuraccount")
if caSource == "secret" {
store.Spec.Provider.Conjur.CAProvider = &esv1beta1.CAProvider{
Type: esv1beta1.CAProviderTypeSecret,
@ -502,7 +521,7 @@ func (c *ConjurMockAPIClient) NewClientFromKey(_ conjurapi.Config, _ authn.Login
return &fake.ConjurMockClient{}, nil
}
func (c *ConjurMockAPIClient) NewClientFromJWT(_ conjurapi.Config, _, _ string) (SecretsClient, error) {
func (c *ConjurMockAPIClient) NewClientFromJWT(_ conjurapi.Config, _, _, _ string) (SecretsClient, error) {
return &fake.ConjurMockClient{}, nil
}