bash: FQDN to an LDAP DN string

119 Views Asked by At

I am configuring an LDAP server from a bash script and I need to convert the fully qualified domain name (FQDN) to ldap DNs.

For example:

  • com -> dc=com
  • world.com -> dc=world,dc=com
  • hello.world.com -> dc=hello,dc=world,dc=com
  • hello.beautiful.world.com -> dc=hello,dc=beautiful,dc=world,dc=com

My bash function works, but it is a little bit verbose. Is there any built-in one-line bash command that I can use? Or how to make my function less verbose?

My code:

#!/bin/bash 
 
function fqdn_to_ldap_dn() {  
   local fqdn parts dn                         
   fqdn="$1"              
   IFS=. parts=(${fqdn##*-})     
   dn=""                            
                              
   for i in "${parts[@]}" ; do
      dn+="dc=$i,"            
   done                          
   dn=${dn%?};                   
   echo $dn                          
}                             
                              
echo $(fqdn_to_ldap_dn "aa.hello.com")
3

There are 3 best solutions below

0
larsks On BEST ANSWER

Something like this will work:

fqdn_to_ldap_dn() {
  sed -e 's/[^ ]*/dc=&/g' <<<"${1//./ }" -e 's/ /,/g'
}

Wrapping that in the following script:

#!/bin/bash

fqdn_to_ldap_dn() {
  sed -e 's/[^ ]*/dc=&/g' <<<"${1//./ }" -e 's/ /,/g'
}

domains="
com
world.com
hello.world.com
hello.beautiful.world.com
"

for domain in $domains; do
    echo "$domain -> $(fqdn_to_ldap_dn $domain)"
done

We get:

com -> dc=com
world.com -> dc=world,dc=com
hello.world.com -> dc=hello,dc=world,dc=com
hello.beautiful.world.com -> dc=hello,dc=beautiful,dc=world,dc=com

Breaking down that command a bit, we have:

  • ${1//./ /} replace all instances of . in $1 with (a space). See the "Parameter Expansion" section of the Bash man page for details.

  • The sed expression s/[^ ]*/dc=&/g searches for all groups of non-space characters and adds dc= in front of them (the & in the replacement means "whatever we matched in the first part of the expression").

  • The sed expression s/ /,/g replaces all spaces with ,

2
Jetchisel On

Using the builtin read, and IFS; something like:

function fqdn_to_ldap_dn() {
  local fqdn parts prefix
  fqdn="$1"
  prefix='dc='
  IFS=. read -ra parts <<< "$fqdn" &&
  (IFS=,; printf '%s\n' "${parts[*]/#/"$prefix"}")
}

fqdn_to_ldap_dn "hello.beautiful.world.com"

Or bash 5.2 has the loadable builtins like the dsv, something like:

function fqdn_to_ldap_dn() {
  local fqdn parts prefix
  enable dsv || return
  fqdn="$1"
  prefix='dc='
  dsv -a parts -d "." -S -- "$fqdn" &&
  (IFS=,; printf '%s\n' "${parts[*]/#/"$prefix"}")
}

fqdn_to_ldap_dn "hello.beautiful.world.com"

A test run on the domains:

domains=(com world.com hello.world.com hello.beautiful.world.com)

for f in "${domains[@]}"; do
  printf %s "$f -> "
  fqdn_to_ldap_dn "$f"
done

Output:

com -> dc=com
world.com -> dc=world,dc=com
hello.world.com -> dc=hello,dc=world,dc=com
hello.beautiful.world.com -> dc=hello,dc=beautiful,dc=world,dc=com

0
user1934428 On
f=hello.beautiful.world.co
dn=dc=${f//./,dc=}
echo $dn  # => dc=hello,dc=beautiful,dc=world,dc=com

The crucial point here is the double-slash in the parameter expansion, which means substitute all occurances of the pattern.