-
Notifications
You must be signed in to change notification settings - Fork 0
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
Feature/message signing #6
Open
ivolz
wants to merge
8
commits into
main
Choose a base branch
from
feature/message-signing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
b9cdc1f
WIP: Changes for message signing in the interceptor
johannesschneiders 1c9b3e2
Add flag to use mutex if message signing is enabled only
0d8e1e3
Revert "Add flag to use mutex if message signing is enabled only"
df484a3
Message signing should check for Approov-Token header inclusion; disa…
0361381
Implement message signing changes to apply to different domains and m…
af023c4
Update ApproovMessageSigningConfig.java
jexh af9ab1b
Update ApproovMessageSigningConfig.java
jexh 3e4e0e7
Update ApproovService.java
jexh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
approov-service/src/main/java/io/approov/service/okhttp/ApproovMessageSigningConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package io.approov.service.okhttp; | ||
|
||
import java.util.ArrayList; | ||
import okhttp3.Request; | ||
|
||
/* Add the following interfaces */ | ||
interface MessageSigningConfig { | ||
String getSigningMessage(); | ||
String getTargetHeaderName(); | ||
String generateTargetHeaderValue(String messageSignature); | ||
} | ||
|
||
interface MessageSigningConfigFactory { | ||
MessageSigningConfig generateMessageSigningConfig(Request request, String approovTokenHeader); | ||
} | ||
|
||
/* message signing configuration | ||
* This class is used to configure the message signing feature. The message signature can be computed based on the | ||
* request URL, the headers specified in signedHeaders in the order in which they are listed and, optionally, the | ||
* body of the message. The signature will be added to the request headers using the header name specified in header. | ||
* You can have multiple configurations for different domains and a default '*' configuration that will be used if no | ||
* specific configuration is found for a domain. | ||
*/ | ||
public final class DefaultMessageSigningConfigFactory implements MessageSigningConfigFactory { | ||
// the name of the header that will be used to send the message signature | ||
private String targetHeader; | ||
// the list of headers to include in the message to be signed, in the order they should be added | ||
private ArrayList<String> signedHeaders; | ||
|
||
// constructor | ||
public ApproovMessageSigningConfig(String targetHeader) { | ||
if (targetHeader == null || targetHeader.isEmpty()) | ||
throw new IllegalArgumentException("The target header must be specified"); | ||
this.targetHeader = targetHeader; | ||
this.signedHeaders = new ArrayList<>(); | ||
} | ||
|
||
/* Get/set methods */ | ||
|
||
/* Get target header */ | ||
public String getTargetHeader() { | ||
return targetHeader; | ||
} | ||
|
||
/* Add a header to the list of signed headers: NOTE the sequence of headers DOES matter */ | ||
public DefaultMessageSigningConfigFactory addSignedHeader(String header) { | ||
if (header == null || header.isEmpty()) | ||
throw new IllegalArgumentException("The header must be specified"); | ||
signedHeaders.add(header); | ||
return this; | ||
} | ||
|
||
MessageSigningConfig generateMessageSigningConfig(Request request, String approovTokenHeader){ | ||
List<String> usedHeaders = new ArrayList<>(); | ||
StringBuilder message = new StringBuilder(); | ||
// 1. Add the Method to the message | ||
message.append(request.method()); | ||
message.append("\n"); | ||
// 2. add the URL to the message, followed by a newline | ||
message.append(request.url()); // TODO make sure this includes all the URL params if there are any | ||
message.append("\n"); | ||
// 3. add the Approov token header to the message | ||
List<String> values = request.headers(approovTokenHeader); // make sure the okhtp lookup works whatever the case used on the header name | ||
if values == null || values.isEmpty() { | ||
throw new IllegalArgumentException("provided request does not include the Approov token header"); | ||
} | ||
usedHeaders.add(approovTokenHeader.toLowerCase()) | ||
for (String value : values) { | ||
message.append(approovTokenHeader.toLowerCase()).append(":"); | ||
if (value != null) { | ||
message.append(value); | ||
} | ||
message.append("\n"); | ||
} | ||
|
||
// 4. add the required headers to the message as 'headername:headervalue', where the headername is in | ||
// lowercase | ||
if (messageSigningConfig.getSignedHeaders() != null) { | ||
for (String header : messageSigningConfig.signedHeaders) { | ||
// add one headername:headervalue\n entry for each header value to be included in the signature | ||
List<String> values = request.headers(header); | ||
if (values != null && values.size() > 0) { | ||
usedHeaders.add(approovTokenHeader.toLowerCase()) | ||
for (String value : values) { | ||
message.append(header.toLowerCase()).append(":"); | ||
if (value != null) { | ||
message.append(value); | ||
} | ||
message.append("\n"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// add the body to the message | ||
okhttp3.RequestBody body = request.body(); | ||
if (body != null && !body.isOneShot()) { // we can't support one-shot bodies without making a copy - we probably need to do that extra work. | ||
Buffer buffer = new Buffer(); | ||
body.writeTo(buffer); | ||
// need to convert the contents of the buffer to b64 - using readUtf8 may still cause serious problems in the message signing code if it contains control characters (or most problematic NULLs) | ||
message.append(buffer.readUtf8()); | ||
} | ||
return new DefaultMessageSigningConfig(targetHeader, usedHeaders, message.String()); | ||
} | ||
} | ||
|
||
public class DefaultMessageSigningConfig implements MessageSigningConfig | ||
// the name of the header that will be used to send the message signature | ||
private String targetHeader; | ||
// the list of headers with counts that are expected by the server and were also included in the message to be signed | ||
private List<String> usedHeaders; | ||
// the message to be signed | ||
private String message; | ||
|
||
DefaultMessageSigningConfig(String targetHeader, String usedHeaders, String message) { | ||
this.targeHeader = targetHeader; | ||
this.usedHeaders = usedHeaders; | ||
this.message = message; | ||
} | ||
|
||
public String getTargetHeaderName(){ return targetHeader } | ||
public String getSigningMessage() { return usedHeadersSpec } | ||
public String generateTargetHeaderValue(String messageSignature) { | ||
// create a JSON object of the following form: | ||
// { | ||
// "accountSig":"messageSignature.String()", | ||
// "headers":usedHeaders list as JSON list of strings | ||
// } | ||
// base 64 the JSON | ||
String b64HeaderValue = "" | ||
return b64HeaderValue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
distributionBase=GRADLE_USER_HOME | ||
distributionPath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip | ||
networkTimeout=10000 | ||
validateDistributionUrl=true | ||
zipStoreBase=GRADLE_USER_HOME | ||
zipStorePath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment needs to be updated to reflect the changes to the class. It should also explain what the message signing behaviour is, which bits are included in the message, the order and any transformation that is performed (b64 encode the body).