Skip to content

Commit c96327c

Browse files
update
1 parent af0889b commit c96327c

3 files changed

Lines changed: 198 additions & 24 deletions

File tree

.github/workflows/README.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# GitHub Actions Workflows
2+
3+
## SPNEGO Integration Tests
4+
5+
**File**: `integration-tests.yml`
6+
7+
### What It Does
8+
9+
Runs end-to-end integration tests for SPNEGO proxy authentication using Docker containers for KDC and Squid proxy.
10+
11+
### When It Runs
12+
13+
**Push Events**:
14+
- `main` branch
15+
- `master` branch
16+
- `add-proxy-auth-support-tests` branch
17+
18+
**Pull Requests** that modify:
19+
- Any Go files (`**.go`)
20+
- Go module files (`go.mod`, `go.sum`)
21+
- Test infrastructure (`pkg/testinfra/**`)
22+
- Integration tests (`integration/**`)
23+
- Proxy auth files (`proxy_auth*.go`)
24+
- This workflow file
25+
26+
### Test Execution
27+
28+
```bash
29+
go test -v -tags=integration -run TestSPNEGOProxy -timeout=15m ./integration/...
30+
```
31+
32+
**Tests Run**:
33+
- `TestSPNEGOProxy/SPNEGOAuthentication` - SPNEGO authenticator creation and validation
34+
- `TestSPNEGOProxy/SPNEGOWithPivnetClient` - Pivnet client with SPNEGO proxy (if `PIVNET_API_TOKEN` is set)
35+
36+
### Environment Variables
37+
38+
- `CGO_ENABLED=1` - Required for some dependencies
39+
- `TESTCONTAINERS_RYUK_DISABLED=true` - Disables Ryuk container reaper
40+
- `DOCKER_HOST=unix:///var/run/docker.sock` - Docker socket path
41+
- `PIVNET_API_TOKEN` - Optional secret for Pivnet API testing
42+
43+
### Secrets Required
44+
45+
#### Optional Secrets
46+
47+
- `PIVNET_API_TOKEN` - Pivnet API token for testing with actual API
48+
- If not set, the Pivnet client test is skipped
49+
- To add: Go to repository Settings → Secrets and variables → Actions → New repository secret
50+
51+
### Infrastructure
52+
53+
The workflow uses Docker to spin up:
54+
1. **KDC Container** (`gcavalcante8808/krb5-server:latest`)
55+
- Kerberos Key Distribution Center
56+
- Creates test principals
57+
- Provides authentication service
58+
59+
2. **Squid Proxy Container** (`ubuntu/squid:latest`)
60+
- Configured with SPNEGO authentication
61+
- Uses keytab from KDC
62+
- Proxies HTTP/HTTPS requests
63+
64+
### Expected Behavior
65+
66+
**Success Cases**:
67+
- Infrastructure starts successfully (KDC + Proxy)
68+
- Principals are created
69+
- Configuration files are generated
70+
- Tests validate the setup
71+
72+
⚠️ **Known Limitations**:
73+
- Kerberos authentication from GitHub Actions runner to containerized KDC may fail
74+
- This is expected due to container networking
75+
- Tests validate infrastructure and handle this gracefully with skip/pass
76+
77+
### Artifacts
78+
79+
On test failure, the following artifacts are uploaded:
80+
- Test logs from `/tmp/*.log`
81+
- Kerberos config files from `/tmp/*/krb5.conf`
82+
- Retained for 7 days
83+
84+
### Local Testing
85+
86+
To run the same tests locally:
87+
88+
```bash
89+
# Basic run
90+
TESTCONTAINERS_RYUK_DISABLED=true go test -tags=integration -v -run TestSPNEGOProxy -timeout=15m ./integration/...
91+
92+
# With Pivnet API token
93+
export PIVNET_API_TOKEN="your-token"
94+
TESTCONTAINERS_RYUK_DISABLED=true go test -tags=integration -v -run TestSPNEGOProxy -timeout=15m ./integration/...
95+
```
96+
97+
### Troubleshooting
98+
99+
#### Workflow Fails to Start
100+
101+
- Check if Docker is available in the runner
102+
- Verify `actions/checkout@v4` and `actions/setup-go@v5` are working
103+
104+
#### Tests Timeout
105+
106+
- Increase timeout in workflow (currently 15m)
107+
- Check Docker resource limits in GitHub Actions
108+
109+
#### Image Pull Failures
110+
111+
- Tests use public Docker images by default
112+
- If you need private registry, update `pkg/testinfra/config.go`
113+
114+
#### Tests Skip Due to Container Networking
115+
116+
- This is expected behavior
117+
- Tests validate infrastructure setup
118+
- Full Kerberos auth may not work in CI environment
119+
120+
### Monitoring
121+
122+
Check workflow status:
123+
- Repository → Actions tab
124+
- Look for "SPNEGO Integration Tests" workflow
125+
- Click on specific run to see logs
126+
127+
### Maintenance
128+
129+
#### Update Go Version
130+
131+
The workflow uses `go-version-file: 'go.mod'` to automatically use the Go version specified in `go.mod`.
132+
133+
#### Update Docker Images
134+
135+
Update in `pkg/testinfra/config.go`:
136+
```go
137+
const (
138+
KDCImage = "gcavalcante8808/krb5-server:latest"
139+
SquidImage = "ubuntu/squid:latest"
140+
)
141+
```
142+
143+
#### Add More Tests
144+
145+
To run additional tests, update the test command:
146+
```yaml
147+
- name: Run SPNEGO Integration Tests
148+
run: |
149+
go test -v -tags=integration -run "TestSPNEGO|TestBasic" -timeout=15m ./integration/...
150+
```
151+
152+
## Future Workflows
153+
154+
Consider adding:
155+
- Unit tests workflow
156+
- Linting workflow
157+
- Security scanning
158+
- Release workflow
159+

integration/e2e_spnego_test.go

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,7 @@ func testSPNEGOAuthentication(t *testing.T, env *testinfra.SPNEGOEnv) {
5858
env.KRB5Path,
5959
)
6060
if err != nil {
61-
// Kerberos authentication from host to containerized KDC often fails due to
62-
// container networking limitations. The infrastructure is validated:
63-
// ✅ KDC container started and initialized
64-
// ✅ Principals created successfully
65-
// ✅ Squid proxy configured with SPNEGO
66-
// ✅ Configuration files generated correctly
67-
t.Logf("SPNEGO auth creation failed (expected in containerized environment): %v", err)
68-
t.Log("✅ Infrastructure validated successfully")
69-
t.Skip("Skipping full Kerberos auth due to container networking limitations")
70-
return
61+
t.Fatalf("Failed to create SPNEGO authenticator: %v", err)
7162
}
7263

7364
t.Log("✅ SPNEGO authenticator created successfully")
@@ -138,11 +129,7 @@ func testSPNEGOWithPivnetClient(t *testing.T, env *testinfra.SPNEGOEnv) {
138129

139130
client, err := pivnet.NewClientWithProxy(tokenService, config, lgr)
140131
if err != nil {
141-
// Expected to fail due to container networking
142-
t.Logf("Client creation failed (expected): %v", err)
143-
t.Log("✅ Proxy configuration validated")
144-
t.Skip("Skipping due to container networking limitations")
145-
return
132+
t.Fatalf("Failed to create client with SPNEGO proxy: %v", err)
146133
}
147134

148135
// Try to list products

pkg/testinfra/kdc.go

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package testinfra
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"time"
78

89
"github.com/testcontainers/testcontainers-go"
@@ -40,17 +41,38 @@ func StartKDC(ctx context.Context, networkName string) (testcontainers.Container
4041

4142
// CreatePrincipal creates a user principal.
4243
func CreatePrincipal(ctx context.Context, kdc testcontainers.Container, principal, password string) error {
44+
// Create the principal
4345
cmd := []string{
4446
"kadmin.local", "-q",
4547
fmt.Sprintf("addprinc -pw %s %s@%s", password, principal, TestRealm),
4648
}
4749

48-
exitCode, _, err := kdc.Exec(ctx, cmd)
50+
exitCode, reader, err := kdc.Exec(ctx, cmd)
4951
if err != nil {
5052
return fmt.Errorf("failed to create principal %s: %w", principal, err)
5153
}
52-
if exitCode != 0 {
53-
return fmt.Errorf("kadmin.local exited with code %d", exitCode)
54+
if reader != nil {
55+
output, _ := io.ReadAll(reader)
56+
if exitCode != 0 {
57+
return fmt.Errorf("kadmin.local exited with code %d, output: %s", exitCode, string(output))
58+
}
59+
}
60+
61+
// Verify the principal was created
62+
verifyCmd := []string{
63+
"kadmin.local", "-q",
64+
fmt.Sprintf("getprinc %s@%s", principal, TestRealm),
65+
}
66+
67+
exitCode, reader, err = kdc.Exec(ctx, verifyCmd)
68+
if err != nil {
69+
return fmt.Errorf("failed to verify principal %s: %w", principal, err)
70+
}
71+
if reader != nil {
72+
output, _ := io.ReadAll(reader)
73+
if exitCode != 0 {
74+
return fmt.Errorf("principal %s not found after creation, output: %s", principal, string(output))
75+
}
5476
}
5577

5678
return nil
@@ -65,25 +87,31 @@ func CreateServicePrincipal(ctx context.Context, kdc testcontainers.Container, s
6587
fmt.Sprintf("addprinc -randkey %s", spn),
6688
}
6789

68-
exitCode, _, err := kdc.Exec(ctx, createCmd)
90+
exitCode, reader, err := kdc.Exec(ctx, createCmd)
6991
if err != nil {
7092
return fmt.Errorf("failed to create service principal %s: %w", spn, err)
7193
}
72-
if exitCode != 0 {
73-
return fmt.Errorf("kadmin.local addprinc exited with code %d", exitCode)
94+
if reader != nil {
95+
output, _ := io.ReadAll(reader)
96+
if exitCode != 0 {
97+
return fmt.Errorf("kadmin.local addprinc exited with code %d, output: %s", exitCode, string(output))
98+
}
7499
}
75100

76101
keytabCmd := []string{
77102
"kadmin.local", "-q",
78103
fmt.Sprintf("ktadd -k /tmp/proxy.keytab %s", spn),
79104
}
80105

81-
exitCode, _, err = kdc.Exec(ctx, keytabCmd)
106+
exitCode, reader, err = kdc.Exec(ctx, keytabCmd)
82107
if err != nil {
83108
return fmt.Errorf("failed to create keytab for %s: %w", spn, err)
84109
}
85-
if exitCode != 0 {
86-
return fmt.Errorf("kadmin.local ktadd exited with code %d", exitCode)
110+
if reader != nil {
111+
output, _ := io.ReadAll(reader)
112+
if exitCode != 0 {
113+
return fmt.Errorf("kadmin.local ktadd exited with code %d, output: %s", exitCode, string(output))
114+
}
87115
}
88116

89117
verifyCmd := []string{"ls", "-la", "/tmp/proxy.keytab"}

0 commit comments

Comments
 (0)