Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
### Added
- N/A

## 1.2.43 - 2018-07-26
### Added
- Support for the OCI Search service. An example of how to call this service is available [here](https://github.com/oracle/oci-java-sdk/blob/master/bmc-examples/src/main/java/ResourceSearchExample.java)
- Support for specifying a backup policy when creating a boot volume in the Block Storage service
- Support for using the Java SDK in a FIPS compliant environment. Details available [here](https://docs.cloud.oracle.com/iaas/Content/API/SDKDocs/javasdk.htm#download)

## 1.2.42 - 2018-07-12
### Added
- Support for tagging Load Balancers in the Load Balancing service
Expand Down
4 changes: 2 additions & 2 deletions bmc-audit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand All @@ -18,7 +18,7 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
</dependency>
</dependencies>

Expand Down
34 changes: 20 additions & 14 deletions bmc-bom/pom.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0"?>
<?xml version='1.0' encoding='UTF-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- http://howtodoinjava.com/maven/maven-bom-bill-of-materials-dependency/ -->
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>oci-java-sdk-bom</artifactId>
Expand All @@ -19,71 +19,77 @@
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<!-- Service modules, alpha sorted -->
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-audit</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-containerengine</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-core</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-database</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-dns</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-email</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-filestorage</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-identity</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-loadbalancer</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-objectstorage</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<optional>false</optional>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-resourcesearch</artifactId>
<optional>false</optional>
<version>1.2.43</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
</project>
2 changes: 1 addition & 1 deletion bmc-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk</artifactId>
<version>1.2.42</version>
<version>1.2.43</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.jce.PrincipalUtil;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;

import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -211,21 +210,15 @@ public static String base64EncodeNoChunking(X509Certificate certificate)
public static String getTenantIdFromCertificate(X509Certificate certificate) {
Preconditions.checkNotNull(certificate);

try {
X500Name name =
X500Name.getInstance(PrincipalUtil.getSubjectX509Principal(certificate));

for (RDN rdn : name.getRDNs(BCStyle.OU)) {
for (AttributeTypeAndValue typeAndValue : rdn.getTypesAndValues()) {
String value = typeAndValue.getValue().toString();
if (value.startsWith("opc-tenant:")) {
return value.substring("opc-tenant:".length());
}
X500Name name = new X500Name(certificate.getSubjectX500Principal().getName());

for (RDN rdn : name.getRDNs(BCStyle.OU)) {
for (AttributeTypeAndValue typeAndValue : rdn.getTypesAndValues()) {
String value = typeAndValue.getValue().toString();
if (value.startsWith("opc-tenant:")) {
return value.substring("opc-tenant:".length());
}
}
} catch (CertificateEncodingException ex) {
throw new InstancePrincipalUnavailableException(
"The certificate is not valid one.", ex);
}

throw new InstancePrincipalUnavailableException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
package com.oracle.bmc.http.signing.internal;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
Expand All @@ -22,6 +23,7 @@
import javax.annotation.concurrent.Immutable;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.ByteStreams;
import com.oracle.bmc.http.signing.RequestSignerException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -143,7 +145,12 @@ private Map<String, String> signRequest(
// 3) calculate any required headers that are missing
final Map<String, String> missingHeaders =
calculateMissingHeaders(
lowerHttpMethod, uri, existingHeaders, body, requiredHeaders);
lowerHttpMethod,
uri,
existingHeaders,
body,
requiredHeaders,
signingConfiguration);

// 4) create a map containing both existing + missing headers
final Map<String, String> allHeaders = new HashMap<>();
Expand Down Expand Up @@ -247,12 +254,14 @@ private static String extractPath(URI uri) {
return path;
}

private Map<String, String> calculateMissingHeaders(
static Map<String, String> calculateMissingHeaders(
final String httpMethod,
final URI uri,
final Map<String, String> existingHeaders,
final Object body,
final List<String> requiredHeaders) {
final List<String> requiredHeaders,
final SigningConfiguration signingConfiguration)
throws IOException {
// all of the required headers that are currently missing
Map<String, String> missingHeaders = new HashMap<>();

Expand Down Expand Up @@ -301,21 +310,10 @@ private Map<String, String> calculateMissingHeaders(
if (!existingHeaders.containsKey(Constants.CONTENT_TYPE)) {
LOG.warn("Missing 'content-type' header, defaulting to 'application/json'");
missingHeaders.put(Constants.CONTENT_TYPE, Constants.JSON_CONTENT_TYPE);
} else if (!existingHeaders
.get(Constants.CONTENT_TYPE)
.toLowerCase(Locale.ROOT)
.equals(Constants.JSON_CONTENT_TYPE)) {
throw new IllegalArgumentException(
"Only 'application/json' supported for content type");
}
}
byte[] bodyBytes;
try {
bodyBytes = getJsonBody(body);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Unable to process JSON body", e);
}

final byte[] bodyBytes = readBodyBytes(body);
if (isRequiredHeaderMissing(Constants.CONTENT_LENGTH, requiredHeaders, existingHeaders)) {
missingHeaders.put(Constants.CONTENT_LENGTH, Integer.toString(bodyBytes.length));
}
Expand Down Expand Up @@ -398,17 +396,19 @@ private List<String> getRequiredSigningHeaders(final String httpMethod) {

// JSON is the only accepted format for message bodies that need to be
// signed.
private static byte[] getJsonBody(Object body) throws JsonProcessingException {
private static byte[] readBodyBytes(Object body) throws IOException {
// empty body is OK
if (body == null) {
return "".getBytes(StandardCharsets.UTF_8);
}
// if already a string, just use it unchanged
if (body instanceof String) {
return ((String) body).getBytes(StandardCharsets.UTF_8);
} else if (body instanceof InputStream) {
return ByteStreams.toByteArray((InputStream) body);
}

throw new IllegalArgumentException("body must be a String");
throw new IllegalArgumentException("Unexpected body type: " + body.getClass().getName());
}

private static String base64Encode(byte[] bytes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
package com.oracle.bmc.http.signing.internal;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.oracle.bmc.http.internal.RestClientFactory;
import com.oracle.bmc.http.signing.RequestSignerException;
import com.oracle.bmc.http.signing.SigningStrategy;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -17,7 +19,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand All @@ -37,6 +44,7 @@
@PrepareForTest({LoggerFactory.class, RestClientFactory.class, RequestSignerImpl.class})
public class RequestSignerImplTest {
private static final String SERIALIZED_MAP_JSON_STRING = "{\"header\":[\"value1\",\"value2\"]}";
private static final byte[] BYTE_BUFFER = new byte[8196];

@Mock private Logger mockLogger;
@Mock private ObjectMapper mockObjectMapper;
Expand Down Expand Up @@ -112,4 +120,76 @@ public void ignoreCaseHeaders_shouldThrowRequestSignerException_whenDuplicateHea
actaulLogMessageValue.contains("More than one value for header [{}] found."));
}
}

@Test
public void calculateMissingHeaders_postStringContentAsJson() throws IOException {
calculateAndVerifyMissingHeaders(
MediaType.APPLICATION_JSON,
SERIALIZED_MAP_JSON_STRING,
SERIALIZED_MAP_JSON_STRING.length());
}

@Test
public void calculateMissingHeaders_postStringContentAsPlainText() throws IOException {
calculateAndVerifyMissingHeaders(
MediaType.TEXT_PLAIN,
SERIALIZED_MAP_JSON_STRING,
SERIALIZED_MAP_JSON_STRING.length());
}

@Test
public void calculateMissingHeaders_postInputStreamAsOctetStream() throws IOException {
calculateAndVerifyMissingHeaders(
MediaType.APPLICATION_OCTET_STREAM,
new ByteArrayInputStream(BYTE_BUFFER),
BYTE_BUFFER.length);
}

@Test
public void calculateMissingHeaders_postInputStreamAsPlainText() throws IOException {
calculateAndVerifyMissingHeaders(
MediaType.TEXT_PLAIN, new ByteArrayInputStream(BYTE_BUFFER), BYTE_BUFFER.length);
}

@Test(expected = IllegalArgumentException.class)
public void calculateMissingHeaders_invalidBody() throws IOException {
calculateAndVerifyMissingHeaders(MediaType.TEXT_PLAIN, BYTE_BUFFER, BYTE_BUFFER.length);
}

private void calculateAndVerifyMissingHeaders(
final String contentType, final Object body, final int contentLength)
throws IOException {
final URI uri = URI.create("https://identity.us-phoenix-1.oraclecloud.com/20160918/users");
final Map<String, String> existingHeaders =
ImmutableMap.of(
HttpHeaders.CONTENT_TYPE.toLowerCase(),
contentType,
"opc-request-id",
"2F9BA4A30BB3452397A5BC1BFE447C5D",
HttpHeaders.ACCEPT.toLowerCase(),
MediaType.APPLICATION_JSON);
final RequestSignerImpl.SigningConfiguration signingConfiguration =
new RequestSignerImpl.SigningConfiguration(
SigningStrategy.STANDARD.getHeadersToSign(),
SigningStrategy.STANDARD.isSkipContentHeadersForStreamingPutRequests());
final Map<String, String> missingHeaders =
RequestSignerImpl.calculateMissingHeaders(
HttpMethod.POST.toLowerCase(),
uri,
existingHeaders,
body,
Constants.ALL_HEADERS,
signingConfiguration);
assertNotNull(missingHeaders);
assertEquals(4, missingHeaders.size());
assertTrue(missingHeaders.containsKey(HttpHeaders.DATE.toLowerCase()));
assertTrue(missingHeaders.containsKey(HttpHeaders.CONTENT_LENGTH.toLowerCase()));
assertEquals(
Integer.toString(contentLength),
missingHeaders.get(HttpHeaders.CONTENT_LENGTH.toLowerCase()));
assertTrue(missingHeaders.containsKey("x-content-sha256"));
assertEquals(
"identity.us-phoenix-1.oraclecloud.com",
missingHeaders.get(HttpHeaders.HOST.toLowerCase()));
}
}
Loading