Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/go_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ jobs:
strategy:
matrix:
environment:
# - "KFC_10_5_0"
# - "KFC_12_3_0_KC"
- "ses_2441"
environment: ${{ matrix.environment }}
steps:
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/keyfactor-starter-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@ name: Keyfactor Bootstrap Workflow
on:
workflow_dispatch:
pull_request:
types: [ opened, closed, synchronize, edited, reopened ]
types: [opened, closed, synchronize, edited, reopened]
push:
create:
branches:
- 'release-*.*'

jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/starter.yml@v3
uses: keyfactor/actions/.github/workflows/starter.yml@v4
with:
command_token_url: ${{ vars.COMMAND_TOKEN_URL }}
command_hostname: ${{ vars.COMMAND_HOSTNAME }}
command_base_api_path: ${{ vars.COMMAND_API_PATH }}
secrets:
token: ${{ secrets.V2BUILDTOKEN}}
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}
scan_token: ${{ secrets.SAST_TOKEN }}
scan_token: ${{ secrets.SAST_TOKEN }}
entra_username: ${{ secrets.DOCTOOL_ENTRA_USERNAME }}
entra_password: ${{ secrets.DOCTOOL_ENTRA_PASSWD }}
command_client_id: ${{ secrets.COMMAND_CLIENT_ID }}
command_client_secret: ${{ secrets.COMMAND_CLIENT_SECRET }}
197 changes: 193 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,30 @@ Currently `Basic Authentication` via `Active Directory` is the *ONLY* supported
| KEYFACTOR_AUTH_ACCESS_TOKEN | Access token to use to authenticate to Keyfactor Command API. This can be supplied directly or generated via client credentials | |
| KEYFACTOR_AUTH_CA_CERT | Either a file path or PEM encoded string to a CA certificate to use when connecting to Keyfactor Auth | |

### Kerberos/SPNEGO Authentication

Kerberos authentication supports three methods: credential cache (ccache), keytab file, or username/password. The authentication method is determined automatically based on which credentials are provided, with the following priority: ccache > keytab > password.

| Name | Description | Default |
|-----------------------------------|----------------------------------------------------------------------------------------------------|-------------------|
| KEYFACTOR_AUTH_KRB_USERNAME | Kerberos principal (username or user@REALM format) | |
| KEYFACTOR_AUTH_KRB_PASSWORD | Password for password-based Kerberos authentication | |
| KEYFACTOR_AUTH_KRB_REALM | Kerberos realm (uppercase, e.g., EXAMPLE.COM). Can be implied from username if using user@REALM | |
| KEYFACTOR_AUTH_KRB_KEYTAB | Path to keytab file for keytab-based authentication | |
| KEYFACTOR_AUTH_KRB_CONFIG | Path to krb5.conf file | `/etc/krb5.conf` |
| KEYFACTOR_AUTH_KRB_CCACHE | Path to credential cache file for ccache-based authentication | |
| KEYFACTOR_AUTH_KRB_SPN | Service Principal Name (optional, auto-generated as HTTP/hostname if not specified) | |
| KEYFACTOR_AUTH_KRB_DISABLE_PAFXFAST | Set to `true` to disable PA-FX-FAST for Active Directory compatibility | `false` |

### Test Environment Variables

These environment variables are used to run go tests. They are not used in the actual client library.

| Name | Description | Default |
|------------------------|-------------------------------------------------------|---------|
| TEST_KEYFACTOR_AD_AUTH | Set to `true` to test Active Directory authentication | false |
| TEST_KEYFACTOR_KC_AUTH | Set to `true` to test Keycloak authentication | false |
| Name | Description | Default |
|-------------------------|-------------------------------------------------------|---------|
| TEST_KEYFACTOR_AD_AUTH | Set to `true` to test Active Directory authentication | false |
| TEST_KEYFACTOR_KC_AUTH | Set to `true` to test Keycloak authentication | false |
| TEST_KEYFACTOR_KRB_AUTH | Set to `true` to test Kerberos authentication | false |

## Configuration File

Expand Down Expand Up @@ -153,6 +169,55 @@ servers:
api_path: KeyfactorAPI
```

### Kerberos/SPNEGO

#### JSON (with keytab)

```json
{
"servers": {
"default": {
"host": "keyfactor.command.kfdelivery.com",
"username": "svc_keyfactor",
"kerberos_realm": "EXAMPLE.COM",
"kerberos_keytab": "/etc/keytabs/svc_keyfactor.keytab",
"kerberos_config": "/etc/krb5.conf",
"api_path": "KeyfactorAPI"
}
}
}
```

#### JSON (with password)

```json
{
"servers": {
"default": {
"host": "keyfactor.command.kfdelivery.com",
"username": "user@EXAMPLE.COM",
"password": "password",
"kerberos_realm": "EXAMPLE.COM",
"kerberos_config": "/etc/krb5.conf",
"api_path": "KeyfactorAPI"
}
}
}
```

#### YAML (with keytab)

```yaml
servers:
default:
host: keyfactor.command.kfdelivery.com
username: svc_keyfactor
kerberos_realm: EXAMPLE.COM
kerberos_keytab: /etc/keytabs/svc_keyfactor.keytab
kerberos_config: /etc/krb5.conf
api_path: KeyfactorAPI
```

## Configuration File Providers

Below are a list of configuration file providers that can be used to load configuration from a file if loading from disk
Expand Down Expand Up @@ -205,4 +270,128 @@ servers:
parameters:
secret_name: <akv_secret_name>
vault_name: <akv_vault_name>
```

# Testing

To run the tests you'll need to provide a `${HOME}/.keyfactor/command_config.json` file for some of the tests to use.

## Example:

```json
{
"servers": {
"default": {
"host": "<insert keyfactor command hostname>",
"port": 443,
"client_id": "<insert valid client_id>",
"client_secret": "<insert valid client_secret>",
"token_url": "https://<insert oauth2 token endpoint hostname>/oauth2/token",
"api_path": "Keyfactor/API",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "oauth"
},
"basic-auth": {
"host": "<insert valid keyfactor command hostname>",
"port": 443,
"username": "<insert valid keyfactor command username>",
"password": "<insert valid keyfactor command password>",
"domain": "<insert valid AD domain name>",
"api_path": "KeyfactorAPI",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "basic"
},
"default": {
"host": "<insert valid keyfactor command hostname>",
"port": 443,
"username": "<insert valid keyfactor command username>",
"password": "<insert valid keyfactor command password>",
"domain": "<insert valid AD domain name>",
"api_path": "KeyfactorAPI",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "basic"
},
Comment on lines +306 to +316
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This JSON configuration has a duplicate "default" server key. The first "default" server at line 284 uses OAuth authentication, while the second at line 306 uses basic authentication. In JSON, duplicate keys are not valid, and the second occurrence will overwrite the first. Either rename one of the servers or remove the duplicate entry.

Copilot uses AI. Check for mistakes.
"invalid-host": {
"host": "<insert valid keyfactor command hostname>",
"port": 443,
"username": "<insert valid keyfactor command username>",
"password": "<insert valid keyfactor command password>",
"domain": "<insert valid AD domain name>",
"api_path": "KeyfactorAPI",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "basic"
},
"invalid-username": {
"host": "<insert valid keyfactor command hostname>",
"port": 443,
"username": "invalid",
"password": "<insert valid keyfactor command password>",
"domain": "<insert valid AD domain name>",
"api_path": "KeyfactorAPI",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "basic"
},
"invalid-password": {
"host": "<insert valid keyfactor command hostname>",
"port": 443,
"username": "<insert valid keyfactor command username>",
"password": "invalid",
"domain": "<insert valid AD domain name>",
"api_path": "KeyfactorAPI",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "basic"
},
"oauth": {
"host": "<insert keyfactor command hostname>",
"port": 443,
"client_id": "<insert valid client_id>",
"client_secret": "<insert valid client_secret>",
"token_url": "https://<insert oauth2 token endpoint hostname>/oauth2/token",
"api_path": "Keyfactor/API",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "oauth"
},
"oauth-invalid-creds": {
"host": "<insert keyfactor command hostname>",
"port": 443,
"client_id": "invalid",
"client_secret": "invalid",
"token_url": "https://<insert oauth2 token endpoint hostname>/oauth2/token",
"api_path": "Keyfactor/API",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "oauth"
},
"oauth-invalid-host": {
"host": "invalid.localhost.dev",
"port": 443,
"client_id": "<insert valid client_id>",
"client_secret": "<insert valid client_secret>",
"token_url": "https://<insert oauth2 token endpoint hostname>/oauth2/token",
"api_path": "Keyfactor/API",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "oauth"
},
"oauth-skiptls": {
"host": "<insert keyfactor command hostname>",
"port": 443,
"client_id": "<insert valid client_id>",
"client_secret": "<insert valid client_secret>",
"token_url": "https://<insert oauth2 token endpoint hostname>/oauth2/token",
"api_path": "Keyfactor/API",
"auth_provider": {},
"skip_tls_verify": true,
"auth_type": "oauth"
}
}
}

```
4 changes: 2 additions & 2 deletions auth_providers/auth_basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,12 @@ func TestCommandAuthConfigBasic_Authenticate(t *testing.T) {

t.Log("Testing Basic Auth with invalid creds implicit config file")
invProfileCreds := &auth_providers.CommandAuthConfigBasic{}
invProfileCreds.WithConfigProfile("invalid_username")
invProfileCreds.WithConfigProfile("invalid-username")
authBasicTest(t, "with invalid creds implicit config file", true, invProfileCreds, invalidCredsExpectedError...)

t.Log("Testing Basic Auth with invalid Command host implicit config file")
invHostConfig := &auth_providers.CommandAuthConfigBasic{}
invHostConfig.WithConfigProfile("invalid_host")
invHostConfig.WithConfigProfile("invalid-host")
invHostExpectedError := []string{"no such host"}
authBasicTest(
t, "with invalid Command host implicit config file", true, invHostConfig,
Expand Down
Loading
Loading