{"id":4461,"date":"2026-07-19T18:22:37","date_gmt":"2026-07-19T16:22:37","guid":{"rendered":"https:\/\/vpxd.dc5.cz\/?p=4461"},"modified":"2026-07-19T22:51:35","modified_gmt":"2026-07-19T20:51:35","slug":"introducing-sso-users-a-fast-go-cli-for-vcenter-sso-user-auditing","status":"publish","type":"post","link":"https:\/\/vpxd.dc5.cz\/index.php\/2026\/07\/19\/introducing-sso-users-a-fast-go-cli-for-vcenter-sso-user-auditing\/","title":{"rendered":"Introducing sso-users \u2013 A Fast Go CLI for vCenter SSO User Auditing"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I built <strong>sso-users<\/strong>\u2014a lightweight Go application that connects directly to the VMware Directory Service (<strong>vmdir<\/strong>) over LDAPS and reports local SSO users together with their <strong>password expiration <\/strong>status.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The project was originally created for <strong>VMware Cloud Foundation (VCF) 9<\/strong> environments, but it should works anywhere the vCenter SSO directory is available over LDAP.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Where to find it -> <a href=\"https:\/\/github.com\/musil\/vSphere_scripts\/tree\/main\/apps\/sso-users\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a> in repository <a href=\"https:\/\/github.com\/musil\/vSphere_scripts.git\" target=\"_blank\" rel=\"noreferrer noopener\">musil\/vSphere_scripts<\/a> on GitHub.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Why I Built It<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When performing security reviews or compliance audits, one of the recurring questions is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Which local SSO accounts exist?<\/li>\n\n\n\n<li>Are any passwords already expired?<\/li>\n\n\n\n<li>Which accounts never expire?<\/li>\n\n\n\n<li>Are any accounts disabled or locked?<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Some of the questions can be answered by PowerCLI and the <code>VMware.vSphere.SsoAdmin<\/code> module. But not all. I wanted something that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>runs anywhere<\/li>\n\n\n\n<li>has zero PowerShell dependencies<\/li>\n\n\n\n<li>is easy to automate<\/li>\n\n\n\n<li>can be integrated into monitoring systems<\/li>\n\n\n\n<li>exposes the data over a simple REST API<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">So I wrote <strong>sso-users<\/strong> in Go.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What It Does<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The application connects securely to <strong>vmdir<\/strong> using LDAPS and retrieves local SSO accounts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For every user it calculates password expiration based on the directory attributes and displays information including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Username<\/li>\n\n\n\n<li>User Principal Name (UPN)<\/li>\n\n\n\n<li>Disabled state<\/li>\n\n\n\n<li>Locked state<\/li>\n\n\n\n<li>Password never expires<\/li>\n\n\n\n<li>Password last changed<\/li>\n\n\n\n<li>Password expiration date (if is not set to password never expire)<\/li>\n\n\n\n<li>Days remaining until expiration (if is not set to password never expire)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of relying on the vSphere UI, the tool reads the information directly from LDAP, making it fast and script-friendly. (<a href=\"https:\/\/raw.githubusercontent.com\/musil\/vSphere_scripts\/main\/apps\/sso-users\/README.md\">GitHub<\/a>)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Flexible Output<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The CLI supports multiple output formats depending on your workflow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For administrators:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Human-readable table output<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1500\" height=\"168\" src=\"https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-1.png\" alt=\"\" class=\"wp-image-4463\" srcset=\"https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-1.png 1500w, https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-1-800x90.png 800w, https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-1-768x86.png 768w, https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-1-1200x134.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">For automation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>JSON output<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"528\" height=\"1080\" src=\"https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-2-528x1080.png\" alt=\"\" class=\"wp-image-4464\" srcset=\"https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-2-528x1080.png 528w, https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-2-391x800.png 391w, https:\/\/vpxd.dc5.cz\/wp-content\/uploads\/2026\/07\/image-2.png 728w\" sizes=\"auto, (max-width: 528px) 85vw, 528px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This makes it easy to integrate with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>monitoring systems<\/li>\n\n\n\n<li>scheduled compliance reports<\/li>\n\n\n\n<li>inventory scripts<\/li>\n\n\n\n<li>CI\/CD pipelines<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Built-in REST API<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Besides the CLI, <strong>sso-users<\/strong> can also run as a small HTTP service.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The API is protected with a bearer token and exposes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/health<\/code><\/li>\n\n\n\n<li><code>\/api\/v1\/users<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This makes it straightforward to integrate with dashboards, Grafana, custom portals, or other internal tooling without repeatedly invoking the CLI. (<a href=\"https:\/\/raw.githubusercontent.com\/musil\/vSphere_scripts\/main\/apps\/sso-users\/README.md\">GitHub<\/a>)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Security First<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Security was one of the design goals.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The application:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>supports interactive password prompts<\/li>\n\n\n\n<li>can read credentials from environment variables<\/li>\n\n\n\n<li>avoids logging passwords or API keys<\/li>\n\n\n\n<li>supports trusted TLS certificates<\/li>\n\n\n\n<li>allows <code>-insecure<\/code> only for internal or lab environments with self-signed certificates<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">It also avoids placing passwords in shell history whenever possible. (<a href=\"https:\/\/raw.githubusercontent.com\/musil\/vSphere_scripts\/main\/apps\/sso-users\/README.md\">GitHub<\/a>)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Why Go?<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Go is a great fit for infrastructure tools.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The resulting binary is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cross-platform<\/li>\n\n\n\n<li>fast<\/li>\n\n\n\n<li>easy to distribute<\/li>\n\n\n\n<li>dependency-free<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Release builds are available for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Linux (amd64)<\/li>\n\n\n\n<li>Windows (amd64)<\/li>\n\n\n\n<li>macOS (Apple Silicon)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Open Source<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The project is completely open source, and I hope it becomes useful for VMware administrators, consultants, and anyone responsible for auditing vCenter environments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Feedback, bug reports, feature requests, and pull requests are always welcome.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Happy automating!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I built sso-users\u2014a lightweight Go application that connects directly to the VMware Directory Service (vmdir) over LDAPS and reports local SSO users together with their password expiration status. The project was originally created for VMware Cloud Foundation (VCF) 9 environments, but it should works anywhere the vCenter SSO directory is available over LDAP. Where to &hellip; <a href=\"https:\/\/vpxd.dc5.cz\/index.php\/2026\/07\/19\/introducing-sso-users-a-fast-go-cli-for-vcenter-sso-user-auditing\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Introducing sso-users \u2013 A Fast Go CLI for vCenter SSO User Auditing&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":4463,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,3,10,53,58,8],"tags":[71,48,17,62,20],"class_list":["post-4461","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-homelab","category-vcenter","category-vcf","category-vcf9","category-vmware","tag-golang","tag-script","tag-vcenter","tag-vcf9","tag-vmware"],"_links":{"self":[{"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/posts\/4461","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/comments?post=4461"}],"version-history":[{"count":2,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/posts\/4461\/revisions"}],"predecessor-version":[{"id":4467,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/posts\/4461\/revisions\/4467"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/media\/4463"}],"wp:attachment":[{"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/media?parent=4461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/categories?post=4461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vpxd.dc5.cz\/index.php\/wp-json\/wp\/v2\/tags?post=4461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}