New bluecat provider CLI options

This commit is contained in:
Sean Malloy 2022-01-21 17:02:28 -06:00
parent 7c19423500
commit 6521557f62
5 changed files with 124 additions and 17 deletions

View File

@ -7,8 +7,72 @@ Install the BlueCat Gateway product and deploy the [community gateway workflows]
## Configuration Options ## Configuration Options
The options for configuring the Bluecat Provider are available through the json file provided to External-DNS via the flag `--bluecat-config-file`. The There are two ways to pass configuration options to the Bluecat Provider JSON configuration file and command line flags. The JSON configuration file option
BlueCat Gateway username and password can be supplied using the configuration file or environment variables `BLUECAT_USERNAME` and `BLUECAT_PASSWORD`. is deprecated and will eventually be removed.
BlueCat provider supports getting the proxy URL from the environment variables. The format is the one specified by golang's [http.ProxyFromEnvironment](https://pkg.go.dev/net/http#ProxyFromEnvironment).
### Using CLI Flags
When using CLI flags to configure the Bluecat Provider the BlueCat Gateway credentials are passed in using environment variables `BLUECAT_USERNAME` and `BLUECAT_PASSWORD`.
#### Deploy
Setup up namespace, deployment, and service account:
```
kubectl create namespace bluecat-example
kubectl create secret generic bluecat-credentials --from-literal=username=bluecatuser --from-literal=password=bluecatpassword -n bluecat-example
cat << EOF > ~/bluecat.yml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
selector:
matchLabels:
app: external-dns
strategy:
type: Recreate
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:v0.8.0
args:
- --log-level=debug
- --source=service
- --provider=bluecat
- --txt-owner-id=bluecat-example
- --bluecat-dns-configuration=Example
- --bluecat-dns-view=Internal
- --bluecat-gateway-host=https://bluecatgw.example.com
- --bluecat-root-zone=example.com
env:
- name: BLUECAT_USERNAME
valueFrom:
secretKeyRef:
name: bluecat-credentials
key: username
- name: BLUECAT_PASSWORD
valueFrom:
secretKeyRef:
name: bluecat-credentials
key: password
EOF
kubectl apply -f ~/bluecat.yml -n bluecat-example
```
### Using JSON Configuration file (DEPRECATED)
The options for configuring the Bluecat Provider are available through the JSON file provided to External-DNS via the flag `--bluecat-config-file`.
| Key | Required | | Key | Required |
| ----------------- | ------------------ | | ----------------- | ------------------ |
@ -20,11 +84,7 @@ BlueCat Gateway username and password can be supplied using the configuration fi
| rootZone | Yes | | rootZone | Yes |
| skipTLSVerify | No (default false) | | skipTLSVerify | No (default false) |
### HTTP proxy #### Deploy
BlueCat provider supports getting the proxy URL from the environment variables. The format is the one specified by golang's [http.ProxyFromEnvironment](https://pkg.go.dev/net/http#ProxyFromEnvironment).
## Deploy
Setup configuration file as k8s `Secret`. Setup configuration file as k8s `Secret`.
``` ```
cat << EOF > ~/bluecat.json cat << EOF > ~/bluecat.json

View File

@ -212,7 +212,7 @@ func main() {
case "azure-private-dns": case "azure-private-dns":
p, err = azure.NewAzurePrivateDNSProvider(cfg.AzureConfigFile, domainFilter, zoneIDFilter, cfg.AzureResourceGroup, cfg.AzureUserAssignedIdentityClientID, cfg.DryRun) p, err = azure.NewAzurePrivateDNSProvider(cfg.AzureConfigFile, domainFilter, zoneIDFilter, cfg.AzureResourceGroup, cfg.AzureUserAssignedIdentityClientID, cfg.DryRun)
case "bluecat": case "bluecat":
p, err = bluecat.NewBluecatProvider(cfg.BluecatConfigFile, domainFilter, zoneIDFilter, cfg.DryRun) p, err = bluecat.NewBluecatProvider(cfg.BluecatConfigFile, cfg.BluecatDNSConfiguration, cfg.BluecatDNSView, cfg.BluecatGatewayHost, cfg.BluecatRootZone, domainFilter, zoneIDFilter, cfg.DryRun, cfg.BluecatSkipTLSVerify)
case "vinyldns": case "vinyldns":
p, err = vinyldns.NewVinylDNSProvider(domainFilter, zoneIDFilter, cfg.DryRun) p, err = vinyldns.NewVinylDNSProvider(domainFilter, zoneIDFilter, cfg.DryRun)
case "vultr": case "vultr":

View File

@ -91,7 +91,12 @@ type Config struct {
AzureResourceGroup string AzureResourceGroup string
AzureSubscriptionID string AzureSubscriptionID string
AzureUserAssignedIdentityClientID string AzureUserAssignedIdentityClientID string
BluecatDNSConfiguration string
BluecatConfigFile string BluecatConfigFile string
BluecatDNSView string
BluecatGatewayHost string
BluecatRootZone string
BluecatSkipTLSVerify bool
CloudflareProxied bool CloudflareProxied bool
CloudflareZonesPerPage int CloudflareZonesPerPage int
CoreDNSPrefix string CoreDNSPrefix string
@ -413,7 +418,15 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("azure-resource-group", "When using the Azure provider, override the Azure resource group to use (required when --provider=azure-private-dns)").Default(defaultConfig.AzureResourceGroup).StringVar(&cfg.AzureResourceGroup) app.Flag("azure-resource-group", "When using the Azure provider, override the Azure resource group to use (required when --provider=azure-private-dns)").Default(defaultConfig.AzureResourceGroup).StringVar(&cfg.AzureResourceGroup)
app.Flag("azure-subscription-id", "When using the Azure provider, specify the Azure configuration file (required when --provider=azure-private-dns)").Default(defaultConfig.AzureSubscriptionID).StringVar(&cfg.AzureSubscriptionID) app.Flag("azure-subscription-id", "When using the Azure provider, specify the Azure configuration file (required when --provider=azure-private-dns)").Default(defaultConfig.AzureSubscriptionID).StringVar(&cfg.AzureSubscriptionID)
app.Flag("azure-user-assigned-identity-client-id", "When using the Azure provider, override the client id of user assigned identity in config file (optional)").Default("").StringVar(&cfg.AzureUserAssignedIdentityClientID) app.Flag("azure-user-assigned-identity-client-id", "When using the Azure provider, override the client id of user assigned identity in config file (optional)").Default("").StringVar(&cfg.AzureUserAssignedIdentityClientID)
app.Flag("bluecat-config-file", "When using the Bluecat provider, specify the Bluecat configuration file (required when --provider=bluecat").Default(defaultConfig.BluecatConfigFile).StringVar(&cfg.BluecatConfigFile)
// Flags related to BlueCat provider
app.Flag("bluecat-dns-configuration", "When using the Bluecat provider, specify the Bluecat DNS configuration string (optional when --provider=bluecat)").Default("").StringVar(&cfg.BluecatDNSConfiguration)
app.Flag("bluecat-config-file", "When using the Bluecat provider, specify the Bluecat configuration file (optional when --provider=bluecat)").Default(defaultConfig.BluecatConfigFile).StringVar(&cfg.BluecatConfigFile)
app.Flag("bluecat-dns-view", "When using the Bluecat provider, specify the Bluecat DNS view string (optional when --provider=bluecat)").Default("").StringVar(&cfg.BluecatDNSView)
app.Flag("bluecat-gateway-host", "When using the Bluecat provider, specify the Bluecat Gateway Host (optional when --provider=bluecat)").Default("").StringVar(&cfg.BluecatGatewayHost)
app.Flag("bluecat-root-zone", "When using the Bluecat provider, specify the Bluecat root zone (optional when --provider=bluecat)").Default("").StringVar(&cfg.BluecatRootZone)
app.Flag("bluecat-skip-tls-verify", "When using the Bluecat provider, specify to skip TLS verification (optional when --provider=bluecat) (default: false)").BoolVar(&cfg.BluecatSkipTLSVerify)
app.Flag("cloudflare-proxied", "When using the Cloudflare provider, specify if the proxy mode must be enabled (default: disabled)").BoolVar(&cfg.CloudflareProxied) app.Flag("cloudflare-proxied", "When using the Cloudflare provider, specify if the proxy mode must be enabled (default: disabled)").BoolVar(&cfg.CloudflareProxied)
app.Flag("cloudflare-zones-per-page", "When using the Cloudflare provider, specify how many zones per page listed, max. possible 50 (default: 50)").Default(strconv.Itoa(defaultConfig.CloudflareZonesPerPage)).IntVar(&cfg.CloudflareZonesPerPage) app.Flag("cloudflare-zones-per-page", "When using the Cloudflare provider, specify how many zones per page listed, max. possible 50 (default: 50)").Default(strconv.Itoa(defaultConfig.CloudflareZonesPerPage)).IntVar(&cfg.CloudflareZonesPerPage)
app.Flag("coredns-prefix", "When using the CoreDNS provider, specify the prefix name").Default(defaultConfig.CoreDNSPrefix).StringVar(&cfg.CoreDNSPrefix) app.Flag("coredns-prefix", "When using the CoreDNS provider, specify the prefix name").Default(defaultConfig.CoreDNSPrefix).StringVar(&cfg.CoreDNSPrefix)

View File

@ -66,7 +66,12 @@ var (
AzureConfigFile: "/etc/kubernetes/azure.json", AzureConfigFile: "/etc/kubernetes/azure.json",
AzureResourceGroup: "", AzureResourceGroup: "",
AzureSubscriptionID: "", AzureSubscriptionID: "",
BluecatDNSConfiguration: "",
BluecatConfigFile: "/etc/kubernetes/bluecat.json", BluecatConfigFile: "/etc/kubernetes/bluecat.json",
BluecatDNSView: "",
BluecatGatewayHost: "",
BluecatRootZone: "",
BluecatSkipTLSVerify: false,
CloudflareProxied: false, CloudflareProxied: false,
CloudflareZonesPerPage: 50, CloudflareZonesPerPage: 50,
CoreDNSPrefix: "/skydns/", CoreDNSPrefix: "/skydns/",
@ -156,7 +161,12 @@ var (
AzureConfigFile: "azure.json", AzureConfigFile: "azure.json",
AzureResourceGroup: "arg", AzureResourceGroup: "arg",
AzureSubscriptionID: "arg", AzureSubscriptionID: "arg",
BluecatDNSConfiguration: "arg",
BluecatConfigFile: "bluecat.json", BluecatConfigFile: "bluecat.json",
BluecatDNSView: "arg",
BluecatGatewayHost: "arg",
BluecatRootZone: "arg",
BluecatSkipTLSVerify: true,
CloudflareProxied: true, CloudflareProxied: true,
CloudflareZonesPerPage: 20, CloudflareZonesPerPage: 20,
CoreDNSPrefix: "/coredns/", CoreDNSPrefix: "/coredns/",
@ -257,7 +267,12 @@ func TestParseFlags(t *testing.T) {
"--azure-config-file=azure.json", "--azure-config-file=azure.json",
"--azure-resource-group=arg", "--azure-resource-group=arg",
"--azure-subscription-id=arg", "--azure-subscription-id=arg",
"--bluecat-dns-configuration=arg",
"--bluecat-config-file=bluecat.json", "--bluecat-config-file=bluecat.json",
"--bluecat-dns-view=arg",
"--bluecat-gateway-host=arg",
"--bluecat-root-zone=arg",
"--bluecat-skip-tls-verify",
"--cloudflare-proxied", "--cloudflare-proxied",
"--cloudflare-zones-per-page=20", "--cloudflare-zones-per-page=20",
"--coredns-prefix=/coredns/", "--coredns-prefix=/coredns/",
@ -363,7 +378,12 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_AZURE_CONFIG_FILE": "azure.json", "EXTERNAL_DNS_AZURE_CONFIG_FILE": "azure.json",
"EXTERNAL_DNS_AZURE_RESOURCE_GROUP": "arg", "EXTERNAL_DNS_AZURE_RESOURCE_GROUP": "arg",
"EXTERNAL_DNS_AZURE_SUBSCRIPTION_ID": "arg", "EXTERNAL_DNS_AZURE_SUBSCRIPTION_ID": "arg",
"EXTERNAL_DNS_BLUECAT_DNS_CONFIGURATION": "arg",
"EXTERNAL_DNS_BLUECAT_CONFIG_FILE": "bluecat.json", "EXTERNAL_DNS_BLUECAT_CONFIG_FILE": "bluecat.json",
"EXTERNAL_DNS_BLUECAT_DNS_VIEW": "arg",
"EXTERNAL_DNS_BLUECAT_GATEWAY_HOST": "arg",
"EXTERNAL_DNS_BLUECAT_ROOT_ZONE": "arg",
"EXTERNAL_DNS_BLUECAT_SKIP_TLS_VERIFY": "1",
"EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1", "EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1",
"EXTERNAL_DNS_CLOUDFLARE_ZONES_PER_PAGE": "20", "EXTERNAL_DNS_CLOUDFLARE_ZONES_PER_PAGE": "20",
"EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/", "EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/",

View File

@ -147,16 +147,28 @@ type bluecatCreateTXTRecordRequest struct {
// NewBluecatProvider creates a new Bluecat provider. // NewBluecatProvider creates a new Bluecat provider.
// //
// Returns a pointer to the provider or an error if a provider could not be created. // Returns a pointer to the provider or an error if a provider could not be created.
func NewBluecatProvider(configFile string, domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool) (*BluecatProvider, error) { func NewBluecatProvider(configFile, dnsConfiguration, dnsView, gatewayHost, rootZone string, domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun, skipTLSVerify bool) (*BluecatProvider, error) {
contents, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, errors.Wrapf(err, "failed to read Bluecat config file %v", configFile)
}
cfg := bluecatConfig{} cfg := bluecatConfig{}
err = json.Unmarshal(contents, &cfg) contents, err := os.ReadFile(configFile)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to read Bluecat config file %v", configFile) if errors.Is(err, os.ErrNotExist) {
cfg = bluecatConfig{
GatewayHost: gatewayHost,
DNSConfiguration: dnsConfiguration,
View: dnsView,
RootZone: rootZone,
SkipTLSVerify: skipTLSVerify,
GatewayUsername: "",
GatewayPassword: "",
}
} else {
return nil, errors.Wrapf(err, "failed to read Bluecat config file %v", configFile)
}
} else {
err = json.Unmarshal(contents, &cfg)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse Bluecat JSON config file %v", configFile)
}
} }
token, cookie, err := getBluecatGatewayToken(cfg) token, cookie, err := getBluecatGatewayToken(cfg)
@ -179,6 +191,8 @@ func NewBluecatProvider(configFile string, domainFilter endpoint.DomainFilter, z
// NewGatewayClient creates and returns a new Bluecat gateway client // NewGatewayClient creates and returns a new Bluecat gateway client
func NewGatewayClient(cookie http.Cookie, token, gatewayHost, dnsConfiguration, view, rootZone string, skipTLSVerify bool) GatewayClientConfig { func NewGatewayClient(cookie http.Cookie, token, gatewayHost, dnsConfiguration, view, rootZone string, skipTLSVerify bool) GatewayClientConfig {
// TODO: do not handle defaulting here
//
// Right now the Bluecat gateway doesn't seem to have a way to get the root zone from the API. If the user // Right now the Bluecat gateway doesn't seem to have a way to get the root zone from the API. If the user
// doesn't provide one via the config file we'll assume it's 'com' // doesn't provide one via the config file we'll assume it's 'com'
if rootZone == "" { if rootZone == "" {