diff --git a/comp/remote-config/rcservice/rcserviceimpl/rcservice.go b/comp/remote-config/rcservice/rcserviceimpl/rcservice.go index 48226f0dcb916..34b5475f28760 100644 --- a/comp/remote-config/rcservice/rcserviceimpl/rcservice.go +++ b/comp/remote-config/rcservice/rcserviceimpl/rcservice.go @@ -75,6 +75,8 @@ func newRemoteConfigService(deps dependencies) (rcservice.Component, error) { options := []remoteconfig.Option{ remoteconfig.WithAPIKey(apiKey), + // KEA: Temp For Testing Out Impl in Staging + remoteconfig.WithPARJWT("eyJhbGciOiJFUzI1NiIsImN0eSI6IkpXVCIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzUyOTU4NjEsIm9yZ0lkIjoyLCJydW5uZXJJZCI6InJ1bm5lci1YUzI2ZWFUVkZaM21KWDNMWktDWXhRIn0.0ZSfsRyZdKzHG_wYjyJAI9zPG7t-ZPhW7U9x0vqMs10cOO_RCbwJCafmZt3LJlCImk3K5wuODEs6RQBQYbCwOQ"), remoteconfig.WithTraceAgentEnv(traceAgentEnv), remoteconfig.WithConfigRootOverride(deps.Cfg.GetString("site"), deps.Cfg.GetString("remote_configuration.config_root")), remoteconfig.WithDirectorRootOverride(deps.Cfg.GetString("site"), deps.Cfg.GetString("remote_configuration.director_root")), diff --git a/pkg/config/remote/api/http.go b/pkg/config/remote/api/http.go index 62f7872a2e671..7f42a2b56ca59 100644 --- a/pkg/config/remote/api/http.go +++ b/pkg/config/remote/api/http.go @@ -46,11 +46,13 @@ type API interface { Fetch(context.Context, *pbgo.LatestConfigsRequest) (*pbgo.LatestConfigsResponse, error) FetchOrgData(context.Context) (*pbgo.OrgDataResponse, error) FetchOrgStatus(context.Context) (*pbgo.OrgStatusResponse, error) + UpdatePARJWT(string) } // Auth defines the possible Authentication data to access the RC backend type Auth struct { APIKey string + PARJWT string AppKey string UseAppKey bool } @@ -66,11 +68,17 @@ type HTTPClient struct { func NewHTTPClient(auth Auth, cfg model.Reader, baseURL *url.URL) (*HTTPClient, error) { header := http.Header{ "Content-Type": []string{"application/x-protobuf"}, - "DD-Api-Key": []string{auth.APIKey}, + } + if auth.PARJWT != "" { + header["DD-PAR-JWT"] = []string{auth.PARJWT} + } + if auth.APIKey != "" { + header["DD-Api-Key"] = []string{auth.APIKey} } if auth.UseAppKey { header["DD-Application-Key"] = []string{auth.AppKey} } + transport := httputils.CreateHTTPTransport(cfg) // Set the keep-alive timeout to 30s instead of the default 90s, so the http RC client is not closed by the backend transport.IdleConnTimeout = 30 * time.Second @@ -216,6 +224,10 @@ func (c *HTTPClient) FetchOrgStatus(ctx context.Context) (*pbgo.OrgStatusRespons return response, err } +func (c *HTTPClient) UpdatePARJWT(jwt string) { + c.header.Set("DD-PAR-JWT", jwt) +} + func checkStatusCode(resp *http.Response) error { // Specific case: authentication method is wrong // we want to be descriptive about what can be done diff --git a/pkg/config/remote/service/service.go b/pkg/config/remote/service/service.go index a379ac5b387ec..ff045f79a431c 100644 --- a/pkg/config/remote/service/service.go +++ b/pkg/config/remote/service/service.go @@ -248,6 +248,7 @@ type options struct { site string rcKey string apiKey string + parJWT string traceAgentEnv string databaseFileName string databaseFilePath string @@ -264,6 +265,7 @@ type options struct { var defaultOptions = options{ rcKey: "", apiKey: "", + parJWT: "", traceAgentEnv: "", databaseFileName: "remote-config.db", databaseFilePath: "", @@ -355,6 +357,11 @@ func WithAPIKey(apiKey string) func(s *options) { return func(s *options) { s.apiKey = apiKey } } +// WithPARJWT sets the JWT for the private action runner +func WithPARJWT(jwt string) func(s *options) { + return func(s *options) { s.parJWT = jwt } +} + // WithClientCacheBypassLimit validates and sets the service client cache bypass limit func WithClientCacheBypassLimit(limit int, cfgPath string) func(s *options) { if limit < minCacheBypassLimit || limit > maxCacheBypassLimit { @@ -415,7 +422,7 @@ func NewService(cfg model.Reader, rcType, baseRawURL, hostname string, tagsGette backoffPolicy := backoff.NewExpBackoffPolicy(minBackoffFactor, baseBackoffTime, options.maxBackoff.Seconds(), recoveryInterval, recoveryReset) - authKeys, err := getRemoteConfigAuthKeys(options.apiKey, options.rcKey) + authKeys, err := getRemoteConfigAuthKeys(options.apiKey, options.rcKey, options.parJWT) if err != nil { return nil, err } @@ -532,6 +539,11 @@ func (s *CoreAgentService) Start() { }() } +// UpdatePARJWT updates the stored JWT for HTTP API calls +func (s *CoreAgentService) UpdatePARJWT(jwt string) { + s.api.UpdatePARJWT(jwt) +} + func startWithAgentPollLoop(s *CoreAgentService) { err := s.refresh() if err != nil { diff --git a/pkg/config/remote/service/service_test.go b/pkg/config/remote/service/service_test.go index 40d8302db3192..8e36efe6b3402 100644 --- a/pkg/config/remote/service/service_test.go +++ b/pkg/config/remote/service/service_test.go @@ -69,6 +69,10 @@ func (m *mockAPI) FetchOrgStatus(ctx context.Context) (*pbgo.OrgStatusResponse, return args.Get(0).(*pbgo.OrgStatusResponse), args.Error(1) } +func (m *mockAPI) UpdatePARJWT(jwt string) { + m.Called(jwt) +} + type mockUptane struct { mock.Mock } diff --git a/pkg/config/remote/service/util.go b/pkg/config/remote/service/util.go index b0d541e964f54..4f91ed6ceb48b 100644 --- a/pkg/config/remote/service/util.go +++ b/pkg/config/remote/service/util.go @@ -139,6 +139,8 @@ func openCacheDB(path string, agentVersion string, apiKey string) (*bbolt.DB, er type remoteConfigAuthKeys struct { apiKey string + parJWT string + rcKeySet bool rcKey *msgpgo.RemoteConfigKey } @@ -146,6 +148,7 @@ type remoteConfigAuthKeys struct { func (k *remoteConfigAuthKeys) apiAuth() api.Auth { auth := api.Auth{ APIKey: k.apiKey, + PARJWT: k.parJWT, } if k.rcKeySet { auth.UseAppKey = true @@ -154,12 +157,15 @@ func (k *remoteConfigAuthKeys) apiAuth() api.Auth { return auth } -func getRemoteConfigAuthKeys(apiKey string, rcKey string) (remoteConfigAuthKeys, error) { +func getRemoteConfigAuthKeys(apiKey string, rcKey string, parJWT string) (remoteConfigAuthKeys, error) { if rcKey == "" { return remoteConfigAuthKeys{ apiKey: apiKey, + parJWT: parJWT, }, nil } + + // Legacy auth with RC specific keys rcKey = strings.TrimPrefix(rcKey, "DDRCM_") encoding := base32.StdEncoding.WithPadding(base32.NoPadding) rawKey, err := encoding.DecodeString(rcKey) @@ -176,6 +182,7 @@ func getRemoteConfigAuthKeys(apiKey string, rcKey string) (remoteConfigAuthKeys, } return remoteConfigAuthKeys{ apiKey: apiKey, + parJWT: parJWT, rcKeySet: true, rcKey: &key, }, nil diff --git a/pkg/config/remote/service/util_test.go b/pkg/config/remote/service/util_test.go index ba4b8eaff1f89..2eb4cabcaedcd 100644 --- a/pkg/config/remote/service/util_test.go +++ b/pkg/config/remote/service/util_test.go @@ -27,6 +27,7 @@ func TestAuthKeys(t *testing.T) { tests := []struct { rcKey string apiKey string + parJWT string err bool output remoteConfigAuthKeys }{ @@ -45,7 +46,7 @@ func TestAuthKeys(t *testing.T) { } for _, test := range tests { t.Run(fmt.Sprintf("%s|%s", test.apiKey, test.rcKey), func(tt *testing.T) { - output, err := getRemoteConfigAuthKeys(test.apiKey, test.rcKey) + output, err := getRemoteConfigAuthKeys(test.apiKey, test.rcKey, test.parJWT) if test.err { assert.Error(tt, err) } else {