Skip to content

Commit d5578a8

Browse files
committed
Fixed issues with use of Instance Principals with the cloud service.
o ensure that access tokens used are not expired o warmup signature cache to reduce security-related latency when a handle is first used o reduce time a signature is cached to ensure that it is refreshed before it times out
1 parent 3af6695 commit d5578a8

14 files changed

+374
-47
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ of a given type, e.g. FieldValue.isInteger(), etc.
2424
- Some methods that would throw NullPointerException for missing or
2525
invalid configurations now throw IllegalArgumentException. Related messages have
2626
been clarified.
27+
- Changed default duration of signature cache of SignatureProvider from 5 to 4 minutes
28+
- NoSQLHandle creation now performs SignatureProvider warm-up that will pre-create
29+
and cache the signature. Errors or delays occur during creating signature may
30+
result in handle creation failure that would not have happened in previous releases (cloud service only)
2731

2832
### Fixed
2933
- Use correct netty constructor when using an HTTP proxy without a username or
@@ -37,6 +41,12 @@ TableNotFoundException
3741
- setProxyPort
3842
- setProxyUsername
3943
- setProxyPassword
44+
- Cloud service only, instance principal issues:
45+
- Fixed an issue where the first request issued using instance principal may take
46+
longer than 5 seconds and throw RequestTimeoutException if handle uses the default
47+
request timeout.
48+
- Fixed a problem where SignatureProvider with instance principal may use expired
49+
security token issued by IAM to create signature, which causes InvalidAuthorizationException.
4050

4151
## [5.2.26] - 2021-02-09
4252

driver/.classpath

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
55
<classpathentry kind="output" path="target/classes"/>
66
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
7-
<classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-core/2.11.2/jackson-core-2.11.2.jar"/>
7+
<classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-core/2.12.1/jackson-core-2.12.1.jar"/>
88
<classpathentry kind="var" path="M2_REPO/io/netty/netty-buffer/4.1.52.Final/netty-buffer-4.1.52.Final.jar"/>
99
<classpathentry kind="var" path="M2_REPO/io/netty/netty-common/4.1.52.Final/netty-common-4.1.52.Final.jar"/>
1010
<classpathentry kind="var" path="M2_REPO/io/netty/netty-codec-http/4.1.52.Final/netty-codec-http-4.1.52.Final.jar"/>
@@ -14,8 +14,8 @@
1414
<classpathentry kind="var" path="M2_REPO/io/netty/netty-handler/4.1.52.Final/netty-handler-4.1.52.Final.jar"/>
1515
<classpathentry kind="var" path="M2_REPO/io/netty/netty-handler-proxy/4.1.52.Final/netty-handler-proxy-4.1.52.Final.jar"/>
1616
<classpathentry kind="var" path="M2_REPO/io/netty/netty-codec-socks/4.1.52.Final/netty-codec-socks-4.1.52.Final.jar"/>
17-
<classpathentry kind="var" path="M2_REPO/org/bouncycastle/bcprov-jdk15on/1.66/bcprov-jdk15on-1.66.jar"/>
18-
<classpathentry kind="var" path="M2_REPO/org/bouncycastle/bcpkix-jdk15on/1.66/bcpkix-jdk15on-1.66.jar"/>
17+
<classpathentry kind="var" path="M2_REPO/org/bouncycastle/bcprov-jdk15on/1.68/bcprov-jdk15on-1.68.jar"/>
18+
<classpathentry kind="var" path="M2_REPO/org/bouncycastle/bcpkix-jdk15on/1.68/bcpkix-jdk15on-1.68.jar"/>
1919
<classpathentry kind="var" path="M2_REPO/junit/junit/4.12/junit-4.12.jar"/>
2020
<classpathentry kind="var" path="M2_REPO/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar"/>
21-
</classpath>
21+
</classpath>

driver/src/main/java/oracle/nosql/driver/http/NoSQLHandleImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ private void configAuthProvider(Logger logger, NoSQLHandleConfig config) {
146146
}
147147
} else if (ap instanceof SignatureProvider) {
148148
SignatureProvider sigProvider = (SignatureProvider) ap;
149-
sigProvider.setServiceHost(config);
149+
sigProvider.prepare(config);
150150
if (sigProvider.getLogger() == null) {
151151
sigProvider.setLogger(logger);
152152
}

driver/src/main/java/oracle/nosql/driver/iam/AuthenticationProfileProvider.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
* @hidden
1414
* Internal use only
1515
* <p>
16-
* The provider to supplies key id and private key that ared used to generate
16+
* The provider to supplies key id and private key that are used to generate
1717
* request signature.
1818
*/
19-
interface AuthenticationProfileProvider {
19+
public interface AuthenticationProfileProvider {
2020

2121
/**
2222
* Returns the keyId used to sign requests.
@@ -42,4 +42,13 @@ interface AuthenticationProfileProvider {
4242
* @return The passphrase as character array, or null if not applicable
4343
*/
4444
char[] getPassphraseCharacters();
45+
46+
/**
47+
* Check validity of key identified by given id.
48+
* @param keyId key id
49+
* @return true if key identified by given id is valid
50+
*/
51+
default boolean isKeyValid(String keyId) {
52+
return true;
53+
}
4554
}

driver/src/main/java/oracle/nosql/driver/iam/InstancePrincipalsProvider.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import oracle.nosql.driver.httpclient.HttpClient;
3030
import oracle.nosql.driver.iam.CertificateSupplier.DefaultCertificateSupplier;
3131
import oracle.nosql.driver.iam.CertificateSupplier.URLResourceDetails;
32+
import oracle.nosql.driver.iam.SecurityTokenSupplier.SecurityTokenBasedProvider;
3233
import oracle.nosql.driver.iam.SessionKeyPairSupplier.DefaultSessionKeySupplier;
3334
import oracle.nosql.driver.iam.SessionKeyPairSupplier.JDKKeyPairSupplier;
3435
import oracle.nosql.driver.util.HttpRequestUtil;
@@ -49,8 +50,10 @@
4950
* compute instance. It authenticates with instance principal and uses security
5051
* token issued by IAM to do the actual request signing.
5152
*/
52-
class InstancePrincipalsProvider
53-
implements AuthenticationProfileProvider, RegionProvider {
53+
public class InstancePrincipalsProvider
54+
implements AuthenticationProfileProvider,
55+
RegionProvider,
56+
SecurityTokenBasedProvider {
5457

5558
protected final SecurityTokenSupplier tokenSupplier;
5659
protected final DefaultSessionKeySupplier sessionKeySupplier;
@@ -69,6 +72,11 @@ public String getKeyId() {
6972
return "ST$" + tokenSupplier.getSecurityToken();
7073
}
7174

75+
@Override
76+
public boolean isKeyValid(String keyId) {
77+
return keyId.equals("ST$" + tokenSupplier.getCurrentToken());
78+
}
79+
7280
@Override
7381
public InputStream getPrivateKey() {
7482
return new ByteArrayInputStream(sessionKeySupplier.getPrivateKeyBytes());
@@ -84,11 +92,17 @@ public Region getRegion() {
8492
return region;
8593
}
8694

95+
@Override
96+
public void setTokenExpirationRefreshWindow(long refreshWindowMS) {
97+
tokenSupplier.setTokenExpirationRefreshWindow(refreshWindowMS);
98+
}
99+
87100
public static InstancePrincipalsProviderBuilder builder() {
88101
return new InstancePrincipalsProviderBuilder();
89102
}
90103

91104
/**
105+
* @hidden
92106
* Cloud service only.
93107
* <p>
94108
* Builder of InstancePrincipalsProvider

driver/src/main/java/oracle/nosql/driver/iam/ResourcePrincipalProvider.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import oracle.nosql.driver.Region.RegionProvider;
1818
import oracle.nosql.driver.iam.ResourcePrincipalTokenSupplier.FileSecurityTokenSupplier;
1919
import oracle.nosql.driver.iam.ResourcePrincipalTokenSupplier.FixedSecurityTokenSupplier;
20+
import oracle.nosql.driver.iam.SecurityTokenSupplier.SecurityTokenBasedProvider;
2021
import oracle.nosql.driver.iam.SessionKeyPairSupplier.DefaultSessionKeySupplier;
2122
import oracle.nosql.driver.iam.SessionKeyPairSupplier.FileKeyPairSupplier;
2223
import oracle.nosql.driver.iam.SessionKeyPairSupplier.FixedKeyPairSupplier;
@@ -65,7 +66,9 @@
6566
* </ul>
6667
*/
6768
class ResourcePrincipalProvider
68-
implements AuthenticationProfileProvider, RegionProvider {
69+
implements AuthenticationProfileProvider,
70+
RegionProvider,
71+
SecurityTokenBasedProvider {
6972

7073
/* Environment variable names used to fetch artifacts */
7174
private static final String OCI_RESOURCE_PRINCIPAL_VERSION =
@@ -164,6 +167,11 @@ public String getKeyId() {
164167
return "ST$" + tokenSupplier.getSecurityToken();
165168
}
166169

170+
@Override
171+
public boolean isKeyValid(String keyId) {
172+
return keyId.equals("ST$" + tokenSupplier.getCurrentToken());
173+
}
174+
167175
@Override
168176
public InputStream getPrivateKey() {
169177
return new ByteArrayInputStream(sessionKeySupplier.getPrivateKeyBytes());
@@ -179,6 +187,11 @@ public Region getRegion() {
179187
return region;
180188
}
181189

190+
@Override
191+
public void setTokenExpirationRefreshWindow(long refreshWindowMS) {
192+
tokenSupplier.setTokenExpirationRefreshWindow(refreshWindowMS);
193+
}
194+
182195
/**
183196
* @hidden
184197
* Internal only

driver/src/main/java/oracle/nosql/driver/iam/ResourcePrincipalTokenSupplier.java

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,33 @@
2222
* @hidden
2323
* Internal use only
2424
* <p>
25-
* This interface to supply security token for resource principal
25+
* The class to supply security token for resource principal
2626
*/
27-
interface ResourcePrincipalTokenSupplier {
27+
abstract class ResourcePrincipalTokenSupplier {
28+
/* Refresh window before token is expired */
29+
protected long tokenExpirationRefreshWindow;
2830

2931
/**
3032
* Return the security token of resource principal.
3133
*/
32-
String getSecurityToken();
34+
abstract String getSecurityToken();
3335

3436
/**
3537
* Return the specific claim in security token by given key.
3638
*/
37-
String getStringClaim(String key);
39+
abstract String getStringClaim(String key);
40+
41+
/**
42+
* Return current cached token.
43+
*/
44+
abstract String getCurrentToken();
45+
46+
/**
47+
* Set token expiration refresh window.
48+
*/
49+
void setTokenExpirationRefreshWindow(long refreshWindowMS) {
50+
this.tokenExpirationRefreshWindow = refreshWindowMS;
51+
}
3852

3953
/**
4054
* @hidden
@@ -45,7 +59,7 @@ interface ResourcePrincipalTokenSupplier {
4559
* <code>com.oracle.bmc.auth.internal.FileBasedResourcePrincipalFederationClient</code>
4660
*/
4761
static class FileSecurityTokenSupplier
48-
implements ResourcePrincipalTokenSupplier {
62+
extends ResourcePrincipalTokenSupplier {
4963

5064
private final SessionKeyPairSupplier sessionKeyPairSupplier;
5165
private final String sessionTokenPath;
@@ -57,7 +71,9 @@ static class FileSecurityTokenSupplier
5771
Logger logger) {
5872
this.sessionKeyPairSupplier = sessKeyPairSupplier;
5973
this.sessionTokenPath = sessionTokenPath;
60-
this.securityToken = new SecurityToken(null, sessionKeyPairSupplier);
74+
this.securityToken = new SecurityToken(null,
75+
tokenExpirationRefreshWindow,
76+
sessionKeyPairSupplier);
6177
this.logger = logger;
6278
}
6379

@@ -75,6 +91,14 @@ public String getStringClaim(String key) {
7591
return securityToken.getStringClaim(key);
7692
}
7793

94+
@Override
95+
public String getCurrentToken() {
96+
if (securityToken.isValid(logger, false)) {
97+
return securityToken.getSecurityToken();
98+
}
99+
return null;
100+
}
101+
78102
private String refreshAndGetSecurityToken() {
79103
synchronized (this) {
80104
if (!securityToken.isValid(logger)) {
@@ -107,7 +131,9 @@ SecurityToken getSecurityTokenFromFile() {
107131
"Unable to read session token from " + sessionTokenPath, e);
108132
}
109133

110-
return new SecurityToken(sessToken, sessionKeyPairSupplier);
134+
return new SecurityToken(sessToken,
135+
tokenExpirationRefreshWindow,
136+
sessionKeyPairSupplier);
111137
}
112138
}
113139

@@ -121,13 +147,14 @@ SecurityToken getSecurityTokenFromFile() {
121147
* <code>com.oracle.bmc.auth.internal.FixedContentResourcePrincipalFederationClient</code>
122148
*/
123149
static class FixedSecurityTokenSupplier
124-
implements ResourcePrincipalTokenSupplier {
150+
extends ResourcePrincipalTokenSupplier {
125151

126152
private final SecurityToken securityToken;
127153

128154
FixedSecurityTokenSupplier(SessionKeyPairSupplier sessionKeySupplier,
129155
String sessionToken) {
130156
this.securityToken = new SecurityToken(sessionToken,
157+
tokenExpirationRefreshWindow,
131158
sessionKeySupplier);
132159
}
133160

@@ -140,5 +167,10 @@ public String getSecurityToken() {
140167
public String getStringClaim(String key) {
141168
return securityToken.getStringClaim(key);
142169
}
170+
171+
@Override
172+
public String getCurrentToken() {
173+
return securityToken.getSecurityToken();
174+
}
143175
}
144176
}

0 commit comments

Comments
 (0)