From 12cb633f8f497791b19c7f0d711cd1b6505747e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20B=C4=9Bh=C3=A1vka?= Date: Tue, 9 Dec 2025 15:16:29 +0100 Subject: [PATCH 1/2] Add the possibility to set url endpoint for service account authentication. --- internal/repository/config.go | 13 +++++++------ internal/repository/dns_client.go | 1 + internal/repository/mock/rrset_repository.go | 17 ++++++++++++----- internal/repository/mock/zone_repository.go | 11 +++++++++-- internal/resolver/config.go | 1 + internal/resolver/mock/config.go | 8 +++++++- internal/resolver/mock/secrets.go | 8 +++++++- 7 files changed, 44 insertions(+), 15 deletions(-) diff --git a/internal/repository/config.go b/internal/repository/config.go index a1dea1e..d692b88 100644 --- a/internal/repository/config.go +++ b/internal/repository/config.go @@ -3,10 +3,11 @@ package repository import "net/http" type Config struct { - ApiBasePath string - AuthToken string - ProjectId string - HttpClient *http.Client - SaKeyPath string - UseSaKey bool + ApiBasePath string + ServiceAccountBaseUrl string + AuthToken string + ProjectId string + HttpClient *http.Client + SaKeyPath string + UseSaKey bool } diff --git a/internal/repository/dns_client.go b/internal/repository/dns_client.go index 2ee140b..de9ce0a 100644 --- a/internal/repository/dns_client.go +++ b/internal/repository/dns_client.go @@ -28,6 +28,7 @@ func newStackitDnsClientKeyPath(config Config) (*stackitdnsclient.APIClient, err stackitconfig.WithServiceAccountKeyPath(config.SaKeyPath), stackitconfig.WithHTTPClient(&httpClient), stackitconfig.WithEndpoint(config.ApiBasePath), + stackitconfig.WithTokenEndpoint(config.ServiceAccountBaseUrl), ) } diff --git a/internal/repository/mock/rrset_repository.go b/internal/repository/mock/rrset_repository.go index 0af09a6..0da9eef 100644 --- a/internal/repository/mock/rrset_repository.go +++ b/internal/repository/mock/rrset_repository.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./rrset_repository.go +// +// Generated by this command: +// +// mockgen -destination=./mock/rrset_repository.go -source=./rrset_repository.go RRSetRepositoryFactory +// // Package mock_repository is a generated GoMock package. package mock_repository @@ -17,6 +22,7 @@ import ( type MockRRSetRepository struct { ctrl *gomock.Controller recorder *MockRRSetRepositoryMockRecorder + isgomock struct{} } // MockRRSetRepositoryMockRecorder is the mock recorder for MockRRSetRepository. @@ -45,7 +51,7 @@ func (m *MockRRSetRepository) CreateRRSet(ctx context.Context, rrSet dns.RecordS } // CreateRRSet indicates an expected call of CreateRRSet. -func (mr *MockRRSetRepositoryMockRecorder) CreateRRSet(ctx, rrSet interface{}) *gomock.Call { +func (mr *MockRRSetRepositoryMockRecorder) CreateRRSet(ctx, rrSet any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateRRSet", reflect.TypeOf((*MockRRSetRepository)(nil).CreateRRSet), ctx, rrSet) } @@ -59,7 +65,7 @@ func (m *MockRRSetRepository) DeleteRRSet(ctx context.Context, rrSetId string) e } // DeleteRRSet indicates an expected call of DeleteRRSet. -func (mr *MockRRSetRepositoryMockRecorder) DeleteRRSet(ctx, rrSetId interface{}) *gomock.Call { +func (mr *MockRRSetRepositoryMockRecorder) DeleteRRSet(ctx, rrSetId any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRRSet", reflect.TypeOf((*MockRRSetRepository)(nil).DeleteRRSet), ctx, rrSetId) } @@ -74,7 +80,7 @@ func (m *MockRRSetRepository) FetchRRSetForZone(ctx context.Context, rrSetName, } // FetchRRSetForZone indicates an expected call of FetchRRSetForZone. -func (mr *MockRRSetRepositoryMockRecorder) FetchRRSetForZone(ctx, rrSetName, rrSetType interface{}) *gomock.Call { +func (mr *MockRRSetRepositoryMockRecorder) FetchRRSetForZone(ctx, rrSetName, rrSetType any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchRRSetForZone", reflect.TypeOf((*MockRRSetRepository)(nil).FetchRRSetForZone), ctx, rrSetName, rrSetType) } @@ -88,7 +94,7 @@ func (m *MockRRSetRepository) UpdateRRSet(ctx context.Context, rrSet dns.RecordS } // UpdateRRSet indicates an expected call of UpdateRRSet. -func (mr *MockRRSetRepositoryMockRecorder) UpdateRRSet(ctx, rrSet interface{}) *gomock.Call { +func (mr *MockRRSetRepositoryMockRecorder) UpdateRRSet(ctx, rrSet any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRRSet", reflect.TypeOf((*MockRRSetRepository)(nil).UpdateRRSet), ctx, rrSet) } @@ -97,6 +103,7 @@ func (mr *MockRRSetRepositoryMockRecorder) UpdateRRSet(ctx, rrSet interface{}) * type MockRRSetRepositoryFactory struct { ctrl *gomock.Controller recorder *MockRRSetRepositoryFactoryMockRecorder + isgomock struct{} } // MockRRSetRepositoryFactoryMockRecorder is the mock recorder for MockRRSetRepositoryFactory. @@ -126,7 +133,7 @@ func (m *MockRRSetRepositoryFactory) NewRRSetRepository(config repository.Config } // NewRRSetRepository indicates an expected call of NewRRSetRepository. -func (mr *MockRRSetRepositoryFactoryMockRecorder) NewRRSetRepository(config, zoneId interface{}) *gomock.Call { +func (mr *MockRRSetRepositoryFactoryMockRecorder) NewRRSetRepository(config, zoneId any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewRRSetRepository", reflect.TypeOf((*MockRRSetRepositoryFactory)(nil).NewRRSetRepository), config, zoneId) } diff --git a/internal/repository/mock/zone_repository.go b/internal/repository/mock/zone_repository.go index 20f8e05..99ea03d 100644 --- a/internal/repository/mock/zone_repository.go +++ b/internal/repository/mock/zone_repository.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./zone_repository.go +// +// Generated by this command: +// +// mockgen -destination=./mock/zone_repository.go -source=./zone_repository.go ZoneRepositoryFactory +// // Package mock_repository is a generated GoMock package. package mock_repository @@ -17,6 +22,7 @@ import ( type MockZoneRepository struct { ctrl *gomock.Controller recorder *MockZoneRepositoryMockRecorder + isgomock struct{} } // MockZoneRepositoryMockRecorder is the mock recorder for MockZoneRepository. @@ -46,7 +52,7 @@ func (m *MockZoneRepository) FetchZone(ctx context.Context, zoneDnsName string) } // FetchZone indicates an expected call of FetchZone. -func (mr *MockZoneRepositoryMockRecorder) FetchZone(ctx, zoneDnsName interface{}) *gomock.Call { +func (mr *MockZoneRepositoryMockRecorder) FetchZone(ctx, zoneDnsName any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchZone", reflect.TypeOf((*MockZoneRepository)(nil).FetchZone), ctx, zoneDnsName) } @@ -55,6 +61,7 @@ func (mr *MockZoneRepositoryMockRecorder) FetchZone(ctx, zoneDnsName interface{} type MockZoneRepositoryFactory struct { ctrl *gomock.Controller recorder *MockZoneRepositoryFactoryMockRecorder + isgomock struct{} } // MockZoneRepositoryFactoryMockRecorder is the mock recorder for MockZoneRepositoryFactory. @@ -84,7 +91,7 @@ func (m *MockZoneRepositoryFactory) NewZoneRepository(config repository.Config) } // NewZoneRepository indicates an expected call of NewZoneRepository. -func (mr *MockZoneRepositoryFactoryMockRecorder) NewZoneRepository(config interface{}) *gomock.Call { +func (mr *MockZoneRepositoryFactoryMockRecorder) NewZoneRepository(config any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewZoneRepository", reflect.TypeOf((*MockZoneRepositoryFactory)(nil).NewZoneRepository), config) } diff --git a/internal/resolver/config.go b/internal/resolver/config.go index 32b9a91..d10c3dc 100644 --- a/internal/resolver/config.go +++ b/internal/resolver/config.go @@ -21,6 +21,7 @@ type defaultConfigProvider struct { type StackitDnsProviderConfig struct { ProjectId string `json:"projectId"` ApiBasePath string `json:"apiBasePath"` + ServiceAccountBaseUrl string `json:"serviceAccountBaseUrl"` AuthTokenSecretRef string `json:"authTokenSecretRef"` AuthTokenSecretKey string `json:"authTokenSecretKey"` AuthTokenSecretNamespace string `json:"authTokenSecretNamespace"` diff --git a/internal/resolver/mock/config.go b/internal/resolver/mock/config.go index e50ac4c..e85c1b5 100644 --- a/internal/resolver/mock/config.go +++ b/internal/resolver/mock/config.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./config.go +// +// Generated by this command: +// +// mockgen -destination=./mock/config.go -source=./config.go ConfigProvider +// // Package mock_resolver is a generated GoMock package. package mock_resolver @@ -16,6 +21,7 @@ import ( type MockConfigProvider struct { ctrl *gomock.Controller recorder *MockConfigProviderMockRecorder + isgomock struct{} } // MockConfigProviderMockRecorder is the mock recorder for MockConfigProvider. @@ -45,7 +51,7 @@ func (m *MockConfigProvider) LoadConfig(cfgJSON *v1.JSON) (resolver.StackitDnsPr } // LoadConfig indicates an expected call of LoadConfig. -func (mr *MockConfigProviderMockRecorder) LoadConfig(cfgJSON interface{}) *gomock.Call { +func (mr *MockConfigProviderMockRecorder) LoadConfig(cfgJSON any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadConfig", reflect.TypeOf((*MockConfigProvider)(nil).LoadConfig), cfgJSON) } diff --git a/internal/resolver/mock/secrets.go b/internal/resolver/mock/secrets.go index 70b71fd..acf3a56 100644 --- a/internal/resolver/mock/secrets.go +++ b/internal/resolver/mock/secrets.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./secrets.go +// +// Generated by this command: +// +// mockgen -destination=./mock/secrets.go -source=./secrets.go SecretFetcher +// // Package mock_resolver is a generated GoMock package. package mock_resolver @@ -14,6 +19,7 @@ import ( type MockSecretFetcher struct { ctrl *gomock.Controller recorder *MockSecretFetcherMockRecorder + isgomock struct{} } // MockSecretFetcherMockRecorder is the mock recorder for MockSecretFetcher. @@ -43,7 +49,7 @@ func (m *MockSecretFetcher) StringFromSecret(namespace, secretName, key string) } // StringFromSecret indicates an expected call of StringFromSecret. -func (mr *MockSecretFetcherMockRecorder) StringFromSecret(namespace, secretName, key interface{}) *gomock.Call { +func (mr *MockSecretFetcherMockRecorder) StringFromSecret(namespace, secretName, key any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StringFromSecret", reflect.TypeOf((*MockSecretFetcher)(nil).StringFromSecret), namespace, secretName, key) } From 208713d8ce7e5143569f309cb4fdaf606457f8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20B=C4=9Bh=C3=A1vka?= Date: Tue, 9 Dec 2025 15:39:29 +0100 Subject: [PATCH 2/2] Add the serviceAccountBaseUrl option into the readme --- README.md | 2 ++ internal/resolver/config.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f2436e5..e527213 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,7 @@ spec: authTokenSecretKey: string authTokenSecretNamespace: string serviceAccountKeyPath: string + serviceAccountBaseUrl: string acmeTxtRecordTTL: int64 ``` @@ -195,6 +196,7 @@ spec: - authTokenSecretKey: The key within the secret containing the STACKIT authentication token. (Default: auth-token) - authTokenSecretNamespace: The namespace of the secret containing the STACKIT authentication token. (Default: cert-manager) - serviceAccountKeyPath: The path to the service account key file. The file must be mounted into the container. +- serviceAccountBaseUrl: The base URL for the STACKIT service account API. (Default: https://service-account.api.stackit.cloud/token) - acmeTxtRecordTTL: The TTL for the ACME TXT record. (Default: 600) ## Test Procedures diff --git a/internal/resolver/config.go b/internal/resolver/config.go index d10c3dc..51ae471 100644 --- a/internal/resolver/config.go +++ b/internal/resolver/config.go @@ -21,11 +21,11 @@ type defaultConfigProvider struct { type StackitDnsProviderConfig struct { ProjectId string `json:"projectId"` ApiBasePath string `json:"apiBasePath"` - ServiceAccountBaseUrl string `json:"serviceAccountBaseUrl"` AuthTokenSecretRef string `json:"authTokenSecretRef"` AuthTokenSecretKey string `json:"authTokenSecretKey"` AuthTokenSecretNamespace string `json:"authTokenSecretNamespace"` ServiceAccountKeyPath string `json:"serviceAccountKeyPath"` + ServiceAccountBaseUrl string `json:"serviceAccountBaseUrl"` AcmeTxtRecordTTL int64 `json:"acmeTxtRecordTTL"` }