-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
384 additions
and
2 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
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 @@ | ||
* @statnett/k3a |
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,4 @@ | ||
{ | ||
"$schema": "https://docs.renovatebot.com/renovate-schema.json", | ||
"extends": ["github>statnett/renovate-config"], | ||
} |
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,18 @@ | ||
--- | ||
name: CI | ||
on: | ||
pull_request: {} | ||
|
||
permissions: | ||
contents: read | ||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-java@v3 | ||
with: | ||
java-version: '11' | ||
distribution: 'temurin' | ||
cache: maven | ||
- run: mvn --batch-mode verify |
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,17 @@ | ||
--- | ||
name: Lint PR | ||
on: | ||
pull_request_target: | ||
types: | ||
- opened | ||
- edited | ||
- synchronize | ||
|
||
permissions: | ||
contents: read | ||
jobs: | ||
trigger: | ||
uses: statnett/github-workflows/.github/workflows/lint-pr.yaml@main | ||
permissions: | ||
pull-requests: write | ||
statuses: write |
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,19 @@ | ||
--- | ||
name: Release Please | ||
on: | ||
push: | ||
branches: | ||
- main | ||
workflow_dispatch: | ||
|
||
permissions: | ||
contents: read | ||
jobs: | ||
trigger: | ||
uses: statnett/github-workflows/.github/workflows/release-please.yaml@main | ||
with: | ||
release-type: maven | ||
secrets: inherit | ||
permissions: | ||
contents: write | ||
pull-requests: write |
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,21 @@ | ||
name: Publish package | ||
on: | ||
release: | ||
types: [created] | ||
jobs: | ||
publish: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-java@v3 | ||
with: | ||
java-version: '11' | ||
distribution: 'temurin' | ||
- name: Build package | ||
run: mvn --batch-mode verify | ||
- name: Push GitHub release artifact | ||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15 | ||
with: | ||
files: target/*.jar |
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,20 @@ | ||
--- | ||
name: Scorecard supply-chain security | ||
on: | ||
branch_protection_rule: | ||
schedule: | ||
- cron: "20 7 * * 2" | ||
push: | ||
branches: | ||
- main | ||
|
||
permissions: | ||
contents: read | ||
jobs: | ||
trigger: | ||
uses: statnett/github-workflows/.github/workflows/scorecard.yaml@main | ||
permissions: | ||
security-events: write | ||
id-token: write | ||
contents: read | ||
actions: read |
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,3 @@ | ||
*~ | ||
.idea/ | ||
target/ |
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,5 @@ | ||
# Changelog | ||
|
||
## 1.0.0 (2021-12-01) | ||
|
||
* Initial, internal version. |
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,2 +1,50 @@ | ||
# k3a-prompt-login-module | ||
A JAAS LoginModule intended for use with Kafka clients, asking for the user's password | ||
# prompt-login-module | ||
|
||
A JAAS `LoginModule` intended for use with Kafka clients. When using | ||
this module, it is not necessary to embed/store the password in the | ||
config. Instead, the user will be prompted for the password (and | ||
optionally, the username, if not present in the config). | ||
|
||
## How to use it | ||
|
||
Make the jar file available to the Kafka tools by installing it in the | ||
shared jar directory of the tools. This will typically be a | ||
`share/java/kafka` sub-directory under the base directory of the tools | ||
installation. If tools are installed in `/opt/kafka`, this command | ||
will install the jar: | ||
|
||
```shell | ||
KAFKA_BASEDIR=/opt/kafka | ||
PROMPT_LOGIN_MODULE_VERSION=1.1.0 | ||
curl -sSfo ${KAFKA_BASEDIR}/share/java/kafka/prompt-login-module.jar \ | ||
https://github.com/statnett/k3a-prompt-login-module/releases/download/v${PROMPT_LOGIN_MODULE_VERSION}/k3a-prompt-login-module-${PROMPT_LOGIN_MODULE_VERSION}.jar | ||
``` | ||
|
||
The latest version may be found [on GitHub](https://github.com/statnett/k3a-prompt-login-module). | ||
|
||
Reference the `io.statnett.k3a.authz.PromptLoginModule` class in | ||
the JAAS section of your Kafka properties file: | ||
|
||
```properties | ||
sasl.mechanism=PLAIN | ||
security.protocol=SASL_SSL | ||
sasl.jaas.config=io.statnett.k3a.authz.PromptLoginModule required \ | ||
username="my.user.name"; | ||
``` | ||
|
||
Run a Kafka command, referencing the Kafka properties, and note how it | ||
now asks for a password from the console (If the JAAS config lacks a | ||
username, it will be prompted for too): | ||
|
||
```shell | ||
$ kafka-topics --bootstrap-server broker:9092 --command-config kafka.properties --list | ||
Password: | ||
__consumer_offsets | ||
__transaction_state | ||
app_strm_demo_topic | ||
: | ||
``` | ||
|
||
If input or output is redirected, the password will not be read from | ||
the console, but instead a dialog window will open asking for the | ||
credentials. |
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,60 @@ | ||
<?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> | ||
|
||
<groupId>io.statnett.k3a</groupId> | ||
<artifactId>k3a-prompt-login-module</artifactId> | ||
<packaging>jar</packaging> | ||
<version>1.0.5-SNAPSHOT</version> | ||
|
||
<name>${project.groupId}:${project.artifactId}</name> | ||
<description>A JAAS LoginModule intended for use with Kafka clients, asking for the user's password</description> | ||
<url>https://github.com/statnett/k3a-prompt-login-module</url> | ||
|
||
<licenses> | ||
<license> | ||
<name>MIT License</name> | ||
<url>https://opensource.org/license/mit/</url> | ||
</license> | ||
</licenses> | ||
|
||
<scm> | ||
<connection>scm:git:git://github.com/statnett/k3a-prompt-login-module.git</connection> | ||
<developerConnection>scm:git:ssh://github.com:statnett/k3a-prompt-login-module.git</developerConnection> | ||
<url>https://github.com/statnett/k3a-prompt-login-module/tree/main</url> | ||
</scm> | ||
|
||
<properties> | ||
<java.version>1.8</java.version> | ||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<kafka.version>3.6.0</kafka.version> | ||
</properties> | ||
|
||
<dependencies> | ||
|
||
<dependency> | ||
<groupId>org.apache.kafka</groupId> | ||
<artifactId>kafka-clients</artifactId> | ||
<version>${kafka.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.11.0</version> | ||
<configuration> | ||
<source>${java.version}</source> | ||
<target>${java.version}</target> | ||
<encoding>UTF-8</encoding> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
166 changes: 166 additions & 0 deletions
166
src/main/java/io/statnett/k3a/authz/PromptLoginModule.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,166 @@ | ||
package io.statnett.k3a.authz; | ||
|
||
import org.apache.kafka.common.security.plain.internals.PlainSaslServerProvider; | ||
|
||
import javax.security.auth.Subject; | ||
import javax.security.auth.callback.CallbackHandler; | ||
import javax.security.auth.spi.LoginModule; | ||
import javax.swing.BorderFactory; | ||
import javax.swing.JButton; | ||
import javax.swing.JDialog; | ||
import javax.swing.JLabel; | ||
import javax.swing.JPanel; | ||
import javax.swing.JPasswordField; | ||
import javax.swing.JTextField; | ||
import javax.swing.WindowConstants; | ||
import java.awt.BorderLayout; | ||
import java.awt.Component; | ||
import java.awt.Frame; | ||
import java.awt.GridBagConstraints; | ||
import java.awt.GridBagLayout; | ||
import java.awt.Insets; | ||
import java.awt.Toolkit; | ||
import java.awt.event.WindowAdapter; | ||
import java.awt.event.WindowEvent; | ||
import java.io.Console; | ||
import java.util.Map; | ||
|
||
/** | ||
* A JAAS LoginModule for Kafka that will look for username and password configuration values, | ||
* and prompt the user for any value that is missing. | ||
* | ||
* If a Java "Console" is available, ie. stdin/stdout is not redirected, the input | ||
* will be read from the console. Otherwise, this class will try to disable | ||
* "headless mode", and display a Swing dialog. | ||
*/ | ||
public final class PromptLoginModule | ||
implements LoginModule { | ||
|
||
private static final String USERNAME_CONFIG = "username"; | ||
private static final String PASSWORD_CONFIG = "password"; | ||
private Subject subject; | ||
private String username; | ||
private String password; | ||
|
||
static { | ||
System.setProperty("java.awt.headless", "false"); | ||
PlainSaslServerProvider.initialize(); | ||
} | ||
|
||
@Override | ||
public void initialize(final Subject subject, final CallbackHandler callbackHandler, final Map<String, ?> sharedState, final Map<String, ?> options) { | ||
this.subject = subject; | ||
username = (String) options.get(USERNAME_CONFIG); | ||
password = (String) options.get(PASSWORD_CONFIG); | ||
promoteNonNulls(); | ||
} | ||
|
||
@Override | ||
public boolean login() { | ||
final Console console = System.console(); | ||
if (console != null) { | ||
inputFromConsole(console); | ||
} else { | ||
inputFromWindow(); | ||
} | ||
promoteNonNulls(); | ||
return true; | ||
} | ||
|
||
private void inputFromConsole(final Console console) { | ||
if (username == null) { | ||
username = console.readLine("Username: "); | ||
} | ||
if (password == null) { | ||
final char[] chars = console.readPassword("Password: "); | ||
if (chars != null) { | ||
password = new String(chars); | ||
} | ||
} | ||
} | ||
|
||
private void inputFromWindow() { | ||
new UsernamePasswordDialog(); | ||
} | ||
|
||
@Override | ||
public boolean logout() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean commit() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean abort() { | ||
return false; | ||
} | ||
|
||
private void promoteNonNulls() { | ||
if (username != null) { | ||
subject.getPublicCredentials().add(username); | ||
} | ||
if (password != null) { | ||
subject.getPrivateCredentials().add(password); | ||
} | ||
} | ||
|
||
private final class UsernamePasswordDialog | ||
extends JDialog { | ||
|
||
UsernamePasswordDialog() { | ||
super((Frame) null, "JAAS Login", true); | ||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); | ||
final JPanel panel = new JPanel(new GridBagLayout()); | ||
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); | ||
final GridBagConstraints constraints = new GridBagConstraints(); | ||
constraints.fill = GridBagConstraints.HORIZONTAL; | ||
constraints.insets = new Insets(2, 5, 2, 5); | ||
final JTextField usernameInput = new JTextField(username == null ? "" : username, 20); | ||
addInput(panel, constraints, 0, "Username", usernameInput); | ||
final JPasswordField passwordInput = new JPasswordField(password == null ? "" : password, 20); | ||
addInput(panel, constraints, 1, "Password", passwordInput); | ||
|
||
final JButton submitButton = new JButton("Submit"); | ||
submitButton.addActionListener(e -> { | ||
username = usernameInput.getText(); | ||
password = new String(passwordInput.getPassword()); | ||
dispose(); | ||
}); | ||
getRootPane().setDefaultButton(submitButton); | ||
final JPanel buttonPanel = new JPanel(); | ||
buttonPanel.add(submitButton); | ||
|
||
getContentPane().add(panel, BorderLayout.CENTER); | ||
getContentPane().add(buttonPanel, BorderLayout.PAGE_END); | ||
|
||
pack(); | ||
setResizable(false); | ||
setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - getWidth()) / 2, | ||
(Toolkit.getDefaultToolkit().getScreenSize().height - getHeight()) / 2); | ||
addWindowFocusListener(new WindowAdapter() { | ||
@Override | ||
public void windowGainedFocus(final WindowEvent e) { | ||
if (username != null) { | ||
passwordInput.requestFocusInWindow(); | ||
} | ||
} | ||
}); | ||
setVisible(true); | ||
} | ||
|
||
private void addInput(final JPanel panel, final GridBagConstraints constraints, final int y, final String label, final Component input) { | ||
constraints.gridy = y; | ||
constraints.gridx = 0; | ||
constraints.gridwidth = 1; | ||
panel.add(new JLabel(label), constraints); | ||
constraints.gridx = 1; | ||
constraints.gridwidth = 2; | ||
panel.add(input, constraints); | ||
} | ||
|
||
} | ||
|
||
} |