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
18 changes: 9 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ jobs:
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Setup Repository
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
cache: 'maven'
check-latest: true
Expand All @@ -27,17 +27,17 @@ jobs:
gpg-private-key: ${{ secrets.GPG_KEY }}
java-package: 'jdk'
java-version: '21'
server-id: ossrh
server-password: OSSRH_PASSWORD
server-username: OSSRH_USERNAME
server-id: central
server-password: CRENTRAL_PASSWORD
server-username: CRENTRAL_USERNAME
- name: Publish to the Maven Central Repository
run: mvn -B -P ossrh -U deploy
run: mvn -B -P central -U deploy
env:
CENTRAL_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
CENTRAL_USERNAME: ${{ secrets.OSSRH_USERNAME }}
GPG_KEY_PASS: ${{ secrets.GPG_KEY_PASS }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
- name: Publish to GitHub Packages
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
cache: 'maven'
check-latest: true
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ jobs:
java-version: '21'

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Set up Java ${{ matrix.java-distribution }} ${{ matrix.java-version }}
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
check-latest: true
distribution: ${{ matrix.java-distribution }}
Expand Down
124 changes: 96 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@
<li><a href="#installation">Installation</a></li>
</ul>
</li>
<li><a href="#usage">Usage</a></li>
<li>
<a href="#usage">Usage</a>
<ul>
<li><a href="#configuration">Configuration</a></li>
</ul>
</li>
<li><a href="#roadmap">Roadmap</a></li>
<li><a href="#contributing">Contributing</a></li>
<li><a href="#license">License</a></li>
Expand Down Expand Up @@ -133,7 +138,7 @@ packages like maven will be needed to utilize the provided pom file.
$jdk_url = "https://aka.ms/download-jdk/microsoft-jdk-21-windows-x64.msi"
$java_home = New-Item -ItemType Directory -Path "$env:ProgramFiles\Java" -Force
$maven_home = New-Item -ItemType Directory -Path "$env:ProgramFiles\Apache\Maven" -Force
$maven_version = "3.9.11"
$maven_version = "3.9.16"
$maven_url = "https://dlcdn.apache.org/maven/maven-3/$maven_version/binaries/apache-maven-$maven_version-bin.zip"
Start-BitsTransfer -Destination "$env:USERPROFILE\Downloads\jdk-21.msi" -Source $jdk_url
Start-BitsTransfer -Destination "$env:USERPROFILE\Downloads\maven.zip" -Source $maven_url
Expand Down Expand Up @@ -180,74 +185,134 @@ packages like maven will be needed to utilize the provided pom file.



### Configuration

Every knob lives in `credcat.properties`. All are optional and fall back to sane
defaults, so an empty file is a working file. The `server.*` settings are ignored
in stand-alone mode.

```properties
# Keeper
keeper.client_key= # one time token for dynamic config creation
keeper.config= # default device config: a path, raw json, or base64
keeper.config.dir= # directory searched for named (configName) configs
keeper.config.env= # env var prefix searched for named (configName) configs
keeper.files= # default save location (os temp dir when unset)
keeper.storage.persistent=false # persist SDK config mutations back to the source file

# Files
file.clean=true # wipe the files directory recursively on shutdown
file.transport=inline # disk | inline | none

# Server
server.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413
server.threads= # worker pool size (defaults to max(8, 2x cpu cores))
```

A named lookup (`configName`) is resolved against `keeper.config.dir` first, then
the `keeper.config.env` prefix; the literal `config` parameter always wins when both
are present, and the `keeper.config` default backs them all.



<!-- USAGE EXAMPLES -->
## Usage

You will need to generate a device config for your KSM application in either
base64 or json format. You can also use the one time password feature to generate
the config dynamically using the clientKey parameter instead. Using the config
parameter provides the means to switch between application vaults. You can pass
one or more of either titles and/or record uid's to retrive multiple records at
once. Exact matches only. Any files are downloaded locally and their save
location is returned in the response.
You will need a device config for your KSM application in either base64 or json
format. Provide it directly with the `config` parameter, as a literal value or a
path to a file holding one. Skip the config entirely and let credcat mint one on
the fly via the one time password feature with the `clientKey` parameter. When
direct or individual handling of device configs is undesired use the `configName`
parameter to switch between pre-defined choices stashed in either a directory or
through environment variables. The `config`, `configName` and `clientKey`
parameters are your means to alternate between application vaults.

Pass one or more of either titles and/or record uid's to retrieve multiple records
at once. Exact matches only.

Attached files are handed back however your deployment prefers, set globally with
the `file.transport` property or overridden per-request with `fileTransport`:

* `disk` ... written to the save location, whose path is returned in the response.
* `inline` ... base64 encoded straight into the response; nothing touches the disk.
* `none` ... skipped entirely; only the file's metadata comes back.

```sh
Usage: java -jar credcat.jar [ -server | '{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
```

1. Payload can be any of the following.
```sh
ADVANCED='{ "clientKey": "7dae669a419ee250d0fd0e12d527f5f1", "config": "config.base64", "saveLocation": "/mnt/share/keeper", "titles": ["development ldap"], "uids": ["chnmFhEC38YCHhNY1pA8Vg"] }'
ADVANCED='{ "clientKey": "7dae669a419ee250d0fd0e12d527f5f1", "config": "config.base64", "fileTransport": "disk", "saveLocation": "/mnt/share/keeper", "titles": ["development ldap"], "uids": ["chnmFhEC38YCHhNY1pA8Vg"] }'
NAMED='{ "configName": "production", "titles": ["Production ClickToCall API Key", "development ldap"] }'
TITLE_ONLY='{ "config": ".keeper/config.base64", "titles": ["Production ClickToCall API Key", "development ldap"] }'
UID_ONLY='{ "config": ".keeper/config.base64", "uids": ["7bN_ceW-p3_alVUNmI09Tw", "chnmGhEC39YCHhNy1pA8vg"] }'
UID_ONLY='{ "config": ".keeper/config.base64", "fileTransport": "disk", "uids": ["7bN_ceW-p3_alVUNmI09Tw", "chnmGhEC39YCHhNy1pA8vg"] }'
```

2. Whether passing title or uid, records are returned nested under its respective uid.
Using the `disk` transport:
```sh
java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService $ADVANCED
java -jar target/credcat.jar $UID_ONLY
java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
java -jar target/credcat.jar "$UID_ONLY"
```
```json
INFO: {
"7bN_ceW-p3_alVUNmI09Tw" : {
"notes" : null,
"files" : [ ],
"type" : "login",
"title" : "development ldap",
"fields" : {
"password" : [ "bingbangboomdongle" ],
"login" : [ "ldaptest" ]
}
},
"files" : [ ],
"title" : "development ldap",
"type" : "login"
},
"chnmGhEC39YCHhNy1pA8vg" : {
"notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
"fields" : {
"password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
"login" : [ "integration.ucaas.call.metadata" ],
"fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
},
"files" : [ {
"name" : "ascii-art.txt",
"path" : "/mnt/share/keeper-2452814181455428916/ascii-art.txt"
"path" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/ascii-art.txt",
"mimeType" : "text/plain",
"size" : 318
}, {
"name" : "integration.ucaas.call.metadata.PNG",
"path" : "/mnt/share/keeper-2452814181455428916/integration.ucaas.call.metadata.PNG"
"path" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
"mimeType" : "image/png",
"size" : 20480
} ],
"type" : "login",
"notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
"title" : "Production ClickToCall API Key",
"fields" : {
"password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
"login" : [ "integration.ucaas.call.metadata" ],
"fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
"type" : "login"
}
}
}
```

The default `inline` transport trades a file `path` for base64 `content`, leaving
nothing on the host:
```json
"files" : [ {
"content" : "ICAgIC9cX18vXAogICAoIC1fLSApCiAgIC8gPiA+IFwK",
"mimeType" : "text/plain",
"name" : "ascii-art.txt",
"size" : 318
} ]
```

3. Running in server mode accepts the same request payload, passed by the http client of your choice.
You can set your preferred host and port in the credcat properties file.
```sh
java -cp "target/classes:target/dependency/*" -server
java -jar target/credcat.jar -server
```
```sh
curl -d $UID_ONLY -H 'Content-Type: application/json' -v -XPOST http://127.0.0.1:8888/api/getSecrets
curl -H 'Content-Type: application/json' -v http://127.0.0.1:8888/api/getVersion
curl -d "$UID_ONLY" -H 'Content-Type: application/json' -s -XPOST http://127.0.0.1:8888/api/getSecrets
curl -H 'Content-Type: application/json' -s http://127.0.0.1:8888/api/getVersion
```


Expand All @@ -263,6 +328,9 @@ location is returned in the response.

- [x] Handle all field types including files & notes
- [x] Handle title & uid searches
- [x] Inline and metadata-only file transports for read-only & ephemeral hosts
- [x] Named config resolution by directory or environment
- [x] Per-request transport & save-location overrides
- [x] Retrieve more than one record in a single request
- [x] Support stand-alone and server modes

Expand Down
4 changes: 2 additions & 2 deletions checks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -308,15 +308,15 @@
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="2"/>
<property name="caseIndent" value="2"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="8"/>
<property name="arrayInitIndent" value="2"/>
</module>

<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="0"/>
<property name="allowedAbbreviationLength" value="2"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
Expand Down
30 changes: 17 additions & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<name>credcat</name>
<packaging>jar</packaging>
<url>https://${source.host}/${source.account}/${project.name}/</url>
<version>1.0.0</version>
<version>1.1.0</version>

<build>
<plugins>
Expand Down Expand Up @@ -331,18 +331,22 @@
<id>github</id>
</profile>
<profile>
<distributionManagement>
<repository>
<id>ossrh</id>
<name>Central Repository OSSRH</name>
<url>https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>ossrh</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<id>ossrh</id>
<build>
<plugins>
<plugin>
<artifactId>central-publishing-maven-plugin</artifactId>
<configuration>
<autoPublish>true</autoPublish>
<publishingServerId>central</publishingServerId>
<waitUntil>published</waitUntil>
</configuration>
<extensions>true</extensions>
<groupId>org.sonatype.central</groupId>
<version>0.10.0</version>
</plugin>
</plugins>
</build>
<id>central</id>
</profile>
</profiles>

Expand Down
Loading
Loading