Create a Post
cancel
Showing results for 
Search instead for 
Did you mean: 
akurtasanov
Contributor
Jump to solution

The best way to remove unused domain objects?

Good day.

Is there a universal way to delete unused domain objects? I need to delete several hundred.

0 Kudos
1 Solution

Accepted Solutions
Bob_Zimmerman
MVP Gold
MVP Gold

I just wrote a quick script to find unused domain objects. For now, it only tells you they are unused so you can delete them yourself, but it would be simple to make it delete them. The only thing you should need to do is set the value of cmaAddress on the first line if you are using an MDS. It should be the address of a CMA as shown in the output of 'mdsstat'.

cmaAddress=""

portNumber=$(api status | grep "APACHE Gaia Port" | awk '{print $NF}')

showAll() {
IFS=$(printf "\377")
sharedArguments=( --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true show "${1}" details-level full limit 500 )
if ! firstResult=$(mgmt_cli "${sharedArguments[@]}");then return 1;fi
toReturn="$(<<<"${firstResult}" jq -c '.objects[]|.')
";objectCount=$(<<<"${firstResult}" jq -c '.total')
if [ "${objectCount}" -lt 501 ];then echo -n "${toReturn}";return 0;fi
for offsetVal in $(seq 500 500 "${objectCount}" 2>/dev/null | tr "\n" "${IFS}");do
toReturn+="$(mgmt_cli "${sharedArguments[@]}" offset "${offsetVal}" \
| jq -c '.objects[]|.')
";done;echo -n "${toReturn}";}

allDomains="$(showAll dns-domains \
| jq -c '{uuid:.uid,name:.name}')"

echo "" && echo "Working in ${cmaAddress:+CMA }${cmaAddress:-SmartCenter}" && \
echo "${allDomains[@]}" | while read dnsDomain;do
printf "Domain: %s" "$(<<<"${dnsDomain}" jq '.name')"
if [ "0" == "$(mgmt_cli --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true \
where-used uid "$(<<<"${dnsDomain}" jq '.uuid')" \
| jq '."used-directly".total')" ];then
echo " is unused"
else
printf "\33[2K\r"
fi
done

It works by dumping a list of all of the domain objects in the management, then running 'where-used' for each of them. It shows the domain it's currently checking. If the domain is unused, it tells you. If it's used by something, it wipes the line and moves on to the next domain. Here's how the output looks on my lab SmartCenter:

[Expert@DallasSC]# echo "${allDomains[@]}"
{"uuid":"f7bb7e18-4bad-4330-8f2e-4236e6b47382","name":".github.com"}
{"uuid":"df0e50bc-9055-42fd-9d70-216dd7eb73b8","name":".test.com"}
{"uuid":"7eb334af-4088-4665-b26e-b4039f4b862e","name":".time.apple.com"}
{"uuid":"c5ee68ba-c77f-44ce-9907-8001689cbea9","name":".time.windows.com"}
{"uuid":"3ca51f4e-edec-4de3-ae4a-c83c84d0d928","name":".updates.windows.com"}
{"uuid":"c439cf97-4762-4ae7-a759-07c1651d4f2a","name":".www.github.com"}

[Expert@DallasSC]# echo "" && echo "Working in ${cmaAddress:+CMA $cmaAddress}${cmaAddress:-SmartCenter}" && \
> echo "${allDomains[@]}" | while read dnsDomain;do
> printf "Domain: %s" "$(<<<"${dnsDomain}" jq '.name')"
> if [ "0" == "$(mgmt_cli --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true \
> where-used uid "$(<<<"${dnsDomain}" jq '.uuid')" \
> | jq '."used-directly".total')" ];then
> echo " is unused"
> else
> printf "\33[2K\r"
> fi
> done

Working in SmartCenter
Domain: ".test.com" is unused

Edited to fix a dumb issue causing the CMA address to be printed twice.

View solution in original post

(2)
27 Replies
Alex-
MVP Silver
MVP Silver

You could use the Objects Explorer to show unused objects, filter on domain objects and delete them all.

Or use the "show-unused-objects" Management API endpoint, filter the output on object type, list and delete the relevant objects accordingly if you're in an automated environment.

0 Kudos
akurtasanov
Contributor

The problem is that domains are not tracked by this functionality.

0 Kudos
CaseyB
Advisor

I am told it supposed to work for un-used objects; however, it is bugged. I think it is on the low priority list for fixes sadly. The response I have for it was back in January 2025.

0 Kudos
the_rock
MVP Diamond
MVP Diamond

It can be little finnicky...

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
the_rock
MVP Diamond
MVP Diamond

Good question...let me do some tests in the lab in the morning and will update you.

Best,
Andy
"Have a great day and if its not, change it"
akurtasanov
Contributor

Thanks.

Will wait.

0 Kudos
the_rock
MVP Diamond
MVP Diamond

Will let you know soon.

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
the_rock
MVP Diamond
MVP Diamond

Just checked and it is there, in object explorer.

Screenshot_1.png

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
Alex-
MVP Silver
MVP Silver

If you switch from "All" to "Unused Objects" in the top left, you will notice that Domains are not listed.

So, another approach might be to list their name/uid with an API call, and iterate that list against the "where-used" endpoint.

Those which aren't used can be saved in a list and another automation could delete them after some verifications.

the_rock
MVP Diamond
MVP Diamond

Correct, but they are definitely listed there.

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
akurtasanov
Contributor

I see all my 3109 domains in Object Explorer but none of them in Unused Objects. And I defenetly know and also see that most of them are not in use.

0 Kudos
the_rock
MVP Diamond
MVP Diamond

Can you not delete them from there then? I know it would be way better if they show in unused objects. I will try do some more testing for this tomorrow in the lab.

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
akurtasanov
Contributor

Screenshot 2025-11-28 164625.png
I did some testing on LAB GW. Same result.

0 Kudos
the_rock
MVP Diamond
MVP Diamond

So you only see 1 unused, but you are saying there is way more than that?

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
akurtasanov
Contributor

I'm unable to show prodaction env. Screen from above was from test gw. And on them 0 unused dimain but I shown one.

0 Kudos
AkosBakos
MVP Silver
MVP Silver

Hi,

A little bit off, but Algosec can do it semaless 🙂

Akos

----------------
\m/_(>_<)_\m/
the_rock
MVP Diamond
MVP Diamond

Never considered that.

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
Vincent_Bacher
MVP Silver
MVP Silver

Tufin as well, I guess.

and now to something completely different - CCVS, CCAS, CCTE, CCCS, CCSM elite
0 Kudos
the_rock
MVP Diamond
MVP Diamond

I believe Firemon does similar as well.

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
Bob_Zimmerman
MVP Gold
MVP Gold

I just wrote a quick script to find unused domain objects. For now, it only tells you they are unused so you can delete them yourself, but it would be simple to make it delete them. The only thing you should need to do is set the value of cmaAddress on the first line if you are using an MDS. It should be the address of a CMA as shown in the output of 'mdsstat'.

cmaAddress=""

portNumber=$(api status | grep "APACHE Gaia Port" | awk '{print $NF}')

showAll() {
IFS=$(printf "\377")
sharedArguments=( --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true show "${1}" details-level full limit 500 )
if ! firstResult=$(mgmt_cli "${sharedArguments[@]}");then return 1;fi
toReturn="$(<<<"${firstResult}" jq -c '.objects[]|.')
";objectCount=$(<<<"${firstResult}" jq -c '.total')
if [ "${objectCount}" -lt 501 ];then echo -n "${toReturn}";return 0;fi
for offsetVal in $(seq 500 500 "${objectCount}" 2>/dev/null | tr "\n" "${IFS}");do
toReturn+="$(mgmt_cli "${sharedArguments[@]}" offset "${offsetVal}" \
| jq -c '.objects[]|.')
";done;echo -n "${toReturn}";}

allDomains="$(showAll dns-domains \
| jq -c '{uuid:.uid,name:.name}')"

echo "" && echo "Working in ${cmaAddress:+CMA }${cmaAddress:-SmartCenter}" && \
echo "${allDomains[@]}" | while read dnsDomain;do
printf "Domain: %s" "$(<<<"${dnsDomain}" jq '.name')"
if [ "0" == "$(mgmt_cli --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true \
where-used uid "$(<<<"${dnsDomain}" jq '.uuid')" \
| jq '."used-directly".total')" ];then
echo " is unused"
else
printf "\33[2K\r"
fi
done

It works by dumping a list of all of the domain objects in the management, then running 'where-used' for each of them. It shows the domain it's currently checking. If the domain is unused, it tells you. If it's used by something, it wipes the line and moves on to the next domain. Here's how the output looks on my lab SmartCenter:

[Expert@DallasSC]# echo "${allDomains[@]}"
{"uuid":"f7bb7e18-4bad-4330-8f2e-4236e6b47382","name":".github.com"}
{"uuid":"df0e50bc-9055-42fd-9d70-216dd7eb73b8","name":".test.com"}
{"uuid":"7eb334af-4088-4665-b26e-b4039f4b862e","name":".time.apple.com"}
{"uuid":"c5ee68ba-c77f-44ce-9907-8001689cbea9","name":".time.windows.com"}
{"uuid":"3ca51f4e-edec-4de3-ae4a-c83c84d0d928","name":".updates.windows.com"}
{"uuid":"c439cf97-4762-4ae7-a759-07c1651d4f2a","name":".www.github.com"}

[Expert@DallasSC]# echo "" && echo "Working in ${cmaAddress:+CMA $cmaAddress}${cmaAddress:-SmartCenter}" && \
> echo "${allDomains[@]}" | while read dnsDomain;do
> printf "Domain: %s" "$(<<<"${dnsDomain}" jq '.name')"
> if [ "0" == "$(mgmt_cli --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true \
> where-used uid "$(<<<"${dnsDomain}" jq '.uuid')" \
> | jq '."used-directly".total')" ];then
> echo " is unused"
> else
> printf "\33[2K\r"
> fi
> done

Working in SmartCenter
Domain: ".test.com" is unused

Edited to fix a dumb issue causing the CMA address to be printed twice.

(2)
CaseyB
Advisor

That worked great for me, thanks!

the_rock
MVP Diamond
MVP Diamond

Tested in my lab as well, great!

Best,
Andy
"Have a great day and if its not, change it"
0 Kudos
Vincent_Bacher
MVP Silver
MVP Silver

Nice. Could be extended to loop over all CMA and/or to select object type and other options.

and now to something completely different - CCVS, CCAS, CCTE, CCCS, CCSM elite
0 Kudos
Bob_Zimmerman
MVP Gold
MVP Gold

Here's a slightly updated version which prompts, then deletes the unused objects if you approve:

cmaAddress=""

portNumber=$(api status | grep "APACHE Gaia Port" | awk '{print $NF}')

showAll() {
IFS=$(printf "\377")
sharedArguments=( --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true show "${1}" details-level full limit 500 )
if ! firstResult=$(mgmt_cli "${sharedArguments[@]}");then return 1;fi
toReturn="$(<<<"${firstResult}" jq -c '.objects[]|.')
";objectCount=$(<<<"${firstResult}" jq -c '.total')
if [ "${objectCount}" -lt 501 ];then echo -n "${toReturn}";return 0;fi
for offsetVal in $(seq 500 500 "${objectCount}" 2>/dev/null | tr "\n" "${IFS}");do
toReturn+="$(mgmt_cli "${sharedArguments[@]}" offset "${offsetVal}" \
| jq -c '.objects[]|.')
";done;echo -n "${toReturn}";}

allDomains="$(showAll dns-domains \
| jq -c '{uuid:.uid,name:.name}')"
unusedUuids=()

echo "" && echo "Working in ${cmaAddress:+CMA }${cmaAddress:-SmartCenter}" && \
while read dnsDomain;do
printf "Domain: %s" "$(<<<"${dnsDomain}" jq '.name')"
if [ "0" == "$(mgmt_cli --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true \
where-used uid "$(<<<"${dnsDomain}" jq '.uuid')" \
| jq '."used-directly".total')" ];then
echo " is unused"
unusedUuids+=("$(<<<"${dnsDomain}" jq '.uuid')")
else
printf "\33[2K\r"
fi
done < <(echo "${allDomains[@]}")

echo "" && echo "Working in ${cmaAddress:+CMA }${cmaAddress:-SmartCenter}" && \
read -p "Delete these objects? " deleteObjects && \
if [ "y" == "${deleteObjects}" ] || [ "Y" == "${deleteObjects}" ];then
sessionCookie=$(mktemp)
mgmt_cli --port "${portNumber}" ${cmaAddress:+-d "${cmaAddress}"} -r true login >"${sessionCookie}"
for unusedUuid in "${unusedUuids[@]}";do
mgmt_cli -s "${sessionCookie}" delete dns-domain uid "${unusedUuid}"
done
mgmt_cli -s "${sessionCookie}" publish
mgmt_cli -s "${sessionCookie}" logout
fi

Edited to fix a dumb issue causing the CMA address to be printed twice.

0 Kudos
Bob_Zimmerman
MVP Gold
MVP Gold

And now a version which works on SmartCenters or CMAs, and which iterates through all of the non-global CMAs on an MDS. I also cleaned up the status messages a little. The prompt to delete will time out after 30 seconds and continue without deleting (this way, you can just let it run on a big MDS without babysitting it).

portNumber=$(api status | grep "APACHE Gaia Port" | awk '{print $NF}')

showAll() {
IFS=$(printf "\377")
sharedArguments=( --port ${portNumber} -f json ${cmaAddress:+-d} ${cmaAddress:+${cmaAddress}} -r true show "$1" details-level full limit 500 )
firstResult=$(mgmt_cli ${sharedArguments[@]})
if [ $? -ne 0 ];then return 1;fi
toReturn="$(echo "${firstResult}" | jq -c '.objects[]|.')
";objectCount=$(echo "${firstResult}" | jq -c '.total')
if [ "$objectCount" -lt 501 ];then echo "${toReturn}" | head -n -1;return 0;fi
for offsetVal in $(seq 500 500 "${objectCount}" 2>/dev/null | tr "\n" "$IFS");do
toReturn+="$(mgmt_cli ${sharedArguments[@]} offset "${offsetVal}" \
| jq -c '.objects[]|.')
";done;echo "${toReturn}" | head -n -1;}

cmaList=$(showAll domains \
| jq -c '{name:.name,server:.servers[]|{host:."multi-domain-server",ipAddress:."ipv4-address"}}' \
| grep $(hostname) \
| jq -c '[.name,.server.ipAddress]')
if [ ${#cmaList} -eq 0 ];then cmaList=("[\"$(hostname)\",\"\"]");fi

for cmaRow in $cmaList;do
cmaAddress=$(<<<"${cmaRow}" jq '.[1]' | sed 's#"##g')
allDomains="$(showAll dns-domains \
| jq -c '{uuid:.uid,name:.name}')"
unusedUuids=()

echo ""echo "Working in ${cmaAddress:+CMA }${cmaAddress:-SmartCenter}"
while read dnsDomain;do
printf "Domain: %s" "$(<<<"${dnsDomain}" jq '.name')"
if [ "0" == "$(mgmt_cli --port "${portNumber}" -f json ${cmaAddress:+-d "${cmaAddress}"} -r true \
where-used uid "$(<<<"${dnsDomain}" jq '.uuid')" \
| jq '."used-directly".total')" ];then
echo " is unused"
unusedUuids+=("$(<<<"${dnsDomain}" jq '.uuid')")
else
printf "\33[2K\r"
fi
done < <(echo "${allDomains[@]}")

echo ""
echo "Found ${#unusedUuids[@]} unused domain objects in ${cmaAddress:+CMA }${cmaAddress:-SmartCenter}"
deleteObjects=""
if [ "0" != "${#unusedUuids[@]}" ];then
timeout 30s read -p "Delete these objects? " deleteObjects
if [ "y" == "${deleteObjects}" ] || [ "Y" == "${deleteObjects}" ];then
sessionCookie=$(mktemp)
mgmt_cli --port "${portNumber}" ${cmaAddress:+-d "${cmaAddress}"} -r true login >"${sessionCookie}"
for unusedUuid in "${unusedUuids[@]}";do
mgmt_cli -s "${sessionCookie}" delete dns-domain uid "${unusedUuid}"
done
mgmt_cli -s "${sessionCookie}" publish
mgmt_cli -s "${sessionCookie}" logout
else echo "";echo "Not deleting.";echo ""
fi
fi

done
0 Kudos
Hugo_vd_Kooij
MVP Gold
MVP Gold

To be honest I like the idea. But I don't like the coding style.

I prefer to indent lines inside loops. Use explicit CR/(/LF)  and not rely on the splitting of lines in the script to get them.

Stuff like that. They make it easiier to pickup a year later to fix or enhance.

<< We make miracles happen while you wait. The impossible jobs take just a wee bit longer. >>
0 Kudos
Bob_Zimmerman
MVP Gold
MVP Gold

I do too, but I develop little throwaway scripts like this in a local file which I paste into a terminal rather than editing a remote file and running it. My access to my lab is limited while I'm connected to work, so I can't just open a new session to edit a file via SCP. Indentation causes problems when pasting blocks of code in the terminal (particularly when pasting a chunk from inside a loop). Here's an example:

### Without indentation works:
for outerCounter in $(seq 1 3);do
for counter in $(seq 1 3);do
echo "Loop iteration ${outerCounter:-0}:${counter}"
done
done



### With indentation fails badly:
for outerCounter in $(seq 1 3);do
	for counter in $(seq 1 3);do
		echo "Loop iteration ${outerCounter:-0}:${counter}"
	done
done

Paste the first one into a terminal, and it works just fine. Paste the second, you'll get a lot of bells, and it starts listing all the executables in your $PATH.

0 Kudos

Leaderboard

Epsum factorial non deposit quid pro quo hic escorol.

Upcoming Events

    CheckMates Events