Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): add ability to skip X-SPINNAKER-ACCOUNTS in SpinnakerRequestInterceptor and SpinnakerRequestHeaderInterceptor #1148

Merged
merged 12 commits into from
Feb 22, 2024

Conversation

dbyron-sf
Copy link
Contributor

for uses of retrofit to communicate outside of spinnaker. Skipping this header avoids possible HTTP 431 response codes where http servers aren't configured to receive large request headers when X-SPINNAKER-ACCOUNTS is large.

There are changes required in orca tests to keep up with the SpinnakerRequestInterceptor constructor changes:

diff --git a/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/config/CloudDriverConfigurationTest.java b/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/config/CloudDriverConfigurationTest.java
index 6d22c323b..cea63b2a6 100644
--- a/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/config/CloudDriverConfigurationTest.java
+++ b/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/config/CloudDriverConfigurationTest.java
@@ -78,7 +78,7 @@ public class CloudDriverConfigurationTest extends YamlFileApplicationContextInit
 
     ObjectMapper objectMapper = new ObjectMapper();
     RestAdapter.LogLevel logLevel = RestAdapter.LogLevel.FULL;
-    RequestInterceptor requestInterceptor = new SpinnakerRequestInterceptor(null);
+    RequestInterceptor requestInterceptor = new SpinnakerRequestInterceptor(true);
 
     this.clouddriverRetrofitBuilder =
         new CloudDriverConfiguration.ClouddriverRetrofitBuilder(
diff --git a/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/tasks/monitoreddeploy/EvaluateDeploymentHealthTaskTest.java b/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/tasks/monitoreddeploy/EvaluateDeploymentHealthTaskTest.java
index c8220e039..1a31a4b4d 100644
--- a/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/tasks/monitoreddeploy/EvaluateDeploymentHealthTaskTest.java
+++ b/orca-clouddriver/src/test/java/com/netflix/spinnaker/orca/clouddriver/tasks/monitoreddeploy/EvaluateDeploymentHealthTaskTest.java
@@ -36,7 +36,6 @@ import com.google.common.collect.Iterables;
 import com.netflix.spectator.api.NoopRegistry;
 import com.netflix.spinnaker.config.DeploymentMonitorDefinition;
 import com.netflix.spinnaker.kork.test.log.MemoryAppender;
-import com.netflix.spinnaker.okhttp.OkHttpClientConfigurationProperties;
 import com.netflix.spinnaker.okhttp.SpinnakerRequestInterceptor;
 import com.netflix.spinnaker.orca.api.pipeline.TaskResult;
 import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus;
@@ -119,7 +118,7 @@ public class EvaluateDeploymentHealthTaskTest {
         new DeploymentMonitorServiceProvider(
             okClient,
             retrofitLogLevel,
-            new SpinnakerRequestInterceptor(new OkHttpClientConfigurationProperties()),
+            new SpinnakerRequestInterceptor(true),
             deploymentMonitorDefinitions);
     evaluateDeploymentHealthTask =
         new EvaluateDeploymentHealthTask(deploymentMonitorServiceProvider, new NoopRegistry());

…to src/main/java

since that's where java files belong
…ConfigurationProperties

to pave the way for multiple SpinnakerRequestInterceptor instances, some configured differently than others.
…stInterceptor

for uses of retrofit to communicate outside of spinnaker.  Skipping this header avoids
possible HTTP 431 response codes where http servers aren't configured to receive large
request headers when X-SPINNAKER-ACCOUNTS is large.
…m groovy to java

because the less groovy we've got, the better.  This also makes converting the test to use
WireMock in preference to mockStatic that much easier.

While we're at it, move the test to the same package as SpinnakerRequestHeaderInterceptor:
com.netflix.spinnaker.okhttp.
…use wiremock

and real requests, instead of static mocking of AuthenticatedRequest since it seems like a
more thorough test.  Matching the structure of SpinnakerRequestInterceptorTest also seems like
a win.
…ClientConfigurationProperties

to pave the way for multiple SpinnakerRequestHeaderInterceptor instances, some configured differently than others.
…stHeaderInterceptor

for uses of retrofit2 to communicate outside of spinnaker.  Skipping this header avoids
possible HTTP 431 response codes where http servers aren't configured to receive large
request headers when X-SPINNAKER-ACCOUNTS is large.
@dbyron-sf
Copy link
Contributor Author

@Mergifyio update

Copy link
Contributor

mergify bot commented Feb 21, 2024

update

✅ Branch has been successfully updated

Copy link
Contributor

@xibz xibz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, but I did have another suggested approach in case custom webhooks, for whatever reason, is relying on that header. However, if that is the case, we probably want to at least make that portion of it configurable which seems to not be via how the bean is constructed.

Either way, let me know your thoughts. I think if we do go with this approach and want this to be merged, allow for it to be configured. Or the other suggestion of choosing a header value size which we could even extend to other headers.

import com.netflix.spinnaker.security.AuthenticatedRequest
import retrofit.RequestInterceptor

class SpinnakerRequestInterceptor implements RequestInterceptor {
private final OkHttpClientConfigurationProperties okHttpClientConfigurationProperties
private final boolean propagateSpinnakerHeaders;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one thing I really dislike about the HTTP spec is that they don't define a limit for header size, so servers just arbitrarily choose one. One thing we can do is also only send the header if the size is manageable (whatever that may be). So rather than needing to configure this, it can just send this header when the header values is less than 8kb or something which should work on most servers.

@@ -82,12 +82,12 @@ public class OkHttpClientComponents {

@Bean
public SpinnakerRequestInterceptor spinnakerRequestInterceptor() {
return new SpinnakerRequestInterceptor(clientProperties);
return new SpinnakerRequestInterceptor(clientProperties.getPropagateSpinnakerHeaders());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be no way to configure sending the account headers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right....sort of. The SpinnakerRequestInterceptor bean keeps the same behavior -- to send the account headers. But now it's possible to construct another SpinnakerRequestInterceptor bean that doesn't.

@dbyron-sf
Copy link
Contributor Author

I think this is fine, but I did have another suggested approach in case custom webhooks, for whatever reason, is relying on that header. However, if that is the case, we probably want to at least make that portion of it configurable which seems to not be via how the bean is constructed.

Either way, let me know your thoughts. I think if we do go with this approach and want this to be merged, allow for it to be configured. Or the other suggestion of choosing a header value size which we could even extend to other headers.

I was figuring that existing uses of the SpinnakerRequestInterceptor bean need to continue sending the accounts header, since they're used to communicate among the various spinnaker microservices. At the moment parts of spinnaker would break without it, so I don't think it needs to be configurable, at least not that way.

As far as configuring a size and only sending the accounts header (or other headers) when they satisfy some size threshold...I can see the appeal of that...except that it seems like the receiving code either needs a complete header, or it doesn't need it at all, so sending a partial one might do more harm than good.

@dbyron-sf dbyron-sf added the ready to merge Approved and ready for merge label Feb 22, 2024
@mergify mergify bot added the auto merged label Feb 22, 2024
@mergify mergify bot merged commit b049ded into spinnaker:master Feb 22, 2024
5 checks passed
@dbyron-sf dbyron-sf deleted the omit-accounts-request-header branch October 30, 2024 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants