Skip to content
Open
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
19 changes: 15 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,27 @@ META-INF
out/config.properties
.okta-aws-cli-session

.idea/workspace.xml

/target/
.classpath
.settings
.project
dependency-reduced-pom.xml
.idea
*.iml
move.bat
.factorypath
.vscode
.idea

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# File-based project format
*.iws

gradle.xml
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
sudo: false
language: java
jdk:
- openjdk11
services:
- docker
cache:
Expand Down
2 changes: 1 addition & 1 deletion Readme.MD
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ NOTE: **okta-aws** is a function loaded from your shell profile, not a typical p
The application was built and compiled with [JetBrains' IntelliJ IDEA](https://www.jetbrains.com/idea/). Note that you don't have to compile the application in order to be able to execute it, since the compiled executable (a JAR file) is available [on GitHub](https://github.com/oktadeveloper/okta-aws-cli-assume-role/releases).

### Prerequisites
First of all, it goes without saying that you will need to install the [Java SE 8x](http://www.oracle.com/technetwork/java/javase/downloads/index.html) or the [Java JDK 8x](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html).
First of all, it goes without saying that you will need to install the [Java 11](http://www.oracle.com/technetwork/java/javase/downloads/index.html) or later.

Then you will need [Maven 2 or later](https://maven.apache.org/install.html) to run the build.

Expand Down
2 changes: 1 addition & 1 deletion bin/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ curl -Ls -o "${dest}" "${url}"

jarpath="${PREFIX}/okta-aws-cli.jar"
echo "Symlinking ${jarpath} → $(basename ${dest})" | sed "s#$HOME#~#g"
ln -s $(basename ${dest}) "${jarpath}"
ln -sf $(basename ${dest}) "${jarpath}"

# bash functions
bash_functions="${PREFIX}/bash_functions"
Expand Down
53 changes: 46 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2017-18 Okta, Inc.
~ Copyright 2017-Present Okta, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,8 @@

<groupId>com.okta.developer</groupId>
<artifactId>okta-aws-cli</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.0.3-SNAPSHOT</version>
<packaging>jar</packaging>

<repositories>
<repository>
Expand All @@ -42,7 +43,7 @@
<jsoup.version>1.11.3</jsoup.version>
<opensaml.version>3.4.2</opensaml.version>
<slf4j.version>1.7.26</slf4j.version>
<openjfx.version>11.0.2</openjfx.version>
<openjfx.version>12.0.1</openjfx.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -104,11 +105,41 @@
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx</artifactId>
<version>${openjfx.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>${openjfx.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${openjfx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${openjfx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${openjfx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>${openjfx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${openjfx.version}</version>
</dependency>

<!-- Test dependencies -->
Expand Down Expand Up @@ -150,8 +181,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
Expand Down Expand Up @@ -190,7 +221,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.1</version>
<version>3.1.2</version>
<configuration>
<archive>
<manifest>
Expand All @@ -211,6 +242,14 @@
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.2</version>
<configuration>
<mainClass>com.okta.tools.WithOkta</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
9 changes: 8 additions & 1 deletion src/main/java/com/okta/tools/WithOkta.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ public static void main(String[] args) throws Exception {
awsEnvironment.put("AWS_ACCESS_KEY_ID", runResult.accessKeyId);
awsEnvironment.put("AWS_SECRET_ACCESS_KEY", runResult.secretAccessKey);
awsEnvironment.put("AWS_SESSION_TOKEN", runResult.sessionToken);
args = removeProfileArguments(args);
}
// Cleanup command line arguments if present
args = removeProfileArguments(args);

if(args.length == 0) {
logger.info("No additional command line arguments provided. Hint: okta-aws <aws cli command>");
System.exit(0);
return;
}
awsProcessBuilder.command(args);
logger.fine(() -> "AWS CLI command line: " + awsProcessBuilder.command().toString());
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/okta/tools/helpers/RoleHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public AssumeRoleWithSAMLRequest chooseAwsRoleToAssume(String samlResponse) thro
public List<AccountOption> getAvailableRoles(String samlResponse) throws IOException {
Map<String, String> roles = AwsSamlRoleUtils.getRoles(samlResponse);
if (roles.size() == 1) {
String roleArn = roles.keySet().iterator().next();
String roleArn = roles.values().iterator().next();
return Collections.singletonList(
new AccountOption("Account: (" + roleArn.substring("arn:aws:iam::".length(), "arn:aws:iam::".length() + 12) + ")",
Collections.singletonList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,16 @@

import com.okta.tools.OktaAwsCliEnvironment;



import java.io.IOException;
import java.net.Proxy;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.*;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.logging.Logger;

final class LoginPageInterceptingProtocolHandler extends sun.net.www.protocol.https.Handler {
final class LoginPageInterceptingProtocolHandler extends URLStreamHandler {
private static final Logger LOGGER = Logger.getLogger(LoginPageInterceptingProtocolHandler.class.getName());
private final OktaAwsCliEnvironment environment;
private final BiFunction<URL, URLConnection, URLConnection> filteringUrlConnectionFactory;
Expand All @@ -37,9 +36,13 @@ final class LoginPageInterceptingProtocolHandler extends sun.net.www.protocol.ht
this.filteringUrlConnectionFactory = filteringUrlConnectionFactory;
}


@Override
protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
URLConnection urlConnection = super.openConnection(url, proxy);
protected URLConnection openConnection(URL url) throws IOException {
return this.openConnection(url,(Proxy)null);
}

private URLConnection handleOpenConnection(URL url, URLConnection urlConnection) throws IOException{
URI oktaAwsAppUri = URI.create(environment.oktaAwsAppUrl);
List<String> domainsToIntercept = Arrays.asList(
environment.oktaOrg,
Expand All @@ -51,7 +54,7 @@ protected URLConnection openConnection(URL url, Proxy proxy) throws IOException
"/auth/services/devicefingerprint"
);
if (domainsToIntercept.contains(url.getHost()) &&
requestPathsToIntercept.contains(url.getPath())
requestPathsToIntercept.contains(url.getPath())
) {
LOGGER.finest(() -> String.format("[%s] Using filtering URLConnection", url));
return filteringUrlConnectionFactory.apply(url, urlConnection);
Expand All @@ -60,4 +63,16 @@ protected URLConnection openConnection(URL url, Proxy proxy) throws IOException
return urlConnection;
}
}

@Override
protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
URLConnection urlConnection = super.openConnection(url, proxy);
//URLConnection urlConnection = new HttpURLConnection(url, url.getHost(), url.getPort());
// default handler
//URLStreamHandler defaultHandler = new sun.net.www.protocol.https.Handler();
//URLConnection urlConnection = new HttpURLConnection(url, proxy, this);
//URLConnection urlConnection = HttpConnectionFactory.GetConnection(url,proxy,this);
//URLConnection = new HttpsURLConnection(url,proxy, this)
return handleOpenConnection(url, urlConnection);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ private SubresourceIntegrityStrippingHack() {}

public static void overrideHttpsProtocolHandler(OktaAwsCliEnvironment environment) {
try {
LOGGER.finest("overrideHttpsProtocolHandler do nothing");
/*
URL.setURLStreamHandlerFactory(protocol -> "https".equals(protocol) ?
new LoginPageInterceptingProtocolHandler(environment,
SubresourceIntegrityStrippingURLConnection::new) :
null
);
LOGGER.finest("Successfully registered custom protocol handler");
*/
} catch (Exception e) {
LOGGER.warning(() -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/okta/tools/saml/AwsSamlRoleUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static Map<String, String> getRoles(String samlResponse) {
String[] parts = roleIdpPair.split(",");
String principalArn = parts[0];
String roleArn = parts[1];
roles.put(roleArn, principalArn);
roles.put(principalArn, roleArn);
}
return roles;
}
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/okta/tools/saml/OktaAppClientImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public Document launchApp(String appUrl) throws IOException {
+ oktaAwsAppResponse.getStatusLine().getStatusCode());
}

// Fix: previous logic was assuming that always was refreshing a previous session and cookies were
// in place.
// This condition throws an exception to trigger authentication with user credentials if no
// cookies from a previous session was present to avoid crash when the tool is installed fresh
// and no previous session cookies are present
if(cookieStore.getCookies().isEmpty()) {
throw new OktaSaml.PromptForCredentialsException("No cookies found, need to create a new okta session");
}

cookieHelper.storeCookies(cookieStore);

return Jsoup.parse(
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/okta/tools/saml/OktaSaml.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public String getSamlResponse() throws IOException, InterruptedException {
} else {
try {
return getSamlResponseForAwsRefresh();
} catch (PromptForReAuthenticationException | PromptForFactorException e) {
} catch (PromptForReAuthenticationException | PromptForFactorException | PromptForCredentialsException e) {
String oktaSessionToken = authentication.getOktaSessionToken();
return getSamlResponseForAws(oktaSessionToken);
}
Expand Down Expand Up @@ -93,6 +93,12 @@ public PromptForFactorException(String message) {
}
}

public static final class PromptForCredentialsException extends IllegalStateException {
public PromptForCredentialsException(String message) {
super(message);
}
}

// Heuristic based on undocumented behavior observed experimentally
// This condition may be missed if Okta significantly changes the app-level re-auth page
private boolean isPasswordAuthenticationChallenge(Document document) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/main.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
1 change: 1 addition & 0 deletions src/test/java/com/okta/tools/RoleHelperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.okta.tools.helpers.RoleHelper;
import com.okta.tools.models.AccountOption;
import com.okta.tools.models.RoleOption;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand Down
12 changes: 12 additions & 0 deletions src/test/test.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="main" />
</component>
</module>