credentials-fetcher is a Linux daemon that retrieves gMSA credentials from Active Directory over LDAP. It creates and refreshes kerberos tickets from gMSA credentials. Kerberos tickets can be used by containers to run apps/services that authenticate using Active Directory.
This daemon works in a similar way as ccg.exe and the gMSA plugin in Windows as described in - https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/manage-serviceaccounts#gmsa-architecture-and-improvements
- Prerequisites
- Building from Source
- Installation
- Configuration
- Setting up Testing Environment
- Testing
- Service Management
- Troubleshooting
Supported Platforms: Amazon Linux 2023 (recommended), Fedora 41+
Required Dependencies:
dnf install openldap-clients krb5-workstation sssd For Domain-Joined Mode (additional):
dnf install realmd oddjob oddjob-mkhomedir adcliBuild Dependencies (AL2023):
# Install Go
sudo dnf install -y golang make krb5-devel
# Install golangci-lint (Optional)
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
# Install gosec (Optional)
go install github.com/securego/gosec/v2/cmd/gosec@latest
# Add to PATH
export PATH=$PATH:$(go env GOPATH)/binmake buildThe binary will be created at bin/credentials-fetcherd.
| Command | Description |
|---|---|
make build |
Build the binary |
make lint-check |
Run golangci-lint |
make security-check |
Run gosec security scanner |
make release-strict |
Full build with security checks, linting, and race detection |
make cf-install |
Build and install to system (requires sudo) |
make cf-create-service |
Generate systemd service file |
Enable debugging symbols:
ENABLE_DEBUGGING=1 make buildEnable code coverage:
CODE_COVERAGE=1 make buildAfter building:
sudo make cf-installThis installs:
- Binary to
/usr/sbin/credentials-fetcherd - Service file to
/usr/lib/systemd/system/credentials-fetcher.service - Config to
/etc/credentials-fetcher.conf
dnf install credentials-fetchersystemctl status credentials-fetcher
credentials-fetcher --versionThe daemon is configured via /etc/credentials-fetcher.conf.
For ECS/Fargate (managed modes): No configuration needed. Default settings work out of the box.
For standalone mode: All options remain optional for basic lease operations. Configuration is only needed if you require automatic credential renewal in non-domain joined standalone deployments.
| Option | Type | Default | Description |
|---|---|---|---|
RunRenewalNonDomainJoined |
bool | false | Enable automatic credential renewal for non-domain joined standalone mode |
CFGmsaSecretName |
string | "" | AWS Secrets Manager secret name containing AD credentials |
LDAPSearchTimeout |
int | 5 | LDAP search timeout in seconds |
Works for all deployment modes without modification:
# /etc/credentials-fetcher.conf
RunRenewalNonDomainJoined =
CFGmsaSecretName = ""
LDAPSearchTimeout = 5Only needed for standalone deployments requiring automatic credential renewal:
# /etc/credentials-fetcher.conf
RunRenewalNonDomainJoined = true
CFGmsaSecretName = "prod/ad-credentials"
LDAPSearchTimeout = 10AWS Secrets Manager secret format:
{"username": "StandardUser01", "password": "p@ssw0rd", "domainName": "contoso.com"}Setup gMSA accounts using instructions here. Both domain-joined and non-domain joined use cases are supported. In Fargate, only non-domain joined is supported.
In non domain joined modes, the AD User credentials need to be stored in a secret store that will be retrieved by the daemon. We use AWS Secret Manager for this.
Save the AD User credentials to AWS secrets manager
{
"username":"StandardUser01",
"password":"p@ssw0rd",
"domainName":"contoso.com"
}Next, on the EC2 instance where credentials-fetcher is installed, navigate to /etc/credentials-fetcher.conf and provide the secrets manager name
For domain joined modes, the host principle needs to be part of the group that is allowed to retrieve the managed password in AD setup.
Once gMSA accounts are created, use the test scripts in tests/test_scripts/ to validate kerberos ticket functionality.
-
Install Python dependencies:
dnf install -y pip cd /path/to/repo python3 -m venv .venv source .venv/bin/activate pip install grpcio grpcio-tools
-
Generate gRPC Python files:
cd tests/test_scripts python -m grpc_tools.protoc --proto_path=../../internal/grpc/proto --python_out=. --grpc_python_out=. credentialsfetcher.proto -
Start credentials-fetcher daemon:
sudo systemctl start credentials-fetcher
Domain-joined mode:
# Replace {CREDSPEC_PLACEHOLDER} with your credspec JSON
python add_kerberos_lease_test.py
# Delete lease (replace {LEASE_ID_PLACEHOLDER} with returned lease_id)
python delete_kerberos_lease_test.pyNon-domain-joined mode:
# Replace {CREDSPEC_PLACEHOLDER} and {PASSWORD_PLACEHOLDER} with actual values
python add_non_domain_joined_kerberos_lease_test.py
# Test renewal
python renew_non_domain_joined_kerberos_lease.pyExpected output: Scripts print GRPC_TEST_RESULT: followed by JSON with success status and lease details.
Domain-Joined Mode:
{
"CmsPlugins": ["ActiveDirectory"],
"DomainJoinConfig": {
"Sid": "S-1-5-21-123456789-123456789-123456789",
"MachineAccountName": "WebApp01",
"Guid": "af602f85-d754-4eea-9fa8-fd76810485f1",
"DnsTreeName": "contoso.com",
"DnsName": "contoso.com",
"NetBiosName": "CONTOSO"
},
"ActiveDirectoryConfig": {
"GroupManagedServiceAccounts": [
{
"Name": "WebApp01",
"Scope": "contoso.com"
}
]
}
}Non-Domain-Joined Mode:
{
"CmsPlugins": ["ActiveDirectory"],
"DomainJoinConfig": {
"Sid": "S-1-5-21-987654321-987654321-987654321",
"MachineAccountName": "WebApp02",
"Guid": "bf702f85-e864-5ffa-8gb9-ge87920596g2",
"DnsTreeName": "contoso.com",
"DnsName": "contoso.com",
"NetBiosName": "CONTOSO"
},
"ActiveDirectoryConfig": {
"GroupManagedServiceAccounts": [
{
"Name": "WebApp02",
"Scope": "contoso.com"
}
],
"HostAccountConfig": {
"PortableCcgVersion": "1",
"PluginGUID": "{859E1386-BDB4-49E8-85C7-3070B13920E1}",
"PluginInput": "prod/ad-credentials" // AWS Secrets Manager secret name
}
}
}# Start the service
sudo systemctl start credentials-fetcher
# Stop the service
sudo systemctl stop credentials-fetcher
# Check status
sudo systemctl status credentials-fetcher
# Enable auto-start
sudo systemctl enable credentials-fetcher
# View logs
sudo journalctl -u credentials-fetcher -fService won't start:
- Check logs:
sudo journalctl -u credentials-fetcher - Verify config file:
/etc/credentials-fetcher.conf - Ensure socket directory exists:
/var/credentials-fetcher/socket
LDAP connection failures:
- Verify AD connectivity:
ldapsearch -H ldap://your-dc.contoso.com - Check DNS resolution:
nslookup your-dc.contoso.com - Validate credentials in AWS Secrets Manager
Kerberos ticket issues:
- Check ticket cache:
klist -c /var/credentials-fetcher/krbdir/*/krb5cc_* - Verify time sync:
timedatectl status - Test kinit manually:
kinit username@DOMAIN.COM
Test script failures:
- Ensure daemon is running:
systemctl status credentials-fetcher - Check socket permissions:
ls -la /var/credentials-fetcher/socket/ - Verify gRPC files generated:
ls -la tests/test_scripts/*_pb2.py
- Service logs:
journalctl -u credentials-fetcher - Application logs:
/var/credentials-fetcher/logging - Kerberos cache:
/var/credentials-fetcher/krbdir