feat: add download command to retrieve PEM bundle from Key Vault
This commit is contained in:
@@ -43,7 +43,8 @@ Commands:
|
|||||||
run Scan DNS zones and issue or renew certificates (default)
|
run Scan DNS zones and issue or renew certificates (default)
|
||||||
scan List all domains tagged for ACME management
|
scan List all domains tagged for ACME management
|
||||||
status Show certificate expiry status for all managed domains
|
status Show certificate expiry status for all managed domains
|
||||||
renew Force-renew a certificate for a specific domain
|
renew Force-renew a certificate for a specific domain
|
||||||
|
download Download the PEM bundle for a domain from Key Vault
|
||||||
|
|
||||||
Common options:
|
Common options:
|
||||||
--keyvault-url <url> Azure KeyVault URL
|
--keyvault-url <url> Azure KeyVault URL
|
||||||
@@ -77,6 +78,18 @@ azure-acme-provisioner run --http 8080
|
|||||||
|
|
||||||
> **Note:** Binding port 80 requires root privileges or `CAP_NET_BIND_SERVICE`. When running in Docker, map the host port to the container: `-p 80:8080` and pass `--http 8080`.
|
> **Note:** Binding port 80 requires root privileges or `CAP_NET_BIND_SERVICE`. When running in Docker, map the host port to the container: `-p 80:8080` and pass `--http 8080`.
|
||||||
|
|
||||||
|
### Downloading certificates
|
||||||
|
|
||||||
|
The `download` command fetches the PEM bundle (private key + certificate + chain) from Key Vault and writes it to stdout or a file:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Print to stdout
|
||||||
|
azure-acme-provisioner download api.example.com
|
||||||
|
|
||||||
|
# Write to a file
|
||||||
|
azure-acme-provisioner download api.example.com --output api.example.com.pem
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
All configuration is via environment variables. CLI flags override env vars when both are provided.
|
All configuration is via environment variables. CLI flags override env vars when both are provided.
|
||||||
|
|||||||
+19
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
import { writeFileSync } from 'node:fs';
|
||||||
import { Command } from 'commander';
|
import { Command } from 'commander';
|
||||||
import { loadConfig } from './lib/config.js';
|
import { loadConfig } from './lib/config.js';
|
||||||
import { domainToCertName, Provisioner } from './lib/provisioner.js';
|
import { domainToCertName, Provisioner } from './lib/provisioner.js';
|
||||||
@@ -119,6 +120,24 @@ sharedOptions(
|
|||||||
if (result.errors.length > 0) process.exit(1);
|
if (result.errors.length > 0) process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sharedOptions(
|
||||||
|
program
|
||||||
|
.command('download <domain>')
|
||||||
|
.description('Download the PEM bundle (private key + certificate + chain) for a domain')
|
||||||
|
.option('--output <file>', 'Write to file instead of stdout')
|
||||||
|
).action(async (domain: string, options: Record<string, unknown>) => {
|
||||||
|
applyOverrides(options);
|
||||||
|
const config = loadConfig();
|
||||||
|
const provisioner = new Provisioner(config);
|
||||||
|
const pem = await provisioner.download(domain);
|
||||||
|
if (options['output']) {
|
||||||
|
writeFileSync(String(options['output']), pem, 'utf8');
|
||||||
|
console.log(`Certificate written to ${options['output']}`);
|
||||||
|
} else {
|
||||||
|
process.stdout.write(pem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
program.parseAsync(process.argv).catch((err: unknown) => {
|
program.parseAsync(process.argv).catch((err: unknown) => {
|
||||||
console.error(err instanceof Error ? err.message : String(err));
|
console.error(err instanceof Error ? err.message : String(err));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -131,6 +131,13 @@ export class Provisioner {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async download(domain: string): Promise<string> {
|
||||||
|
const certName = domainToCertName(domain);
|
||||||
|
const pem = await this.store.getSecret(certName);
|
||||||
|
if (!pem) throw new Error(`Certificate not found in KeyVault: ${certName}`);
|
||||||
|
return pem;
|
||||||
|
}
|
||||||
|
|
||||||
async scan(): Promise<DomainRecord[]> {
|
async scan(): Promise<DomainRecord[]> {
|
||||||
return scanDnsZones(this.credential, this.config);
|
return scanDnsZones(this.credential, this.config);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user