Skip to content

Commit ffa53d1

Browse files
author
rzisholz
committed
CP-21164: add jwtsource package for reading projected SA tokens
Introduces a small, isolated interface for reading a JWT from a file path — the first piece of the upcoming Conjur JWT authentication path, split out on its own since nothing else in this PR depends on it yet.
1 parent 398313d commit ffa53d1

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// internal/cyberark/jwtsource/jwtsource.go
2+
package jwtsource
3+
4+
import (
5+
"context"
6+
"fmt"
7+
"os"
8+
"strings"
9+
)
10+
11+
// DefaultTokenPath is the default projected ServiceAccount token mount (aud=conjur).
12+
const DefaultTokenPath = "/var/run/secrets/tokens/jwt"
13+
14+
// Source produces a raw JWT to exchange at SMS authn-jwt.
15+
type Source interface {
16+
Read(ctx context.Context) (string, error)
17+
}
18+
19+
type fileSource struct{ path string }
20+
21+
// NewFileSource reads a JWT from a file (the projected SA token).
22+
func NewFileSource(path string) Source {
23+
if path == "" {
24+
path = DefaultTokenPath
25+
}
26+
return &fileSource{path: path}
27+
}
28+
29+
func (f *fileSource) Read(_ context.Context) (string, error) {
30+
b, err := os.ReadFile(f.path)
31+
if err != nil {
32+
return "", fmt.Errorf("jwt source file %q not found or unreadable (is the projected serviceAccountToken volume mounted?): %w", f.path, err)
33+
}
34+
tok := strings.TrimSpace(string(b))
35+
if tok == "" {
36+
return "", fmt.Errorf("jwt source file %q is empty", f.path)
37+
}
38+
return tok, nil
39+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// internal/cyberark/jwtsource/jwtsource_test.go
2+
package jwtsource
3+
4+
import (
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestFileSource_ReadsToken(t *testing.T) {
13+
dir := t.TempDir()
14+
p := filepath.Join(dir, "jwt")
15+
require.NoError(t, os.WriteFile(p, []byte("the-jwt\n"), 0o600))
16+
got, err := NewFileSource(p).Read(t.Context())
17+
require.NoError(t, err)
18+
require.Equal(t, "the-jwt", got) // trimmed
19+
}
20+
21+
func TestFileSource_MissingFile(t *testing.T) {
22+
_, err := NewFileSource("/no/such/file").Read(t.Context())
23+
require.Error(t, err)
24+
}
25+
26+
func TestFileSource_EmptyFile(t *testing.T) {
27+
dir := t.TempDir()
28+
p := filepath.Join(dir, "jwt")
29+
require.NoError(t, os.WriteFile(p, []byte(" \n"), 0o600))
30+
_, err := NewFileSource(p).Read(t.Context())
31+
require.Error(t, err)
32+
}

0 commit comments

Comments
 (0)