diff --git a/CHANGELOG.md b/CHANGELOG.md index bc878e251..9f1aa724a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ## Release (2026-MM-DD) +- `core`: [v0.26.0](core/CHANGELOG.md#v0260) + - **Feature:** Added support for custom `TokenEndpoint` in service account credentials. - `core`: [v0.25.0](core/CHANGELOG.md#v0250) - Minimal go version is now Go 1.25 - `alb`: diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 6303e9ef2..32c8d176c 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.26.0 +- **Feature:** Added support for custom `TokenEndpoint` in service account credentials. + ## v0.25.0 - Minimal go version is now Go 1.25 diff --git a/core/VERSION b/core/VERSION index 5bd9725a3..eaf8bae70 100644 --- a/core/VERSION +++ b/core/VERSION @@ -1 +1 @@ -v0.25.0 +v0.26.0 diff --git a/core/clients/key_flow.go b/core/clients/key_flow.go index bac4022cd..6c5624b88 100644 --- a/core/clients/key_flow.go +++ b/core/clients/key_flow.go @@ -78,11 +78,12 @@ type ServiceAccountKeyResponse struct { } type ServiceAccountKeyCredentials struct { - Aud string `json:"aud"` - Iss string `json:"iss"` - Kid string `json:"kid"` - PrivateKey *string `json:"privateKey,omitempty"` - Sub uuid.UUID `json:"sub"` + Aud string `json:"aud"` + Iss string `json:"iss"` + Kid string `json:"kid"` + PrivateKey *string `json:"privateKey,omitempty"` + Sub uuid.UUID `json:"sub"` + TokenEndpoint string `json:"tokenEndpoint"` } // GetConfig returns the flow configuration @@ -117,13 +118,26 @@ func (c *KeyFlow) GetToken() TokenResponseBody { return *c.token } +// getCredentialsTokenEndpoint returns the token endpoint from credentials or a default fallback +func (cfg *KeyFlowConfig) getCredentialsTokenEndpoint() string { + if cfg.ServiceAccountKey == nil || cfg.ServiceAccountKey.Credentials == nil { + return tokenAPI + } + + if cfg.ServiceAccountKey.Credentials.TokenEndpoint == "" { + return tokenAPI + } + + return cfg.ServiceAccountKey.Credentials.TokenEndpoint +} + func (c *KeyFlow) Init(cfg *KeyFlowConfig) error { // No concurrency at this point, so no mutex check needed c.token = &TokenResponseBody{} c.config = cfg if c.config.TokenUrl == "" { - c.config.TokenUrl = tokenAPI + c.config.TokenUrl = c.config.getCredentialsTokenEndpoint() } c.tokenExpirationLeeway = defaultTokenExpirationLeeway diff --git a/core/clients/key_flow_test.go b/core/clients/key_flow_test.go index 045bd28d2..f2d57886c 100644 --- a/core/clients/key_flow_test.go +++ b/core/clients/key_flow_test.go @@ -76,12 +76,14 @@ func TestKeyFlowInit(t *testing.T) { genPrivateKey bool invalidPrivateKey bool wantErr bool + wantTokenUrl string }{ { name: "ok-provided-private-key", serviceAccountKey: fixtureServiceAccountKey(), genPrivateKey: true, wantErr: false, + wantTokenUrl: tokenAPI, }, { name: "missing_private_key", @@ -102,6 +104,15 @@ func TestKeyFlowInit(t *testing.T) { invalidPrivateKey: true, wantErr: true, }, + { + name: "ok-custom-token-endpoint", + serviceAccountKey: fixtureServiceAccountKey(func(s *ServiceAccountKeyResponse) { + s.Credentials.TokenEndpoint = "https://custom.stackit.cloud/token" + }), + genPrivateKey: true, + wantErr: false, + wantTokenUrl: "https://custom.stackit.cloud/token", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -126,6 +137,12 @@ func TestKeyFlowInit(t *testing.T) { if keyFlow.config == nil { t.Error("config is nil") } + + if !tt.wantErr && tt.wantTokenUrl != "" { + if keyFlow.config.TokenUrl != tt.wantTokenUrl { + t.Errorf("KeyFlow.Init() TokenUrl = %v, wantTokenUrl %v", keyFlow.config.TokenUrl, tt.wantTokenUrl) + } + } }) } }