Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

ContributorsForksStargazersIssuesproject_license


Logo

credcat

Bound by sacred cyphers and powered by forgotten rites; access without a path, only a destination. Your vital sigils safe, their essence known to none but their holder, sealed by the magic of pure ignorance.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

Extending access to Keeper secrets manager for api retrival in distributed or disconnected processes. Serves as a quality of life abstraction to diminish the scourge of hard-coded, insecurely handled credentials in our code bases.

(back to top)

Built With

  • Java

Java is like a bad relationship. It's too object-oriented

(back to top)

Getting Started

Compiling is not necessary as release binaries are available. If you're so inclined the sections below are for you.

Prerequisites

Your going to need a compiler, I recommend anything not Oracle java. Depending on your os, the installation process will vary. Additional packages like maven will be needed to utilize the provided pom file.

CentOS

  • bash
    sudo dnf install java-21-openjdk java-21-openjdk-devel maven

Debian

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Ubuntu

  • bash
    sudo apt install maven openjdk-21-jdk-headless

Windows

  • powershell

    winget install maven
    winget install Microsoft.OpenJDK.21
    refreshenv
    $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.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_urlStart-BitsTransfer-Destination "$env:USERPROFILE\Downloads\maven.zip"-Source $maven_urlStart-Process-Wait -FilePath msiexec -ArgumentList /i,"$env:USERPROFILE\Downloads\jdk-21.msi","ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome",'INSTALLDIR="$java_home"',/quiet -Verb RunAs
    Expand-Archive-DestinationPath "$env:USERPROFILE\Downloads\maven"-Path "$env:USERPROFILE\Downloads\maven.zip"$parentDir=Get-ChildItem-Path "$env:USERPROFILE\Downloads\maven"|Select-Object-First 1Move-Item-Destination $maven_home-Path "$parentDir\*"-Force
    [Environment]::SetEnvironmentVariable('M2_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('MAVEN_HOME',$maven_home, [System.EnvironmentVariableTarget]::User)
    [Environment]::SetEnvironmentVariable('PATH',"$env:PATH;$maven_home\bin", [System.EnvironmentVariableTarget]::User)
    Remove-Item"$env:USERPROFILE\Downloads\jdk-21.msi"Remove-Item"$env:USERPROFILE\Downloads\maven.zip"Remove-Item"$env:USERPROFILE\Downloads\maven"-Recurse -Force

Installation

  1. Clone the repo
    git clone https://github.com/byteskeptical/credcat.git
    cd credcat
  2. Compile binary, prepare release
    # build binary
    mvn compile
    # create package
    mvn install
    # prepare package for official release
    mvn package
  3. Run tests, (optional). Making changes, (required)
    mvn test
  4. Clean up after yourself
    mvn clean

(back to top)

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.

# Keeperkeeper.client_key= # one time token for dynamic config creationkeeper.config= # default device config: a path, raw json, or base64keeper.config.dir= # directory searched for named (configName) configskeeper.config.env= # env var prefix searched for named (configName) configskeeper.files= # default save location (os temp dir when unset)keeper.storage.persistent=false # persist SDK config mutations back to the source file# Filesfile.clean=true # wipe the files directory recursively on shutdownfile.transport=inline # disk | inline | none# Serverserver.host=127.0.0.1
server.port=8888
server.max_request_bytes=1048576 # larger request bodies are rejected with a 413server.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

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.

    Usage: java -jar credcat.jar [ -server |'{ "config": ".keeper/config.base64", "titles": ["RECORD_TITLE"], "uids": ["RECORD_UID"] }' ]
  1. Payload can be any of the following.

    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", "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:

    java -cp "target/classes:target/dependency/*" com.byteskeptical.credcat.SecretsService "$ADVANCED"
    java -jar target/credcat.jar "$UID_ONLY"
    INFO: {"7bN_ceW-p3_alVUNmI09Tw" : {
    "fields" : {
    "password" : [ "bingbangboomdongle" ],
    "login" : [ "ldaptest" ]
    },
    "files" : [ ],
    "title" : "development ldap",
    "type" : "login"
    },
    "chnmGhEC39YCHhNy1pA8vg" : {
    "fields" : {
    "password" : [ "be0d988f-063c-d654-ad1b-a54337f87233" ],
    "login" : [ "integration.ucaas.call.metadata" ],
    "fileref" : [ "3HcX3vCCvHBTBcOqCgCnsQ", "cGBiPmG_9GlZszFbsQmJea" ]
    },
    "files" : [ {
    "name" : "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" : "/tmp/credcat_8f3a1c20-5e7b-4a9d-bd11-2c6f0e9a4477/integration.ucaas.call.metadata.PNG",
    "mimeType" : "image/png",
    "size" : 20480
    } ],
    "notes" : "VALUE = x-ClickToCall-APIKey:be0d988f-063c-d654-ad1b-a54337f87233",
    "title" : "Production ClickToCall API Key",
    "type" : "login"
    }
    }}

    The default inline transport trades a file path for base64 content, leaving nothing on the host:

    "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.

    java -cp "target/classes:target/dependency/*" -server
    java -jar target/credcat.jar -server
    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

Product Name Screen Shot

(back to top)

Roadmap

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

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Top contributors:

contrib image

License

Distributed under the project_license. See LICENSE for more information.

(back to top)

Contact

byteskeptical - @byteskeptical - bug@byteskeptical.com

Project Link: https://github.com/byteskeptical/credcat

(back to top)

Acknowledgments

(back to top)

About

Keeper Security Manager application vault access. Meant to be served behind a protected API enpoint, returns records as json.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages