SignatureDoesNotMatch on gCloud - java

I cannot get the upload on a Google Cloud Signed URL to work. I get the same SignatureDoesNotMatch error.
I tried lots of things including:
deactivating the v4 for the v2
adding or removing content type
changing fetch with axios
using Postman
try to be a wizard with POST and then PUT and x-goog-resumable:start
change the CORS of my bucket
increasing the timeout
I just never get the upload to work.
The token creation code:
public static String generateV4PutObjectSignedUrl(String objectName) throws StorageException {
// String projectId = "my-project-id";
// String bucketName = "my-bucket";
// String objectName = "my-object";
Storage storage = StorageOptions.getDefaultInstance().getService();
// Define Resource
BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of("mybucket", objectName)).build();
// Generate Signed URL
Map<String, String> extensionHeaders = new HashMap<>();
extensionHeaders.put("Content-Type", "application/octet-stream");
URL url = storage.signUrl(
blobInfo,
15,
TimeUnit.HOURS,
Storage.SignUrlOption.httpMethod(HttpMethod.PUT),
Storage.SignUrlOption.withExtHeaders(extensionHeaders),
Storage.SignUrlOption.withV4Signature()
);
String urlS = url.toString();
System.out.println("Generated PUT signed URL:"+urlS);
return urlS;
}
then the CORS of the bucket:
[{"maxAgeSeconds": 3600000, "method": ["GET", "PUT", "OPTIONS", "POST"], "origin": ["LIVE", "http://localhost:8080", "http://0.0.0.0:8080"], "responseHeader": ["Content-Type", "x-goog-resumable"]}]
And then my attempts to put:
const signedUrl = await fetch("$STORAGE_FUN/" + apkFile.name.replace(" ", "_")).then((res) => res.text());
await axios.put(signedUrl, apkFile);
As well as:
const put = await fetch(signedUrl, {
method: 'PUT',
headers: {'Content-Type': 'application/octet-stream'},
body: apkFile
})
As well as:
curl --location --request PUT 'https://storage.googleapis.com/mybucket/no-heroes-here.apk?GoogleAccessId=autodeploy#company.iam.gserviceaccount.com&Expires=1676643070&Signature=ZYU7CjzWRcKaqjOufUZ%2BkOJA%2FsB1vVpWBZAfpeUKIrmQRHJ6ZgXE7bwmqtaIWwBCbZv%2Fa1naYV3xC2OMqhpZ7ene46ZWS4JH%2FIvVn2U5SMBjYG38SrKqICLfj3l4sN%2BR39ijTxPwP4nWCpvMm39CxtCZAC6n5FovsNterZ7NqByXHP7YXgzOXeiBALabDv%2B%2BnclpVtoJ4K6h%2ByFKyQ6odzT0PTDIvpED4ph%2BIrdptwxraFFpLNL8k0ocAsd1zn9U4cxRrTTFCMzzMaXdhXRfVAtkSl5NW7BosdkRmgGtB%2FA1TEifea%2BnfXyXtbRaW7QG5TA9WxrA3VmHNMWz3At29A%3D%3D' \
-H 'Content-Type:' \
--data-binary '#/somepath/original/noheroeshere/no-heroes-here.apk'
And we get a similar error as:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
<StringToSign>GOOG4-RSA-SHA256
20230216T232500Z
20230216/auto/storage/goog4_request
338a1267c21129d5a991a59881cf42c0112f6cfd5cc067c162e0716adc059d5e</StringToSign>
<CanonicalRequest>PUT
/mybucket/no-heroes-here.apk
X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=autodeploy%40company.iam.gserviceaccount.com%2F20230216%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20230216T232500Z&X-Goog-Expires=54000&X-Goog-SignedHeaders=content-type%3Bhost
content-type:application/octet-stream
host:storage.googleapis.com
content-type;host
UNSIGNED-PAYLOAD</CanonicalRequest>
</Error>
Many questions:
Do you see an obvious error in my code?
Is there a way to debug the Signature Error like some logs in the bucket that where we could see what is actually not matching?
Can it be a permission problem of the service account that I'm using?
Would the URL be generated if the service account wouldn't work?

Related

Can't authenticate using REST POST method

Basically i'm new to groovy, and i'm trying to use it to add a device to "netbox" using API, i tried some GET requests that needed authentication and they worked fine, but i couldn't make any POST request work, i'm always getting 403 no matter what method i try to authenticate Basic using creds or using API Token.
Here's the code i wrote for the POST request :
def url = "http://192.168.12.89:8000/api/dcim/devices"
def connection = url.toURL().openConnection()
def message = '{"name":"R4","device_type":"1","device_role":"1","site":"1"}'
connection.setRequestMethod("POST")
connection.setDoOutput(true)
connection.setDoInput(true)
connection.addRequestProperty("Accept", "application/json;charset=UTF-8")
connection.addRequestProperty("Content-Type", "application/json")
//def auth = "admin:admin".bytes.encodeBase64()
//connection.setRequestProperty("Authorization", "Basic ${auth}")
connection.setRequestProperty("Authorization", "Token 63091d94b00d40e9e0a4e1286e181c09deca6e89")
connection.getOutputStream().write(message.getBytes("UTF-8"))
def responseCode = connection.getResponseCode()
InputStream response = null
println "${responseCode}"
if (responseCode != 200) {
response = connection.getErrorStream()
} else {
response = connection.getInputStream()
}
def responseBody = response?.text
response?.close()
println responseBody
My API key works fine with the get method and it has the write permissions included, also tried a python POST request works perfectly fine, so i guess the problem is in my groovy coding.
I hope i can get a bit of help cause i've been trying for two days :x
Thank you :x

How do I send an authorization token at header when I am using grooy

I am trying to to the same thing like this curl command line
curl -H 'Authorization: token this_is_my_token' this_is_my_url
final DataUrl = new URL("this_is_my_url?access_token=this_is_my_token"
getList new JsonSlurper().parse(DataUrl.newReader())
but it's not working
which I've tried was
def DataUrl =new GetMethod("this_is_my_url");
DataUrl.setRequestHeader("Authorization",token this_is_my_token)
getList new JsonSlurper().parse(DataUrl.newReader())
Your syntax doesn't look correct, for example following line.
DataUrl.setRequestHeader("Authorization",token + "this_is_my_token")
I have used the following method.
def accessToken = "ACCESS_TOKEN" // If you want to Base64 encode use "ACCESS_TOKEN".bytes.encodeBase64().toString()
def get = new URL("https://raw.githubusercontent.com/xxxx/something/hosts").openConnection();
get.setRequestProperty("Authorization", "token " + accessToken)
def content = get.getInputStream().getText()

AWS S3 Pre Signed URL with Metadata

Here is the code snippet where I am trying to upload a document with some custom metadata using AWS S3 pre signed URL.
try (CloseableHttpClient httpClient = HttpClients.createSystem()) {
var tempFile = File.createTempFile(document.getName(), FilenameUtils.getExtension(document.getOriginalFilename()));
document.transferTo(tempFile);
var fileEntity = new FileEntity(tempFile);
var httpPut = new HttpPut(url);
// Here 403 httpPut.setHeader("x-amz-meta-title", "Test Title");
httpPut.setEntity(fileEntity);
var response = httpClient.execute(httpPut);
log.info("HTTP response code {}", response.getStatusLine().getStatusCode());
} catch (IOException e) {
log.error("Oops! Error", e);
}
Unfortunately setting a custom header as above throws 403. It works fine when I take out the header. Even works okay when you add an irrelevant metadata key say "abc" - Obviously not adding metadata, but returns 200 OK. The issue seems only when you specify "x-amz-meta-".
Any thoughts?
The metadata of a presigned url are set, when you create it. They are prefilled and can't be modified by the client.
The only thing you can do is set an expected value and optionally a condition. In the condition you can specify to reject the upload, if the expected meta-data value isn't supplied.

Use resteasy with user and password

I am trying to convert this line to resteasy stuff.
curl -X GET --digest -u myuser:mypassword --header 'Accept:application/json; charset=utf-8' http://localhost:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/live/instances
this is how I am trying to connect to that endpoint
clientREST = new ResteasyClientBuilder().build();
clientREST.register(new BasicAuthentication(userWowza, passWowza));
String targetStr = "http://" + host + ":" + portEndpoint + endPoint + red5App + "/instances";
System.out.println(targetStr);
ResteasyWebTarget target = clientREST
.target(targetStr);
Response response = target.request().post(Entity.entity("", "application/json"));
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
But I get HTTP error code : 401. So it is like user and password is no working. Am I sending the headers correctly?
Update
So I couldnt find any example of resteasy with digest auth, so I found that wowza seems to suppport basic and digest at the same time
Actually your curl uses --digest not BASIC authentication. So it looks like Server does not accept BASIC Authorization schema.

Translate Python requests code to Java (UniRest)

I am working with the Snapchat API to make a Java Client. I am using an endpoint which takes the following parameters from an HTTP POST:
{
username: snapchat username,
timestamp: UNIX timestamp,
media_id: random string,
type: 0,
req_token: request token,
data: encrypted data
}
I have no problem generating the params hash, and I have the data as a File object.
In Python I have confirmed that the following works:
f = open('encrypted.jpg')
params = { ... all params besides data ... }
files = { 'data' : f }
r = requests.post(path, params, files=files)
That Python code gets me a 200. I am using tokens and data/files generated by Java code, so the data sent is identical.
In Java I am doing the following with UniRest:
Map<String, Object> params = ... same params ...;
File f = new File('encrypted.jpg');
HttpRequestWithBody req = Unirest.post(path);
req.fields(params);
req.field("data", f);
HttpResponse<String> resp = req.asString();
However this gives me a 500 response from the server. How can I write Java that emulates the Python exactly? Or how can I snoop my own network traffic to see the difference in what the code for each is doing? Seems crazy to me that one works and the other does not.
try to chain methods, i.e.
req = Unirest.post(path).fields(params).field("data", f);
or change the lines:
req = req.fields(params);
req = req.field("data", f);

Categories

Resources