Skip to content

Commit 997c609

Browse files
authored
feat: add serviceaccount authentication (#279)
1 parent 089a1a3 commit 997c609

File tree

5 files changed

+95
-17
lines changed

5 files changed

+95
-17
lines changed

common/apis/v1alpha1/clusteraccess_types.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ type AuthConfig struct {
4545

4646
// ServiceAccount is the name of the service account to use
4747
// +optional
48-
ServiceAccount string `json:"serviceAccount,omitempty"`
48+
ServiceAccount *ServiceAccountRef `json:"serviceAccount,omitempty"`
4949

5050
// ClientCertificateRef points to secrets containing client certificate and key for mTLS
5151
// +optional
@@ -85,6 +85,13 @@ type ClusterAccessStatus struct {
8585
Conditions []metav1.Condition `json:"conditions,omitempty"`
8686
}
8787

88+
type ServiceAccountRef struct {
89+
Name string `json:"name,omitempty"`
90+
Namespace string `json:"namespace,omitempty"`
91+
Audience []string `json:"audience,omitempty"`
92+
TokenExpiration *metav1.Duration `json:"token_expiration,omitempty"`
93+
}
94+
8895
//+kubebuilder:object:root=true
8996
//+kubebuilder:subresource:status
9097
//+kubebuilder:resource:scope=Cluster,shortName=ca

common/apis/v1alpha1/zz_generated.deepcopy.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/auth/config.go

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66
"errors"
77
"fmt"
88

9+
authv1 "k8s.io/api/authentication/v1"
910
corev1 "k8s.io/api/core/v1"
11+
1012
"k8s.io/apimachinery/pkg/types"
1113
"k8s.io/client-go/rest"
1214
"k8s.io/client-go/tools/clientcmd"
@@ -254,9 +256,49 @@ func ConfigureAuthentication(config *rest.Config, auth *gatewayv1alpha1.AuthConf
254256
return nil
255257
}
256258

257-
if auth.ServiceAccount != "" {
258-
// TODO: Implement service account-based authentication
259-
return errors.New("service account authentication not yet implemented")
259+
if auth.ServiceAccount != nil {
260+
var expirationSeconds int64
261+
if auth.ServiceAccount.TokenExpiration != nil {
262+
// If TokenExpiration is provided, use its value
263+
expirationSeconds = int64(auth.ServiceAccount.TokenExpiration.Duration.Seconds())
264+
} else {
265+
// If TokenExpiration is nil, use the desired default (3600 seconds = 1 hour)
266+
expirationSeconds = 3600
267+
fmt.Println("Warning: auth.ServiceAccount.TokenExpiration is nil, defaulting to 3600 seconds.")
268+
}
269+
270+
// Build the TokenRequest object
271+
tokenRequest := &authv1.TokenRequest{
272+
Spec: authv1.TokenRequestSpec{
273+
Audiences: auth.ServiceAccount.Audience,
274+
// Optionally set ExpirationSeconds, BoundObjectRef, etc.
275+
ExpirationSeconds: &expirationSeconds,
276+
},
277+
}
278+
279+
// Get the service account token using the Kubernetes API
280+
sa := &corev1.ServiceAccount{}
281+
err := k8sClient.Get(ctx, types.NamespacedName{
282+
Name: auth.ServiceAccount.Name,
283+
Namespace: auth.ServiceAccount.Namespace,
284+
}, sa)
285+
if err != nil {
286+
return errors.Join(errors.New("failed to get service account"), err)
287+
}
288+
289+
err = k8sClient.SubResource("token").Create(ctx, sa, tokenRequest)
290+
if err != nil {
291+
return errors.Join(errors.New("failed to create token request for service account"), err)
292+
}
293+
294+
if tokenRequest.Status.Token == "" {
295+
return errors.New("received empty token from TokenRequest API")
296+
}
297+
298+
config.BearerToken = tokenRequest.Status.Token
299+
300+
fmt.Println("Token:", config.BearerToken)
301+
return nil
260302
}
261303

262304
// No authentication configured - this might work for some clusters

config/crd/gateway.openmfp.org_clusteraccesses.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,18 @@ spec:
8282
serviceAccount:
8383
description: ServiceAccount is the name of the service account
8484
to use
85-
type: string
85+
properties:
86+
audience:
87+
items:
88+
type: string
89+
type: array
90+
name:
91+
type: string
92+
namespace:
93+
type: string
94+
token_expiration:
95+
type: string
96+
type: object
8697
type: object
8798
ca:
8899
description: CA configuration for the cluster

listener/reconciler/clusteraccess/auth_extractor_test.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,18 +169,6 @@ clusters:
169169
},
170170
wantErr: false,
171171
},
172-
{
173-
name: "service_account_auth_not_implemented",
174-
auth: &gatewayv1alpha1.AuthConfig{
175-
ServiceAccount: "test-sa",
176-
},
177-
mockSetup: func(m *mocks.MockClient) {},
178-
wantConfig: func(config *rest.Config) *rest.Config {
179-
return config
180-
},
181-
wantErr: true,
182-
errContains: "service account authentication not yet implemented",
183-
},
184172
{
185173
name: "secret_not_found",
186174
auth: &gatewayv1alpha1.AuthConfig{

0 commit comments

Comments
 (0)